Let mods rewrite game CIL before it's loaded
spacechase0 opened this issue ยท 5 comments
There are some cases where something can't be cleanly hook into, and the pointer magic to completely replace a method is cumbersome and would only work for one mod, even if only a single line is changed in a hundred line function. Being able to edit things using Mono.Cecil before the game loads would help this.
Two immediate use cases come to mind:
- Custom Farm Types - I need to change some
location.GetType() == typeof (Farm)
tolocation is Farm
. - Entoarox Framework - Assuming EntoFramework 2.0 works similarly to 1.0, it would allow replacing
SerializableDictionary.WriteXml
andSerializableDictionary.ReadXml
to use theTypeRegistry
types. This is necessary for customTerrainFeature
s and placedObject
s to deserialize correctly. (I couldn't even figure out how to do it with pointer magic, since it is generic.)
My probably-overengineered idea: https://pastebin.com/JHeKkXhq
Heh, that's kinda why Minecraft Forge has started tightening up their rules for coremods. :P
This would be more of a temporary solution until SMAPI does add those APIs. For those two specific examples:
- Custom farm types would be more of a thing for SMAPI 3.0, right? Isn't that pretty far off?
- Are custom
TerrainFeature
s planned for #315? If not immediately, having every mod go through everyGameLocation.terrainFeatures
/objects
and remove-serialize/deserialize-add their stuff every time the game saves and loads could take a while when multiple mods start doing it.
While I agree that letting mods rewrite the game could impact stability negatively, if done carefully it could also impact it positively. Directly replacing methods with pointer magic even from, say, 1.2.16 to 1.2.31 could cause a lot of problems. Rewriting the methods needed (in Custom Farm Types case) to just change those type checks would stay working -- the only changes needed would be to check a few more methods if more type checks that use location.GetType() == typeof (Farm)
show up.
Also, I imagine only a handful of mods (possibly Entoarox Framework, I'd probably limit mine to SpaceCore, etc.) would even use this to begin with. IL rewriting isn't exactly intuitive. (And I suppose if you really wanted to discourage it, it could be left as an undocumented feature.)
I'm not sure we should let mods rewrite the game; I think that would significantly impact stability and maintenance in a way that would be hard to troubleshoot. I would much prefer any such rewriting be done by SMAPI, and expose APIs for things like custom farm types. I'm open to discussion and feedback, though.
I'm leaning towards declining the feature for the reasons I stated, but I'm keeping it open for feedback. While some mods aren't currently possible as you mentioned, I'd much rather focus on figuring out how to add APIs for those rather than exposing CIL rewriting to mods.
I found this Harmony project to hijack methods during runtime which is widely used for modding Rim World. I also tried it in some of my mods. I think this could be a solution.