From 64ff966bae99813229dff6629fd9131a91ba7484 Mon Sep 17 00:00:00 2001
From: Loic Blot <loic.blot@unix-experience.fr>
Date: Mon, 2 Mar 2015 17:31:31 +0100
Subject: [PATCH] Send Player HP when setHP (or a setHP caller) is called
 instead of looping and testing the state change.

---
 src/content_sao.cpp                   | 20 +++++---------------
 src/content_sao.h                     |  1 -
 src/network/packethandlers/server.cpp | 27 +++++++++++++++++++--------
 src/script/lua_api/l_object.cpp       | 21 +++++++++++++++++++++
 src/server.cpp                        | 26 ++++++++------------------
 src/server.h                          |  1 +
 6 files changed, 54 insertions(+), 42 deletions(-)

diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index 8cb8fa788..835996cc7 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -718,7 +718,6 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
 	// public
 	m_moved(false),
 	m_inventory_not_sent(false),
-	m_hp_not_sent(false),
 	m_breath_not_sent(false),
 	m_wielded_item_not_sent(false),
 	m_physics_override_speed(1),
@@ -1081,27 +1080,18 @@ void PlayerSAO::setHP(s16 hp)
 {
 	s16 oldhp = m_player->hp;
 
-	if(hp < 0)
+	if (hp < 0)
 		hp = 0;
-	else if(hp > PLAYER_MAX_HP)
+	else if (hp > PLAYER_MAX_HP)
 		hp = PLAYER_MAX_HP;
 
-	if(hp < oldhp && g_settings->getBool("enable_damage") == false)
-	{
-		m_hp_not_sent = true; // fix wrong prediction on client
-		return;
-	}
-
 	m_player->hp = hp;
 
-	if(hp != oldhp) {
-		m_hp_not_sent = true;
-		if(oldhp > hp)
-			m_damage += oldhp - hp;
-	}
+	if (oldhp > hp)
+		m_damage += (oldhp - hp);
 
 	// Update properties on death
-	if((hp == 0) != (oldhp == 0))
+	if ((hp == 0) != (oldhp == 0))
 		m_properties_sent = false;
 }
 
diff --git a/src/content_sao.h b/src/content_sao.h
index 05f727e16..efbece3ca 100644
--- a/src/content_sao.h
+++ b/src/content_sao.h
@@ -318,7 +318,6 @@ class PlayerSAO : public ServerActiveObject
 	// Some flags used by Server
 	bool m_moved;
 	bool m_inventory_not_sent;
-	bool m_hp_not_sent;
 	bool m_breath_not_sent;
 	bool m_wielded_item_not_sent;
 
diff --git a/src/network/packethandlers/server.cpp b/src/network/packethandlers/server.cpp
index 137327e0b..d9ba8c314 100644
--- a/src/network/packethandlers/server.cpp
+++ b/src/network/packethandlers/server.cpp
@@ -893,12 +893,7 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
 				<< std::endl;
 
 		playersao->setHP(playersao->getHP() - damage);
-
-		if (playersao->getHP() == 0 && playersao->m_hp_not_sent)
-			DiePlayer(pkt->getPeerId());
-
-		if (playersao->m_hp_not_sent)
-			SendPlayerHP(pkt->getPeerId());
+		SendPlayerHPOrDie(playersao->getPeerID(), playersao->getHP() == 0);
 	}
 }
 
@@ -1048,8 +1043,8 @@ void Server::handleCommand_Respawn(NetworkPacket* pkt)
 
 	RespawnPlayer(pkt->getPeerId());
 
-	actionstream<<player->getName()<<" respawns at "
-			<<PP(player->getPosition()/BS)<<std::endl;
+	actionstream << player->getName() << " respawns at "
+			<< PP(player->getPosition()/BS) << std::endl;
 
 	// ActiveObject is added to environment in AsyncRunStep after
 	// the previous addition has been succesfully removed
@@ -1234,8 +1229,24 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
 						).normalize();
 			float time_from_last_punch =
 				playersao->resetTimeFromLastPunch();
+
+			s16 src_original_hp = pointed_object->getHP();
+			s16 dst_origin_hp = playersao->getHP();
+
 			pointed_object->punch(dir, &toolcap, playersao,
 					time_from_last_punch);
+
+			// If the object is a player and its HP changed
+			if (src_original_hp != pointed_object->getHP() &&
+					pointed_object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
+				SendPlayerHPOrDie(((PlayerSAO*)pointed_object)->getPeerID(),
+						pointed_object->getHP() == 0);
+			}
+
+			// If the puncher is a player and its HP changed
+			if (dst_origin_hp != playersao->getHP()) {
+				SendPlayerHPOrDie(playersao->getPeerID(), playersao->getHP() == 0);
+			}
 		}
 
 	} // action == 0
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index 73f6e93b3..e6a50c3ba 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -208,8 +208,26 @@ int ObjectRef::l_punch(lua_State *L)
 		time_from_last_punch = lua_tonumber(L, 3);
 	ToolCapabilities toolcap = read_tool_capabilities(L, 4);
 	dir.normalize();
+
+	s16 src_original_hp = co->getHP();
+	s16 dst_origin_hp = puncher->getHP();
+
 	// Do it
 	co->punch(dir, &toolcap, puncher, time_from_last_punch);
+
+	// If the punched is a player, and its HP changed
+	if (src_original_hp != co->getHP() &&
+			co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
+		getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)co)->getPeerID(),
+				co->getHP() == 0);
+	}
+
+	// If the puncher is a player, and its HP changed
+	if (dst_origin_hp != puncher->getHP() &&
+			puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
+		getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)puncher)->getPeerID(),
+				puncher->getHP() == 0);
+	}
 	return 0;
 }
 
@@ -243,6 +261,9 @@ int ObjectRef::l_set_hp(lua_State *L)
 			<<" hp="<<hp<<std::endl;*/
 	// Do it
 	co->setHP(hp);
+	if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
+		getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)co)->getPeerID(), co->getHP() == 0);
+	}
 	// Return
 	return 0;
 }
diff --git a/src/server.cpp b/src/server.cpp
index 6a1e8085b..3536471bf 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -604,17 +604,6 @@ void Server::AsyncRunStep(bool initial_step)
 			if(playersao == NULL)
 				continue;
 
-			/*
-				Handle player HPs (die if hp=0)
-			*/
-			if(playersao->m_hp_not_sent && g_settings->getBool("enable_damage"))
-			{
-				if(playersao->getHP() == 0)
-					DiePlayer(*i);
-				else
-					SendPlayerHP(*i);
-			}
-
 			/*
 				Send player breath if changed
 			*/
@@ -1889,7 +1878,6 @@ void Server::SendPlayerHP(u16 peer_id)
 	DSTACK(__FUNCTION_NAME);
 	PlayerSAO *playersao = getPlayerSAO(peer_id);
 	assert(playersao);
-	playersao->m_hp_not_sent = false;
 	SendHP(peer_id, playersao->getHP());
 	m_script->player_event(playersao,"health_changed");
 
@@ -2588,9 +2576,9 @@ void Server::DiePlayer(u16 peer_id)
 	PlayerSAO *playersao = getPlayerSAO(peer_id);
 	assert(playersao);
 
-	infostream<<"Server::DiePlayer(): Player "
-			<<playersao->getPlayer()->getName()
-			<<" dies"<<std::endl;
+	infostream << "Server::DiePlayer(): Player "
+			<< playersao->getPlayer()->getName()
+			<< " dies" << std::endl;
 
 	playersao->setHP(0);
 
@@ -2608,13 +2596,15 @@ void Server::RespawnPlayer(u16 peer_id)
 	PlayerSAO *playersao = getPlayerSAO(peer_id);
 	assert(playersao);
 
-	infostream<<"Server::RespawnPlayer(): Player "
-			<<playersao->getPlayer()->getName()
-			<<" respawns"<<std::endl;
+	infostream << "Server::RespawnPlayer(): Player "
+			<< playersao->getPlayer()->getName()
+			<< " respawns" << std::endl;
 
 	playersao->setHP(PLAYER_MAX_HP);
 	playersao->setBreath(PLAYER_MAX_BREATH);
 
+	SendPlayerHP(peer_id);
+
 	bool repositioned = m_script->on_respawnplayer(playersao);
 	if(!repositioned){
 		v3f pos = findSpawnPos(m_env->getServerMap());
diff --git a/src/server.h b/src/server.h
index fa9f9ebcf..5dbbcd22b 100644
--- a/src/server.h
+++ b/src/server.h
@@ -372,6 +372,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 			u8* ser_vers, u16* prot_vers, u8* major, u8* minor, u8* patch,
 			std::string* vers_string);
 
+	void SendPlayerHPOrDie(u16 peer_id, bool die) { die ? DiePlayer(peer_id) : SendPlayerHP(peer_id); }
 	// Bind address
 	Address m_bind_addr;
 
-- 
GitLab