diff --git a/builtin/item.lua b/builtin/item.lua index 5cd28303a..08b8d1c58 100644 --- a/builtin/item.lua +++ b/builtin/item.lua @@ -125,50 +125,70 @@ function minetest.item_place_node(itemstack, placer, pointed_thing) local item = itemstack:peek_item() local def = itemstack:get_definition() if def.type == "node" and pointed_thing.type == "node" then - local pos = pointed_thing.above - local oldnode = minetest.env:get_node(pos) - local olddef = ItemStack({name=oldnode.name}):get_definition() + local under = pointed_thing.under + local oldnode_under = minetest.env:get_node(under) + local olddef_under = ItemStack({name=oldnode_under.name}):get_definition() + olddef_under = olddef_under or minetest.nodedef_default + local above = pointed_thing.above + local oldnode_above = minetest.env:get_node(above) + local olddef_above = ItemStack({name=oldnode_above.name}):get_definition() + olddef_above = olddef_above or minetest.nodedef_default - if not olddef.buildable_to then + if not olddef_above.buildable_to and not olddef_under.buildable_to then minetest.log("info", placer:get_player_name() .. " tried to place" - .. " node in invalid position " .. minetest.pos_to_string(pos) - .. ", replacing " .. oldnode.name) + .. " node in invalid position " .. minetest.pos_to_string(above) + .. ", replacing " .. oldnode_above.name) return end + -- Place above pointed node + local place_to = {x = above.x, y = above.y, z = above.z} + + -- If node under is buildable_to, place into it instead (eg. snow) + if olddef_under.buildable_to then + minetest.log("info", "node under is buildable to") + place_to = {x = under.x, y = under.y, z = under.z} + end + minetest.log("action", placer:get_player_name() .. " places node " - .. def.name .. " at " .. minetest.pos_to_string(pos)) + .. def.name .. " at " .. minetest.pos_to_string(place_to)) local newnode = {name = def.name, param1 = 0, param2 = 0} -- Calculate direction for wall mounted stuff like torches and signs if def.paramtype2 == 'wallmounted' then - local under = pointed_thing.under - local above = pointed_thing.above - local dir = {x = under.x - above.x, y = under.y - above.y, z = under.z - above.z} + local dir = { + x = under.x - above.x, + y = under.y - above.y, + z = under.z - above.z + } newnode.param2 = minetest.dir_to_wallmounted(dir) -- Calculate the direction for furnaces and chests and stuff elseif def.paramtype2 == 'facedir' then local placer_pos = placer:getpos() if placer_pos then - local dir = {x = pos.x - placer_pos.x, y = pos.y - placer_pos.y, z = pos.z - placer_pos.z} + local dir = { + x = above.x - placer_pos.x, + y = above.y - placer_pos.y, + z = above.z - placer_pos.z + } newnode.param2 = minetest.dir_to_facedir(dir) minetest.log("action", "facedir: " .. newnode.param2) end end -- Add node and update - minetest.env:add_node(pos, newnode) + minetest.env:add_node(place_to, newnode) -- Run callback if def.after_place_node then - def.after_place_node(pos, placer) + def.after_place_node(place_to, placer) end -- Run script hook (deprecated) local _, callback for _, callback in ipairs(minetest.registered_on_placenodes) do - callback(pos, newnode, placer) + callback(place_to, newnode, placer) end itemstack:take_item() diff --git a/src/game.cpp b/src/game.cpp index 19c4707de..7d93e3db2 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2304,6 +2304,13 @@ void the_game( <get(n_under).buildable_to) + p = nodepos; + }catch(InvalidPositionException &e){} + // Find id of predicted node content_t id; bool found = nodedef->getId(def.node_placement_prediction, id);