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)
-- get player physics
local def = player:get_physics_override()
if player then
-- 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(
player, def.speed + SPRINT_SPEED)
stamina.players[name].sprint = player_monoids.speed:add_change(
player, def.speed + SPRINT_SPEED)
stamina.players[name].jump = player_monoids.jump:add_change(
player, def.jump + SPRINT_JUMP)
stamina.players[name].jump = player_monoids.jump:add_change(
player, def.jump + SPRINT_JUMP)
elseif pova_mod then
elseif pova_mod then
pova.add_override(name, "sprint",
{speed = SPRINT_SPEED, jump = SPRINT_JUMP})
pova.add_override(name, "sprint",
{speed = SPRINT_SPEED, jump = SPRINT_JUMP})
pova.do_override(player)
pova.do_override(player)
stamina.players[name].sprint = true
else
player:set_physics_override({
speed = def.speed + SPRINT_SPEED,
jump = def.jump + SPRINT_JUMP,
})
stamina.players[name].sprint = true
else
player:set_physics_override({
speed = def.speed + SPRINT_SPEED,
jump = def.jump + SPRINT_JUMP,
})
stamina.players[name].sprint = true
end
stamina.players[name].sprint = true
end
elseif sprinting == false
and stamina.players[name]
and stamina.players[name].sprint then
elseif sprinting == false
and stamina.players[name]
and stamina.players[name].sprint then
if monoids then
if monoids then
player_monoids.speed:del_change(player, stamina.players[name].sprint)
player_monoids.jump:del_change(player, stamina.players[name].jump)
player_monoids.speed:del_change(player, stamina.players[name].sprint)
player_monoids.jump:del_change(player, stamina.players[name].jump)
stamina.players[name].sprint = nil
stamina.players[name].jump = nil
stamina.players[name].sprint = nil
stamina.players[name].jump = nil
elseif pova_mod then
elseif pova_mod then
pova.del_override(name, "sprint")
pova.do_override(player)
pova.del_override(name, "sprint")
pova.do_override(player)
stamina.players[name].sprint = nil
else
player:set_physics_override({
speed = def.speed - SPRINT_SPEED,
jump = def.jump - SPRINT_JUMP,
})
stamina.players[name].sprint = nil
else
player:set_physics_override({
speed = def.speed - SPRINT_SPEED,
jump = def.jump - SPRINT_JUMP,
})
stamina.players[name].sprint = nil
stamina.players[name].sprint = nil
end
end
end
end
@ -207,71 +209,79 @@ end
local function head_particle(player, texture)
local prop = player:get_properties()
local pos = player:get_pos() ; pos.y = pos.y + prop.eye_height -- mouth level
local dir = player:get_look_dir()
if player then
local prop = player:get_properties()
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({
amount = 5,
time = 0.1,
minpos = pos,
maxpos = pos,
minvel = {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},
maxacc = {x = 0, y = -9, z = 0},
minexptime = 1,
maxexptime = 1,
minsize = 1,
maxsize = 2,
texture = texture
})
minetest.add_particlespawner({
amount = 5,
time = 0.1,
minpos = pos,
maxpos = pos,
minvel = {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},
maxacc = {x = 0, y = -9, z = 0},
minexptime = 1,
maxexptime = 1,
minsize = 1,
maxsize = 2,
texture = texture
})
end
end
local function drunk_tick()
for _,player in ipairs(minetest.get_connected_players()) do
local name = player:get_player_name()
if player then
if name
and stamina.players[name]
and stamina.players[name].drunk then
local name = player:get_player_name()
-- play burp sound every 20 seconds when drunk
local num = stamina.players[name].drunk
if name
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",
{to_player = name, gain = 0.7}, true)
end
head_particle(player, "bubble.png")
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
stamina.players[name].units = 0
if stamina.players[name].drunk < 1 then
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,
"text", "stamina_hud_fg.png")
if not stamina.players[name].poisoned then
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
-- 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
@ -280,29 +290,32 @@ local function health_tick()
for _,player in ipairs(minetest.get_connected_players()) do
local air = player:get_breath() or 0
local hp = player:get_hp()
local h = get_int_attribute(player)
local name = player:get_player_name()
if player then
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 h and h < STAMINA_STARVE_LVL
and hp > 0 then
player:set_hp(hp - STAMINA_STARVE, {hunger = true})
end
if name then
-- 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
-- damage player by 1 hp if saturation is < 2
if h and h < STAMINA_STARVE_LVL
and hp > 0 then
player:set_hp(hp - STAMINA_STARVE, {hunger = true})
end
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
@ -313,82 +326,85 @@ local function action_tick()
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
if controls then
local controls = player and player:get_player_control()
if controls.jump then
exhaust_player(player, STAMINA_EXHAUST_JUMP)
-- Determine if the player is walking or jumping
if controls then
elseif controls.up
or controls.down
or controls.left
or controls.right then
exhaust_player(player, STAMINA_EXHAUST_MOVE)
if controls.jump then
exhaust_player(player, STAMINA_EXHAUST_JUMP)
elseif controls.up
or controls.down
or controls.left
or controls.right then
exhaust_player(player, STAMINA_EXHAUST_MOVE)
end
end
end
--- START sprint
if enable_sprint then
--- START sprint
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)
if name
and stamina.players[name]
and not stamina.players[name].poisoned
and not stamina.players[name].drunk
and controls and controls.aux1 and controls.up
and not minetest.check_player_privs(player, {fast = true})
and get_int_attribute(player) > 6 then
-- check if player can sprint (stamina must be over 6 points)
if name
and stamina.players[name]
and not stamina.players[name].poisoned
and not stamina.players[name].drunk
and controls and controls.aux1 and controls.up
and not minetest.check_player_privs(player, {fast = true})
and get_int_attribute(player) > 6 then
set_sprinting(name, true)
set_sprinting(name, true)
-- create particles behind player when sprinting
if enable_sprint_particles then
-- create particles behind player when sprinting
if enable_sprint_particles then
local pos = player:get_pos()
local node = minetest.get_node({
x = pos.x,
y = pos.y - 1,
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"
local pos = player:get_pos()
local node = minetest.get_node({
x = pos.x,
y = pos.y - 1,
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"
})
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
-- 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 sprint
end
-- END sprint
end
end
@ -397,35 +413,38 @@ local function poison_tick()
for _,player in ipairs(minetest.get_connected_players()) do
local name = player and player:get_player_name()
if player then
if name
and stamina.players[name]
and stamina.players[name].poisoned
and stamina.players[name].poisoned > 0 then
local name = player:get_player_name()
stamina.players[name].poisoned =
stamina.players[name].poisoned - 1
if name
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
player:set_hp(hp, {poison = true})
head_particle(player, "stamina_poison_particle.png")
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
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
@ -435,11 +454,16 @@ local function stamina_tick()
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
@ -614,53 +638,57 @@ and minetest.settings:get_bool("enable_stamina") ~= false then
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)
else
local meta = player:get_meta()
level = math.min(get_int_attribute(player), STAMINA_VISUAL_MAX)
else
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
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)
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
or stamina.players[name].drunk then
player:hud_change(stamina.players[name].hud_id, "text", "stamina_hud_fg.png")
if stamina.players[name].poisoned
or stamina.players[name].drunk then
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
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)
minetest.register_globalstep(stamina_globaltimer)
@ -686,14 +714,18 @@ else
-- create player table on join
minetest.register_on_joinplayer(function(player)
stamina.players[player:get_player_name()] = {
poisoned = nil, sprint = nil, drunk = nil, exhaustion = 0}
if player then
stamina.players[player:get_player_name()] = {
poisoned = nil, sprint = nil, drunk = nil, exhaustion = 0}
end
end)
end
-- clear when player leaves
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)
@ -705,28 +737,31 @@ and minetest.settings:get_bool("enable_stamina") ~= false then
local effect_me = function(pos, player, def)
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,
"text", "stamina_hud_poison.png")
player:hud_change(stamina.players[name].hud_id,
"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
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
lucky_block:add_blocks({