Skip to content

Commit dfc8198

Browse files
authoredMar 28, 2018
Add reasons to on_dieplayer and on_hpchange
1 parent 2323842 commit dfc8198

File tree

14 files changed

+219
-52
lines changed

14 files changed

+219
-52
lines changed
 

Diff for: ‎builtin/game/register.lua

+3-3
Original file line numberDiff line numberDiff line change
@@ -529,11 +529,11 @@ end
529529

530530
core.registered_on_player_hpchanges = { modifiers = { }, loggers = { } }
531531

532-
function core.registered_on_player_hpchange(player, hp_change)
532+
function core.registered_on_player_hpchange(player, hp_change, reason)
533533
local last = false
534534
for i = #core.registered_on_player_hpchanges.modifiers, 1, -1 do
535535
local func = core.registered_on_player_hpchanges.modifiers[i]
536-
hp_change, last = func(player, hp_change)
536+
hp_change, last = func(player, hp_change, reason)
537537
if type(hp_change) ~= "number" then
538538
local debuginfo = debug.getinfo(func)
539539
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)
544544
end
545545
end
546546
for i, func in ipairs(core.registered_on_player_hpchanges.loggers) do
547-
func(player, hp_change)
547+
func(player, hp_change, reason)
548548
end
549549
return hp_change
550550
end

Diff for: ‎doc/lua_api.txt

+21-9
Original file line numberDiff line numberDiff line change
@@ -1136,7 +1136,7 @@ previous.
11361136

11371137
This combination results in noise varying very roughly between -2.0 and 2.0 and
11381138
with an average value of 0.0, so `scale` and `offset` are then used to multiply
1139-
and offset the noise variation.
1139+
and offset the noise variation.
11401140

11411141
The final perlin noise variation is created as follows:
11421142

@@ -2779,8 +2779,6 @@ Call these functions only at load time!
27792779
is a bit faster than usually.
27802780
* `minetest.register_on_newplayer(func(ObjectRef))`
27812781
* Called after a new player has been created
2782-
* `minetest.register_on_dieplayer(func(ObjectRef))`
2783-
* Called when a player dies
27842782
* `minetest.register_on_punchplayer(func(player, hitter, time_from_last_punch, tool_capabilities, dir, damage))`
27852783
* Called when a player is punched
27862784
* `player` - ObjectRef - Player that was punched
@@ -2792,15 +2790,28 @@ Call these functions only at load time!
27922790
the puncher to the punched.
27932791
* `damage` - number that represents the damage calculated by the engine
27942792
* should return `true` to prevent the default damage mechanism
2795-
* `minetest.register_on_player_hpchange(func(player, hp_change), modifier)`
2793+
* `minetest.register_on_player_hpchange(func(player, hp_change, reason), modifier)`
27962794
* Called when the player gets damaged or healed
27972795
* `player`: ObjectRef of the player
27982796
* `hp_change`: the amount of change. Negative when it is damage.
2797+
* `reason`: a PlayerHPChangeReason table.
2798+
* The `type` field will have one of the following values:
2799+
* `set_hp` - A mod or the engine called `set_hp` without
2800+
giving a type - use this for custom damage types.
2801+
* `punch` - Was punched. `reason.object` will hold the puncher, or nil if none.
2802+
* `fall`
2803+
* `node_damage` - damage_per_second from a neighbouring node.
2804+
* `drown`
2805+
* `respawn`
2806+
* Any of the above types may have additional fields from mods.
2807+
* `reason.from` will be `mod` or `engine`.
27992808
* `modifier`: when true, the function should return the actual `hp_change`.
2800-
Note: modifiers only get a temporary hp_change that can be modified by
2801-
later modifiers. modifiers can return true as a second argument to stop
2802-
the execution of further functions. Non-modifiers receive the final hp
2803-
change calculated by the modifiers.
2809+
Note: modifiers only get a temporary hp_change that can be modified by later modifiers.
2810+
modifiers can return true as a second argument to stop the execution of further functions.
2811+
Non-modifiers receive the final hp change calculated by the modifiers.
2812+
* `minetest.register_on_dieplayer(func(ObjectRef, reason))`
2813+
* Called when a player dies
2814+
* `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange
28042815
* `minetest.register_on_respawnplayer(func(ObjectRef))`
28052816
* Called when player is to be respawned
28062817
* Called _before_ repositioning of player occurs
@@ -3939,7 +3950,8 @@ This is basically a reference to a C++ `ServerActiveObject`
39393950
* `direction`: can be `nil`
39403951
* `right_click(clicker)`; `clicker` is another `ObjectRef`
39413952
* `get_hp()`: returns number of hitpoints (2 * number of hearts)
3942-
* `set_hp(hp)`: set number of hitpoints (2 * number of hearts)
3953+
* `set_hp(hp, reason)`: set number of hitpoints (2 * number of hearts).
3954+
* See reason in register_on_player_hpchange
39433955
* `get_inventory()`: returns an `InvRef`
39443956
* `get_wield_list()`: returns the name of the inventory list the wielded item
39453957
is in.

Diff for: ‎games/minimal/mods/test/init.lua

+29
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,32 @@ assert(pseudo:next() == 22290)
99
assert(pseudo:next() == 13854)
1010

1111

12+
--
13+
-- HP Change Reasons
14+
--
15+
local expect = nil
16+
minetest.register_on_joinplayer(function(player)
17+
expect = { type = "set_hp", from = "mod" }
18+
player:set_hp(3)
19+
assert(expect == nil)
20+
21+
expect = { a = 234, type = "set_hp", from = "mod" }
22+
player:set_hp(10, { a= 234 })
23+
assert(expect == nil)
24+
25+
expect = { df = 3458973454, type = "fall", from = "mod" }
26+
player:set_hp(10, { type = "fall", df = 3458973454 })
27+
assert(expect == nil)
28+
end)
29+
30+
minetest.register_on_player_hpchange(function(player, hp, reason)
31+
for key, value in pairs(reason) do
32+
assert(expect[key] == value)
33+
end
34+
35+
for key, value in pairs(expect) do
36+
assert(reason[key] == value)
37+
end
38+
39+
expect = nil
40+
end)

Diff for: ‎src/content_sao.cpp

+10-7
Original file line numberDiff line numberDiff line change
@@ -921,8 +921,9 @@ void PlayerSAO::step(float dtime, bool send_recommended)
921921

922922
// No more breath, damage player
923923
if (m_breath == 0) {
924-
setHP(m_hp - c.drowning);
925-
m_env->getGameDef()->SendPlayerHPOrDie(this);
924+
PlayerHPChangeReason reason(PlayerHPChangeReason::DROWNING);
925+
setHP(m_hp - c.drowning, reason);
926+
m_env->getGameDef()->SendPlayerHPOrDie(this, reason);
926927
}
927928
}
928929
}
@@ -961,8 +962,9 @@ void PlayerSAO::step(float dtime, bool send_recommended)
961962

962963
if (damage_per_second != 0 && m_hp > 0) {
963964
s16 newhp = ((s32) damage_per_second > m_hp ? 0 : m_hp - damage_per_second);
964-
setHP(newhp);
965-
m_env->getGameDef()->SendPlayerHPOrDie(this);
965+
PlayerHPChangeReason reason(PlayerHPChangeReason::NODE_DAMAGE);
966+
setHP(newhp, reason);
967+
m_env->getGameDef()->SendPlayerHPOrDie(this, reason);
966968
}
967969
}
968970

@@ -1208,7 +1210,8 @@ int PlayerSAO::punch(v3f dir,
12081210
hitparams.hp);
12091211

12101212
if (!damage_handled) {
1211-
setHP(getHP() - hitparams.hp);
1213+
setHP(getHP() - hitparams.hp,
1214+
PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher));
12121215
} else { // override client prediction
12131216
if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
12141217
std::string str = gob_cmd_punched(0, getHP());
@@ -1238,11 +1241,11 @@ s16 PlayerSAO::readDamage()
12381241
return damage;
12391242
}
12401243

1241-
void PlayerSAO::setHP(s16 hp)
1244+
void PlayerSAO::setHP(s16 hp, const PlayerHPChangeReason &reason)
12421245
{
12431246
s16 oldhp = m_hp;
12441247

1245-
s16 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - oldhp);
1248+
s16 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - oldhp, reason);
12461249
if (hp_change == 0)
12471250
return;
12481251
hp = oldhp + hp_change;

Diff for: ‎src/content_sao.h

+62-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ class PlayerSAO : public UnitSAO
245245
ServerActiveObject *puncher,
246246
float time_from_last_punch);
247247
void rightClick(ServerActiveObject *clicker) {}
248-
void setHP(s16 hp);
248+
void setHP(s16 hp, const PlayerHPChangeReason &reason);
249249
void setHPRaw(s16 hp) { m_hp = hp; }
250250
s16 readDamage();
251251
u16 getBreath() const { return m_breath; }
@@ -417,3 +417,64 @@ class PlayerSAO : public UnitSAO
417417
bool m_physics_override_new_move = true;
418418
bool m_physics_override_sent = false;
419419
};
420+
421+
422+
struct PlayerHPChangeReason {
423+
enum Type : u8 {
424+
SET_HP,
425+
PLAYER_PUNCH,
426+
FALL,
427+
NODE_DAMAGE,
428+
DROWNING,
429+
RESPAWN
430+
};
431+
432+
Type type = SET_HP;
433+
ServerActiveObject *object;
434+
bool from_mod = false;
435+
int lua_reference = -1;
436+
437+
bool setTypeFromString(const std::string &typestr)
438+
{
439+
if (typestr == "set_hp")
440+
type = SET_HP;
441+
else if (typestr == "punch")
442+
type = PLAYER_PUNCH;
443+
else if (typestr == "fall")
444+
type = FALL;
445+
else if (typestr == "node_damage")
446+
type = NODE_DAMAGE;
447+
else if (typestr == "drown")
448+
type = DROWNING;
449+
else if (typestr == "respawn")
450+
type = RESPAWN;
451+
else
452+
return false;
453+
454+
return true;
455+
}
456+
457+
std::string getTypeAsString() const
458+
{
459+
switch (type) {
460+
case PlayerHPChangeReason::SET_HP:
461+
return "set_hp";
462+
case PlayerHPChangeReason::PLAYER_PUNCH:
463+
return "punch";
464+
case PlayerHPChangeReason::FALL:
465+
return "fall";
466+
case PlayerHPChangeReason::NODE_DAMAGE:
467+
return "node_damage";
468+
case PlayerHPChangeReason::DROWNING:
469+
return "drown";
470+
case PlayerHPChangeReason::RESPAWN:
471+
return "respawn";
472+
default:
473+
return "?";
474+
}
475+
}
476+
477+
PlayerHPChangeReason(Type type, ServerActiveObject *object=NULL):
478+
type(type), object(object)
479+
{}
480+
};

Diff for: ‎src/network/serverpackethandler.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -812,8 +812,9 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
812812
<< (int)damage << " hp at " << PP(playersao->getBasePosition() / BS)
813813
<< std::endl;
814814

815-
playersao->setHP(playersao->getHP() - damage);
816-
SendPlayerHPOrDie(playersao);
815+
PlayerHPChangeReason reason(PlayerHPChangeReason::FALL);
816+
playersao->setHP(playersao->getHP() - damage, reason);
817+
SendPlayerHPOrDie(playersao, reason);
817818
}
818819
}
819820

@@ -1175,12 +1176,14 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
11751176
// If the object is a player and its HP changed
11761177
if (src_original_hp != pointed_object->getHP() &&
11771178
pointed_object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
1178-
SendPlayerHPOrDie((PlayerSAO *)pointed_object);
1179+
SendPlayerHPOrDie((PlayerSAO *)pointed_object,
1180+
PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, playersao));
11791181
}
11801182

11811183
// If the puncher is a player and its HP changed
11821184
if (dst_origin_hp != playersao->getHP())
1183-
SendPlayerHPOrDie(playersao);
1185+
SendPlayerHPOrDie(playersao,
1186+
PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, pointed_object));
11841187
}
11851188

11861189
} // action == 0

Diff for: ‎src/script/cpp_api/s_base.cpp

+22-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ extern "C" {
4343
#include <cstdio>
4444
#include <cstdarg>
4545
#include "script/common/c_content.h"
46+
#include "content_sao.h"
4647
#include <sstream>
4748

4849

@@ -151,7 +152,7 @@ void ScriptApiBase::clientOpenLibs(lua_State *L)
151152
{ LUA_JITLIBNAME, luaopen_jit },
152153
#endif
153154
};
154-
155+
155156
for (const std::pair<std::string, lua_CFunction> &lib : m_libs) {
156157
lua_pushcfunction(L, lib.second);
157158
lua_pushstring(L, lib.first.c_str());
@@ -381,6 +382,26 @@ void ScriptApiBase::objectrefGetOrCreate(lua_State *L,
381382
}
382383
}
383384

385+
void ScriptApiBase::pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason &reason)
386+
{
387+
if (reason.lua_reference >= 0) {
388+
lua_rawgeti(L, LUA_REGISTRYINDEX, reason.lua_reference);
389+
luaL_unref(L, LUA_REGISTRYINDEX, reason.lua_reference);
390+
} else
391+
lua_newtable(L);
392+
393+
lua_pushstring(L, reason.getTypeAsString().c_str());
394+
lua_setfield(L, -2, "type");
395+
396+
lua_pushstring(L, reason.from_mod ? "mod" : "engine");
397+
lua_setfield(L, -2, "from");
398+
399+
if (reason.object) {
400+
objectrefGetOrCreate(L, reason.object);
401+
lua_setfield(L, -2, "object");
402+
}
403+
}
404+
384405
Server* ScriptApiBase::getServer()
385406
{
386407
return dynamic_cast<Server *>(m_gamedef);

Diff for: ‎src/script/cpp_api/s_base.h

+3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class IGameDef;
7272
class Environment;
7373
class GUIEngine;
7474
class ServerActiveObject;
75+
class PlayerHPChangeReason;
7576

7677
class ScriptApiBase {
7778
public:
@@ -139,6 +140,8 @@ class ScriptApiBase {
139140

140141
void objectrefGetOrCreate(lua_State *L, ServerActiveObject *cobj);
141142

143+
void pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason& reason);
144+
142145
std::recursive_mutex m_luastackmutex;
143146
std::string m_last_run_mod;
144147
bool m_secure = false;

Diff for: ‎src/script/cpp_api/s_player.cpp

+14-6
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,20 @@ void ScriptApiPlayer::on_newplayer(ServerActiveObject *player)
3636
runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
3737
}
3838

39-
void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player)
39+
void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player, const PlayerHPChangeReason &reason)
4040
{
4141
SCRIPTAPI_PRECHECKHEADER
4242

43-
// Get core.registered_on_dieplayers
43+
// Get callback table
4444
lua_getglobal(L, "core");
4545
lua_getfield(L, -1, "registered_on_dieplayers");
46-
// Call callbacks
46+
47+
// Push arguments
4748
objectrefGetOrCreate(L, player);
48-
runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
49+
pushPlayerHPChangeReason(L, reason);
50+
51+
// Run callbacks
52+
runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
4953
}
5054

5155
bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player,
@@ -71,7 +75,7 @@ bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player,
7175
}
7276

7377
s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player,
74-
s16 hp_change)
78+
s16 hp_change, const PlayerHPChangeReason &reason)
7579
{
7680
SCRIPTAPI_PRECHECKHEADER
7781

@@ -82,9 +86,13 @@ s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player,
8286
lua_getfield(L, -1, "registered_on_player_hpchange");
8387
lua_remove(L, -2);
8488

89+
// Push arguments
8590
objectrefGetOrCreate(L, player);
8691
lua_pushnumber(L, hp_change);
87-
PCALL_RES(lua_pcall(L, 2, 1, error_handler));
92+
pushPlayerHPChangeReason(L, reason);
93+
94+
// Call callbacks
95+
PCALL_RES(lua_pcall(L, 3, 1, error_handler));
8896
hp_change = lua_tointeger(L, -1);
8997
lua_pop(L, 2); // Pop result and error handler
9098
return hp_change;

0 commit comments

Comments
 (0)
Please sign in to comment.