hotfixes checks for player object on sudden disconnections

* is very know bug never resolved at https://github.com/minetest/minetest#8452
* In fact there's already some check for players around connected players but only for names
* this fixed and close https://notabug.org/TenPlus1/stamina/issues/8
* this fixed and close https://codeberg.org/minenux/minetest-mod-stamina/issues/8
* already fix backguard compat for eye_height close https://codeberg.org/minenux/minetest-mod-stamina/issues/9
* already fix backguard compat for eye_height closes https://notabug.org/TenPlus1/stamina/issues/9
This commit is contained in:
Герхард PICCORO Lenz McKAY 2022-01-21 09:39:43 -04:00
parent 5fd2b2e5c9
commit 7912e7c95b

525
init.lua
View File

@ -143,63 +143,65 @@ local function set_sprinting(name, sprinting)
local player = minetest.get_player_by_name(name) local player = minetest.get_player_by_name(name)
-- get player physics if player then
local def = player:get_physics_override() -- get player physics
local def = player:get_physics_override()
--print ("---", def.speed, def.jump) --print ("---", def.speed, def.jump)
if sprinting == true and not stamina.players[name].sprint then if sprinting == true and not stamina.players[name].sprint then
if monoids then if monoids then
stamina.players[name].sprint = player_monoids.speed:add_change( stamina.players[name].sprint = player_monoids.speed:add_change(
player, def.speed + SPRINT_SPEED) player, def.speed + SPRINT_SPEED)
stamina.players[name].jump = player_monoids.jump:add_change( stamina.players[name].jump = player_monoids.jump:add_change(
player, def.jump + SPRINT_JUMP) player, def.jump + SPRINT_JUMP)
elseif pova_mod then elseif pova_mod then
pova.add_override(name, "sprint", pova.add_override(name, "sprint",
{speed = SPRINT_SPEED, jump = SPRINT_JUMP}) {speed = SPRINT_SPEED, jump = SPRINT_JUMP})
pova.do_override(player) pova.do_override(player)
stamina.players[name].sprint = true stamina.players[name].sprint = true
else else
player:set_physics_override({ player:set_physics_override({
speed = def.speed + SPRINT_SPEED, speed = def.speed + SPRINT_SPEED,
jump = def.jump + SPRINT_JUMP, jump = def.jump + SPRINT_JUMP,
}) })
stamina.players[name].sprint = true stamina.players[name].sprint = true
end end
elseif sprinting == false elseif sprinting == false
and stamina.players[name] and stamina.players[name]
and stamina.players[name].sprint then and stamina.players[name].sprint then
if monoids then if monoids then
player_monoids.speed:del_change(player, stamina.players[name].sprint) player_monoids.speed:del_change(player, stamina.players[name].sprint)
player_monoids.jump:del_change(player, stamina.players[name].jump) player_monoids.jump:del_change(player, stamina.players[name].jump)
stamina.players[name].sprint = nil stamina.players[name].sprint = nil
stamina.players[name].jump = nil stamina.players[name].jump = nil
elseif pova_mod then elseif pova_mod then
pova.del_override(name, "sprint") pova.del_override(name, "sprint")
pova.do_override(player) pova.do_override(player)
stamina.players[name].sprint = nil stamina.players[name].sprint = nil
else else
player:set_physics_override({ player:set_physics_override({
speed = def.speed - SPRINT_SPEED, speed = def.speed - SPRINT_SPEED,
jump = def.jump - SPRINT_JUMP, jump = def.jump - SPRINT_JUMP,
}) })
stamina.players[name].sprint = nil stamina.players[name].sprint = nil
end
end end
end end
end end
@ -207,71 +209,79 @@ end
local function head_particle(player, texture) local function head_particle(player, texture)
local prop = player:get_properties() if player then
local pos = player:get_pos() ; pos.y = pos.y + prop.eye_height -- mouth level local prop = player:get_properties()
local dir = player:get_look_dir() local eye_height = prop.eye_height or 1.23
local pos = player:get_pos() ; pos.y = pos.y + eye_height -- mouth level
local dir = player:get_look_dir()
minetest.add_particlespawner({ minetest.add_particlespawner({
amount = 5, amount = 5,
time = 0.1, time = 0.1,
minpos = pos, minpos = pos,
maxpos = pos, maxpos = pos,
minvel = {x = dir.x - 1, y = dir.y, z = dir.z - 1}, minvel = {x = dir.x - 1, y = dir.y, z = dir.z - 1},
maxvel = {x = dir.x + 1, y = dir.y, z = dir.z + 1}, maxvel = {x = dir.x + 1, y = dir.y, z = dir.z + 1},
minacc = {x = 0, y = -5, z = 0}, minacc = {x = 0, y = -5, z = 0},
maxacc = {x = 0, y = -9, z = 0}, maxacc = {x = 0, y = -9, z = 0},
minexptime = 1, minexptime = 1,
maxexptime = 1, maxexptime = 1,
minsize = 1, minsize = 1,
maxsize = 2, maxsize = 2,
texture = texture texture = texture
}) })
end
end end
local function drunk_tick() local function drunk_tick()
for _,player in ipairs(minetest.get_connected_players()) do for _,player in ipairs(minetest.get_connected_players()) do
local name = player:get_player_name() if player then
if name local name = player:get_player_name()
and stamina.players[name]
and stamina.players[name].drunk then
-- play burp sound every 20 seconds when drunk if name
local num = stamina.players[name].drunk and stamina.players[name]
and stamina.players[name].drunk then
if num and num > 0 and math.floor(num / 20) == num / 20 then -- play burp sound every 20 seconds when drunk
local num = stamina.players[name].drunk
head_particle(player, "bubble.png") if num and num > 0 and math.floor(num / 20) == num / 20 then
minetest.sound_play("stamina_burp", head_particle(player, "bubble.png")
{to_player = name, gain = 0.7}, true)
end
stamina.players[name].drunk = stamina.players[name].drunk - 1 minetest.sound_play("stamina_burp",
{to_player = name, gain = 0.7}, true)
end
if stamina.players[name].drunk < 1 then stamina.players[name].drunk = stamina.players[name].drunk - 1
stamina.players[name].drunk = nil if stamina.players[name].drunk < 1 then
stamina.players[name].units = 0
if not stamina.players[name].poisoned then stamina.players[name].drunk = nil
stamina.players[name].units = 0
player:hud_change(stamina.players[name].hud_id, if not stamina.players[name].poisoned then
"text", "stamina_hud_fg.png")
player:hud_change(stamina.players[name].hud_id,
"text", "stamina_hud_fg.png")
end
end
-- effect only works when not riding boat/cart/horse etc.
if not player:get_attach() then
local yaw = player:get_look_horizontal() + math.random(-0.5, 0.5)
player:set_look_horizontal(yaw)
end end
end end
-- effect only works when not riding boat/cart/horse etc.
if not player:get_attach() then
local yaw = player:get_look_horizontal() + math.random(-0.5, 0.5)
player:set_look_horizontal(yaw)
end
end end
end end
end end
@ -280,29 +290,32 @@ local function health_tick()
for _,player in ipairs(minetest.get_connected_players()) do for _,player in ipairs(minetest.get_connected_players()) do
local air = player:get_breath() or 0 if player then
local hp = player:get_hp()
local h = get_int_attribute(player)
local name = player:get_player_name()
if name then local air = player:get_breath() or 0
local hp = player:get_hp()
local h = get_int_attribute(player)
local name = player:get_player_name()
-- damage player by 1 hp if saturation is < 2 if name then
if h and h < STAMINA_STARVE_LVL
and hp > 0 then
player:set_hp(hp - STAMINA_STARVE, {hunger = true})
end
-- don't heal if drowning or dead or poisoned -- damage player by 1 hp if saturation is < 2
if h and h >= STAMINA_HEAL_LVL if h and h < STAMINA_STARVE_LVL
and h >= hp and hp > 0 then
and hp > 0 player:set_hp(hp - STAMINA_STARVE, {hunger = true})
and air > 0 end
and not stamina.players[name].poisoned then
player:set_hp(hp + STAMINA_HEAL) -- don't heal if drowning or dead or poisoned
if h and h >= STAMINA_HEAL_LVL
and h >= hp
and hp > 0
and air > 0
and not stamina.players[name].poisoned then
stamina_update_level(player, h - 1) player:set_hp(hp + STAMINA_HEAL)
stamina_update_level(player, h - 1)
end
end end
end end
end end
@ -313,82 +326,85 @@ local function action_tick()
for _,player in ipairs(minetest.get_connected_players()) do for _,player in ipairs(minetest.get_connected_players()) do
local controls = player and player:get_player_control() if player then
-- Determine if the player is walking or jumping local controls = player and player:get_player_control()
if controls then
if controls.jump then -- Determine if the player is walking or jumping
exhaust_player(player, STAMINA_EXHAUST_JUMP) if controls then
elseif controls.up if controls.jump then
or controls.down exhaust_player(player, STAMINA_EXHAUST_JUMP)
or controls.left
or controls.right then elseif controls.up
exhaust_player(player, STAMINA_EXHAUST_MOVE) or controls.down
or controls.left
or controls.right then
exhaust_player(player, STAMINA_EXHAUST_MOVE)
end
end end
end
--- START sprint --- START sprint
if enable_sprint then if enable_sprint then
local name = player and player:get_player_name() local name = player and player:get_player_name()
-- check if player can sprint (stamina must be over 6 points) -- check if player can sprint (stamina must be over 6 points)
if name if name
and stamina.players[name] and stamina.players[name]
and not stamina.players[name].poisoned and not stamina.players[name].poisoned
and not stamina.players[name].drunk and not stamina.players[name].drunk
and controls and controls.aux1 and controls.up and controls and controls.aux1 and controls.up
and not minetest.check_player_privs(player, {fast = true}) and not minetest.check_player_privs(player, {fast = true})
and get_int_attribute(player) > 6 then and get_int_attribute(player) > 6 then
set_sprinting(name, true) set_sprinting(name, true)
-- create particles behind player when sprinting -- create particles behind player when sprinting
if enable_sprint_particles then if enable_sprint_particles then
local pos = player:get_pos() local pos = player:get_pos()
local node = minetest.get_node({ local node = minetest.get_node({
x = pos.x, x = pos.x,
y = pos.y - 1, y = pos.y - 1,
z = pos.z z = pos.z
})
if node.name ~= "air" then
minetest.add_particlespawner({
amount = 5,
time = 0.01,
minpos = {x = pos.x - 0.25, y = pos.y + 0.1, z = pos.z - 0.25},
maxpos = {x = pos.x + 0.25, y = pos.y + 0.1, z = pos.z + 0.25},
minvel = {x = -0.5, y = 1, z = -0.5},
maxvel = {x = 0.5, y = 2, z = 0.5},
minacc = {x = 0, y = -5, z = 0},
maxacc = {x = 0, y = -12, z = 0},
minexptime = 0.25,
maxexptime = 0.5,
minsize = 0.5,
maxsize = 1.0,
vertical = false,
collisiondetection = false,
texture = "default_dirt.png"
}) })
if node.name ~= "air" then
minetest.add_particlespawner({
amount = 5,
time = 0.01,
minpos = {x = pos.x - 0.25, y = pos.y + 0.1, z = pos.z - 0.25},
maxpos = {x = pos.x + 0.25, y = pos.y + 0.1, z = pos.z + 0.25},
minvel = {x = -0.5, y = 1, z = -0.5},
maxvel = {x = 0.5, y = 2, z = 0.5},
minacc = {x = 0, y = -5, z = 0},
maxacc = {x = 0, y = -12, z = 0},
minexptime = 0.25,
maxexptime = 0.5,
minsize = 0.5,
maxsize = 1.0,
vertical = false,
collisiondetection = false,
texture = "default_dirt.png"
})
end
end end
-- Lower the player's stamina when sprinting
local level = get_int_attribute(player)
stamina_update_level(player,
level - (SPRINT_DRAIN * STAMINA_MOVE_TICK))
elseif name then
set_sprinting(name, false)
end end
-- Lower the player's stamina when sprinting
local level = get_int_attribute(player)
stamina_update_level(player,
level - (SPRINT_DRAIN * STAMINA_MOVE_TICK))
elseif name then
set_sprinting(name, false)
end end
-- END sprint
end end
-- END sprint
end end
end end
@ -397,35 +413,38 @@ local function poison_tick()
for _,player in ipairs(minetest.get_connected_players()) do for _,player in ipairs(minetest.get_connected_players()) do
local name = player and player:get_player_name() if player then
if name local name = player:get_player_name()
and stamina.players[name]
and stamina.players[name].poisoned
and stamina.players[name].poisoned > 0 then
stamina.players[name].poisoned = if name
stamina.players[name].poisoned - 1 and stamina.players[name]
and stamina.players[name].poisoned
and stamina.players[name].poisoned > 0 then
local hp = player:get_hp() - 1 stamina.players[name].poisoned =
stamina.players[name].poisoned - 1
head_particle(player, "stamina_poison_particle.png") local hp = player:get_hp() - 1
if hp > 0 then head_particle(player, "stamina_poison_particle.png")
player:set_hp(hp, {poison = true})
if hp > 0 then
player:set_hp(hp, {poison = true})
end
elseif name
and stamina.players[name]
and stamina.players[name].poisoned then
if not stamina.players[name].drunk then
player:hud_change(stamina.players[name].hud_id,
"text", "stamina_hud_fg.png")
end
stamina.players[name].poisoned = nil
end end
elseif name
and stamina.players[name]
and stamina.players[name].poisoned then
if not stamina.players[name].drunk then
player:hud_change(stamina.players[name].hud_id,
"text", "stamina_hud_fg.png")
end
stamina.players[name].poisoned = nil
end end
end end
end end
@ -435,11 +454,16 @@ local function stamina_tick()
for _,player in ipairs(minetest.get_connected_players()) do for _,player in ipairs(minetest.get_connected_players()) do
local h = get_int_attribute(player) if player then
local h = get_int_attribute(player)
if h and h > STAMINA_TICK_MIN then
stamina_update_level(player, h - 1)
end
if h and h > STAMINA_TICK_MIN then
stamina_update_level(player, h - 1)
end end
end end
end end
@ -614,53 +638,57 @@ and minetest.settings:get_bool("enable_stamina") ~= false then
local level = STAMINA_VISUAL_MAX -- TODO local level = STAMINA_VISUAL_MAX -- TODO
if get_int_attribute(player) then if player then
if get_int_attribute(player) then
level = math.min(get_int_attribute(player), STAMINA_VISUAL_MAX) level = math.min(get_int_attribute(player), STAMINA_VISUAL_MAX)
else else
local meta = player:get_meta() local meta = player:get_meta()
meta:set_string("stamina:level", level) meta:set_string("stamina:level", level)
end
local name = player:get_player_name()
local id = player:hud_add({
name = "stamina",
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
size = {x = 24, y = 24},
text = "stamina_hud_fg.png",
number = level,
alignment = {x = -1, y = -1},
offset = {x = -266, y = -110},
max = 0
})
stamina.players[name] = {
hud_id = id,
exhaustion = 0,
poisoned = nil,
drunk = nil,
sprint = nil
}
end end
local name = player:get_player_name()
local id = player:hud_add({
name = "stamina",
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
size = {x = 24, y = 24},
text = "stamina_hud_fg.png",
number = level,
alignment = {x = -1, y = -1},
offset = {x = -266, y = -110},
max = 0
})
stamina.players[name] = {
hud_id = id,
exhaustion = 0,
poisoned = nil,
drunk = nil,
sprint = nil
}
end) end)
minetest.register_on_respawnplayer(function(player) minetest.register_on_respawnplayer(function(player)
local name = player:get_player_name() if player then
local name = player:get_player_name()
if stamina.players[name].poisoned if stamina.players[name].poisoned
or stamina.players[name].drunk then or stamina.players[name].drunk then
player:hud_change(stamina.players[name].hud_id, "text", "stamina_hud_fg.png") player:hud_change(stamina.players[name].hud_id, "text", "stamina_hud_fg.png")
end
stamina.players[name].exhaustion = 0
stamina.players[name].poisoned = nil
stamina.players[name].drunk = nil
stamina.players[name].sprint = nil
stamina_update_level(player, STAMINA_VISUAL_MAX)
end end
stamina.players[name].exhaustion = 0
stamina.players[name].poisoned = nil
stamina.players[name].drunk = nil
stamina.players[name].sprint = nil
stamina_update_level(player, STAMINA_VISUAL_MAX)
end) end)
minetest.register_globalstep(stamina_globaltimer) minetest.register_globalstep(stamina_globaltimer)
@ -686,14 +714,18 @@ else
-- create player table on join -- create player table on join
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
stamina.players[player:get_player_name()] = { if player then
poisoned = nil, sprint = nil, drunk = nil, exhaustion = 0} stamina.players[player:get_player_name()] = {
poisoned = nil, sprint = nil, drunk = nil, exhaustion = 0}
end
end) end)
end end
-- clear when player leaves -- clear when player leaves
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
stamina.players[player:get_player_name()] = nil if player then
stamina.players[player:get_player_name()] = nil
end
end) end)
@ -705,28 +737,31 @@ and minetest.settings:get_bool("enable_stamina") ~= false then
local effect_me = function(pos, player, def) local effect_me = function(pos, player, def)
local green = minetest.get_color_escape_sequence("#bada55") local green = minetest.get_color_escape_sequence("#bada55")
local name = player:get_player_name() if player then
local name = player:get_player_name()
if def.poison or def.drunk then if def.poison or def.drunk then
player:hud_change(stamina.players[name].hud_id, player:hud_change(stamina.players[name].hud_id,
"text", "stamina_hud_poison.png") "text", "stamina_hud_poison.png")
end
if def.poison and def.poison > 0 then
stamina.players[name].poisoned = def.poison
minetest.chat_send_player(name,
green .. "Seems you have been poisoned!")
elseif def.drunk and def.drunk > 0 then
stamina.players[name].drunk = def.drunk
minetest.chat_send_player(name,
green .. "You seem a little tipsy!")
end
end end
if def.poison and def.poison > 0 then
stamina.players[name].poisoned = def.poison
minetest.chat_send_player(name,
green .. "Seems you have been poisoned!")
elseif def.drunk and def.drunk > 0 then
stamina.players[name].drunk = def.drunk
minetest.chat_send_player(name,
green .. "You seem a little tipsy!")
end
end end
lucky_block:add_blocks({ lucky_block:add_blocks({