Add reasons to on_dieplayer and on_hpchange
authorAndrew Ward <rw@rubenwardy.com>
Wed, 28 Mar 2018 15:05:18 +0000 (16:05 +0100)
committerGitHub <noreply@github.com>
Wed, 28 Mar 2018 15:05:18 +0000 (16:05 +0100)
14 files changed:
builtin/game/register.lua
doc/lua_api.txt
games/minimal/mods/test/init.lua
src/content_sao.cpp
src/content_sao.h
src/network/serverpackethandler.cpp
src/script/cpp_api/s_base.cpp
src/script/cpp_api/s_base.h
src/script/cpp_api/s_player.cpp
src/script/cpp_api/s_player.h
src/script/lua_api/l_object.cpp
src/server.cpp
src/server.h
src/serverobject.h

index 5ce8caf3a7fd0f83506f91db5be1901a308bab1d..7b2b149e3fa58f18e7430c8b4d9c3f01898ad0f1 100644 (file)
@@ -529,11 +529,11 @@ end
 
 core.registered_on_player_hpchanges = { modifiers = { }, loggers = { } }
 
-function core.registered_on_player_hpchange(player, hp_change)
+function core.registered_on_player_hpchange(player, hp_change, reason)
        local last = false
        for i = #core.registered_on_player_hpchanges.modifiers, 1, -1 do
                local func = core.registered_on_player_hpchanges.modifiers[i]
-               hp_change, last = func(player, hp_change)
+               hp_change, last = func(player, hp_change, reason)
                if type(hp_change) ~= "number" then
                        local debuginfo = debug.getinfo(func)
                        error("The register_on_hp_changes function has to return a number at " ..
@@ -544,7 +544,7 @@ function core.registered_on_player_hpchange(player, hp_change)
                end
        end
        for i, func in ipairs(core.registered_on_player_hpchanges.loggers) do
-               func(player, hp_change)
+               func(player, hp_change, reason)
        end
        return hp_change
 end
index 730e6de9a8f90792de5d592d01d8093e610ac816..413990f61d2e16ef5af37677f3994df178205183 100644 (file)
@@ -1136,7 +1136,7 @@ previous.
 
 This combination results in noise varying very roughly between -2.0 and 2.0 and
 with an average value of 0.0, so `scale` and `offset` are then used to multiply
-and offset the noise variation. 
+and offset the noise variation.
 
 The final perlin noise variation is created as follows:
 
@@ -2779,8 +2779,6 @@ Call these functions only at load time!
       is a bit faster than usually.
 * `minetest.register_on_newplayer(func(ObjectRef))`
     * Called after a new player has been created
-* `minetest.register_on_dieplayer(func(ObjectRef))`
-    * Called when a player dies
 * `minetest.register_on_punchplayer(func(player, hitter, time_from_last_punch, tool_capabilities, dir, damage))`
     * Called when a player is punched
     * `player` - ObjectRef - Player that was punched
@@ -2792,15 +2790,28 @@ Call these functions only at load time!
       the puncher to the punched.
     * `damage` - number that represents the damage calculated by the engine
     * should return `true` to prevent the default damage mechanism
-* `minetest.register_on_player_hpchange(func(player, hp_change), modifier)`
+* `minetest.register_on_player_hpchange(func(player, hp_change, reason), modifier)`
     * Called when the player gets damaged or healed
     * `player`: ObjectRef of the player
     * `hp_change`: the amount of change. Negative when it is damage.
+    * `reason`: a PlayerHPChangeReason table.
+        * The `type` field will have one of the following values:
+            * `set_hp` - A mod or the engine called `set_hp` without
+                         giving a type - use this for custom damage types.
+            * `punch` - Was punched. `reason.object` will hold the puncher, or nil if none.
+            * `fall`
+            * `node_damage` - damage_per_second from a neighbouring node.
+            * `drown`
+            * `respawn`
+        * Any of the above types may have additional fields from mods.
+        * `reason.from` will be `mod` or `engine`.
     * `modifier`: when true, the function should return the actual `hp_change`.
-      Note: modifiers only get a temporary hp_change that can be modified by
-      later modifiers. modifiers can return true as a second argument to stop
-      the execution of further functions. Non-modifiers receive the final hp
-      change calculated by the modifiers.
+       Note: modifiers only get a temporary hp_change that can be modified by later modifiers.
+       modifiers can return true as a second argument to stop the execution of further functions.
+       Non-modifiers receive the final hp change calculated by the modifiers.
+* `minetest.register_on_dieplayer(func(ObjectRef, reason))`
+    * Called when a player dies
+    * `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange
 * `minetest.register_on_respawnplayer(func(ObjectRef))`
     * Called when player is to be respawned
     * Called _before_ repositioning of player occurs
@@ -3939,7 +3950,8 @@ This is basically a reference to a C++ `ServerActiveObject`
     * `direction`: can be `nil`
 * `right_click(clicker)`; `clicker` is another `ObjectRef`
 * `get_hp()`: returns number of hitpoints (2 * number of hearts)
-* `set_hp(hp)`: set number of hitpoints (2 * number of hearts)
+* `set_hp(hp, reason)`: set number of hitpoints (2 * number of hearts).
+    * See reason in register_on_player_hpchange
 * `get_inventory()`: returns an `InvRef`
 * `get_wield_list()`: returns the name of the inventory list the wielded item
    is in.
index 051b47906eaa387262e8ce52c2a1251646eda5b6..b08ddfa94e00063accded14801cb56ebfd4727b7 100644 (file)
@@ -9,3 +9,32 @@ assert(pseudo:next() == 22290)
 assert(pseudo:next() == 13854)
 
 
+--
+-- HP Change Reasons
+--
+local expect = nil
+minetest.register_on_joinplayer(function(player)
+       expect = { type = "set_hp", from = "mod" }
+       player:set_hp(3)
+       assert(expect == nil)
+
+       expect = { a = 234, type = "set_hp", from = "mod" }
+       player:set_hp(10, { a= 234 })
+       assert(expect == nil)
+
+       expect = { df = 3458973454, type = "fall", from = "mod" }
+       player:set_hp(10, { type = "fall", df = 3458973454 })
+       assert(expect == nil)
+end)
+
+minetest.register_on_player_hpchange(function(player, hp, reason)
+       for key, value in pairs(reason) do
+               assert(expect[key] == value)
+       end
+
+       for key, value in pairs(expect) do
+               assert(reason[key] == value)
+       end
+
+       expect = nil
+end)
index 816f47b723b8c7b9439180748c67b0ee0da48000..f2cd0ff11e0a6f19b9929017edd808008e194fed 100644 (file)
@@ -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;
index 683a2fb5f6236176339a5982a1919c9d982b5a1b..10630014c6f8499de794b2e3ad9d269953e0c5f1 100644 (file)
@@ -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)
+       {}
+};
index 76a2dc3c289ce924f2abc955eea34b0b035cc741..2d810836ba5785a40b67aebf5e858e06188b4ec7 100644 (file)
@@ -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
index f451156bdac1e1aaafef11dcdda2d0b785c5a1fd..571bac611b06f945857b37e6066c72685ad72094 100644 (file)
@@ -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);
index 4837f4f993f9366bacc068619b3c870d3c2cf27d..dc7b581e39f6555a3f21c8e9a472f99465c74b8c 100644 (file)
@@ -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;
index 578298e24817c6ed5f9e8f7ce8238bdd8b06ad0e..cc2b96d5e6e6e1f83bdecbcbdd205051697184f6 100644 (file)
@@ -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;
index 562805695e7e2e17684d0f4cb80e43e995ce69f0..59e1505ae6a3dcf1ecc4da28abe234b59a9dca51 100644 (file)
@@ -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);
index 5fc6f9d3c89823e7263d2171dd911e936d3a4944..e4c478df702b1787c98c7daceed02090b9d9ecdc 100644 (file)
@@ -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;
index 8be223f746715a07a96d9a1781aadefd4b7f8375..ca2743ad2a556bbe1637c20501625ea701a5ea6d 100644 (file)
@@ -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);
index 0820753e099abc12dfee6ac0846536fbfb1a0fc3..2d813630c735febc67d16c2fed0450329e6348a4 100644 (file)
@@ -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);
index 304281093cc20302b4cd414803508fd5f6763746..77b70146426fd9f701d46a94b11091cfd9212c4a 100644 (file)
@@ -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; }