-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Add more information in PlayerHPChangeReason #16024
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
doc/lua_api.md
Outdated
| * `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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
detail feels quite vague as a name - how about calling this custom_type?
Or perhaps the type field could be a string rather than enum and allow custom types if they follow the modname:typename convention. This feels quite nice, although idk if this would confuse some existing mods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about die_reason ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's HP change and not necessarily death. As for reason, this entire table is hp change reason
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. So something like change_reason or change_type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. So something like
change_reasonorchange_type.
There's an existing field reason.type (where reason is of type PlayerHPChangeReason). Adding a new field reason.change_reason or reason.change_type wouldn't make sense in terms of consistency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reason.event = __builtin:fall" etc...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about this again: detail has the same purpose as type. If we were the designing a new API, they would be the same field. However, there is backwards compatibility to take into account here.
The ideal option would be to add to new possible enum (string) values, or just fully custom game/mod-provided string values, to PlayerHPChangeReason.type.
If we did that, it would break mods which assume that only the enum values specified in the documentation occur, and that the enum is never extended. I don't think our backwards compatibility guarantee should include "enums are never extended". See also luanti-org/docs.luanti.org#223.
Looking at CTF's kill log and appgurueu's "Kill History", for example, they handle unknown types properly (although the latter is broken with some modlib-related error).
It could also break mods that somehow override core.item_eat or the /kill command to set some internal state, and then check for type == "set_hp" and their custom state in core.register_on_player_hpchange to figure out where damage is coming from. This would be quite hacky, and not something officially supported.
So I think extending type would be acceptable, and is what I suggest as it would be the cleanest API.
The other option would be to keep this as custom_type or similar, say "meant to be used with type == "set_hp"" and "not included in type for legacy reasons".
|
I'm waiting for the opinion of other core devs before I change the But I'm not sure if updating the |
|
Maybe |
|
@sfence: We already have a |
|
I think we can remove fields as |
doc/lua_api.md
Outdated
| * `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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about this again: detail has the same purpose as type. If we were the designing a new API, they would be the same field. However, there is backwards compatibility to take into account here.
The ideal option would be to add to new possible enum (string) values, or just fully custom game/mod-provided string values, to PlayerHPChangeReason.type.
If we did that, it would break mods which assume that only the enum values specified in the documentation occur, and that the enum is never extended. I don't think our backwards compatibility guarantee should include "enums are never extended". See also luanti-org/docs.luanti.org#223.
Looking at CTF's kill log and appgurueu's "Kill History", for example, they handle unknown types properly (although the latter is broken with some modlib-related error).
It could also break mods that somehow override core.item_eat or the /kill command to set some internal state, and then check for type == "set_hp" and their custom state in core.register_on_player_hpchange to figure out where damage is coming from. This would be quite hacky, and not something officially supported.
So I think extending type would be acceptable, and is what I suggest as it would be the cleanest API.
The other option would be to keep this as custom_type or similar, say "meant to be used with type == "set_hp"" and "not included in type for legacy reasons".
|
@grorp: So I have thought about your suggestion about extending So one way to do it by just adding the types In fact, I've pushed an "experimental" commit for just that. Please tell me if this is OK (just for concept approval). I'm not sure if I'm very happy about that because mods that previously relied on I dislike your approach (but pushed an experimental commit anyway) because it effectively changes the meaning of the Frankly, if I have to pick between a slightly more verbose API, and a backwards-compatibiltiy-breaking API (plus, in a normal release!), I pick the verbose API. I am ok with the suggestion of renaming the |
|
Two cents:
Long story short: For the purpose of dehardcoding, it suffices to let modders set the type, which is backwards compatible. I don't consider the engine's game-specific logic (e.g. regarding item eating, |
|
The main reason for this PR is to allow mods to learn when the I don't like the "solution" of "don't do anything, mods have to figure it out on their own" because it doesn't work. What if the builtin kill command was not touched by a mod? Which is completely reasonable btw. Technically, none of the two approaches being discussed (extending type directly vs adding a The argument "kill command and do_item_eat should't have been in engine to begin with" is false. It's in builtin. OK, I know you meant to say 'builtin'. In that case, I agree. However, the fact is, it IS in builtin now and we have to deal with it somehow and provide support. Backwards-compat is very important to me, I don't like the idea of "clean API" (which is COMPLETELY subjective) if we have to sacrifice backwards-compatibility just for nice-looking functions. Hmm, I'm afraid this PR is currently stuck in limbo. It's not clear how to move forward. Too many conflicting solutions suggested; it's confusing. My favourite approach still remains the new |
WARNING: This PR currently contains an experimental commit! Do NOT merge yet. Read #16024 (comment) for details.
This PR adds more details to the
PlayerHPChangeReasonand improves the documentation. Specifically, it does the following:nodeandnode_posfield for thedrownfield (analog tonode_damagetype)detailfield to allow a standardized way to report more details of the HP changebuiltinreport adetailfor the HP changes caused by the/killcommand andcore.do_item_eatPlayerHPChangeReasonto its own sectionRead the documentation updates for details.
Rationale
I feel like adding the node and node pos for drowning is a no-brainer, given we already have the same fields for
node_damage. This is probably the least controversial change.I added
detailbecause our current way to report more information was just us saying "mods, invent your custom field" which wasn't ideal. The new documentation requires this to be a string (to keep it simple) and suggests amodname:detailtextnaming convention, with builtin using__builtin:kill_commandand__builtin:item_eat.detailis of course optional.More annoyingly, the
/killcommand and thecore.do_item_eatHP change currently do not provide any reason for the HP change. This frustrated me when working on a death messages mod (= a mod printing a death message in chat, along with reason) and there was no way to detect a/killandcore.do_item_eatHP change cleanly without injecting or overwriting stuff. Which works, but is ugly code-wise. Now that the reason is provided by default, this should allow for cleaner mod code.I believe this PR should now cover all possible HP change events caused by the engine and builtin.
How to test
Create a dummy mod with the following code:
Then start a DevTest world with this mod activated. Now go drowning, try the
/killcommand or eat the apple and look at the output in chat. Then, try out other health-changing events to make sure all the other HP changes still work like they should.I did some of those tests myself and it looks fine, but please do it on your own as well. Thanks.