summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Ward <rw@rubenwardy.com>2018-03-28 16:05:18 +0100
committerGitHub <noreply@github.com>2018-03-28 16:05:18 +0100
commitdfc81983491417c5cd1c99d7db05e421c409379d (patch)
tree7b0457f0ff86f038cfad1a095d3ab0b6c44f2def /src
parent2323842dd3dd336b087ca3cf9756e0680b3a1244 (diff)
downloadminetest-dfc81983491417c5cd1c99d7db05e421c409379d.tar.gz
minetest-dfc81983491417c5cd1c99d7db05e421c409379d.tar.bz2
minetest-dfc81983491417c5cd1c99d7db05e421c409379d.zip
Add reasons to on_dieplayer and on_hpchange
Diffstat (limited to 'src')
-rw-r--r--src/content_sao.cpp17
-rw-r--r--src/content_sao.h63
-rw-r--r--src/network/serverpackethandler.cpp11
-rw-r--r--src/script/cpp_api/s_base.cpp23
-rw-r--r--src/script/cpp_api/s_base.h3
-rw-r--r--src/script/cpp_api/s_player.cpp20
-rw-r--r--src/script/cpp_api/s_player.h6
-rw-r--r--src/script/lua_api/l_object.cpp39
-rw-r--r--src/server.cpp16
-rw-r--r--src/server.h5
-rw-r--r--src/serverobject.h3
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; }