In the Beta e1.5.9, the modding community found out that most of the UI Widgets are now auto-generated in C# instead of being parsed from their XML definitions in the runtime.
The game has an API to switch to the previous behavior, but the .xml definitions are not the same as the auto-generated files (at least some we tested in e1.5.9), so the game throws an error, because it expects a different content in the XML files when we try to switch to the old behavior.
From our modding perspective, this is a huge backstep. The safest way for us to mod the UI was to change the XML, preventing many possible runtime issues that can now happen when we need to patch directly the autogens. Also, because they are auto-generated, most likely the patches will be broken each game update, when the devs will be re-running the auto-generation and update them.
Hardcoding the widgets will limit our modding capability. While we still can patch them individually, it will require knowledge of both reverse-engineering and potentially IL patching, whether it's a tool like Harmony or low level stuff like MonoMod/Mono.Cecil.
This will lead to a huge decrease of the quality of mods doing changing the UI, as the curve of learning how to edit the XML is nothing compared to the curve of patching C# code.
We don't understand the reasoning for the auto-generation. We suspect this is done to speed-up the Widget creation and make its memory footprint smaller, but in our opinion, this is not worth the limitation. At least without having an opt-out option!
As we understand, this is what the devs aim to:
We also would appreciate if you could release the Widget generator so we could use it to make our custom UI less resource demanding!
As a bonus, here is an example of how we use the API introduced in e1.5.9 right now via patching by Harmony:
The game has an API to switch to the previous behavior, but the .xml definitions are not the same as the auto-generated files (at least some we tested in e1.5.9), so the game throws an error, because it expects a different content in the XML files when we try to switch to the old behavior.
From our modding perspective, this is a huge backstep. The safest way for us to mod the UI was to change the XML, preventing many possible runtime issues that can now happen when we need to patch directly the autogens. Also, because they are auto-generated, most likely the patches will be broken each game update, when the devs will be re-running the auto-generation and update them.
Hardcoding the widgets will limit our modding capability. While we still can patch them individually, it will require knowledge of both reverse-engineering and potentially IL patching, whether it's a tool like Harmony or low level stuff like MonoMod/Mono.Cecil.
This will lead to a huge decrease of the quality of mods doing changing the UI, as the curve of learning how to edit the XML is nothing compared to the curve of patching C# code.
We don't understand the reasoning for the auto-generation. We suspect this is done to speed-up the Widget creation and make its memory footprint smaller, but in our opinion, this is not worth the limitation. At least without having an opt-out option!
As we understand, this is what the devs aim to:
If we are correct in our understanding, his would be a nice compromise for the current situation!By default, all Widgets are created from the auto-generated classes, but once a mod wants to change it, it requests via the API to switch to the XML generation to enable us the ability for modification. This way, unless needed, the game always uses the optimized autogens.
We also would appreciate if you could release the Widget generator so we could use it to make our custom UI less resource demanding!
As a bonus, here is an example of how we use the API introduced in e1.5.9 right now via patching by Harmony:
C#:
internal static class GauntletMoviePatch
{
public static void Patch(Harmony harmony)
{
harmony.Patch(
AccessTools.Method("TaleWorlds.GauntletUI.Data.GauntletMovie:Load"),
prefix: new HarmonyMethod(AccessTools.Method(typeof(GauntletMoviePatch), nameof(LoadPrefix))));
}
private static void LoadPrefix(string movieName, ref bool doNotUseGeneratedPrefabs)
{
if (movieName == "SettlementNameplate") // Widget name that will switch back to loading the XML
doNotUseGeneratedPrefabs = true;
}
}