mirror of
				https://github.com/minetest-mods/3d_armor.git
				synced 2025-10-27 03:05:29 +01:00 
			
		
		
		
	Fix item duplication vulnerability
This commit is contained in:
		| @@ -68,6 +68,9 @@ armor_fire_protect = false | ||||
| -- Enable punch damage effects. | ||||
| armor_punch_damage = true | ||||
|  | ||||
| -- Enable migration of old armor inventories | ||||
| armor_migrate_old_inventory = true | ||||
|  | ||||
| API | ||||
| --- | ||||
|  | ||||
|   | ||||
| @@ -69,6 +69,7 @@ armor = { | ||||
| 		on_damage = {}, | ||||
| 		on_destroy = {}, | ||||
| 	}, | ||||
| 	migrate_old_inventory = true, | ||||
| 	version = "0.4.9", | ||||
| } | ||||
|  | ||||
| @@ -177,7 +178,7 @@ armor.update_player_visuals = function(self, player) | ||||
| end | ||||
|  | ||||
| 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 | ||||
| 		return | ||||
| 	end | ||||
| @@ -205,7 +206,10 @@ armor.set_player_armor = function(self, player) | ||||
| 		change[group] = 1 | ||||
| 		levels[group] = 0 | ||||
| 	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 | ||||
| 		if stack:get_count() == 1 then | ||||
| 			local def = stack:get_definition() | ||||
| @@ -221,6 +225,7 @@ armor.set_player_armor = function(self, player) | ||||
| 						local level = def.groups["armor_"..element] | ||||
| 						levels["fleshy"] = levels["fleshy"] + level | ||||
| 					end | ||||
| 					break | ||||
| 				end | ||||
| 				-- DEPRECATED, use armor_groups instead | ||||
| 				if def.groups["armor_radiation"] and levels["radiation"] then | ||||
| @@ -299,7 +304,7 @@ armor.set_player_armor = function(self, player) | ||||
| end | ||||
|  | ||||
| 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 | ||||
| 		return | ||||
| 	end | ||||
| @@ -307,7 +312,7 @@ armor.punch = function(self, player, hitter, time_from_last_punch, tool_capabili | ||||
| 	local count = 0 | ||||
| 	local recip = true | ||||
| 	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 | ||||
| 		if stack:get_count() == 1 then | ||||
| 			local name = stack:get_name() | ||||
| @@ -399,12 +404,64 @@ armor.get_armor_formspec = function(self, name, listring) | ||||
| 	for _, attr in pairs(self.attributes) do | ||||
| 		formspec = formspec:gsub("armor_attr_"..attr, armor.def[name][attr]) | ||||
| 	end | ||||
| 	for _, group in pairs(self.attributes) do | ||||
| 		formspec = formspec:gsub("armor_group_"..group, armor.def[name][group]) | ||||
| 	for group, _ in pairs(self.registered_groups) do | ||||
| 		formspec = formspec:gsub("armor_group_"..group, | ||||
| 			armor.def[name].groups[group]) | ||||
| 	end | ||||
| 	return formspec | ||||
| 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) | ||||
| 	-- DEPRECATED: Legacy inventory support | ||||
| end | ||||
| @@ -416,17 +473,13 @@ armor.set_inventory_stack = function(self, player, i, stack) | ||||
| 		minetest.log("warning", "3d_armor: Player name is nil "..msg) | ||||
| 		return | ||||
| 	end | ||||
| 	local player_inv = player:get_inventory() | ||||
| 	local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"}) | ||||
| 	if not player_inv then | ||||
| 		minetest.log("warning", "3d_armor: Player inventory is nil "..msg) | ||||
| 		return | ||||
| 	elseif not armor_inv then | ||||
| 		minetest.log("warning", "3d_armor: Detached armor inventory is nil "..msg) | ||||
| 	if not armor_inv then | ||||
| 		minetest.log("warning", S("3d_armor: Detached armor inventory is nil @1", msg)) | ||||
| 		return | ||||
| 	end | ||||
| 	player_inv:set_stack("armor", i, stack) | ||||
| 	armor_inv:set_stack("armor", i, stack) | ||||
| 	self:save_armor_inventory(player) | ||||
| end | ||||
|  | ||||
| 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) | ||||
| 		return | ||||
| 	end | ||||
| 	local inv = player:get_inventory() | ||||
| 	local inv = minetest.get_inventory({type="detached", name=name.."_armor"}) | ||||
| 	if not inv then | ||||
| 		minetest.log("warning", "3d_armor: Player inventory is nil "..msg) | ||||
| 		return | ||||
|   | ||||
| @@ -101,27 +101,23 @@ end) | ||||
|  | ||||
| local function init_player_armor(player) | ||||
| 	local name = player:get_player_name() | ||||
| 	local player_inv = player:get_inventory() | ||||
| 	local pos = player:getpos() | ||||
| 	if not name or not player_inv or not pos then | ||||
| 	if not name or not pos then | ||||
| 		return false | ||||
| 	end | ||||
| 	local armor_inv = minetest.create_detached_inventory(name.."_armor", { | ||||
| 		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:set_player_armor(player) | ||||
| 		end, | ||||
| 		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:set_player_armor(player) | ||||
| 		end, | ||||
| 		on_move = function(inv, from_list, from_index, to_list, to_index, count, player) | ||||
| 			local plaver_inv = player:get_inventory() | ||||
| 			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:save_armor_inventory(player) | ||||
| 			armor:set_player_armor(player) | ||||
| 		end, | ||||
| 		allow_put = function(inv, listname, index, stack, player) | ||||
| @@ -148,10 +144,18 @@ local function init_player_armor(player) | ||||
| 		end, | ||||
| 	}, name) | ||||
| 	armor_inv:set_size("armor", 6) | ||||
| 	player_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) | ||||
| 		for i=1, 6 do | ||||
| 			local stack = player_inv:get_stack("armor", i) | ||||
| 			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 = player_inv:get_stack("armor", i) | ||||
| 		armor_inv:set_stack("armor", i, stack) | ||||
| 		local stack = armor_inv:get_stack("armor", i) | ||||
| 		armor:run_callbacks("on_equip", player, i, stack) | ||||
| 	end | ||||
| 	armor.def[name] = { | ||||
| @@ -220,13 +224,13 @@ end) | ||||
|  | ||||
| if armor.config.drop == true or armor.config.destroy == true then | ||||
| 	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 | ||||
| 			return | ||||
| 		end | ||||
| 		local drop = {} | ||||
| 		for i=1, player_inv:get_size("armor") do | ||||
| 			local stack = player_inv:get_stack("armor", i) | ||||
| 		for i=1, armor_inv:get_size("armor") do | ||||
| 			local stack = armor_inv:get_stack("armor", i) | ||||
| 			if stack:get_count() > 0 then | ||||
| 				table.insert(drop, stack) | ||||
| 				armor:set_inventory_stack(player, i, nil) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user