mirror of
https://github.com/minetest-mods/3d_armor.git
synced 2024-11-10 20:40:28 +01:00
Fix item duplication vulnerability
This commit is contained in:
parent
b1f9e9f1fd
commit
c36b1e5fc4
|
@ -68,6 +68,9 @@ armor_fire_protect = false
|
||||||
-- Enable punch damage effects.
|
-- Enable punch damage effects.
|
||||||
armor_punch_damage = true
|
armor_punch_damage = true
|
||||||
|
|
||||||
|
-- Enable migration of old armor inventories
|
||||||
|
armor_migrate_old_inventory = true
|
||||||
|
|
||||||
API
|
API
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ armor = {
|
||||||
on_damage = {},
|
on_damage = {},
|
||||||
on_destroy = {},
|
on_destroy = {},
|
||||||
},
|
},
|
||||||
|
migrate_old_inventory = true,
|
||||||
version = "0.4.9",
|
version = "0.4.9",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +178,7 @@ armor.update_player_visuals = function(self, player)
|
||||||
end
|
end
|
||||||
|
|
||||||
armor.set_player_armor = function(self, player)
|
armor.set_player_armor = function(self, player)
|
||||||
local name, player_inv = self:get_valid_player(player, "[set_player_armor]")
|
local name, armor_inv = self:get_valid_player(player, "[set_player_armor]")
|
||||||
if not name then
|
if not name then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -205,7 +206,10 @@ armor.set_player_armor = function(self, player)
|
||||||
change[group] = 1
|
change[group] = 1
|
||||||
levels[group] = 0
|
levels[group] = 0
|
||||||
end
|
end
|
||||||
local list = player_inv:get_list("armor") or {}
|
local list = armor_inv:get_list("armor")
|
||||||
|
if type(list) ~= "table" then
|
||||||
|
return
|
||||||
|
end
|
||||||
for i, stack in pairs(list) do
|
for i, stack in pairs(list) do
|
||||||
if stack:get_count() == 1 then
|
if stack:get_count() == 1 then
|
||||||
local def = stack:get_definition()
|
local def = stack:get_definition()
|
||||||
|
@ -221,6 +225,7 @@ armor.set_player_armor = function(self, player)
|
||||||
local level = def.groups["armor_"..element]
|
local level = def.groups["armor_"..element]
|
||||||
levels["fleshy"] = levels["fleshy"] + level
|
levels["fleshy"] = levels["fleshy"] + level
|
||||||
end
|
end
|
||||||
|
break
|
||||||
end
|
end
|
||||||
-- DEPRECATED, use armor_groups instead
|
-- DEPRECATED, use armor_groups instead
|
||||||
if def.groups["armor_radiation"] and levels["radiation"] then
|
if def.groups["armor_radiation"] and levels["radiation"] then
|
||||||
|
@ -299,7 +304,7 @@ armor.set_player_armor = function(self, player)
|
||||||
end
|
end
|
||||||
|
|
||||||
armor.punch = function(self, player, hitter, time_from_last_punch, tool_capabilities)
|
armor.punch = function(self, player, hitter, time_from_last_punch, tool_capabilities)
|
||||||
local name, player_inv = self:get_valid_player(player, "[punch]")
|
local name, armor_inv = self:get_valid_player(player, "[punch]")
|
||||||
if not name then
|
if not name then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -307,7 +312,7 @@ armor.punch = function(self, player, hitter, time_from_last_punch, tool_capabili
|
||||||
local count = 0
|
local count = 0
|
||||||
local recip = true
|
local recip = true
|
||||||
local default_groups = {cracky=3, snappy=3, choppy=3, crumbly=3, level=1}
|
local default_groups = {cracky=3, snappy=3, choppy=3, crumbly=3, level=1}
|
||||||
local list = player_inv:get_list("armor")
|
local list = armor_inv:get_list("armor")
|
||||||
for i, stack in pairs(list) do
|
for i, stack in pairs(list) do
|
||||||
if stack:get_count() == 1 then
|
if stack:get_count() == 1 then
|
||||||
local name = stack:get_name()
|
local name = stack:get_name()
|
||||||
|
@ -399,12 +404,64 @@ armor.get_armor_formspec = function(self, name, listring)
|
||||||
for _, attr in pairs(self.attributes) do
|
for _, attr in pairs(self.attributes) do
|
||||||
formspec = formspec:gsub("armor_attr_"..attr, armor.def[name][attr])
|
formspec = formspec:gsub("armor_attr_"..attr, armor.def[name][attr])
|
||||||
end
|
end
|
||||||
for _, group in pairs(self.attributes) do
|
for group, _ in pairs(self.registered_groups) do
|
||||||
formspec = formspec:gsub("armor_group_"..group, armor.def[name][group])
|
formspec = formspec:gsub("armor_group_"..group,
|
||||||
|
armor.def[name].groups[group])
|
||||||
end
|
end
|
||||||
return formspec
|
return formspec
|
||||||
end
|
end
|
||||||
|
|
||||||
|
armor.serialize_inventory_list = function(self, list)
|
||||||
|
local list_table = {}
|
||||||
|
for _, stack in ipairs(list) do
|
||||||
|
table.insert(list_table, stack:to_string())
|
||||||
|
end
|
||||||
|
return minetest.serialize(list_table)
|
||||||
|
end
|
||||||
|
|
||||||
|
armor.deserialize_inventory_list = function(self, list_string)
|
||||||
|
local list_table = minetest.deserialize(list_string)
|
||||||
|
local list = {}
|
||||||
|
for _, stack in ipairs(list_table or {}) do
|
||||||
|
table.insert(list, ItemStack(stack))
|
||||||
|
end
|
||||||
|
return list
|
||||||
|
end
|
||||||
|
|
||||||
|
armor.load_armor_inventory = function(self, player)
|
||||||
|
local msg = "[load_armor_inventory]"
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if not name then
|
||||||
|
minetest.log("warning", S("3d_armor: Player name is nil @1", msg))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"})
|
||||||
|
if not armor_inv then
|
||||||
|
minetest.log("warning", S("3d_armor: Detached armor inventory is nil @1", msg))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local armor_list_string = player:get_attribute("3d_armor_inventory")
|
||||||
|
if armor_list_string then
|
||||||
|
armor_inv:set_list("armor", self:deserialize_inventory_list(armor_list_string))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
armor.save_armor_inventory = function(self, player)
|
||||||
|
local msg = "[save_armor_inventory]"
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if not name then
|
||||||
|
minetest.log("warning", S("3d_armor: Player name is nil @1", msg))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"})
|
||||||
|
if not armor_inv then
|
||||||
|
minetest.log("warning", S("3d_armor: Detached armor inventory is nil @1", msg))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
player:set_attribute("3d_armor_inventory", self:serialize_inventory_list(armor_inv:get_list("armor")))
|
||||||
|
end
|
||||||
|
|
||||||
armor.update_inventory = function(self, player)
|
armor.update_inventory = function(self, player)
|
||||||
-- DEPRECATED: Legacy inventory support
|
-- DEPRECATED: Legacy inventory support
|
||||||
end
|
end
|
||||||
|
@ -416,17 +473,13 @@ armor.set_inventory_stack = function(self, player, i, stack)
|
||||||
minetest.log("warning", "3d_armor: Player name is nil "..msg)
|
minetest.log("warning", "3d_armor: Player name is nil "..msg)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local player_inv = player:get_inventory()
|
|
||||||
local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"})
|
local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"})
|
||||||
if not player_inv then
|
if not armor_inv then
|
||||||
minetest.log("warning", "3d_armor: Player inventory is nil "..msg)
|
minetest.log("warning", S("3d_armor: Detached armor inventory is nil @1", msg))
|
||||||
return
|
|
||||||
elseif not armor_inv then
|
|
||||||
minetest.log("warning", "3d_armor: Detached armor inventory is nil "..msg)
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
player_inv:set_stack("armor", i, stack)
|
|
||||||
armor_inv:set_stack("armor", i, stack)
|
armor_inv:set_stack("armor", i, stack)
|
||||||
|
self:save_armor_inventory(player)
|
||||||
end
|
end
|
||||||
|
|
||||||
armor.get_valid_player = function(self, player, msg)
|
armor.get_valid_player = function(self, player, msg)
|
||||||
|
@ -440,7 +493,7 @@ armor.get_valid_player = function(self, player, msg)
|
||||||
minetest.log("warning", "3d_armor: Player name is nil "..msg)
|
minetest.log("warning", "3d_armor: Player name is nil "..msg)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local inv = player:get_inventory()
|
local inv = minetest.get_inventory({type="detached", name=name.."_armor"})
|
||||||
if not inv then
|
if not inv then
|
||||||
minetest.log("warning", "3d_armor: Player inventory is nil "..msg)
|
minetest.log("warning", "3d_armor: Player inventory is nil "..msg)
|
||||||
return
|
return
|
||||||
|
|
|
@ -101,27 +101,23 @@ end)
|
||||||
|
|
||||||
local function init_player_armor(player)
|
local function init_player_armor(player)
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
local player_inv = player:get_inventory()
|
|
||||||
local pos = player:getpos()
|
local pos = player:getpos()
|
||||||
if not name or not player_inv or not pos then
|
if not name or not pos then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local armor_inv = minetest.create_detached_inventory(name.."_armor", {
|
local armor_inv = minetest.create_detached_inventory(name.."_armor", {
|
||||||
on_put = function(inv, listname, index, stack, player)
|
on_put = function(inv, listname, index, stack, player)
|
||||||
player:get_inventory():set_stack(listname, index, stack)
|
armor:save_armor_inventory(player)
|
||||||
armor:run_callbacks("on_equip", player, index, stack)
|
armor:run_callbacks("on_equip", player, index, stack)
|
||||||
armor:set_player_armor(player)
|
armor:set_player_armor(player)
|
||||||
end,
|
end,
|
||||||
on_take = function(inv, listname, index, stack, player)
|
on_take = function(inv, listname, index, stack, player)
|
||||||
player:get_inventory():set_stack(listname, index, nil)
|
armor:save_armor_inventory(player)
|
||||||
armor:run_callbacks("on_unequip", player, index, stack)
|
armor:run_callbacks("on_unequip", player, index, stack)
|
||||||
armor:set_player_armor(player)
|
armor:set_player_armor(player)
|
||||||
end,
|
end,
|
||||||
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||||
local plaver_inv = player:get_inventory()
|
armor:save_armor_inventory(player)
|
||||||
local stack = inv:get_stack(to_list, to_index)
|
|
||||||
player_inv:set_stack(to_list, to_index, stack)
|
|
||||||
player_inv:set_stack(from_list, from_index, nil)
|
|
||||||
armor:set_player_armor(player)
|
armor:set_player_armor(player)
|
||||||
end,
|
end,
|
||||||
allow_put = function(inv, listname, index, stack, player)
|
allow_put = function(inv, listname, index, stack, player)
|
||||||
|
@ -148,10 +144,18 @@ local function init_player_armor(player)
|
||||||
end,
|
end,
|
||||||
}, name)
|
}, name)
|
||||||
armor_inv:set_size("armor", 6)
|
armor_inv:set_size("armor", 6)
|
||||||
|
if not armor:load_armor_inventory(player) and armor.migrate_old_inventory then
|
||||||
|
local player_inv = player:get_inventory()
|
||||||
player_inv:set_size("armor", 6)
|
player_inv:set_size("armor", 6)
|
||||||
for i=1, 6 do
|
for i=1, 6 do
|
||||||
local stack = player_inv:get_stack("armor", i)
|
local stack = player_inv:get_stack("armor", i)
|
||||||
armor_inv:set_stack("armor", i, stack)
|
armor_inv:set_stack("armor", i, stack)
|
||||||
|
end
|
||||||
|
armor:save_armor_inventory(player)
|
||||||
|
player_inv:set_size("armor", 0)
|
||||||
|
end
|
||||||
|
for i=1, 6 do
|
||||||
|
local stack = armor_inv:get_stack("armor", i)
|
||||||
armor:run_callbacks("on_equip", player, i, stack)
|
armor:run_callbacks("on_equip", player, i, stack)
|
||||||
end
|
end
|
||||||
armor.def[name] = {
|
armor.def[name] = {
|
||||||
|
@ -220,13 +224,13 @@ end)
|
||||||
|
|
||||||
if armor.config.drop == true or armor.config.destroy == true then
|
if armor.config.drop == true or armor.config.destroy == true then
|
||||||
minetest.register_on_dieplayer(function(player)
|
minetest.register_on_dieplayer(function(player)
|
||||||
local name, player_inv = armor:get_valid_player(player, "[on_dieplayer]")
|
local name, armor_inv = armor:get_valid_player(player, "[on_dieplayer]")
|
||||||
if not name then
|
if not name then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local drop = {}
|
local drop = {}
|
||||||
for i=1, player_inv:get_size("armor") do
|
for i=1, armor_inv:get_size("armor") do
|
||||||
local stack = player_inv:get_stack("armor", i)
|
local stack = armor_inv:get_stack("armor", i)
|
||||||
if stack:get_count() > 0 then
|
if stack:get_count() > 0 then
|
||||||
table.insert(drop, stack)
|
table.insert(drop, stack)
|
||||||
armor:set_inventory_stack(player, i, nil)
|
armor:set_inventory_stack(player, i, nil)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user