aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoic Blot <loic.blot@unix-experience.fr>2017-01-01 16:13:01 +0100
committerLoic Blot <loic.blot@unix-experience.fr>2017-01-01 23:11:26 +0100
commit52ba1f867e5edb579a59a44fbb8286d4f1e54931 (patch)
treed95e2032d3fcf18bd972cc018e6b44470664d75c
parenta1346c916e1d0f0cde2ccecc680857896c717a3d (diff)
downloadminetest-52ba1f867e5edb579a59a44fbb8286d4f1e54931.tar.gz
minetest-52ba1f867e5edb579a59a44fbb8286d4f1e54931.tar.bz2
minetest-52ba1f867e5edb579a59a44fbb8286d4f1e54931.zip
Breath cheat fix: server side
Breath is now handled server side. Changing this behaviour required some modifications to core: * Ignore TOSERVER_BREATH package, marking it as obsolete * Clients doesn't send the breath to server anymore * Use PlayerSAO pointer instead of peer_id in Server::SendPlayerBreath to prevent a useless lookup (little perf gain) * drop a useless static_cast in emergePlayer
-rw-r--r--src/client.cpp11
-rw-r--r--src/content_sao.cpp39
-rw-r--r--src/content_sao.h7
-rw-r--r--src/environment.cpp84
-rw-r--r--src/network/clientopcodes.cpp2
-rw-r--r--src/network/networkprotocol.h6
-rw-r--r--src/network/serveropcodes.cpp2
-rw-r--r--src/network/serverpackethandler.cpp40
-rw-r--r--src/remoteplayer.cpp2
-rw-r--r--src/script/lua_api/l_object.cpp5
-rw-r--r--src/server.cpp15
-rw-r--r--src/server.h3
-rw-r--r--src/unittest/test_player.cpp4
13 files changed, 107 insertions, 113 deletions
diff --git a/src/client.cpp b/src/client.cpp
index 5476aad0e..1446ebad8 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -499,9 +499,10 @@ void Client::step(float dtime)
m_client_event_queue.push(event);
}
}
- else if(event.type == CEE_PLAYER_BREATH) {
- u16 breath = event.player_breath.amount;
- sendBreath(breath);
+ // Protocol v29 or greater obsoleted this event
+ else if (event.type == CEE_PLAYER_BREATH && m_proto_ver < 29) {
+ u16 breath = event.player_breath.amount;
+ sendBreath(breath);
}
}
@@ -1270,6 +1271,10 @@ void Client::sendBreath(u16 breath)
{
DSTACK(FUNCTION_NAME);
+ // Protocol v29 make this obsolete
+ if (m_proto_ver >= 29)
+ return;
+
NetworkPacket pkt(TOSERVER_BREATH, sizeof(u16));
pkt << breath;
Send(&pkt);
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index 77ab51a02..f866d4372 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h" // For compressZlib
#include "tool.h" // For ToolCapabilities
#include "gamedef.h"
+#include "nodedef.h"
#include "remoteplayer.h"
#include "server.h"
#include "scripting_game.h"
@@ -940,8 +941,35 @@ bool PlayerSAO::isAttached()
void PlayerSAO::step(float dtime, bool send_recommended)
{
- if(!m_properties_sent)
- {
+ if (m_drowning_interval.step(dtime, 2.0)) {
+ // get head position
+ v3s16 p = floatToInt(m_base_position + v3f(0, BS * 1.6, 0), BS);
+ MapNode n = m_env->getMap().getNodeNoEx(p);
+ const ContentFeatures &c = ((Server*) m_env->getGameDef())->ndef()->get(n);
+ // If node generates drown
+ if (c.drowning > 0) {
+ if (m_hp > 0 && m_breath > 0)
+ setBreath(m_breath - 1);
+
+ // No more breath, damage player
+ if (m_breath == 0) {
+ setHP(m_hp - c.drowning);
+ ((Server*) m_env->getGameDef())->SendPlayerHPOrDie(this);
+ }
+ }
+ }
+
+ if (m_breathing_interval.step(dtime, 0.5)) {
+ // get head position
+ v3s16 p = floatToInt(m_base_position + v3f(0, BS * 1.6, 0), BS);
+ MapNode n = m_env->getMap().getNodeNoEx(p);
+ const ContentFeatures &c = ((Server*) m_env->getGameDef())->ndef()->get(n);
+ // If player is alive & no drowning, breath
+ if (m_hp > 0 && c.drowning == 0)
+ setBreath(m_breath + 1);
+ }
+
+ if (!m_properties_sent) {
m_properties_sent = true;
std::string str = getPropertyPacket();
// create message and add to list
@@ -1237,12 +1265,15 @@ void PlayerSAO::setHP(s16 hp)
m_properties_sent = false;
}
-void PlayerSAO::setBreath(const u16 breath)
+void PlayerSAO::setBreath(const u16 breath, bool send)
{
if (m_player && breath != m_breath)
m_player->setDirty(true);
- m_breath = breath;
+ m_breath = MYMIN(breath, PLAYER_MAX_BREATH);
+
+ if (send)
+ ((Server *) m_env->getGameDef())->SendPlayerBreath(this);
}
void PlayerSAO::setArmorGroups(const ItemGroupList &armor_groups)
diff --git a/src/content_sao.h b/src/content_sao.h
index 86255183d..9c66068b3 100644
--- a/src/content_sao.h
+++ b/src/content_sao.h
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef CONTENT_SAO_HEADER
#define CONTENT_SAO_HEADER
+#include <util/numeric.h>
#include "serverobject.h"
#include "itemgroup.h"
#include "object_properties.h"
@@ -232,7 +233,7 @@ public:
void setHPRaw(s16 hp) { m_hp = hp; }
s16 readDamage();
u16 getBreath() const { return m_breath; }
- void setBreath(const u16 breath);
+ void setBreath(const u16 breath, bool send = true);
void setArmorGroups(const ItemGroupList &armor_groups);
ItemGroupList getArmorGroups();
void setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop);
@@ -339,6 +340,10 @@ private:
v3s16 m_nocheat_dig_pos;
float m_nocheat_dig_time;
+ // Timers
+ IntervalLimiter m_breathing_interval;
+ IntervalLimiter m_drowning_interval;
+
int m_wield_index;
bool m_position_not_sent;
ItemGroupList m_armor_groups;
diff --git a/src/environment.cpp b/src/environment.cpp
index 707d89659..ac9b5b079 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -2511,51 +2511,51 @@ void ClientEnvironment::step(float dtime)
}
}
- /*
- Drowning
- */
- if(m_drowning_interval.step(dtime, 2.0))
- {
- v3f pf = lplayer->getPosition();
-
- // head
- v3s16 p = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
- MapNode n = m_map->getNodeNoEx(p);
- ContentFeatures c = m_gamedef->ndef()->get(n);
- u8 drowning_damage = c.drowning;
- if(drowning_damage > 0 && lplayer->hp > 0){
- u16 breath = lplayer->getBreath();
- if(breath > 10){
- breath = 11;
- }
- if(breath > 0){
- breath -= 1;
+ // Protocol v29 make this behaviour obsolete
+ if (((Client*) getGameDef())->getProtoVersion() < 29) {
+ /*
+ Drowning
+ */
+ if (m_drowning_interval.step(dtime, 2.0)) {
+ v3f pf = lplayer->getPosition();
+
+ // head
+ v3s16 p = floatToInt(pf + v3f(0, BS * 1.6, 0), BS);
+ MapNode n = m_map->getNodeNoEx(p);
+ ContentFeatures c = m_gamedef->ndef()->get(n);
+ u8 drowning_damage = c.drowning;
+ if (drowning_damage > 0 && lplayer->hp > 0) {
+ u16 breath = lplayer->getBreath();
+ if (breath > 10) {
+ breath = 11;
+ }
+ if (breath > 0) {
+ breath -= 1;
+ }
+ lplayer->setBreath(breath);
+ updateLocalPlayerBreath(breath);
}
- lplayer->setBreath(breath);
- updateLocalPlayerBreath(breath);
- }
- if(lplayer->getBreath() == 0 && drowning_damage > 0){
- damageLocalPlayer(drowning_damage, true);
+ if (lplayer->getBreath() == 0 && drowning_damage > 0) {
+ damageLocalPlayer(drowning_damage, true);
+ }
}
- }
- if(m_breathing_interval.step(dtime, 0.5))
- {
- v3f pf = lplayer->getPosition();
-
- // head
- v3s16 p = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
- MapNode n = m_map->getNodeNoEx(p);
- ContentFeatures c = m_gamedef->ndef()->get(n);
- if (!lplayer->hp){
- lplayer->setBreath(11);
- }
- else if(c.drowning == 0){
- u16 breath = lplayer->getBreath();
- if(breath <= 10){
- breath += 1;
- lplayer->setBreath(breath);
- updateLocalPlayerBreath(breath);
+ if (m_breathing_interval.step(dtime, 0.5)) {
+ v3f pf = lplayer->getPosition();
+
+ // head
+ v3s16 p = floatToInt(pf + v3f(0, BS * 1.6, 0), BS);
+ MapNode n = m_map->getNodeNoEx(p);
+ ContentFeatures c = m_gamedef->ndef()->get(n);
+ if (!lplayer->hp) {
+ lplayer->setBreath(11);
+ } else if (c.drowning == 0) {
+ u16 breath = lplayer->getBreath();
+ if (breath <= 10) {
+ breath += 1;
+ lplayer->setBreath(breath);
+ updateLocalPlayerBreath(breath);
+ }
}
}
}
diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp
index 3364de8c5..6defdcf1b 100644
--- a/src/network/clientopcodes.cpp
+++ b/src/network/clientopcodes.cpp
@@ -193,7 +193,7 @@ const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES] =
null_command_factory, // 0x3f
{ "TOSERVER_REQUEST_MEDIA", 1, true }, // 0x40
{ "TOSERVER_RECEIVED_MEDIA", 1, true }, // 0x41
- { "TOSERVER_BREATH", 0, true }, // 0x42
+ null_command_factory, // 0x42 old TOSERVER_BREATH. Ignored by servers
{ "TOSERVER_CLIENT_READY", 0, true }, // 0x43
null_command_factory, // 0x44
null_command_factory, // 0x45
diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h
index 018b392b6..f65167380 100644
--- a/src/network/networkprotocol.h
+++ b/src/network/networkprotocol.h
@@ -138,9 +138,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Add nodedef v3 - connected nodeboxes
PROTOCOL_VERSION 28:
CPT2_MESHOPTIONS
+ PROTOCOL_VERSION 29:
+ Server doesn't accept TOSERVER_BREATH anymore
*/
-#define LATEST_PROTOCOL_VERSION 28
+#define LATEST_PROTOCOL_VERSION 29
// Server's supported network protocol range
#define SERVER_PROTOCOL_VERSION_MIN 13
@@ -833,7 +835,7 @@ enum ToServerCommand
<no payload data>
*/
- TOSERVER_BREATH = 0x42,
+ TOSERVER_BREATH = 0x42, // Obsolete
/*
u16 breath
*/
diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp
index 9b14a1be3..642dd376a 100644
--- a/src/network/serveropcodes.cpp
+++ b/src/network/serveropcodes.cpp
@@ -90,7 +90,7 @@ const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] =
null_command_handler, // 0x3f
{ "TOSERVER_REQUEST_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_RequestMedia }, // 0x40
{ "TOSERVER_RECEIVED_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_ReceivedMedia }, // 0x41
- { "TOSERVER_BREATH", TOSERVER_STATE_INGAME, &Server::handleCommand_Breath }, // 0x42
+ { "TOSERVER_BREATH", TOSERVER_STATE_INGAME, &Server::handleCommand_Deprecated }, // 0x42 Old breath model which is now deprecated for anticheating
{ "TOSERVER_CLIENT_READY", TOSERVER_STATE_STARTUP, &Server::handleCommand_ClientReady }, // 0x43
null_command_handler, // 0x44
null_command_handler, // 0x45
diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp
index d0f4d948d..eeabcca71 100644
--- a/src/network/serverpackethandler.cpp
+++ b/src/network/serverpackethandler.cpp
@@ -1136,46 +1136,6 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
}
}
-void Server::handleCommand_Breath(NetworkPacket* pkt)
-{
- u16 breath;
-
- *pkt >> breath;
-
- RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
-
- if (player == NULL) {
- errorstream << "Server::ProcessData(): Canceling: "
- "No player for peer_id=" << pkt->getPeerId()
- << " disconnecting peer!" << std::endl;
- m_con.DisconnectPeer(pkt->getPeerId());
- return;
- }
-
-
- PlayerSAO *playersao = player->getPlayerSAO();
- if (playersao == NULL) {
- errorstream << "Server::ProcessData(): Canceling: "
- "No player object for peer_id=" << pkt->getPeerId()
- << " disconnecting peer!" << std::endl;
- m_con.DisconnectPeer(pkt->getPeerId());
- return;
- }
-
- /*
- * If player is dead, we don't need to update the breath
- * He is dead !
- */
- if (playersao->isDead()) {
- verbosestream << "TOSERVER_BREATH: " << player->getName()
- << " is dead. Ignoring packet";
- return;
- }
-
- playersao->setBreath(breath);
- SendPlayerBreath(pkt->getPeerId());
-}
-
void Server::handleCommand_Password(NetworkPacket* pkt)
{
if (pkt->getSize() != PASSWORD_SIZE * 2)
diff --git a/src/remoteplayer.cpp b/src/remoteplayer.cpp
index 67ab89113..18bfa1030 100644
--- a/src/remoteplayer.cpp
+++ b/src/remoteplayer.cpp
@@ -148,7 +148,7 @@ void RemotePlayer::deSerialize(std::istream &is, const std::string &playername,
} catch (SettingNotFoundException &e) {}
try {
- sao->setBreath(args.getS32("breath"));
+ sao->setBreath(args.getS32("breath"), false);
} catch (SettingNotFoundException &e) {}
}
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index 2a8b8a64e..cfdceb28e 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -1152,13 +1152,8 @@ int ObjectRef::l_set_breath(lua_State *L)
PlayerSAO* co = getplayersao(ref);
if (co == NULL) return 0;
u16 breath = luaL_checknumber(L, 2);
- // Do it
co->setBreath(breath);
- // If the object is a player sent the breath to client
- if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
- getServer(L)->SendPlayerBreath(((PlayerSAO*)co)->getPeerID());
-
return 0;
}
diff --git a/src/server.cpp b/src/server.cpp
index fa7a838d4..60dbef0d2 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1076,8 +1076,7 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
}
m_clients.unlock();
- RemotePlayer *player =
- static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str()));
+ RemotePlayer *player = m_env->getPlayer(playername.c_str());
// If failed, cancel
if ((playersao == NULL) || (player == NULL)) {
@@ -1113,7 +1112,7 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
SendPlayerHPOrDie(playersao);
// Send Breath
- SendPlayerBreath(peer_id);
+ SendPlayerBreath(playersao);
// Show death screen if necessary
if (playersao->isDead())
@@ -1857,14 +1856,13 @@ void Server::SendPlayerHP(u16 peer_id)
playersao->m_messages_out.push(aom);
}
-void Server::SendPlayerBreath(u16 peer_id)
+void Server::SendPlayerBreath(PlayerSAO *sao)
{
DSTACK(FUNCTION_NAME);
- PlayerSAO *playersao = getPlayerSAO(peer_id);
- assert(playersao);
+ assert(sao);
- m_script->player_event(playersao, "breath_changed");
- SendBreath(peer_id, playersao->getBreath());
+ m_script->player_event(sao, "breath_changed");
+ SendBreath(sao->getPeerID(), sao->getBreath());
}
void Server::SendMovePlayer(u16 peer_id)
@@ -2565,7 +2563,6 @@ void Server::RespawnPlayer(u16 peer_id)
}
SendPlayerHP(peer_id);
- SendPlayerBreath(peer_id);
}
diff --git a/src/server.h b/src/server.h
index cab7e2445..f0df0f9ec 100644
--- a/src/server.h
+++ b/src/server.h
@@ -180,7 +180,6 @@ public:
void handleCommand_InventoryAction(NetworkPacket* pkt);
void handleCommand_ChatMessage(NetworkPacket* pkt);
void handleCommand_Damage(NetworkPacket* pkt);
- void handleCommand_Breath(NetworkPacket* pkt);
void handleCommand_Password(NetworkPacket* pkt);
void handleCommand_PlayerItem(NetworkPacket* pkt);
void handleCommand_Respawn(NetworkPacket* pkt);
@@ -358,7 +357,7 @@ public:
void printToConsoleOnly(const std::string &text);
void SendPlayerHPOrDie(PlayerSAO *player);
- void SendPlayerBreath(u16 peer_id);
+ void SendPlayerBreath(PlayerSAO *sao);
void SendInventory(PlayerSAO* playerSAO);
void SendMovePlayer(u16 peer_id);
diff --git a/src/unittest/test_player.cpp b/src/unittest/test_player.cpp
index 85fbc8b2d..655ee08fd 100644
--- a/src/unittest/test_player.cpp
+++ b/src/unittest/test_player.cpp
@@ -49,7 +49,7 @@ void TestPlayer::testSave(IGameDef *gamedef)
PlayerSAO sao(NULL, 1, false);
sao.initialize(&rplayer, std::set<std::string>());
rplayer.setPlayerSAO(&sao);
- sao.setBreath(10);
+ sao.setBreath(10, false);
sao.setHPRaw(8);
sao.setYaw(0.1f);
sao.setPitch(0.6f);
@@ -64,7 +64,7 @@ void TestPlayer::testLoad(IGameDef *gamedef)
PlayerSAO sao(NULL, 1, false);
sao.initialize(&rplayer, std::set<std::string>());
rplayer.setPlayerSAO(&sao);
- sao.setBreath(10);
+ sao.setBreath(10, false);
sao.setHPRaw(8);
sao.setYaw(0.1f);
sao.setPitch(0.6f);