diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/content_sao.cpp | 17 | ||||
-rw-r--r-- | src/content_sao.h | 63 | ||||
-rw-r--r-- | src/network/serverpackethandler.cpp | 11 | ||||
-rw-r--r-- | src/script/cpp_api/s_base.cpp | 23 | ||||
-rw-r--r-- | src/script/cpp_api/s_base.h | 3 | ||||
-rw-r--r-- | src/script/cpp_api/s_player.cpp | 20 | ||||
-rw-r--r-- | src/script/cpp_api/s_player.h | 6 | ||||
-rw-r--r-- | src/script/lua_api/l_object.cpp | 39 | ||||
-rw-r--r-- | src/server.cpp | 16 | ||||
-rw-r--r-- | src/server.h | 5 | ||||
-rw-r--r-- | src/serverobject.h | 3 |
11 files changed, 166 insertions, 40 deletions
diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 816f47b72..f2cd0ff11 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -921,8 +921,9 @@ void PlayerSAO::step(float dtime, bool send_recommended) // No more breath, damage player if (m_breath == 0) { - setHP(m_hp - c.drowning); - m_env->getGameDef()->SendPlayerHPOrDie(this); + PlayerHPChangeReason reason(PlayerHPChangeReason::DROWNING); + setHP(m_hp - c.drowning, reason); + m_env->getGameDef()->SendPlayerHPOrDie(this, reason); } } } @@ -961,8 +962,9 @@ void PlayerSAO::step(float dtime, bool send_recommended) if (damage_per_second != 0 && m_hp > 0) { s16 newhp = ((s32) damage_per_second > m_hp ? 0 : m_hp - damage_per_second); - setHP(newhp); - m_env->getGameDef()->SendPlayerHPOrDie(this); + PlayerHPChangeReason reason(PlayerHPChangeReason::NODE_DAMAGE); + setHP(newhp, reason); + m_env->getGameDef()->SendPlayerHPOrDie(this, reason); } } @@ -1208,7 +1210,8 @@ int PlayerSAO::punch(v3f dir, hitparams.hp); if (!damage_handled) { - setHP(getHP() - hitparams.hp); + setHP(getHP() - hitparams.hp, + PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher)); } else { // override client prediction if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) { std::string str = gob_cmd_punched(0, getHP()); @@ -1238,11 +1241,11 @@ s16 PlayerSAO::readDamage() return damage; } -void PlayerSAO::setHP(s16 hp) +void PlayerSAO::setHP(s16 hp, const PlayerHPChangeReason &reason) { s16 oldhp = m_hp; - s16 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - oldhp); + s16 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - oldhp, reason); if (hp_change == 0) return; hp = oldhp + hp_change; diff --git a/src/content_sao.h b/src/content_sao.h index 683a2fb5f..10630014c 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -245,7 +245,7 @@ public: ServerActiveObject *puncher, float time_from_last_punch); void rightClick(ServerActiveObject *clicker) {} - void setHP(s16 hp); + void setHP(s16 hp, const PlayerHPChangeReason &reason); void setHPRaw(s16 hp) { m_hp = hp; } s16 readDamage(); u16 getBreath() const { return m_breath; } @@ -417,3 +417,64 @@ public: bool m_physics_override_new_move = true; bool m_physics_override_sent = false; }; + + +struct PlayerHPChangeReason { + enum Type : u8 { + SET_HP, + PLAYER_PUNCH, + FALL, + NODE_DAMAGE, + DROWNING, + RESPAWN + }; + + Type type = SET_HP; + ServerActiveObject *object; + bool from_mod = false; + int lua_reference = -1; + + bool setTypeFromString(const std::string &typestr) + { + if (typestr == "set_hp") + type = SET_HP; + else if (typestr == "punch") + type = PLAYER_PUNCH; + else if (typestr == "fall") + type = FALL; + else if (typestr == "node_damage") + type = NODE_DAMAGE; + else if (typestr == "drown") + type = DROWNING; + else if (typestr == "respawn") + type = RESPAWN; + else + return false; + + return true; + } + + std::string getTypeAsString() const + { + switch (type) { + case PlayerHPChangeReason::SET_HP: + return "set_hp"; + case PlayerHPChangeReason::PLAYER_PUNCH: + return "punch"; + case PlayerHPChangeReason::FALL: + return "fall"; + case PlayerHPChangeReason::NODE_DAMAGE: + return "node_damage"; + case PlayerHPChangeReason::DROWNING: + return "drown"; + case PlayerHPChangeReason::RESPAWN: + return "respawn"; + default: + return "?"; + } + } + + PlayerHPChangeReason(Type type, ServerActiveObject *object=NULL): + type(type), object(object) + {} +}; diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 76a2dc3c2..2d810836b 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -812,8 +812,9 @@ void Server::handleCommand_Damage(NetworkPacket* pkt) << (int)damage << " hp at " << PP(playersao->getBasePosition() / BS) << std::endl; - playersao->setHP(playersao->getHP() - damage); - SendPlayerHPOrDie(playersao); + PlayerHPChangeReason reason(PlayerHPChangeReason::FALL); + playersao->setHP(playersao->getHP() - damage, reason); + SendPlayerHPOrDie(playersao, reason); } } @@ -1175,12 +1176,14 @@ void Server::handleCommand_Interact(NetworkPacket* pkt) // 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); + SendPlayerHPOrDie((PlayerSAO *)pointed_object, + PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, playersao)); } // If the puncher is a player and its HP changed if (dst_origin_hp != playersao->getHP()) - SendPlayerHPOrDie(playersao); + SendPlayerHPOrDie(playersao, + PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, pointed_object)); } } // action == 0 diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index f451156bd..571bac611 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -43,6 +43,7 @@ extern "C" { #include <cstdio> #include <cstdarg> #include "script/common/c_content.h" +#include "content_sao.h" #include <sstream> @@ -151,7 +152,7 @@ void ScriptApiBase::clientOpenLibs(lua_State *L) { LUA_JITLIBNAME, luaopen_jit }, #endif }; - + for (const std::pair<std::string, lua_CFunction> &lib : m_libs) { lua_pushcfunction(L, lib.second); lua_pushstring(L, lib.first.c_str()); @@ -381,6 +382,26 @@ void ScriptApiBase::objectrefGetOrCreate(lua_State *L, } } +void ScriptApiBase::pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason &reason) +{ + if (reason.lua_reference >= 0) { + lua_rawgeti(L, LUA_REGISTRYINDEX, reason.lua_reference); + luaL_unref(L, LUA_REGISTRYINDEX, reason.lua_reference); + } else + lua_newtable(L); + + lua_pushstring(L, reason.getTypeAsString().c_str()); + lua_setfield(L, -2, "type"); + + lua_pushstring(L, reason.from_mod ? "mod" : "engine"); + lua_setfield(L, -2, "from"); + + if (reason.object) { + objectrefGetOrCreate(L, reason.object); + lua_setfield(L, -2, "object"); + } +} + Server* ScriptApiBase::getServer() { return dynamic_cast<Server *>(m_gamedef); diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index 4837f4f99..dc7b581e3 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -72,6 +72,7 @@ class IGameDef; class Environment; class GUIEngine; class ServerActiveObject; +class PlayerHPChangeReason; class ScriptApiBase { public: @@ -139,6 +140,8 @@ protected: void objectrefGetOrCreate(lua_State *L, ServerActiveObject *cobj); + void pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason& reason); + std::recursive_mutex m_luastackmutex; std::string m_last_run_mod; bool m_secure = false; diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp index 578298e24..cc2b96d5e 100644 --- a/src/script/cpp_api/s_player.cpp +++ b/src/script/cpp_api/s_player.cpp @@ -36,16 +36,20 @@ void ScriptApiPlayer::on_newplayer(ServerActiveObject *player) runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); } -void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player) +void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player, const PlayerHPChangeReason &reason) { SCRIPTAPI_PRECHECKHEADER - // Get core.registered_on_dieplayers + // Get callback table lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_dieplayers"); - // Call callbacks + + // Push arguments objectrefGetOrCreate(L, player); - runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); + pushPlayerHPChangeReason(L, reason); + + // Run callbacks + runCallbacks(2, RUN_CALLBACKS_MODE_FIRST); } bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player, @@ -71,7 +75,7 @@ bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player, } s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player, - s16 hp_change) + s16 hp_change, const PlayerHPChangeReason &reason) { SCRIPTAPI_PRECHECKHEADER @@ -82,9 +86,13 @@ s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player, lua_getfield(L, -1, "registered_on_player_hpchange"); lua_remove(L, -2); + // Push arguments objectrefGetOrCreate(L, player); lua_pushnumber(L, hp_change); - PCALL_RES(lua_pcall(L, 2, 1, error_handler)); + pushPlayerHPChangeReason(L, reason); + + // Call callbacks + PCALL_RES(lua_pcall(L, 3, 1, error_handler)); hp_change = lua_tointeger(L, -1); lua_pop(L, 2); // Pop result and error handler return hp_change; diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h index 562805695..59e1505ae 100644 --- a/src/script/cpp_api/s_player.h +++ b/src/script/cpp_api/s_player.h @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" struct ToolCapabilities; +struct PlayerHPChangeReason; class ScriptApiPlayer : virtual public ScriptApiBase { @@ -31,7 +32,7 @@ public: virtual ~ScriptApiPlayer() = default; void on_newplayer(ServerActiveObject *player); - void on_dieplayer(ServerActiveObject *player); + void on_dieplayer(ServerActiveObject *player, const PlayerHPChangeReason &reason); bool on_respawnplayer(ServerActiveObject *player); bool on_prejoinplayer(const std::string &name, const std::string &ip, std::string *reason); @@ -42,7 +43,8 @@ public: bool on_punchplayer(ServerActiveObject *player, ServerActiveObject *hitter, float time_from_last_punch, const ToolCapabilities *toolcap, v3f dir, s16 damage); - s16 on_player_hpchange(ServerActiveObject *player, s16 hp_change); + s16 on_player_hpchange(ServerActiveObject *player, s16 hp_change, + const PlayerHPChangeReason &reason); void on_playerReceiveFields(ServerActiveObject *player, const std::string &formname, const StringMap &fields); void on_auth_failure(const std::string &name, const std::string &ip); diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 5fc6f9d3c..e4c478df7 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -194,13 +194,14 @@ int ObjectRef::l_punch(lua_State *L) // 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); + getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher)); } // 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); + getServer(L)->SendPlayerHPOrDie((PlayerSAO *)puncher, + PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, co)); } return 0; } @@ -226,17 +227,36 @@ int ObjectRef::l_right_click(lua_State *L) int ObjectRef::l_set_hp(lua_State *L) { NO_MAP_LOCK_REQUIRED; + + // Get Object ObjectRef *ref = checkobject(L, 1); luaL_checknumber(L, 2); ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; + if (co == NULL) + return 0; + + // Get HP int hp = lua_tonumber(L, 2); - /*infostream<<"ObjectRef::l_set_hp(): id="<<co->getId() - <<" hp="<<hp<<std::endl;*/ + + // Get Reason + PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP); + reason.from_mod = true; + if (lua_istable(L, 3)) { + lua_pushvalue(L, 3); + + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1) && !reason.setTypeFromString(lua_tostring(L, -1))) { + errorstream << "Bad type given!" << std::endl; + } + lua_pop(L, 1); + + reason.lua_reference = luaL_ref(L, LUA_REGISTRYINDEX); + } + // Do it - co->setHP(hp); + co->setHP(hp, reason); if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER) - getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co); + getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, reason); // Return return 0; @@ -729,9 +749,10 @@ int ObjectRef::l_set_properties(lua_State *L) return 0; read_object_properties(L, 2, prop, getServer(L)->idef()); if (prop->hp_max < co->getHP()) { - co->setHP(prop->hp_max); + PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP); + co->setHP(prop->hp_max, reason); if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER) - getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co); + getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, reason); } co->notifyObjectPropertiesModified(); return 0; diff --git a/src/server.cpp b/src/server.cpp index 8be223f74..ca2743ad2 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1029,7 +1029,8 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id) if (playersao->isDead()) SendDeathscreen(peer_id, false, v3f(0,0,0)); else - SendPlayerHPOrDie(playersao); + SendPlayerHPOrDie(playersao, + PlayerHPChangeReason(PlayerHPChangeReason::SET_HP)); // Send Breath SendPlayerBreath(playersao); @@ -1392,7 +1393,7 @@ void Server::SendMovement(session_t peer_id) Send(&pkt); } -void Server::SendPlayerHPOrDie(PlayerSAO *playersao) +void Server::SendPlayerHPOrDie(PlayerSAO *playersao, const PlayerHPChangeReason &reason) { if (!g_settings->getBool("enable_damage")) return; @@ -1403,7 +1404,7 @@ void Server::SendPlayerHPOrDie(PlayerSAO *playersao) if (is_alive) SendPlayerHP(peer_id); else - DiePlayer(peer_id); + DiePlayer(peer_id, reason); } void Server::SendHP(session_t peer_id, u16 hp) @@ -2493,7 +2494,7 @@ void Server::sendDetachedInventories(session_t peer_id) Something random */ -void Server::DiePlayer(session_t peer_id) +void Server::DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason) { PlayerSAO *playersao = getPlayerSAO(peer_id); // In some rare cases this can be NULL -- if the player is disconnected @@ -2505,10 +2506,10 @@ void Server::DiePlayer(session_t peer_id) << playersao->getPlayer()->getName() << " dies" << std::endl; - playersao->setHP(0); + playersao->setHP(0, reason); // Trigger scripted stuff - m_script->on_dieplayer(playersao); + m_script->on_dieplayer(playersao, reason); SendPlayerHP(peer_id); SendDeathscreen(peer_id, false, v3f(0,0,0)); @@ -2523,7 +2524,8 @@ void Server::RespawnPlayer(session_t peer_id) << playersao->getPlayer()->getName() << " respawns" << std::endl; - playersao->setHP(playersao->accessObjectProperties()->hp_max); + playersao->setHP(playersao->accessObjectProperties()->hp_max, + PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN)); playersao->setBreath(playersao->accessObjectProperties()->breath_max); bool repositioned = m_script->on_respawnplayer(playersao); diff --git a/src/server.h b/src/server.h index 0820753e0..2d813630c 100644 --- a/src/server.h +++ b/src/server.h @@ -53,6 +53,7 @@ class Inventory; class ModChannelMgr; class RemotePlayer; class PlayerSAO; +struct PlayerHPChangeReason; class IRollbackManager; struct RollbackAction; class EmergeManager; @@ -328,7 +329,7 @@ public: void printToConsoleOnly(const std::string &text); - void SendPlayerHPOrDie(PlayerSAO *player); + void SendPlayerHPOrDie(PlayerSAO *player, const PlayerHPChangeReason &reason); void SendPlayerBreath(PlayerSAO *sao); void SendInventory(PlayerSAO* playerSAO); void SendMovePlayer(session_t peer_id); @@ -451,7 +452,7 @@ private: Something random */ - void DiePlayer(session_t peer_id); + void DiePlayer(session_t peer_id, 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/serverobject.h b/src/serverobject.h index 304281093..77b701464 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -46,6 +46,7 @@ class ServerEnvironment; struct ItemStack; struct ToolCapabilities; struct ObjectProperties; +struct PlayerHPChangeReason; class ServerActiveObject : public ActiveObject { @@ -139,7 +140,7 @@ public: { return 0; } virtual void rightClick(ServerActiveObject *clicker) {} - virtual void setHP(s16 hp) + virtual void setHP(s16 hp, const PlayerHPChangeReason &reason) {} virtual s16 getHP() const { return 0; } |