Protect against frame leak.

Until now, it was possible for the player to obtain any item if
the frame was left unlocked. The items that are not obtainable
have significant placement liberties that can break many boxes and
potentially allow players to brick their box.

To secure this, we lock all frames automatically and do not allow
them to become unlocked unless they contain obtainable items.
This commit is contained in:
Auke Kok 2019-01-23 22:08:09 -08:00
parent 01b5b690df
commit a5962a296a

View File

@ -22,10 +22,24 @@ local function frame_on_punch(pos, node, puncher, pointed_thing)
end end
end end
local def = minetest.registered_nodes[node.name]
-- lock/unlock -- lock/unlock
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if puncher:get_player_control().sneak and (boxes.players_editing_boxes[name] or if puncher:get_player_control().sneak and (boxes.players_editing_boxes[name] or
minetest.check_player_privs(puncher, "server")) then minetest.check_player_privs(puncher, "server")) then
local idef = minetest.registered_nodes[def.frame_contents]
if not idef then
return false
end
if not(idef.groups.hand or idef.groups.axe or idef.groups.shovel or idef.groups.pickaxe) then
meta:set_int("locked", 1)
minetest.chat_send_player(name, "Item frame contains item the player can not obtain, is therefore locked")
return false
end
if meta:get_int("locked") == 1 then if meta:get_int("locked") == 1 then
meta:set_int("locked", 0) meta:set_int("locked", 0)
minetest.chat_send_player(name, "Item frame is now unlocked") minetest.chat_send_player(name, "Item frame is now unlocked")
@ -38,14 +52,14 @@ local function frame_on_punch(pos, node, puncher, pointed_thing)
end end
if meta:get_int("locked") == 1 then if meta:get_int("locked") == 1 then
return false if not(boxes.players_editing_boxes[name] or minetest.check_player_privs(puncher, "server")) then
return false
end
end end
local def = minetest.registered_nodes[node.name]
local item = ItemStack(def.frame_contents)
-- preserve itemstack metadata and wear -- preserve itemstack metadata and wear
local wear = meta:get_int("wear") local wear = meta:get_int("wear")
local item = ItemStack(def.frame_contents)
if wear then if wear then
item:set_wear(wear) item:set_wear(wear)
end end
@ -69,7 +83,7 @@ local frame_admin = {
["tools:grow"] = true, ["tools:grow"] = true,
} }
-- handle node insertion into frame -- handle node insertion into empty frame
local function frame_on_rightclick(pos, node, clicker, itemstack, pointed_thing) local function frame_on_rightclick(pos, node, clicker, itemstack, pointed_thing)
if clicker and not minetest.check_player_privs(clicker, "protection_bypass") then if clicker and not minetest.check_player_privs(clicker, "protection_bypass") then
local name = clicker:get_player_name() local name = clicker:get_player_name()
@ -88,14 +102,23 @@ local function frame_on_rightclick(pos, node, clicker, itemstack, pointed_thing)
return false return false
end end
local idef = minetest.registered_nodes[nodename]
if not idef then
return false
end
local meta = minetest.get_meta(pos)
if not(idef.groups.hand or idef.groups.axe or idef.groups.shovel or idef.groups.pickaxe) then
meta:set_int("locked", 1)
minetest.chat_send_player(clicker:get_player_name(), "Item inserted into frame is not obtainable, frame locked")
end
local wear = itemstack:get_wear() local wear = itemstack:get_wear()
if wear then if wear then
local meta = minetest.get_meta(pos)
meta:set_int("wear", wear) meta:set_int("wear", wear)
end end
local metadata = itemstack:get_metadata() local metadata = itemstack:get_metadata()
if metadata ~= "" then if metadata ~= "" then
local meta = minetest.get_meta(pos)
meta:set_string("metadata", metadata) meta:set_string("metadata", metadata)
end end