Document event order

Place to report issues and suggest improvements to the API documentation.
i142857
Burner Inserter
Burner Inserter
Posts: 11
Joined: Mon Nov 04, 2024 9:56 am
Contact:

Document event order

Post by i142857 »

A single player action can create multiple events, for example on_player_cursor_stack_changed and on_player_main_inventory_changed. Could you document what to expect in mods about this order?

a. "No guarantees whatsoever": the events can be raised in a different order every time, even for the same user action and the same factorio version -- I doubt this is the case, but tell us if it is.
b. "Can change from one version to another": on the same factorio version, for the same action, the order will be stable, but no promises about it being stable across versions.
c. "Stable order": here is the order events are raised in, if multiple need to be raised in the same tick, if we change it we'll document that as an API change.

Of course I'd love it if the answer was c (would clean up a lot of edge cases from my mod's code), but I suspect you wouldn't do it just for that. But I'm asking because, who knows, maybe the way you've built mod events, it just so happens the order _is_ stable. I can imagine for instance that the code might collect all relevant events during the tick processing, then iterate through them based on a fixed list and so on. If that's the case, it would be awesome if you made the event order part of the API.

Thank you!
Bilka
Factorio Staff
Factorio Staff
Posts: 3311
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: Document event order

Post by Bilka »

For events where there are ordering expectations they are documented on the lua actions that raise those events. E.g. https://lua-api.factorio.com/latest/cla ... n_crafting instantly raises on_pre_player_crafted_item and at some point in the current tick on_player_main_inventory_changed is raised.

However, generally there is no expected order as other things can happen inside events that themselves raise events. For example, another mod could subscribe to on_pre_player_crafted_item and call begin_crafting (so another on_pre_player_crafted_item event is raised instantly, before on_player_main_inventory_changed is called) or that other mod could call begin_crafting in on_player_main_inventory_changed instead (so another on_pre_player_crafted_item event is instantly raised after on_pre_player_crafted_item and on_player_main_inventory_changed both have already been raised).

Like almost everything in Factorio, this order is deterministic (based on user input, current game version and installed mods). But it is not defined in any way that can be documented in a static document or that mods should rely on.
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.
i142857
Burner Inserter
Burner Inserter
Posts: 11
Joined: Mon Nov 04, 2024 9:56 am
Contact:

Re: Document event order

Post by i142857 »

Thanks, Bilka!
Bilka wrote: Fri Jan 17, 2025 11:59 am For events where there are ordering expectations they are documented on the lua actions that raise those events. E.g. https://lua-api.factorio.com/latest/cla ... n_crafting instantly raises on_pre_player_crafted_item and at some point in the current tick on_player_main_inventory_changed is raised.
Have you considered similar documentation for player actions where the order is clear? It's nice to know what events a lua action produces, but I tend to care more about stuff the player does :)

In my case, for example, I need to track what happens to some items in the player's inventory. There are some actions where the only event is on_player_cursor_stack_changed, like the player putting the item into a container inventory slot. For other actions, we have dedicated, richer events, like on_player_dropped_item. If I knew that on_player_dropped_item happens first, then I could rely on that event to handle the "drop" case. But while that works in my tests today, I can't rely on it. If I might get cursor_stack_changed first, it's very hard to tell it's been dropped there, so I'd end up doing a bunch of useless searching just to eventually give up and hope for a drop event to follow.

Similarly, I need to do some inventory scanning to update some state when the inventory changes, but because I can't rely that on_player_main_inventory_changed happens before any other event like on_cursor_stack_changed, I have to redundantly scan the inventory in most event handlers, just in case.
Bilka wrote: Fri Jan 17, 2025 11:59 am However, generally there is no expected order as other things can happen inside events that themselves raise events. For example, another mod could subscribe to on_pre_player_crafted_item and call begin_crafting (so another on_pre_player_crafted_item event is raised instantly, before on_player_main_inventory_changed is called) or that other mod could call begin_crafting in on_player_main_inventory_changed instead (so another on_pre_player_crafted_item event is instantly raised after on_pre_player_crafted_item and on_player_main_inventory_changed both have already been raised).
Understood, though I think the relative order of events raised by the same action doesn't change. I guess I'm saying "if a player action or lua call raises events A and B, we promise A is raised before B, but not necessarily that B follows A immediately".
Bilka wrote: Fri Jan 17, 2025 11:59 am Like almost everything in Factorio, this order is deterministic (based on user input, current game version and installed mods). But it is not defined in any way that can be documented in a static document or that mods should rely on.
If nothing else, perhaps adding a paragraph like this to https://lua-api.factorio.com/latest/events.html would be worth it.

Thanks again!
i142857
Burner Inserter
Burner Inserter
Posts: 11
Joined: Mon Nov 04, 2024 9:56 am
Contact:

Re: Document event order

Post by i142857 »

Ah, I have a simpler idea that perhaps is easier to commit to.

Could you document/commit that when there is an event "X changed", then you cannot see the new value of X from Lua before the event has fired? Put differently, which events are instant, no matter what causes them (Lua or the engine because of a player action).

For example, that no matter how a player's main inventory changes, you will not see the changes from Lua before on_player_main_inventory_changed event is raised. Or that no matter how the player's position changes, you will not see the new position until on_player_changed_position, and so on.

It sounds fancy but this helps in so many cases, because it means you can cache something based on that state and know that until you receive the "changed" event your cache is valid. Without this you have to assume that any cache is up to 1 tick old.

If this is not true for all events, it would be worth describing this for each, for example like:

- instant: guaranteed to fire before you can read any value change
- same tick: guaranteed to fire in the same tick when a value changes but not necessarily instantly

What do you think?
User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 3412
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: Document event order

Post by boskid »

Guarantee of "you cannot see the new value of X from Lua before the event has fired" is impossible to achieve.

Lets assume there would be a variable X with a value of 1, and an event on_x_value_changed. For some unspecified reason value of variable X changes to 2 and immediately raises an event on_x_value_changed. But in the game there are 2 mods listening for this event: mod A and mod B.
- mod A receives on_x_value_changed event and calls a remote interface modB.remote. Mod B receives a remote interface call when value of variable X is already 2, but the event was not yet dispatched to mod B.
- then mod B receives on_x_value_changed event. Its too late, there was already a different piece of code that saw the new value of X.
Post Reply

Return to “Documentation Improvement Requests”