-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathnodes.lua
249 lines (218 loc) · 10.2 KB
/
nodes.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
---------------------------------------------------------------------------------------
-- helper node that is used during construction of a house; scaffolding
---------------------------------------------------------------------------------------
-- this node can be crafted
minetest.register_node("handle_schematics:support", {
description = "support structure for buildings",
tiles = {"handle_schematics_support.png"},
groups = {snappy=3,choppy=3,oddly_breakable_by_hand=3},
visual_scale = 1.2,
walkable = false,
climbable = true,
paramtype = "light",
drawtype = "plantlike",
-- -- the small selection box allows the player to dig one or two nodes below
-- selection_box = {
-- type = "fixed",
-- fixed = {-2 / 16, -0.5, -2 / 16, 2 / 16, 0.5, 2 / 16}
-- },
})
minetest.register_craft({
output = "handle_schematics:support 4",
recipe = {
{"group:stick", "", "group:stick" }
}
})
-- always handle the bottommost support node first
-- mobs who wish to use this function have to provide the required item in itemstack
handle_schematics.place_node_using_support_setup = function(pos, clicker, itemstack )
-- TODO: does can_interact_with_node work with mobs?
if not( handle_schematics.can_interact_with_node(clicker, pos)) then
return itemstack;
end
-- pass right-clicks on to support nodes below (else some floor nodes may not be reachable)
local node_below = minetest.get_node( {x=pos.x, y=pos.y-1, z=pos.z} );
if( node_below and node_below.name and node_below.name == "handle_schematics:support_setup" ) then
return handle_schematics.place_node_using_support_setup({x=pos.x, y=pos.y-1, z=pos.z}, clicker, itemstack );
end
local meta = minetest.get_meta( pos );
local node_wanted = meta:get_string( "node_wanted" );
local param2_wanted = meta:get_int( "param2_wanted" );
if( not(meta) or not(node_wanted) or node_wanted == "" or not(clicker)) then
-- if metadata is missing: set to air
minetest.set_node( pos, {name="air"});
return itemstack;
end
local node_really_wanted = node_wanted;
-- some nodes like i.e. dirt with grass or stone with coal cannot be obtained;
-- in such a case we ask for the drop
node_really_wanted = handle_schematics.get_what_player_can_provide( node_wanted );
-- the player might be wielding the requested item
if( itemstack and itemstack:get_name() and itemstack:get_name()==node_really_wanted and itemstack:get_count()>0 ) then
itemstack:take_item();
-- clicker does not have an inventory; it might be a mob
elseif( not( clicker.get_inventory )) then
return itemstack;
-- ...or it might be found elsewhere in the player's inventory
elseif(not( clicker:get_inventory():contains_item("main", node_really_wanted ))) then
if( clicker:is_player()) then
local descr = "-?-";
if( minetest.registered_items[ node_really_wanted ] ) then
descr = minetest.registered_items[ node_really_wanted ].description;
if( not( descr )) then
descr = minetest.registered_items[ node_really_wanted ].name;
end
end
minetest.chat_send_player( clicker:get_player_name(),
"You have no "..( descr or "such node").." ["..node_really_wanted.."].");
end
return itemstack;
end
-- give the player some feedback (might scroll a bit..)
local node_def = handle_schematics.node_defined( node_really_wanted );
if( clicker:is_player()
and node_def
and node_def.description) then
minetest.chat_send_player( clicker:get_player_name(),
"Placed "..( node_def.description or node_really_wanted)..".");
end
-- take the item from the player (provided it actually is a player and not a mob)
if( clicker.get_inventory ) then
clicker:get_inventory():remove_item("main", node_really_wanted.." 1");
-- if a bucket:bucket_* was used for placing water: return the empty bucket
if( node_really_wanted ~= "bucket:bucket_empty"
and string.sub( node_really_wanted, 1, 14)=="bucket:bucket_") then
clicker:get_inventory():add_item("main", "bucket:bucket_empty 1");
end
-- if a seed is placed: hoe the ground below if needed (it might have returned
-- to base or dry state due to water not having been placed yet)
if( string.sub( node_really_wanted, 1, 13 )=="farming:seed_") then
local node_below = minetest.get_node( {x=pos.x, y=pos.y-1, z=pos.z});
if( node_below and node_below.name) then
local def = minetest.registered_nodes[ node_below.name ];
if( def and def.soil and def.soil.base and def.soil.base==node_below.name
and def.soil.wet) then
minetest.set_node( {x=pos.x, y=pos.y-1, z=pos.z}, {name=def.soil.wet} );
end
end
end
-- avoid consuming two beds (because top and bottom both have the same drop)
if( string.sub( node_wanted, 1, 5 )=="beds:") then
if( string.sub( node_wanted, -7)=="_bottom") then
local top_pos = vector.add(pos, minetest.facedir_to_dir(param2_wanted));
local top_name = string.sub( node_wanted, 1, -8).."_top";
minetest.set_node(top_pos, {name = top_name, param2 = param2_wanted});
elseif( string.sub( node_wanted, -4)=="_top") then
local bot_pos = vector.add(pos, minetest.facedir_to_dir((param2_wanted+2)%4));
local bot_name = string.sub( node_wanted, 1, -5).."_bottom";
minetest.set_node(bot_pos, {name = bot_name, param2 = param2_wanted});
end
end
end
minetest.remove_node( pos );
minetest.set_node( pos, { name = node_wanted, param1 = 0, param2 = param2_wanted } );
return itemstack;
end
-- right-clicking a dig_here-indicator ought to dig the next node below it that needs digging and place appropriate scaffolding
handle_schematics.dig_node_using_dig_here_indicator = function(pos, clicker, itemstack )
if not( handle_schematics.can_interact_with_node(clicker, pos)) then
return itemstack;
end
-- TODO: itemstack:get_tool_capabilities() can be used to check and wear down the tool
--if( itemstack ) then minetest.chat_send_player("singleplayer", "You are trying to dig with "..minetest.serialize(itemstack:get_name()).." with tool capabilities: "..minetest.serialize(itemstack:get_tool_capabilities())); end
local meta = minetest.get_meta( pos );
local nodes_wanted_str = meta:get_string( "node_wanted_down_there");
if( not( nodes_wanted_str )) then
return itemstack;
end
local nodes_wanted = minetest.deserialize( nodes_wanted_str );
local cid_air = minetest.get_content_id("air");
if( nodes_wanted ) then
for i=1,table.getn( nodes_wanted ) do
local p = {x=pos.x, y=pos.y-i, z=pos.z};
local node = minetest.get_node( p );
-- found a node that is not yet scaffolding
if( node and node.name and node.name ~= "handle_schematics:support_setup") then
for j,v in ipairs( nodes_wanted ) do
-- get the entry at the right position
if( v and v[1] == p.y ) then
-- dig the old node and add it to the inventory
-- TODO: can mobs dig that way?
-- TODO: require suitable tools
-- TODO: tools ought to get dammaged a bit by digging
if( node.name ~= "air") then
minetest.node_dig(p, node, clicker);
-- TODO: if the digged node is the first that is to go into this itemstack it won't end up in the player's inventory
return itemstack;
end
if( v[2] ~= cid_air) then
-- place the scaffolding node
minetest.set_node( p, {name="handle_schematics:support_setup"});
-- configure the scaffolding node
handle_schematics.setup_scaffolding( { x=p.x, y=p.y, z=p.z, node_wanted=v[2], param2_wanted=v[3] });
-- we are done
return itemstack;
end
end
end
end
end
end
-- we are done; the dig_here-indicator can be removed
minetest.set_node( pos, {name="air"});
-- the place where the dig_here indicator used to be may require a scaffolding node
if( nodes_wanted
and nodes_wanted[#nodes_wanted]
and nodes_wanted[#nodes_wanted][1]
and nodes_wanted[#nodes_wanted][1] == pos.y
and nodes_wanted[#nodes_wanted][2] ~= cid_air) then
local v = nodes_wanted[#nodes_wanted];
local p = pos;
minetest.set_node( p, {name="handle_schematics:support_setup"});
handle_schematics.setup_scaffolding( { x=p.x, y=p.y, z=p.z, node_wanted=v[2], param2_wanted=v[3] });
end
return itemstack;
end
-- this node will only be placed by spawning a house with handle_schematics
minetest.register_node("handle_schematics:support_setup", {
description = "support structure for buildings (configured)",
tiles = {"handle_schematics_support.png"},
groups = {snappy=3,choppy=3,oddly_breakable_by_hand=3},
visual_scale = 1.2,
walkable = false,
climbable = true,
paramtype = "light",
drawtype = "plantlike",
-- after it is digged, the node looses its information and becomes a normal, unconfigured one
-- -> changed to no drop because it is automaticly placed in almost unlimited amount
drop = "", --"handle_schematics:support",
-- note: mobs that want to use this function ought to provide "clicker" in a way so that clicker:get_inventory
-- can get used (at least if they want to have a limited inventory)
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
return handle_schematics.place_node_using_support_setup(pos, clicker, itemstack );
end
})
-- no craft receipe for this node as it's only an indicator that the player shall dig here
minetest.register_node("handle_schematics:dig_here", {
description = "dig the node below this one",
tiles = {"default_tool_mesepick.png^[colorize:#FF0000^[transformFXR90"},
inventory_image = "default_tool_mesepick.png^[colorize:#FF0000^[transformFXR90";
-- falling node; will notice if the node below it is beeing digged; cannot be destroyed the normal way
groups = {snappy=3,choppy=3,oddly_breakable_by_hand=3}, --{falling_node = 1},
-- no drop because it is only an indicator and automaticly placed
drop = "",
visual_scale = 0.6,
walkable = false,
climbable = true,
paramtype = "light",
drawtype = "torchlike",
-- this node's purpose is to indicate that the player shall dig here;
-- that requires beeing able to actually aim at that node below
selection_box = {
type = "fixed",
fixed = {-2 / 16, -0.5, -2 / 16, 2 / 16, 6 / 16, 2 / 16}
},
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
return handle_schematics.dig_node_using_dig_here_indicator(pos, clicker, itemstack );
end
})