Research Queue: The Old New Thing


Allows players to queue research, filter research according to required science packs, and automatically queue prerequisites for desired tech. The current maintainer is Saeuissimus. Originally developed by Mr Doomah, with updates by Doomquill, Chrisgbk and thelordodin.

Utilities
4 years ago
0.17 - 0.18
43

b [1.7.5] Crash, incompatible with Will-o'-the-Wisps mod

5 years ago

The mod : https://mods.factorio.com/mod/Will-o-the-Wisps_updated

Error log :
29.897 Error MainLoop.cpp:1173: Exception at tick 0: The mod Research Queue: The Old New Thing caused a non-recoverable error.
Please report this error to the mod author.

Error while running event research-queue-the-old-new-thing::on_nth_tick(60)
...rch-queue-the-old-new-thing__/functions/update_queue.lua:229: attempt to get length of field '?' (a nil value)
stack traceback:
...rch-queue-the-old-new-thing__/functions/update_queue.lua:229: in function 'update_queue_force'
research-queue-the-old-new-thing/control.lua:286: in function <research-queue-the-old-new-thing/control.lua:283

5 years ago

This looks like a tough one. That mod is not written with the factorio data lifecycle in mind so difficult to track conflicts could arise... Still, it looks like it's occurring at the first tick as soon as you start a new game. Is that right? I might be able to glean some information out if I try debugging it.

5 years ago
(updated 5 years ago)

Yes, it crash when starting new game or loading a save.

5 years ago
(updated 5 years ago)

Currently wisps mod has Init.state_tick() running on first nth_tick handler when loading it into a new/existing game for the first time.
Two new forces are added there (for peaceful/aggressive wisps), and I think issue is that script.on_nth_tick(60) runs update_queue_force() on all forces in the game, one of which apparently isn't initialized in global.researchQ table.

I see that it's supposed to be initialized in defines.events.on_force_created event handler, which is a bit puzzling, as it's explicitly documented as "Called when a new force is created using game.create_force()", and that's how all forces are created in wisps mod, don't think there's even any other way.

Adding simple print() to when create_force() is called, as well as defines.events.on_force_created handler and update_queue_force, I'm getting this sequence:

---------- wisp_force_init: wisp
---------- wisp_force_init: wisp_attack
---------- update_queue_force: player
---------- update_queue_force last_row: player
...
---------- update_queue_force: wisp
---------- update_queue_force last_row: wisp

I.e. handler for that event simply does not get invoked when create_force() is called in that wisp_force_init function.
Afaict both of these wisp_force_init calls are done in on_init handler too, which seems perfectly valid.

So I'd suggest adding something like if not global.researchQ[force.name] then global.researchQ[force.name] = {} end to update_queue_force or into that nth_tick handler somewhere before update_queue.lua:229 line runs as a workaround.
And guess I'll report that bug somewhere on official forums.

I've changed init sequence in wisps mod quite a bit since this thread was opened (mostly to fix potential multiplayer desync issues due to using locals), but don't think this particular init bit changed, so not sure what you mean about data lifecycle.

5 years ago
(updated 5 years ago)

Oh, also, simple workaround for this issue might be to:

  • (only for existing game) Disable Research Queue mod, if it was enabled, load game, save it.
  • Enable Will-o'-the-Wisps mod but not Research Queue, start/load game, save it.
  • Enable Research Queue mod, load the game, it sound work fine from there.

I.e. idea is to have will-o-wisps mod init its forces before this one is loaded, instead of relying on that hook above that doesn't seem to work.

5 years ago

And guess I'll report that bug somewhere on official forums.

Reported it here: https://forums.factorio.com/viewtopic.php?f=7&t=70952&p=430652

5 years ago
(updated 5 years ago)

It's been quickly pointed out in the bug forum thread that 0.16.21 changelog (link - https://forums.factorio.com/viewtopic.php?f=3&t=57372 ) has this line:
"Changed events so they won't fire until every mod has had on_init ran."

Which I think means that relying solely on on_init + on_force_created events to keep track of all forces, like done in this mod, is a bug - they are guaranteed to miss forces that are created during on_init in other mods.

Simple fix might be (as also pointed out in that thread) to re-scan game.forces in on_configuration_changed event handler, which is probably better than proposed workaround above, though both should work just fine in such simple case, I think.

Might also change wisps mod to create forces in on_nth_tick handler instead of on_init, to be more compatible with mods that don't take this factorio event-handling quirk into account... which can cause mp desyncs if done incorrectly, but guess I'll try to avoid that.

5 years ago
(updated 5 years ago)

re-scan game.forces in on_configuration_changed event handler

Unfortunately that won't work either for new games or when first adding the mod to a game, as was later pointed-out in that thread as well, so I'd go with that lazy-init hack, if you want to handle force changes in other mods' on_init correctly.

EDIT (to not add another msg here): That is until Rseding91 came and announced that they fixed the issue, so I guess it should work correctly in upcoming factorio release if you iterate/check through all forces in both on_init and on_configuration_changed (which don't think this mod does in the latter case currently).

5 years ago
(updated 5 years ago)

Thanks a lot mk-fg for investigating this issue! I noticed that things were going to get tricky and couldn't dig into it in time. I'll add the initialisation logic to the on_configuration_changed event. This should improve compatibility with other mods too.

Edit: I actually spoke too soon. As far as I can see, the initialisation logic is already triggered in the on_configuration_changed event. I'll check it more thoroughly this weekend though. If I find I still can't solve the incompatibility with this mod I may try posting to the thread you linked to and see if anyone has any idea. There might be a bug in the event loop after all.

Edit 2: I now reread the whole thread and noticed the lazy-init hack. If Rseding91 says this was fixed I guess there's nothing left for me to do. I will test both mods this weekend as soon as I can anyway.

5 years ago
(updated 5 years ago)

the initialisation logic is already triggered in the on_configuration_changed event

I think you might mean this bit:

script.on_configuration_changed(function(event)
    if event.mod_changes ~= nil and event.mod_changes["research-queue-the-old-new-thing"] ~= nil then
        init()
...

And "if" check there is why it won't be triggered when other mods are added to a saved game after this one, creating forces in their on_init.

Consider the case where wisps mod being first added to a saved game with this mod already initialized in it.
What should happen is:

  • will-o-wisps.on_init (creating new forces there)
  • research-queue.on_configuration_changed
    (with event.mod_changes['research-queue-the-old-new-thing'] == nil as it wasn't updated, only other mod was added, and init() will not run)
  • research-queue.on_nth_tick (with a crash due to new forces)

Note: no on_force_created events were fired, because no events are fired during on_init, unless it's a new game start after Rseding91's fix.
(as Rseding91 pointed out, they did not change anything regarding adding mods to a saved game, only "starting new game" sequence, where there was no such on_configuration_changed event for any of the mods)

So pretty sure something like init() should run in on_configuration_changed of this mod, regardless of whether it was this mod that got updated - it was not in example above, which is the problem, as globals.researchQ is only initialized there afaict.

Lazy-init fix that I initially suggested can also fix the issue, of course, as init process here is pretty trivial (just set key to empty table), and can be easily done on any random tick.

5 years ago
(updated 5 years ago)

Of course, you're right. I was thinking of removing that if and making sure there's not too much going on in init(). As far as I can see this should only impact new games and loading games with a different set of mods. I would only worry about this if something like mod hotloading ends up being implemented in factorio :P.

5 years ago

I also think that on_force_created can be using global.researchQ before it is initialized when starting new game after Rseding91's fix, as pointed out in e.g. this old thread - https://forums.factorio.com/viewtopic.php?f=7&t=39906 (this was before 0.16.21 change where events were disabled, but now this should be reverted for new games).

I.e. if other mods' on_init runs before this one in a new game, on_force_created event will be fired before gloabl.researchQ is initialized and on_force_created handler will raise an error, which can probably be fixed by some kind of "if not global.initialized then return end" check at the start, if it doesn't need to run before full check in on_init.

New response