41c2b2aeea
Tested with nodebreaker, fire. If called from lua, minetest.remove_node() calls on_destruct() callbacks before the map is actually updated. This means that we can't look at the map data to determine if we're done cleaning up adjacent nodes, and we have to stop recursing some other way. There's no data we can pass around through functions that would survive scope to a secondary on_destruct() callback, so we have to maintain local state somewhere in the mod namespace. In this case, we keep a bitflag. The bitflag is set to "true" by default. On the first half removal, the flag is flipped and afterwards we remove the other half node. When the on_destruct for the other half is running, it's value is false and we flip it back to true without removing the other half node. This thus prevents recursing. To facilitate easier finding of the bed partner, we tell our on_destruct whether we're a top or bottom half node through a passed flag. Now that the top is diggable, we just need to assure that it drops a bottom bed part.
132 lines
3.5 KiB
Lua
132 lines
3.5 KiB
Lua
|
|
local reverse = true
|
|
|
|
local function destruct_bed(pos, n)
|
|
local node = minetest.get_node(pos)
|
|
local other
|
|
|
|
if n == 2 then
|
|
local dir = minetest.facedir_to_dir(node.param2)
|
|
other = vector.subtract(pos, dir)
|
|
elseif n == 1 then
|
|
local dir = minetest.facedir_to_dir(node.param2)
|
|
other = vector.add(pos, dir)
|
|
end
|
|
|
|
if reverse then
|
|
reverse = not reverse
|
|
minetest.remove_node(other)
|
|
nodeupdate(other)
|
|
else
|
|
reverse = not reverse
|
|
end
|
|
end
|
|
|
|
function beds.register_bed(name, def)
|
|
minetest.register_node(name .. "_bottom", {
|
|
description = def.description,
|
|
inventory_image = def.inventory_image,
|
|
wield_image = def.wield_image,
|
|
drawtype = "nodebox",
|
|
tiles = def.tiles.bottom,
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
is_ground_content = false,
|
|
stack_max = 1,
|
|
groups = {snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 1},
|
|
sounds = default.node_sound_wood_defaults(),
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = def.nodebox.bottom,
|
|
},
|
|
selection_box = {
|
|
type = "fixed",
|
|
fixed = def.selectionbox,
|
|
},
|
|
|
|
after_place_node = function(pos, placer, itemstack)
|
|
local n = minetest.get_node_or_nil(pos)
|
|
if not n or not n.param2 then
|
|
minetest.remove_node(pos)
|
|
return true
|
|
end
|
|
local dir = minetest.facedir_to_dir(n.param2)
|
|
local p = vector.add(pos, dir)
|
|
local n2 = minetest.get_node_or_nil(p)
|
|
local def = n2 and minetest.registered_items[n2.name]
|
|
if not def or not def.buildable_to then
|
|
minetest.remove_node(pos)
|
|
return true
|
|
end
|
|
minetest.set_node(p, {name = n.name:gsub("%_bottom", "_top"), param2 = n.param2})
|
|
return false
|
|
end,
|
|
|
|
on_destruct = function(pos)
|
|
destruct_bed(pos, 1)
|
|
end,
|
|
|
|
on_rightclick = function(pos, node, clicker)
|
|
beds.on_rightclick(pos, clicker)
|
|
end,
|
|
|
|
on_rotate = function(pos, node, user, mode, new_param2)
|
|
local dir = minetest.facedir_to_dir(node.param2)
|
|
local p = vector.add(pos, dir)
|
|
local node2 = minetest.get_node_or_nil(p)
|
|
if not node2 or not minetest.get_item_group(node2.name, "bed") == 2 or
|
|
not node.param2 == node2.param2 then
|
|
return false
|
|
end
|
|
if minetest.is_protected(p, user:get_player_name()) then
|
|
minetest.record_protection_violation(p, user:get_player_name())
|
|
return false
|
|
end
|
|
if mode ~= screwdriver.ROTATE_FACE then
|
|
return false
|
|
end
|
|
local newp = vector.add(pos, minetest.facedir_to_dir(new_param2))
|
|
local node3 = minetest.get_node_or_nil(newp)
|
|
local def = node3 and minetest.registered_nodes[node3.name]
|
|
if not def or not def.buildable_to then
|
|
return false
|
|
end
|
|
if minetest.is_protected(newp, user:get_player_name()) then
|
|
minetest.record_protection_violation(newp, user:get_player_name())
|
|
return false
|
|
end
|
|
node.param2 = new_param2
|
|
minetest.swap_node(pos, node)
|
|
minetest.remove_node(p)
|
|
minetest.set_node(newp, {name = node.name:gsub("%_bottom", "_top"), param2 = new_param2})
|
|
return true
|
|
end,
|
|
})
|
|
|
|
minetest.register_node(name .. "_top", {
|
|
drawtype = "nodebox",
|
|
tiles = def.tiles.top,
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
is_ground_content = false,
|
|
pointable = false,
|
|
groups = {snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 2},
|
|
sounds = default.node_sound_wood_defaults(),
|
|
drop = name .. "_bottom",
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = def.nodebox.top,
|
|
},
|
|
on_destruct = function(pos)
|
|
destruct_bed(pos, 2)
|
|
end,
|
|
})
|
|
|
|
minetest.register_alias(name, name .. "_bottom")
|
|
|
|
minetest.register_craft({
|
|
output = name,
|
|
recipe = def.recipe
|
|
})
|
|
end
|