3d_armor - add nil check in armor.damage, partially fixes a bug

* add some check and backguard compatibility with older engines
  on each minetest loading time waith to 0.1
* backported "add nil check in `armor.damage`" from upstream
  https://github.com/minetest-mods/3d_armor/pull/109/files
* by example shields already set the valid part to wear in
  6eb492b09c/shields/init.lua (L24)
  with `armor.elements` but in 3darmor/init.lua there's no usage
  of the `armor.elements` table, just seems its taken from string
  configuration and convertered to table in line
  6eb492b09c/3d_armor/init.lua (L68)
  using `armor.config.set_elements` event the `armor.elements` variable,
  its a miracle that the mod still works as spected! puff
This commit is contained in:
mckaygerhard 2023-08-06 01:34:25 -04:00
parent 6327ac1eb0
commit 5b37aa6387
2 changed files with 69 additions and 34 deletions

View File

@ -414,15 +414,16 @@ armor.set_player_armor = function(self, player)
end
local state = 0
local count = 0
local material = {count=1}
local preview = armor:get_preview(name)
local texture = "3d_armor_trans.png"
local textures = {}
local physics = {}
local attributes = {}
local levels = {}
local groups = {}
local change = {}
local set_worn = {}
local armor_multi = 0
local worn_armor = armor:get_weared_armor_elements(player)
for _, phys in pairs(self.physics) do
physics[phys] = 1
end
@ -478,21 +479,38 @@ armor.set_player_armor = function(self, player)
local value = def.groups["armor_"..attr] or 0
attributes[attr] = attributes[attr] + value
end
local mat = string.match(item, "%:.+_(.+)$")
if material.name then
if material.name == mat then
material.count = material.count + 1
end
end
-- The following code compares player worn armor items against requirements
-- of which armor pieces are needed to be worn to meet set bonus requirements
for loc,item in pairs(worn_armor) do
local item_mat = string.match(item, "%:.+_(.+)$")
local worn_key = item_mat or "unknown"
-- Perform location checks to ensure the armor is worn correctly
for k,set_loc in pairs(armor.config.set_elements)do
if set_loc == loc then
if set_worn[worn_key] == nil then
set_worn[worn_key] = 0
set_worn[worn_key] = set_worn[worn_key] + 1
else
set_worn[worn_key] = set_worn[worn_key] + 1
end
else
material.name = mat
end
end
end
-- Apply the armor multiplier only if the player is wearing a full set of armor
for mat_name,arm_piece_num in pairs(set_worn) do
if arm_piece_num == #armor.config.set_elements then
armor_multi = armor.config.set_multiplier
end
end
for group, level in pairs(levels) do
if level > 0 then
level = level * armor.config.level_multiplier
if material.name and material.count == #self.elements then
level = level * 1.1
if armor_multi ~= 0 then
level = level * armor.config.set_multiplier
end
end
local base = self.registered_groups[group]
@ -661,6 +679,7 @@ end
armor.damage = function(self, player, index, stack, use)
local old_stack = ItemStack(stack)
local worn_armor = armor:get_weared_armor_elements(player)
if not worn_armor then return end
local armor_worn_cnt = 0
for k,v in pairs(worn_armor) do
armor_worn_cnt = armor_worn_cnt + 1
@ -701,8 +720,8 @@ end
--
-- @function armor:equip
-- @tparam ObjectRef player Player to whom item is equipped.
-- @tparam armor_name itemstack Armor item to be equipped.
-- @treturn armor_name Leftover item stack.
-- @tparam ItemStack itemstack Armor item to be equipped.
-- @treturn ItemStack Leftover item stack.
armor.equip = function(self, player, itemstack)
local name, armor_inv = self:get_valid_player(player, "[equip]")
local armor_element = self:get_element(itemstack:get_name())
@ -737,8 +756,8 @@ end
--
-- @function armor:unequip
-- @tparam ObjectRef player Player from whom item is removed.
-- @tparam string armor_name Armor type identifier associated with the item
-- to be removed (armor_name).
-- @tparam string armor_element Armor type identifier associated with the item
-- to be removed ("head", "torso", "hands", "shield", "legs", "feet", etc.).
armor.unequip = function(self, player, armor_element)
local name, armor_inv = self:get_valid_player(player, "[unequip]")
if not name then
@ -805,7 +824,7 @@ end
-- @function armor:update_skin
-- @tparam string name Player name.
armor.update_skin = function(self, name)
minetest.after(0, function()
minetest.after(0.1, function()
local pplayer = minetest.get_player_by_name(name)
if pplayer then
self.textures[name].skin = self:get_player_skin(name)
@ -926,7 +945,7 @@ armor.load_armor_inventory = function(self, player)
end
end
--- Saves armor inventory in player attribute string "3d\_armor\_inventory".
--- Saves armor inventory in player attribute or `PlayerMetaRef` string "3d\_armor\_inventory".
--
-- @function armor:save_armor_inventory
-- @tparam ObjectRef player

View File

@ -58,6 +58,10 @@ for material, _ in pairs(armor.materials) do
end
end
-- Convert set_elements to a Lua table splitting on blank spaces
local t_set_elements = armor.config.set_elements
armor.config.set_elements = string.split(t_set_elements, " ")
-- Remove torch damage if fire_protect_torch == false
if armor.config.fire_protect_torch == false and armor.config.fire_protect == true then
for k,v in pairs(armor.fire_nodes) do
@ -339,7 +343,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local player_name = player:get_player_name()
for field, _ in pairs(fields) do
if string.find(field, "skins_set") then
minetest.after(0, function(player)
minetest.after(0.1, function(player)
local skin = armor:get_player_skin(name)
armor.textures[name].skin = skin
armor:set_player_armor(player)
@ -351,7 +355,7 @@ end)
minetest.register_on_joinplayer(function(player)
armor.player_set_model(player, modelchar)
local player_name = player:get_player_name()
minetest.after(0, function(player)
minetest.after(0.1, function(player)
local pplayer = minetest.get_player_by_name(player_name)
if pplayer and init_player_armor(player) == false then
pending_players[player] = 0
@ -476,26 +480,38 @@ minetest.register_globalstep(function(dtime)
end
end
if timer > armor.config.init_delay then
for player, count in pairs(pending_players) do
local remove = init_player_armor(player) == true
pending_players[player] = count + 1
if remove == false and count > armor.config.init_times then
minetest.log("warning", "3d_armor: Failed to initialize player")
remove = true
end
if remove == true then
pending_players[player] = nil
if timer <= armor.config.init_delay then
return
end
timer = 0
for player, count in pairs(pending_players) do
local remove = init_player_armor(player) == true
pending_players[player] = count + 1
if remove == false and count > armor.config.init_times then
minetest.log("warning", "3d_armor: Failed to initialize player")
remove = true
end
if remove == true then
pending_players[player] = nil
end
end
-- water breathing protection, added by TenPlus1
if armor.config.water_protect == true then
for _,player in pairs(minetest.get_connected_players()) do
local name = player:get_player_name()
if armor.def[name].water > 0 and
player:get_breath() < 10 then
player:set_breath(10)
end
end
timer = 0
end
end)
-- Fire Protection and water breating, added by TenPlus1
-- Fire Protection, added by TenPlus1.
if armor.config.fire_protect == true then
-- override hot nodes so they do not hurt player anywhere but mod
-- override any hot nodes that do not already deal damage
for _, row in pairs(armor.fire_nodes) do
if minetest.registered_nodes[row[1]] then
minetest.override_item(row[1], {damage_per_second = 0})
@ -534,9 +550,9 @@ if armor.config.water_protect == true or armor.config.fire_protect == true then
-- fire protection
if armor.config.fire_protect == true then
local fire_damage = true
pos.y = pos.y + 1.4 -- head level
pos.y = pos.y + 1.41 -- head level
local node_head = minetest.get_node(pos).name
pos.y = pos.y - 1.2 -- feet level
pos.y = pos.y - 1.21 -- feet level
local node_feet = minetest.get_node(pos).name
-- is player inside a hot node?
for _, row in pairs(armor.fire_nodes) do