[0.17.41] lua on_force_created event handler is not called on game.create_force()

Place to get help with not working mods / modding interface.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

[0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

Starting New Game with two mods, one with "defines.events.on_force_created" handler and another calling game.create_force() from script.on_init() handler, handlers in the first mod do not get called.

This is a follow-up on the bug discussed here: https://mods.factorio.com/mod/research- ... 000dfca76c
  • What did I do:

    Start a game with two mods installed/unpacked/enabled - https://mods.factorio.com/mod/Will-o-the-Wisps_updated and https://mods.factorio.com/mod/research- ... -new-thing
    Other mods were enabled as well at the time, but none that should interfere with this sequence afaik.

    First mod (Will-o-the-Wisps_updated) has code like this:

    Code: Select all

    local function wisp_force_init(name)
      print(('---------- wisp_force_init: %s'):format(name))
      wisps = game.create_force(name)
      ...
    end
    
    script.on_init(function()
      ...
      wisp_force_init('wisp')
      wisp_force_init('wisp_attack')
      ...
    end
    
    Second one has code like this:

    Code: Select all

    script.on_nth_tick(60, function(event)
      print('---------- nth_tick')
      ...
    end)
    
    script.on_event(defines.events.on_force_created, function(event)
      print(('---------- on_force_created hook: %s'):format(event.force.name))
      ...
    end)
    
  • Expected result:

    When starting new game, I'll see output like this in stdout from running factorio game (among other stuff):

    Code: Select all

    ---------- wisp_force_init: wisp
    ---------- on_force_created hook: wisp
    ---------- wisp_force_init: wisp_attack
    ---------- on_force_created hook: wisp_attack
    ---------- nth_tick
    
    This is expected because on_force_created event is explicitly documented as "Called when a new force is created using game.create_force()"
    game.create_force() is called from on_init(), so event hook should presumably be called sometime after that, before nth_tick.

    This is not what happens.
  • Actual result:

    Following sequence of events is observed instead:

    Code: Select all

    ---------- wisp_force_init: wisp
    ---------- wisp_force_init: wisp_attack
    ---------- nth_tick
    ---------- nth_tick
    ...
    
    I.e. contrary to documentation, on_force_created event is never fired when game.create_force() is called.
Issue seem to be 100% reproducible with code above, and seem to be the cause of reported incompatibility between these two mods, confirmed by at least two other people.

I didn't try it in complete isolation (i.e. creating only trivial 10-liner mods with only code above), but given how early it happens and that nothing else interferes with events in these two mods, con't see any reason why it should break here either.

Some earlier thread on this forum that was able to find - viewtopic.php?f=7&t=39906 - seem to explicitly suggest that it should work in this exact situation between two mods, at least in 0.14.x.

If it should not fire from on_init sequence, I think it'd be best to add that to lua-api documentation, as that's where I think forces are usually initialized in mods, so it's a very important limitation that is worth mentioning.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

mk-fg wrote: ↑Fri May 17, 2019 4:23 pm Start a game with two mods installed/unpacked/enabled - https://mods.factorio.com/mod/Will-o-the-Wisps_updated and https://mods.factorio.com/mod/research- ... -new-thing
Other mods were enabled as well at the time, but none that should interfere with this sequence afaik.
Was able to reproduce same thing with just these two mods enabled, with print() statements added to relevant event handlers there.
Attached log file, collected from its console output (so that any print() will be there too).
Attachments
factorio.log
(4.97 KiB) Downloaded 82 times
User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5207
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by eradicator »

A mod can not recieve events before it's own on_init has finished. You need to for pairs() through all existing forces in the on_init of the second mod, and call your own handler internally. Otherwise you'd also miss any events that happend before the mod was even installed.
LuaBootstrap wrote: on_init(f)

Register a callback to be run on mod init. This is called once when a new save game is created or once when a save file is loaded that previously didn't contain the mod. This is always called before other event handlers and is meant for setting up initial values that a mod will use for its lifetime.
DataLifecycle wrote: 4. control.lua init
[...]
Note: until on_init has finished executing for a given mod (scenario scripts are also counted as a mod) the game will not raise any game events for that mod.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

LuaBootstrap wrote: on_init(f)

Register a callback to be run on mod init. This is called once when a new save game is created or once when a save file is loaded that previously didn't contain the mod. This is always called before other event handlers and is meant for setting up initial values that a mod will use for its lifetime.
I read "This is always called before other event handlers" as "it will always be called before first event handler".
Not as "events will be silently dropped and ignored due to arbitrary ordering of on_init calls for different mods".

Is my interpretation incorrect?
eradicator wrote: ↑Fri May 17, 2019 4:46 pm A mod can not recieve events before it's own on_init has finished.
(I thought there's a more explicit explanation, but can't find it atm.)
Adding similar print() as a first line to script.on_init() handler in each mod, it doesn't seem to be the casue of this issue:

Code: Select all

---------- on_init: rq
---------- on_init_done: rq
---------- on_init: wisps
---------- wisp_force_init: wisp
---------- wisp_force_init: wisp_attack
---------- nth_tick
I.e. on_init is called and finished in research-queue mod always before on_force_created events should be generated.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

Replying to updated message above:
eradicator wrote: ↑Fri May 17, 2019 4:46 pm A mod can not recieve events before it's own on_init has finished. You need to for pairs() through all existing forces in the on_init of the second mod, and call your own handler internally. Otherwise you'd also miss any events that happend before the mod was even installed.
DataLifecycle wrote: 4. control.lua init
[...]
Note: until on_init has finished executing for a given mod (scenario scripts are also counted as a mod) the game will not raise any game events for that mod.
This is actually what is already done in research-queue mod's on_init function, afaict, hence it works fine if you load it into existing game with wisps mod - if all forces are present during its on_init, it enumerates them and works perfectly.

But if New Game is started with both mods enabled, and wisps mod happens to run its on_init after research-queue mod, latter does not get its on_force_created events and only aware of forces that were present during its on_init call.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

DataLifecycle wrote: 4. control.lua init
[...]
Note: until on_init has finished executing for a given mod (scenario scripts are also counted as a mod) the game will not raise any game events for that mod.
Also, to be clear on this - I'm talking about on_force_created events not being raised in mod-B from on_init of mod-A.
I.e. "the game will not raise any game events for that mod" case does not apply here, as it's two different mods not getting events from each other.
User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5207
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by eradicator »

mk-fg wrote: ↑Fri May 17, 2019 5:03 pm I.e. "the game will not raise any game events for that mod" case does not apply here, as it's two different mods not getting events from each other.
I do not follow that logic. The rules stated above *do* apply for different mods.
mk-fg wrote: ↑Fri May 17, 2019 5:00 pm But if New Game is started with both mods enabled, and wisps mod happens to run its on_init after research-queue mod, latter does not get its on_force_created events and only aware of forces that were present during its on_init call.
In the opening post you describe that the first_loaded_mod creates a force in its on_init, which would then naturally *not* be recieved by the second_loaded_mod (as described above). Now you say the force creation happens in the second_loaded_mod?

You can view the order with print(script.get_event_order()).

Edit: Btw, this limitation was added in 0.15 or early 0.16 i think, so the 0.14 thread you linked does not apply anymore.

Edit2:
0.16.21 Changelog wrote: Changed events so they won't fire until every mod has had on_init ran.
Hm..*every* mod. That's even stricter than i thought (or the documentation states), so i wonder which one it is.
Last edited by eradicator on Fri May 17, 2019 5:23 pm, edited 1 time in total.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

eradicator wrote: ↑Fri May 17, 2019 5:14 pm I do not follow that logic. The rules stated above *do* apply for different mods.
While indeed it seem to be the case in practice, it's very unobvious from the text you quoted to me:
Note: until on_init has finished executing for a given mod (scenario scripts are also counted as a mod) the game will not raise any game events for that mod.
Note how it very deliberately highlights that it's only events in that mod where on_init runs that are affected.
(which makes sense as otherwise it's easy to write recursive calls which generate more events from event handlers, creating infinite loop and crashing the game)

So guess that wiki documentation should be fixed as well, to not say that it only applies "for that mod", but "for all mods" instead.
E.g. "Note: until on_init has finished executing, no events are raised."

I still think you are misreading that line, to be honest, but again have to admit that's how it seem to work in practice.
User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5207
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by eradicator »

mk-fg wrote: ↑Fri May 17, 2019 5:23 pm I still think you are misreading that line, to be honest, but again have to admit that's how it seem to work in practice.
You think i'm wrong, but you observe i'm right?
Added the relevant changelog in above posts Edit2.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

eradicator wrote: ↑Fri May 17, 2019 5:14 pm In the opening post you describe that the first_loaded_mod creates a force in its on_init, which would then naturally *not* be recieved by the second_loaded_mod (as described above). Now you say the force creation happens in the second_loaded_mod?
I didn't mean to imply any kind of "mod load order" in the first post at all, and didn't know it was even a thing in factorio.
I.e. thought it does not matter how mods are named and order in which they are initialized should also not be very relevant, as long as all of them have event handlers that process what other mods do in their on_init.
eradicator wrote: ↑Fri May 17, 2019 5:14 pm Edit: Btw, this limitation was added in 0.15 or early 0.16 i think, so the 0.14 thread you linked does not apply anymore.

Edit2:
0.16.21 Changelog wrote: Changed events so they won't fire until every mod has had on_init ran.
Hm..*every* mod. That's even stricter than i thought (or the documentation states), so i wonder which one it is.
This indeed makes sense for what I'm seeing happening.
Thanks for explaining.

(though I kinda wish you'd split these "edits" into messages, as it's really hard to follow a conversation, where history gets rewritten every other minute)
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

eradicator wrote: ↑Fri May 17, 2019 5:26 pm You think i'm wrong, but you observe i'm right?
Added the relevant changelog in above posts Edit2.
Well, if documentation says "sky is red", you observe that it's actually blue, it doesn't change the fact that documentation says that it's red.
Which is all that I meant, not that you're wrong about how game behaves, but about what that docs page was meant to imply.
Last edited by mk-fg on Fri May 17, 2019 5:31 pm, edited 1 time in total.
User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5207
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by eradicator »

mk-fg wrote: ↑Fri May 17, 2019 5:27 pm (though I kinda wish you'd split these "edits" into messages, as it's really hard to follow a conversation, where history gets rewritten every other minute)
That happens when you answer so fast that i only see your next message after finishing the edit.

I do agree that the changelog entry and the current documentation describe different behaviors. As stated above "i wonder which one it is". If event raising is completely suspended during on_init that would mean no mod would ever recieve events caused by on_init. And mean that mods would need to re-scanning on on_config_changed too, which would be a major PITA.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

eradicator wrote: ↑Fri May 17, 2019 5:31 pm If event raising is completely suspended during on_init that would mean no mod would ever recieve events caused by on_init.
And mean that mods would need to re-scanning on on_config_changed too, which would be a major PITA.
Yes, guess I'll need to move init for these forces into first on_nth_tick event.
Not a huge deal in this case, but indeed one more quirk to always keep in mind.
User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5207
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by eradicator »

mk-fg wrote: ↑Fri May 17, 2019 5:35 pm Yes, guess I'll need to move init for these forces into first on_nth_tick event.
Happy desyncing.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

eradicator wrote: ↑Fri May 17, 2019 5:37 pm
mk-fg wrote: ↑Fri May 17, 2019 5:35 pm Yes, guess I'll need to move init for these forces into first on_nth_tick event.
Happy desyncing.
Wait, do creating forces outside of on_init causes multiplayer desync?
(which is really weird, as then why there're even events for force-created/merged, if this should never be done in practice)

Never played mp myself, and it was pointed out that all known issues that cause it are listed here:
https://wiki.factorio.com/Tutorial:Modd ... nd_desyncs

Do you maybe have any link wrt adding forces also causing desync?
I'll try to report it to kind folks who pointed out that it was complete list (to their knowledge), and maybe have it updated.
User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5207
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by eradicator »

mk-fg wrote: ↑Fri May 17, 2019 5:42 pm Wait, do creating forces outside of on_init causes multiplayer desync?
"Doing stuff on the first tick" is generally bad practice and has a high likelyhood of causing desyncs because it's done wrong. It's not specific to create force. You should do the creation in on_configuration_changed or on_init (duh, yea i know...) and do the relevant "for k,v in pairs(game.forces)" scans there too. If you're the author of both mods you could also hardcode the force names. (But that should be discussed in a spererate help thread if this is indeed not a bug after all, which we don't know yet i guess?)
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5207
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by eradicator »

Basically in MP you don't know who joins the game when. So "on first recieved tick" is not the same for everyone in the game. Which makes it very easy to mess up.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

Ah, right, think I've seen this "done wrong" case happening in my mods indeed.

But guess there's no other way to co-operate with mods that use only on_init + on_force_created events (not the author/maintainer of other mod and potentially many others), and forces created on some arbitrary nth tick of game host should be synced to later-joining clients, same as any globals initialized there (but not e.g. locals, which is a common "done wrong" issue in that list above).
Will try to keep such init to a necessary minimum.

Thanks for poiniting out why it's a bad idea in particular, only now realized why locals would obviously cause desync when reading that last msg.
Bilka
Factorio Staff
Factorio Staff
Posts: 3309
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by Bilka »

Moved to modding help

eradicator is right so far that second_mod does not get events that first_mod raises in on_init. I don't have a safe answer to the "all mods/this mod's on init" problem with the doc, but I will investigate and update the documentation after the weekend (if it is wrong). I think it is only suspended for that mod, not all, but i will double check. So much to the bug report.

Now to modding. Something that strikes me as weird is that you rely on the force created being called for every force in your second_mod. It is well known that mods can be added in the middle of the game, so you must loop through all forces, regardless of whether events are received before on_init runs. This makes me wonder why this topic is even a topic - a mod that works correctly (as in, can be added to running game) should never have a problem with not receiving events before initialisation.
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.
mk-fg
Long Handed Inserter
Long Handed Inserter
Posts: 69
Joined: Wed May 30, 2018 11:01 am
Contact:

Re: [0.17.41] lua on_force_created event handler is not called on game.create_force()

Post by mk-fg »

Bilka wrote: ↑Fri May 17, 2019 6:26 pm Now to modding. Something that strikes me as weird is that you rely on the force created being called for every force in your second_mod. It is well known that mods can be added in the middle of the game, so you must loop through all forces, regardless of whether events are received before on_init runs.
I'm afraid you have misunderstood the problem, maybe check description above again, as I think I've re-iterated on all misunderstandings above.

Second mod is not mine, and:
- It loops through all forces in its on_init.
- It registers on_force_created event handler in proper way in control.lua.
- It's still not sufficient to keep track of all forces, as conversation above revealed.
Post Reply

Return to β€œModding help”