Page 1 of 1

Initialization trouble

Posted: Sat Aug 22, 2020 9:45 am
by Pi-C
Suppose a mod has some runtime-global settings. Settings are processed and stored in the mod's global table. There's a handler for defines.events.on_runtime_mod_setting_changed, so whenever one of the settings is changed during the game, the mod will react to it and store the new values in global.

Let's assume this is a single player game. After changing the settings, the player continues the game for a while, makes a save and turns off the computer. Next time, after starting Factorio but before loading the saved game, the player decides to change settings of the mod. After that, the game is loaded -- but the settings have been reverted to the state in the saved game!

I'm quite at a loss at this point. on_init will only trigger when a new game is started or when a mod is added to an existing game. on_player_joined_game is useful for multiplayer games, but will only be triggered once in singleplayer mode. on_runtime_mod_setting_changed will only trigger for changes made during the game, not between saves. on_configuration_changed won't register runtime-global settings. And running the initialization (which is writing to global) from on_load is tempting, but a very bad idea. So, what other way is there -- apart from reading the settings in on_tick? :-D

Re: Initialization trouble

Posted: Sat Aug 22, 2020 10:44 am
by Pi-C
I've been told since that this is the expected behavior: these are per map settings, so it would make sense to keep them. This does make sense, but …

The current behavior definitely makes sense in multiplayer games where changes of runtime-global settings affect all players. That's why only admins are allowed to make such changes.

In singleplayer games, the situation is different. There are players who will play a map without updating the game or mods and without adding or removing mods during the game. I tend to have a rather slow playstyle, spending hundreds of hours on a map without coming even close to launching a rocket. I like to try out new mods, and if I don't like them, I also remove them from the game again. Usually, after adding or updating a mod, I check and adjust the settings -- all off them (startup/map/player) in one session. It's quite frustrating to realize after loading the game that the changes I've just made have been ignored, and that I'll have to apply them again during the game. (The grade of frustration is directly proportional to the number of active mods, by the way.)

An idea to solve this issue that popped up here: Add an option on loading games to sync/not sync settings with the saved state. If this is set to "not sync", trigger on_runtime_mod_setting_changed after loading the game, so that mods can react to changes of any of their settings.

Re: Initialization trouble

Posted: Tue Aug 25, 2020 2:38 pm
by eradicator
As far as i remember my last test on this (long time ago) changes in menu are reflected in-game and properly raise on_runtime_mod_setting_changed. But *only* if you disable "settings -> other -> use different mod settings per save".

Depending on how often you need the setting you can also try to
a) always read it directly from settings[] when you need it (slightly more cpu-intensive i guess, but much more reliable and easier to handle)
b) or if you really need the performance cache it in a local instead of global and refresh it in on_load (increased risk of desync if you do it wrong, but perfectly fine if done right).[Edit:Doesn't solve the problem.]

Re: Initialization trouble

Posted: Tue Aug 25, 2020 3:10 pm
by Pi-C
eradicator wrote: Tue Aug 25, 2020 2:38 pm As far as i remember my last test on this (long time ago) changes in menu are reflected in-game and properly raise on_runtime_mod_setting_changed. But *only* if you disable "settings -> other -> use different mod settings per save".
Oh, right … I've completely forgot about that setting! Have to check again whether this will really work, but if it does, that would solve my problem.
Depending on how often you need the setting you can also try to
a) always read it directly from settings[] when you need it (slightly more cpu-intensive i guess, but much more reliable and easier to handle)
Have to check again how often settings are read in the mod. In a heavily used event that wouldn't be very practical. :-)
b) or if you really need the performance cache it in a local instead of global and refresh it in on_load (increased risk of desync if you do it wrong, but perfectly fine if done right).
I probably didn't do it right then when I tried -- it resulted in immediate desyncs.

Re: Initialization trouble

Posted: Tue Aug 25, 2020 3:21 pm
by eradicator
Pi-C wrote: Tue Aug 25, 2020 3:10 pm
eradicator wrote: Tue Aug 25, 2020 2:38 pm b) or if you really need the performance cache it in a local instead of global and refresh it in on_load (increased risk of desync if you do it wrong, but perfectly fine if done right).
I probably didn't do it right then when I tried -- it resulted in immediate desyncs.
On second thought, this wouldn't help anyway. If there is a "hole" in the event chain and you miss a setting being changed, then the storage location doesn't matter. That would need to be fixed in the engine.

Re: Initialization trouble

Posted: Tue Aug 25, 2020 3:25 pm
by eradicator
Pi-C wrote: Tue Aug 25, 2020 3:10 pm
Depending on how often you need the setting you can also try to
a) always read it directly from settings[] when you need it (slightly more cpu-intensive i guess, but much more reliable and easier to handle)
Have to check again how often settings are read in the mod. In a heavily used event that wouldn't be very practical. :-)
Heavily depends on the definition of "heavily used". Anything that happens less than once per second is probably fine.

Re: Initialization trouble

Posted: Tue Aug 25, 2020 3:42 pm
by Pi-C
eradicator wrote: Tue Aug 25, 2020 3:25 pm Heavily depends on the definition of "heavily used". Anything that happens less than once per second is probably fine.
The issue was with this mod, which may spawn many entities (capped at 1250 per default, if I remember correctly) during nights. It's not my own code (I've just been keeping it alive for a while, and making some fixes), so I'd really have to check again where exactly settings are polled. But the mod has crashed my computer in the past already when it went into a loop where entity spawning got completely out of hand, and UPS was getting smaller than 1. So I'd rather be very careful with this. :-D

Re: Initialization trouble

Posted: Tue Aug 25, 2020 4:11 pm
by robot256
If there is a "hole" in the event chain and you miss a setting being changed, then the storage location doesn't matter
There is no event hole. I just tested that with "Use different mod settings per save" disabled, the event does trigger when you load a save after changing the settings in the game menu.

In one of my mods, I cache the runtime-global settings simply by reading them into local variables at the top of control.lua (not in OnLoad, not sure if it makes a difference), and re-reading them in the on_runtime_mod_settings_changed event.

Re: Initialization trouble

Posted: Tue Aug 25, 2020 4:39 pm
by eradicator
Thanks for confirming the event works as expected. As for on_load i jumped on @OPs thought train there, if settings is available before that there's no difference.

Re: Initialization trouble

Posted: Tue Aug 25, 2020 9:35 pm
by robot256
Yeah, On_load is a little confusing. You can read but not write the globals table. I only use it for reregistering conditional events, like the API docs suggest. Apparently you can read the settings table before anything happens.