Simple solution for me
Make it so that technologies that not enabled do not show up in the technology list, even if they're researched.
Context
The mod I wrote (https://mods.factorio.com/mod/qol_research) adds a bunch of quality of life modifiers (think movement speed, reach, etc.), that are calculated based on runtime settings.
As most mods of this caliber did, I started out using modifiers on LuaForce to set these bonuses. This however causes numerous problems:
- reset_technology_effects() Popular mods such as bobsplates will reset the technology effects in the control stage, and even though I went through several implementation, adding several heuristics to detect whether the effects were reset, and reapplying them. There was no way to get it to be bullet-proof, and numerous times in weird situations with different modpacks, stuff would just break. I've asked about an event to detect the reset situations, and Klonan responded with:
As much as this could be considered incorrect usage, it's the real-world usage, and it's not the mod that does it incorrectly that breaks, it's the one which relies on LuaForce modifiers.
Code: Select all
If its called from a running script in the middle of nowhere, then there is no way to detect it Just like if a mod randomly decides to disable any recipes, technology, change some bonus etc. But it is incorrect usage to use it that way
- Bad user experience modifying mods. The user removes a mod, but its effects persist.
- Mod incompatibility. Even besides the reset_technology_effects(), the LuaForce method is nearly impossible to make compatible with other mods modifying the same values. If every mod was properly coded and coordinated, it's potentially possible, but that doesn't happen in real-life.
- Immediate application. Because property changes are not deferred, you easily run into situations where you get things like inventory explosions. It's not hard to code around, but annoying to say the least.
- Inconsistent behavior. Different properties behave different, most of them are relative modifiers, but for example quickbar_count is not. I had to write code that scans which technologies have effects that add quickbars, store that, then every time the value needs to be updated, inspect which of those technologies are researched on the current force, and then add that to the relative modifier my mod should provide. Again, not hard to code, but extra hurdles in the way of using modifiers on LuaForce.
As an example (x = 0.01, m = 12):
Code: Select all
0.01 movement speed
0.02 movement speed
0.04 movement speed
...
1310.72 movement speed
2621.44 movement speed
5242.88 movement speed
- Disable all these internal technologies, they would not get researched by research_all_technologies().
- Research a disabled technology, its effects would still apply.
- Put them in the same upgrade-tree, add a dummy research (with no effects) at the end, and disable that dummy research, they'd never show up in the technology list.
The last hack, which allowed me to hide those technologies broke in a recent patch. Although I'm not entirely certain, I think the bugfix in viewtopic.php?t=57600 is the likely culprit. So whilst right now, the mod still functions perfectly fine, the previously hidden technologies are visible in the technology window, which isn't the prettiest sight.
Solution
For my specific mod, the simple solution posted above would resolve the issue, however, I propose a more general solution, that'd fix this issue for all mods, allow for more new and varied situations to be fixed, and doesn't require these gross workarounds (I'm registering over 150 technologies to get all the fields working properly).
A method for applying technology effects during control stage.
Give every mod a set of modifiers they can edit. Concrete API:
On LuaForce, add the following:
Code: Select all
add_mod_effect(name: string, modifiers: Modifier[]): void
mod_effects: read only dictionary of [string => array of Modifier]
remove_mod_effect(name: string): void === add_mod_effect(name, nil)
Mod effects should not be shared between mods. Each mod should have its own dictionary of mod effects, this is so that upon uninstallation of the mod, these are removed.
In the Factorio code base, by the very nature of being able to research and unresearch technologies, this should be possible to implement. (Though I'm not sure about the nature of the LuaObject system, so the functionality might have to be moved to LuaBootstrap or LuaGameScript.)
Implementing this or similar functionality through a different API would prevent pretty much all mod incompatibility issues related to these kinds of things.