From 6d3057b08ebe712e4d63eff090aabd8f37985101 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 14 Apr 2025 17:55:17 +0200 Subject: [PATCH 1/4] Add `detail` field to PlayerHPChangeReason --- builtin/game/chat.lua | 2 +- builtin/game/item.lua | 2 +- doc/lua_api.md | 45 +++++++++++++++++++++++++++++-------------- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/builtin/game/chat.lua b/builtin/game/chat.lua index 80c9a6e812..277b20fcd5 100644 --- a/builtin/game/chat.lua +++ b/builtin/game/chat.lua @@ -1346,7 +1346,7 @@ local function handle_kill_command(killer, victim) core.log("action", string.format("%s killed %s", killer, victim)) end -- Kill victim - victimref:set_hp(0) + victimref:set_hp(0, {type="set_hp", detail="__builtin:kill_command"}) return true, S("@1 has been killed.", victim) end diff --git a/builtin/game/item.lua b/builtin/game/item.lua index 5dd5312aaa..d3d0529015 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -435,7 +435,7 @@ function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed core.add_item(pos, replace_with_item) end - user:set_hp(user:get_hp() + hp_change) + user:set_hp(user:get_hp() + hp_change, {type="set_hp", detail="__builtin:item_eat"}) return nil -- don't overwrite wield item a second time end diff --git a/doc/lua_api.md b/doc/lua_api.md index 882bfe3412..ed4fa26473 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -6112,25 +6112,13 @@ Call these functions only at load time! calculating the HP change. This clamping has been removed as of version 5.10.0 * `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 neighboring node. - `reason.node` will hold the node name or nil. - `reason.node_pos` will hold the position of the 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. * `core.register_on_dieplayer(function(ObjectRef, reason))` * Called when a player dies - * `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange + * `reason`: a `PlayerHPChangeReason` table * For customizing the death screen, see `core.show_death_screen`. * `core.register_on_respawnplayer(function(ObjectRef))` * Called when player is to be respawned @@ -8333,7 +8321,7 @@ child will follow movement and rotation of that bone. * note: this is called `right_click` for historical reasons only * `get_hp()`: returns number of health points * `set_hp(hp, reason)`: set number of health points - * See reason in register_on_player_hpchange + * reason: A PlayerHPChangeReason table (optional) * Is limited to the range of 0 ... 65535 (2^16 - 1) * For players: HP are also limited by `hp_max` specified in object properties * `get_inventory()`: returns an `InvRef` for players, otherwise returns `nil` @@ -11084,6 +11072,35 @@ See [Decoration types]. Used by `core.register_decoration`. } ``` +PlayerHPChangeReason table definition +------------------------------------- + +The `PlayerHPChangeReason` table specifies a reason for player health changes. + +* The `type` field will have one of the following values: + * `set_hp`: A mod or the engine called `set_hp`, either without + giving a reason, or by setting `set_hp` as damage type + explicitly + * `punch`: Was punched. `reason.object` will hold the puncher, or nil if none. + * `fall`: Fall damage. + * `node_damage`: `damage_per_second` from a neighboring node. + `reason.node` will hold the node name or nil. + `reason.node_pos` will hold the position of the node + * `drown`: Drowning damage. + * `respawn`: HP restored by respawning. +* The `detail` field may optionally be used to provide a more detailed reason + as a string. It's recommended to follow the `modname:detail` naming convention. + These detail names exist by default: + * `__builtin:item_eat`: HP change caused by `core.do_item_eat` + * `__builtin:kill_command`: `/kill` command +* The `from` field denotes the origin of the HP change: + * `engine`: Engine + * `mod`: Mod or builtin +* Mods may add additional fields + +Note: The `from` field doesn't need to be provided in the `set_hp` method, +the engine will automatically set it to `mod`. + Chat command definition ----------------------- From a21dd0a992a34b558773d91ab46de2b102a1b611 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 14 Apr 2025 18:09:37 +0200 Subject: [PATCH 2/4] Report node for drowning in PlayerHPChangeReason --- doc/lua_api.md | 3 ++- src/server/player_sao.cpp | 3 ++- src/server/player_sao.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index ed4fa26473..fbe7c11dc3 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -11086,7 +11086,8 @@ The `PlayerHPChangeReason` table specifies a reason for player health changes. * `node_damage`: `damage_per_second` from a neighboring node. `reason.node` will hold the node name or nil. `reason.node_pos` will hold the position of the node - * `drown`: Drowning damage. + * `drown`: Drowning damage from a node with the `drowning` field set. + `reason.node` and `reason.node_pos` are same as for `node_damage` * `respawn`: HP restored by respawning. * The `detail` field may optionally be used to provide a more detailed reason as a string. It's recommended to follow the `modname:detail` naming convention. diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 068b2b29fe..0be301a79b 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -154,7 +154,8 @@ void PlayerSAO::step(float dtime, bool send_recommended) // No more breath, damage player if (m_breath == 0) { - PlayerHPChangeReason reason(PlayerHPChangeReason::DROWNING); + std::string nodename = c.name; + PlayerHPChangeReason reason(PlayerHPChangeReason::DROWNING, nodename, p); setHP(m_hp - c.drowning, reason); } } diff --git a/src/server/player_sao.h b/src/server/player_sao.h index a19177a7ed..052f2941ca 100644 --- a/src/server/player_sao.h +++ b/src/server/player_sao.h @@ -245,7 +245,7 @@ struct PlayerHPChangeReason // For PLAYER_PUNCH ServerActiveObject *object = nullptr; - // For NODE_DAMAGE + // For NODE_DAMAGE and DROWNING std::string node; v3s16 node_pos; From 4374f1d7eded6658dd16b102357cf4df47932f78 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Fri, 4 Jul 2025 12:36:05 +0200 Subject: [PATCH 3/4] Minor doc updates for PlayerHPChangeReason updates --- doc/lua_api.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index fbe7c11dc3..38202c03dc 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -11079,8 +11079,8 @@ The `PlayerHPChangeReason` table specifies a reason for player health changes. * The `type` field will have one of the following values: * `set_hp`: A mod or the engine called `set_hp`, either without - giving a reason, or by setting `set_hp` as damage type - explicitly + giving a reason, or by setting `set_hp` as damage type + explicitly * `punch`: Was punched. `reason.object` will hold the puncher, or nil if none. * `fall`: Fall damage. * `node_damage`: `damage_per_second` from a neighboring node. @@ -11099,8 +11099,8 @@ The `PlayerHPChangeReason` table specifies a reason for player health changes. * `mod`: Mod or builtin * Mods may add additional fields -Note: The `from` field doesn't need to be provided in the `set_hp` method, -the engine will automatically set it to `mod`. +Note: The `from` is ignored by `ObjectRef:set_hp`, the engine will always +set it to `mod`. Chat command definition ----------------------- From 9fad09d4a1d11eab7de20bcf3ce507645851fc12 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Fri, 4 Jul 2025 12:48:23 +0200 Subject: [PATCH 4/4] PlayerHPChangeReason: Replace detail by 2 types --- builtin/game/chat.lua | 2 +- builtin/game/item.lua | 2 +- doc/lua_api.md | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/builtin/game/chat.lua b/builtin/game/chat.lua index 277b20fcd5..c409b8957a 100644 --- a/builtin/game/chat.lua +++ b/builtin/game/chat.lua @@ -1346,7 +1346,7 @@ local function handle_kill_command(killer, victim) core.log("action", string.format("%s killed %s", killer, victim)) end -- Kill victim - victimref:set_hp(0, {type="set_hp", detail="__builtin:kill_command"}) + victimref:set_hp(0, {type="kill_command"}) return true, S("@1 has been killed.", victim) end diff --git a/builtin/game/item.lua b/builtin/game/item.lua index d3d0529015..71529adf6a 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -435,7 +435,7 @@ function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed core.add_item(pos, replace_with_item) end - user:set_hp(user:get_hp() + hp_change, {type="set_hp", detail="__builtin:item_eat"}) + user:set_hp(user:get_hp() + hp_change, {type="item_eat"}) return nil -- don't overwrite wield item a second time end diff --git a/doc/lua_api.md b/doc/lua_api.md index 38202c03dc..b537f0d9d0 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -11089,11 +11089,12 @@ The `PlayerHPChangeReason` table specifies a reason for player health changes. * `drown`: Drowning damage from a node with the `drowning` field set. `reason.node` and `reason.node_pos` are same as for `node_damage` * `respawn`: HP restored by respawning. -* The `detail` field may optionally be used to provide a more detailed reason - as a string. It's recommended to follow the `modname:detail` naming convention. - These detail names exist by default: - * `__builtin:item_eat`: HP change caused by `core.do_item_eat` - * `__builtin:kill_command`: `/kill` command + * `item_eat`: HP change caused by `core.do_item_eat` + * `kill_command`: `/kill` command + * A custom value. This may be used by mods to inform other mods + about a damage type when none of the above applies. It should + follow a `_:` naming convention. + Example: `_example:poison` for poison damage from a mod named `example` * The `from` field denotes the origin of the HP change: * `engine`: Engine * `mod`: Mod or builtin