mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-26 04:21:07 +01:00
[mcl_beds] Fix screwdriver/bed duplication glitch, https://git.minetest.land/MineClone2/MineClone2/issues/1149
This commit is contained in:
parent
c7d91baadf
commit
1e5ae0bbac
1 changed files with 94 additions and 53 deletions
|
@ -1,23 +1,95 @@
|
||||||
local S = minetest.get_translator("mcl_beds")
|
local S = minetest.get_translator("mcl_beds")
|
||||||
|
|
||||||
local function destruct_bed(pos, oldnode)
|
local minetest_get_node = minetest.get_node
|
||||||
local node = oldnode or minetest.get_node(pos)
|
local minetest_get_node_or_nil = minetest.get_node_or_nil
|
||||||
|
local minetest_remove_node = minetest.remove_node
|
||||||
|
local minetest_facedir_to_dir = minetest.facedir_to_dir
|
||||||
|
local minetest_add_item = minetest.add_item
|
||||||
|
local vector_add = vector.add
|
||||||
|
local vector_subtract = vector.subtract
|
||||||
|
|
||||||
|
local function get_bed_next_node(pos, node)
|
||||||
|
local node = node or minetest_get_node_or_nil(pos)
|
||||||
if not node then return end
|
if not node then return end
|
||||||
local dir = minetest.facedir_to_dir(node.param2)
|
|
||||||
local pos2, node2
|
local dir = minetest_facedir_to_dir(node.param2)
|
||||||
|
|
||||||
|
local pos2, bottom
|
||||||
if string.sub(node.name, -4) == "_top" then
|
if string.sub(node.name, -4) == "_top" then
|
||||||
pos2 = vector.subtract(pos, dir)
|
pos2 = vector_subtract(pos, dir)
|
||||||
node2 = minetest.get_node(pos2)
|
else
|
||||||
if node2 and string.sub(node2.name, -7) == "_bottom" then
|
pos2 = vector_add(pos, dir)
|
||||||
minetest.remove_node(pos2)
|
bottom = true
|
||||||
end
|
end
|
||||||
minetest.check_for_falling(pos)
|
|
||||||
elseif string.sub(node.name, -7) == "_bottom" then
|
local node2 = minetest_get_node(pos2)
|
||||||
minetest.add_item(pos, node.name)
|
return pos2, node2, bottom, dir
|
||||||
pos2 = vector.add(pos, dir)
|
end
|
||||||
node2 = minetest.get_node(pos2)
|
|
||||||
|
local function rotate(pos, node, user, mode, new_param2)
|
||||||
|
if mode ~= screwdriver.ROTATE_FACE then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local p, node2, bottom = get_bed_next_node(pos, node)
|
||||||
|
if not node2 then return end
|
||||||
|
|
||||||
|
local name = node2.name
|
||||||
|
if not minetest.get_item_group(name, "bed") == 2 or not node.param2 == node2.param2 then return false end
|
||||||
|
|
||||||
|
if bottom then
|
||||||
|
name = string.sub(name, 1, -5)
|
||||||
|
else
|
||||||
|
name = string.sub(name, 1, -8)
|
||||||
|
end
|
||||||
|
|
||||||
|
if minetest.is_protected(p, user:get_player_name()) then
|
||||||
|
minetest.record_protection_violation(p, user:get_player_name())
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local new_dir, newp = minetest_facedir_to_dir(new_param2)
|
||||||
|
if bottom then
|
||||||
|
newp = vector_add(pos, new_dir)
|
||||||
|
else
|
||||||
|
newp = vector_subtract(pos, new_dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
local node3 = minetest_get_node_or_nil(newp)
|
||||||
|
if not node3 then return false end
|
||||||
|
|
||||||
|
local node_def = minetest.registered_nodes[node3.name]
|
||||||
|
if not node_def or not node_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
|
||||||
|
-- do not remove_node here - it will trigger destroy_bed()
|
||||||
|
minetest.swap_node(p, {name = "air"})
|
||||||
|
minetest.swap_node(pos, node)
|
||||||
|
minetest.swap_node(newp, {name = name .. (bottom and "_top" or "_bottom"), param2 = new_param2})
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function destruct_bed(pos, oldnode)
|
||||||
|
local node = oldnode or minetest_get_node_or_nil(pos)
|
||||||
|
if not node then return end
|
||||||
|
|
||||||
|
local pos2, node2, bottom = get_bed_next_node(pos, oldnode)
|
||||||
|
|
||||||
|
if bottom then
|
||||||
|
minetest_add_item(pos, node.name)
|
||||||
if node2 and string.sub(node2.name, -4) == "_top" then
|
if node2 and string.sub(node2.name, -4) == "_top" then
|
||||||
minetest.remove_node(pos2)
|
minetest_remove_node(pos2)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if node2 and string.sub(node2.name, -7) == "_bottom" then
|
||||||
|
minetest_remove_node(pos2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -94,7 +166,7 @@ function mcl_beds.register_bed(name, def)
|
||||||
local under = pointed_thing.under
|
local under = pointed_thing.under
|
||||||
|
|
||||||
-- Use pointed node's on_rightclick function first, if present
|
-- Use pointed node's on_rightclick function first, if present
|
||||||
local node = minetest.get_node(under)
|
local node = minetest_get_node(under)
|
||||||
if placer and not placer:get_player_control().sneak then
|
if placer and not placer:get_player_control().sneak then
|
||||||
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
|
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
|
||||||
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
|
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
|
||||||
|
@ -102,7 +174,7 @@ function mcl_beds.register_bed(name, def)
|
||||||
end
|
end
|
||||||
|
|
||||||
local pos
|
local pos
|
||||||
local undername = minetest.get_node(under).name
|
local undername = minetest_get_node(under).name
|
||||||
if minetest.registered_items[undername] and minetest.registered_items[undername].buildable_to then
|
if minetest.registered_items[undername] and minetest.registered_items[undername].buildable_to then
|
||||||
pos = under
|
pos = under
|
||||||
else
|
else
|
||||||
|
@ -115,13 +187,13 @@ function mcl_beds.register_bed(name, def)
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
local node_def = minetest.registered_nodes[minetest.get_node(pos).name]
|
local node_def = minetest.registered_nodes[minetest_get_node(pos).name]
|
||||||
if not node_def or not node_def.buildable_to then
|
if not node_def or not node_def.buildable_to then
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
local dir = minetest.dir_to_facedir(placer:get_look_dir())
|
local dir = minetest.dir_to_facedir(placer:get_look_dir())
|
||||||
local botpos = vector.add(pos, minetest.facedir_to_dir(dir))
|
local botpos = vector_add(pos, minetest_facedir_to_dir(dir))
|
||||||
|
|
||||||
if minetest.is_protected(botpos, placer:get_player_name()) and
|
if minetest.is_protected(botpos, placer:get_player_name()) and
|
||||||
not minetest.check_player_privs(placer, "protection_bypass") then
|
not minetest.check_player_privs(placer, "protection_bypass") then
|
||||||
|
@ -129,7 +201,7 @@ function mcl_beds.register_bed(name, def)
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
local botdef = minetest.registered_nodes[minetest.get_node(botpos).name]
|
local botdef = minetest.registered_nodes[minetest_get_node(botpos).name]
|
||||||
if not botdef or not botdef.buildable_to then
|
if not botdef or not botdef.buildable_to then
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
@ -152,38 +224,7 @@ function mcl_beds.register_bed(name, def)
|
||||||
return itemstack
|
return itemstack
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_rotate = function(pos, node, user, mode, new_param2)
|
on_rotate = rotate,
|
||||||
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 node_def = node3 and minetest.registered_nodes[node3.name]
|
|
||||||
if not node_def or not node_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
|
|
||||||
-- do not remove_node here - it will trigger destroy_bed()
|
|
||||||
minetest.set_node(p, {name = "air"})
|
|
||||||
minetest.set_node(pos, node)
|
|
||||||
minetest.set_node(newp, {name = name .. "_top", param2 = new_param2})
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
local node_box_top, selection_box_top, collision_box_top
|
local node_box_top, selection_box_top, collision_box_top
|
||||||
|
@ -217,7 +258,7 @@ function mcl_beds.register_bed(name, def)
|
||||||
mcl_beds.on_rightclick(pos, clicker, true)
|
mcl_beds.on_rightclick(pos, clicker, true)
|
||||||
return itemstack
|
return itemstack
|
||||||
end,
|
end,
|
||||||
on_rotate = false,
|
on_rotate = rotate,
|
||||||
after_destruct = destruct_bed,
|
after_destruct = destruct_bed,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue