From 72b14bd994659163d4c2ea0d769d329df8a0f937 Mon Sep 17 00:00:00 2001 From: savilli <78875209+savilli@users.noreply.github.com> Date: Sat, 15 Jan 2022 17:44:55 +0100 Subject: [PATCH] Don't call on_dieplayer callback two times (#11874) --- src/network/serverpackethandler.cpp | 3 +- src/server.cpp | 51 ++++++++++------------------- src/server.h | 6 ++-- src/server/player_sao.cpp | 37 ++++++++++----------- src/server/player_sao.h | 4 +-- 5 files changed, 41 insertions(+), 60 deletions(-) diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 37b62c5cb..12dc24460 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -819,8 +819,7 @@ void Server::handleCommand_Damage(NetworkPacket* pkt) << std::endl; PlayerHPChangeReason reason(PlayerHPChangeReason::FALL); - playersao->setHP((s32)playersao->getHP() - (s32)damage, reason, false); - SendPlayerHPOrDie(playersao, reason); // correct client side prediction + playersao->setHP((s32)playersao->getHP() - (s32)damage, reason, true); } } diff --git a/src/server.cpp b/src/server.cpp index 6cf790de1..45156db61 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1095,11 +1095,12 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id) // Send inventory SendInventory(playersao, false); - // Send HP or death screen + // Send HP + SendPlayerHP(playersao); + + // Send death screen if (playersao->isDead()) SendDeathscreen(peer_id, false, v3f(0,0,0)); - else - SendPlayerHP(peer_id); // Send Breath SendPlayerBreath(playersao); @@ -1365,18 +1366,21 @@ void Server::SendMovement(session_t peer_id) Send(&pkt); } -void Server::SendPlayerHPOrDie(PlayerSAO *playersao, const PlayerHPChangeReason &reason) +void Server::HandlePlayerHPChange(PlayerSAO *playersao, const PlayerHPChangeReason &reason) { - if (playersao->isImmortal()) - return; + m_script->player_event(playersao, "health_changed"); + SendPlayerHP(playersao); - session_t peer_id = playersao->getPeerID(); - bool is_alive = !playersao->isDead(); + // Send to other clients + playersao->sendPunchCommand(); - if (is_alive) - SendPlayerHP(peer_id); - else - DiePlayer(peer_id, reason); + if (playersao->isDead()) + HandlePlayerDeath(playersao, reason); +} + +void Server::SendPlayerHP(PlayerSAO *playersao) +{ + SendHP(playersao->getPeerID(), playersao->getHP()); } void Server::SendHP(session_t peer_id, u16 hp) @@ -1810,18 +1814,6 @@ void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed) } } -void Server::SendPlayerHP(session_t peer_id) -{ - PlayerSAO *playersao = getPlayerSAO(peer_id); - assert(playersao); - - SendHP(peer_id, playersao->getHP()); - m_script->player_event(playersao,"health_changed"); - - // Send to other clients - playersao->sendPunchCommand(); -} - void Server::SendPlayerBreath(PlayerSAO *sao) { assert(sao); @@ -2750,23 +2742,18 @@ void Server::sendDetachedInventories(session_t peer_id, bool incremental) Something random */ -void Server::DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason) +void Server::HandlePlayerDeath(PlayerSAO *playersao, const PlayerHPChangeReason &reason) { - PlayerSAO *playersao = getPlayerSAO(peer_id); - assert(playersao); - infostream << "Server::DiePlayer(): Player " << playersao->getPlayer()->getName() << " dies" << std::endl; - playersao->setHP(0, reason); playersao->clearParentAttachment(); // Trigger scripted stuff m_script->on_dieplayer(playersao, reason); - SendPlayerHP(peer_id); - SendDeathscreen(peer_id, false, v3f(0,0,0)); + SendDeathscreen(playersao->getPeerID(), false, v3f(0,0,0)); } void Server::RespawnPlayer(session_t peer_id) @@ -2787,8 +2774,6 @@ void Server::RespawnPlayer(session_t peer_id) // setPos will send the new position to client playersao->setPos(findSpawnPos()); } - - SendPlayerHP(peer_id); } diff --git a/src/server.h b/src/server.h index 12158feb7..2741b3157 100644 --- a/src/server.h +++ b/src/server.h @@ -350,7 +350,8 @@ public: void printToConsoleOnly(const std::string &text); - void SendPlayerHPOrDie(PlayerSAO *player, const PlayerHPChangeReason &reason); + void HandlePlayerHPChange(PlayerSAO *sao, const PlayerHPChangeReason &reason); + void SendPlayerHP(PlayerSAO *sao); void SendPlayerBreath(PlayerSAO *sao); void SendInventory(PlayerSAO *playerSAO, bool incremental); void SendMovePlayer(session_t peer_id); @@ -438,7 +439,6 @@ private: virtual void SendChatMessage(session_t peer_id, const ChatMessage &message); void SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed); - void SendPlayerHP(session_t peer_id); void SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4], f32 animation_speed); @@ -510,7 +510,7 @@ private: Something random */ - void DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason); + void HandlePlayerDeath(PlayerSAO* sao, const PlayerHPChangeReason &reason); void RespawnPlayer(session_t peer_id); void DeleteClient(session_t peer_id, ClientDeletionReason reason); void UpdateCrafting(RemotePlayer *player); diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 83e17f830..d076d5783 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -463,36 +463,33 @@ void PlayerSAO::rightClick(ServerActiveObject *clicker) m_env->getScriptIface()->on_rightclickplayer(this, clicker); } -void PlayerSAO::setHP(s32 hp, const PlayerHPChangeReason &reason, bool send) +void PlayerSAO::setHP(s32 target_hp, const PlayerHPChangeReason &reason, bool from_client) { - if (hp == (s32)m_hp) + target_hp = rangelim(target_hp, 0, U16_MAX); + + if (target_hp == m_hp) return; // Nothing to do - if (m_hp <= 0 && hp < (s32)m_hp) - return; // Cannot take more damage + s32 hp_change = m_env->getScriptIface()->on_player_hpchange(this, target_hp - (s32)m_hp, reason); - { - s32 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - m_hp, reason); - if (hp_change == 0) - return; + s32 hp = (s32)m_hp + std::min(hp_change, U16_MAX); // Protection against s32 overflow + hp = rangelim(hp, 0, U16_MAX); - hp = m_hp + hp_change; - } + if (hp > m_prop.hp_max) + hp = m_prop.hp_max; - s32 oldhp = m_hp; - hp = rangelim(hp, 0, m_prop.hp_max); - - if (hp < oldhp && isImmortal()) - return; // Do not allow immortal players to be damaged - - m_hp = hp; + if (hp < m_hp && isImmortal()) + hp = m_hp; // Do not allow immortal players to be damaged // Update properties on death - if ((hp == 0) != (oldhp == 0)) + if ((hp == 0) != (m_hp == 0)) m_properties_sent = false; - if (send) - m_env->getGameDef()->SendPlayerHPOrDie(this, reason); + if (hp != m_hp) { + m_hp = hp; + m_env->getGameDef()->HandlePlayerHPChange(this, reason); + } else if (from_client) + m_env->getGameDef()->SendPlayerHP(this); } void PlayerSAO::setBreath(const u16 breath, bool send) diff --git a/src/server/player_sao.h b/src/server/player_sao.h index 47fe85413..96d8f7189 100644 --- a/src/server/player_sao.h +++ b/src/server/player_sao.h @@ -114,9 +114,9 @@ public: void rightClick(ServerActiveObject *clicker); void setHP(s32 hp, const PlayerHPChangeReason &reason) override { - return setHP(hp, reason, true); + return setHP(hp, reason, false); } - void setHP(s32 hp, const PlayerHPChangeReason &reason, bool send); + void setHP(s32 hp, const PlayerHPChangeReason &reason, bool from_client); void setHPRaw(u16 hp) { m_hp = hp; } u16 getBreath() const { return m_breath; } void setBreath(const u16 breath, bool send = true);