diff options
Diffstat (limited to 'src/script')
-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 |
5 files changed, 73 insertions, 18 deletions
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; |