From 277b01179c83bebbf0578666a8bec569713834c3 Mon Sep 17 00:00:00 2001 From: Vitalii Mikhailov Date: Tue, 12 Sep 2023 23:46:45 +0300 Subject: [PATCH] * Might have fixed a reported save issue * Reflection improvement --- build/common.props | 2 +- changelog.txt | 5 + .../Patches/MBGameManagerPatch.cs | 6 +- .../Patches/ModulePatch.cs | 6 +- .../MBObjectExtensionDataStore.cs | 24 +--- .../Patches/CampaignBehaviorManagerPatch.cs | 121 +++++++++--------- .../SaveSystem/Patches/BehaviourNamePatch.cs | 4 +- .../Patches/DefinitionContextPatch.cs | 2 +- .../SaveSystem/Patches/TypeExtensionsPatch.cs | 6 +- .../DelayedSubModuleManager.cs | 30 ++--- .../ExceptionHandler/BEWPatch.cs | 2 +- .../IMBObjectExtensionDataStore.cs | 2 +- .../Patches/MBSubModuleBasePatch.cs | 46 +++---- 13 files changed, 121 insertions(+), 135 deletions(-) diff --git a/build/common.props b/build/common.props index bd014535..7f449c31 100644 --- a/build/common.props +++ b/build/common.props @@ -4,7 +4,7 @@ - 2.8.12 + 2.8.13 2.2.2 3.2.0.77 diff --git a/changelog.txt b/changelog.txt index 55aac469..c08b96b4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,9 @@ --------------------------------------------------------------------------------------------------- +Version: 2.8.13 +Game Versions: v1.0.0,v1.0.1,v1.0.2,v1.0.3,v1.1.0,v1.1.1,v1.1.2,v1.1.3,v1.1.4,v1.1.5,v1.2.0,v1.2.1,v1.2.2,v1.2.3 +* Might have fixed a reported save issue +* Reflection improvement +--------------------------------------------------------------------------------------------------- Version: 2.8.12 Game Versions: v1.0.0,v1.0.1,v1.0.2,v1.0.3,v1.1.0,v1.1.1,v1.1.2,v1.1.3,v1.1.4,v1.1.5,v1.2.0,v1.2.1,v1.2.2,v1.2.3 * Improved logging diff --git a/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/Patches/MBGameManagerPatch.cs b/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/Patches/MBGameManagerPatch.cs index b2c4b3ba..eae9e286 100644 --- a/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/Patches/MBGameManagerPatch.cs +++ b/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/Patches/MBGameManagerPatch.cs @@ -28,13 +28,13 @@ internal sealed class MBGameManagerPatch private static readonly MethodInfo? miTargetMethodGameStart = AccessTools2.Method("TaleWorlds.MountAndBlade.MBGameManager:OnGameStart"); private static readonly MethodInfo? miTargetMethodGameEnd = AccessTools2.Method("TaleWorlds.MountAndBlade.MBGameManager:OnGameEnd"); - private static readonly MethodInfo? miPatchMethod = AccessTools2.Method("Bannerlord.ButterLib.Implementation.MBSubModuleBaseExtended.Patches.MBGameManagerPatch:Transpiler"); + private static readonly MethodInfo? miPatchMethod = SymbolExtensions2.GetMethodInfo((IEnumerable x, MethodBase y) => Transpiler(x, y)); private static readonly MethodInfo? miMBSubModuleBaseOnGameStartEvent = AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnGameStart"); private static readonly MethodInfo? miMBSubModuleBaseOnGameEndEvent = AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnGameEnd"); - private static readonly MethodInfo? miDelayedOnGameStartEventCaller = AccessTools2.Method("Bannerlord.ButterLib.Implementation.MBSubModuleBaseExtended.Patches.MBGameManagerPatch:DelayedOnGameStartEvent"); - private static readonly MethodInfo? miDelayedOnGameEndEventCaller = AccessTools2.Method("Bannerlord.ButterLib.Implementation.MBSubModuleBaseExtended.Patches.MBGameManagerPatch:DelayedOnGameEndEvent"); + private static readonly MethodInfo? miDelayedOnGameStartEventCaller = SymbolExtensions2.GetMethodInfo((Game x, IGameStarter y) => DelayedOnGameStartEvent(x, y)); + private static readonly MethodInfo? miDelayedOnGameEndEventCaller = SymbolExtensions2.GetMethodInfo((Game x) => DelayedOnGameEndEvent(x)); internal static bool Enable(Harmony harmony) { diff --git a/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/Patches/ModulePatch.cs b/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/Patches/ModulePatch.cs index 1b52dd4f..f30d480d 100644 --- a/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/Patches/ModulePatch.cs +++ b/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/Patches/ModulePatch.cs @@ -26,13 +26,13 @@ internal sealed class ModulePatch private static readonly Type? TargetType = typeof(TWModule); private static readonly MethodInfo? miTargetMethodUnLoad = AccessTools2.Method(TargetType, "FinalizeSubModules"); - private static readonly MethodInfo? miPatchMethodUnLoad = AccessTools2.Method("Bannerlord.ButterLib.Implementation.MBSubModuleBaseExtended.Patches.ModulePatch:FinalizeSubModulesPostfix"); + private static readonly MethodInfo? miPatchMethodUnLoad = SymbolExtensions2.GetMethodInfo((TWModule x) => FinalizeSubModulesPostfix(x)); private static readonly MethodInfo? miTargetMethodScreenAsRoot = AccessTools2.Method(TargetType, "SetInitialModuleScreenAsRootScreen"); - private static readonly MethodInfo? miPatchMethodScreenAsRoot = AccessTools2.Method("Bannerlord.ButterLib.Implementation.MBSubModuleBaseExtended.Patches.ModulePatch:Transpiler"); + private static readonly MethodInfo? miPatchMethodScreenAsRoot = SymbolExtensions2.GetMethodInfo((IEnumerable x) => Transpiler(x)); private static readonly MethodInfo? miMBSubModuleBaseScreenAsRootEvent = AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnBeforeInitialModuleScreenSetAsRoot"); - private static readonly MethodInfo? miDelayedScreenAsRootEventCaller = AccessTools2.Method("Bannerlord.ButterLib.Implementation.MBSubModuleBaseExtended.Patches.ModulePatch:DelayedScreenAsRootEvent"); + private static readonly MethodInfo? miDelayedScreenAsRootEventCaller = SymbolExtensions2.GetMethodInfo((TWModule x) => DelayedScreenAsRootEvent(x)); internal static bool Enable(Harmony harmony) { diff --git a/src/Bannerlord.ButterLib.Implementation/ObjectSystem/MBObjectExtensionDataStore.cs b/src/Bannerlord.ButterLib.Implementation/ObjectSystem/MBObjectExtensionDataStore.cs index eea1e567..9032038d 100755 --- a/src/Bannerlord.ButterLib.Implementation/ObjectSystem/MBObjectExtensionDataStore.cs +++ b/src/Bannerlord.ButterLib.Implementation/ObjectSystem/MBObjectExtensionDataStore.cs @@ -75,19 +75,17 @@ static bool DoesNotExist(MBGUID objectId) public void SetVariable(MBObjectBase @object, string name, object? data) => _vars[DataKey.Make(@object, name)] = data; -#nullable disable - public bool TryGetVariable(MBObjectBase @object, string name, out T value) + public bool TryGetVariable(MBObjectBase @object, string name, out T? value) { - if (_vars.TryGetValue(DataKey.Make(@object, name), out var val) && (val is T || val is null)) + if (_vars.TryGetValue(DataKey.Make(@object, name), out var val) && val is T or null) { - value = (T) val; + value = (T?) val; return true; } value = default; return false; } -#nullable restore /* Flags Implementation */ @@ -101,24 +99,10 @@ public bool TryGetVariable(MBObjectBase @object, string name, out T value) /* DataKey Implementation */ - private sealed class DataKey : IEquatable + private sealed record DataKey([field: SaveableField(0)] MBGUID ObjectId, [field: SaveableField(1)] string? Key) { - [SaveableField(0)] - internal readonly MBGUID ObjectId; - - [SaveableField(1)] - internal readonly string? Key; - - private DataKey(MBGUID objectId, string key) => (ObjectId, Key) = (objectId, key); - internal static DataKey Make(MBObjectBase obj, string key) => new(obj.Id, key); - public bool Equals(DataKey? other) => ObjectId == other?.ObjectId && !(Key is null || other.Key is null) && Key.Equals(other.Key); - - public override bool Equals(object? obj) => obj is DataKey k && Equals(k); - - public override int GetHashCode() => HashCode.Combine(ObjectId, Key); - public override string ToString() => $"{ObjectId}::{Key}"; } diff --git a/src/Bannerlord.ButterLib.Implementation/ObjectSystem/Patches/CampaignBehaviorManagerPatch.cs b/src/Bannerlord.ButterLib.Implementation/ObjectSystem/Patches/CampaignBehaviorManagerPatch.cs index c54bcaae..8c40139f 100755 --- a/src/Bannerlord.ButterLib.Implementation/ObjectSystem/Patches/CampaignBehaviorManagerPatch.cs +++ b/src/Bannerlord.ButterLib.Implementation/ObjectSystem/Patches/CampaignBehaviorManagerPatch.cs @@ -21,37 +21,32 @@ internal sealed class CampaignBehaviorManagerPatch private delegate void SaveBehaviorDataDelegate(CampaignBehaviorBase campaignBehavior); private delegate void LoadBehaviorDataDelegate(CampaignBehaviorBase campaignBehavior); - private static ILogger _log = default!; + private static readonly MethodInfo? OnGameLoadedTargetMI = + AccessTools2.Method("TaleWorlds.CampaignSystem.CampaignBehaviors.CampaignBehaviorManager:OnGameLoaded") ?? + AccessTools2.Method("TaleWorlds.CampaignSystem.CampaignBehaviors.CampaignBehaviorManager:LoadBehaviorData"); + + private static readonly MethodInfo? OnBeforeSaveTargetMI = + AccessTools2.Method("TaleWorlds.CampaignSystem.CampaignBehaviors.CampaignBehaviorManager:OnBeforeSave"); - // Application: + private static readonly MethodInfo? OnGameLoadedPatchMI = SymbolExtensions2.GetMethodInfo((object? x) => OnGameLoadedPrefix(x)); + private static readonly MethodInfo? OnBeforeSavePatchMI = SymbolExtensions2.GetMethodInfo((object? x) => OnBeforeSavePostfix(x)); internal static void Enable(Harmony harmony) { var provider = ButterLibSubModule.Instance?.GetServiceProvider() ?? ButterLibSubModule.Instance?.GetTempServiceProvider(); - _log = provider?.GetService>() ?? NullLogger.Instance; + var log = provider?.GetService>() ?? NullLogger.Instance; if (OnGameLoadedTargetMI is null) - _log.LogError("{Method} is null", nameof(OnGameLoadedTargetMI)); + log.LogError("{Method} is null", nameof(OnGameLoadedTargetMI)); if (OnBeforeSaveTargetMI is null) - _log.LogError("{Method} is null", nameof(OnBeforeSaveTargetMI)); + log.LogError("{Method} is null", nameof(OnBeforeSaveTargetMI)); if (OnGameLoadedPatchMI is null) - _log.LogError("{Method} is null", nameof(OnGameLoadedPatchMI)); + log.LogError("{Method} is null", nameof(OnGameLoadedPatchMI)); if (OnBeforeSavePatchMI is null) - _log.LogError("{Method} is null", nameof(OnBeforeSavePatchMI)); - if (LoadBehaviorDataMI is null) - _log.LogError("{Method} is null", nameof(LoadBehaviorDataMI)); - if (SaveBehaviorDataMI is null) - _log.LogError("{Method} is null", nameof(SaveBehaviorDataMI)); - if (CampaignBehaviorDataStoreT is null) - _log.LogError("{Method} is null", nameof(CampaignBehaviorDataStoreT)); - - if (OnGameLoadedTargetMI is null || OnBeforeSaveTargetMI is null || - OnGameLoadedPatchMI is null || OnBeforeSavePatchMI is null || - LoadBehaviorDataMI is null || SaveBehaviorDataMI is null || - CampaignBehaviorDataStoreT is null) - { + log.LogError("{Method} is null", nameof(OnBeforeSavePatchMI)); + + if (OnGameLoadedTargetMI is null || OnBeforeSaveTargetMI is null || OnGameLoadedPatchMI is null || OnBeforeSavePatchMI is null) return; - } harmony.Patch(OnGameLoadedTargetMI, prefix: new HarmonyMethod(OnGameLoadedPatchMI)); harmony.Patch(OnBeforeSaveTargetMI, postfix: new HarmonyMethod(OnBeforeSavePatchMI)); @@ -59,84 +54,86 @@ LoadBehaviorDataMI is null || SaveBehaviorDataMI is null || internal static void Disable(Harmony harmony) { } - // Target and patch methods: - - private static readonly MethodInfo? OnGameLoadedTargetMI = - AccessTools2.Method("TaleWorlds.CampaignSystem.CampaignBehaviors.CampaignBehaviorManager:OnGameLoaded") ?? - AccessTools2.Method("TaleWorlds.CampaignSystem.CampaignBehaviors.CampaignBehaviorManager:InitializeCampaignBehaviors"); - - private static readonly MethodInfo? OnBeforeSaveTargetMI = - AccessTools2.Method("TaleWorlds.CampaignSystem.CampaignBehaviors.CampaignBehaviorManager:OnBeforeSave"); - - private static readonly MethodInfo? OnGameLoadedPatchMI = - AccessTools2.Method("Bannerlord.ButterLib.Implementation.ObjectSystem.Patches.CampaignBehaviorManagerPatch:OnGameLoadedPrefix"); - - private static readonly MethodInfo? OnBeforeSavePatchMI = - AccessTools2.Method("Bannerlord.ButterLib.Implementation.ObjectSystem.Patches.CampaignBehaviorManagerPatch:OnBeforeSavePostfix"); - - // Necessary reflection: - - private static readonly Type? CampaignBehaviorDataStoreT = - typeof(Campaign).Assembly.GetType("TaleWorlds.CampaignSystem.CampaignBehaviorDataStore"); - - private static readonly MethodInfo? LoadBehaviorDataMI = AccessTools2.Method(CampaignBehaviorDataStoreT!, "LoadBehaviorData"); - - private static readonly MethodInfo? SaveBehaviorDataMI = AccessTools2.Method(CampaignBehaviorDataStoreT!, "SaveBehaviorData"); - - // Patch implementation: - [MethodImpl(MethodImplOptions.NoInlining)] private static void OnGameLoadedPrefix(object? ____campaignBehaviorDataStore) { - var mbObjectVariableStorage = ButterLibSubModule.Instance?.GetServiceProvider()?.GetService(); + var provider = ButterLibSubModule.Instance?.GetServiceProvider() ?? ButterLibSubModule.Instance?.GetTempServiceProvider(); + var log = provider?.GetService>() ?? NullLogger.Instance; - if (mbObjectVariableStorage is null) + if (____campaignBehaviorDataStore is null) + { + log.LogError("{Method}: {Variable} is null", nameof(OnGameLoadedPrefix), nameof(____campaignBehaviorDataStore)); + return; + } + + if (ButterLibSubModule.Instance?.GetServiceProvider()?.GetService() is not { } mbObjectVariableStorage) { - _log.LogError("{Method}: {Variable} is null", nameof(OnGameLoadedPrefix), nameof(mbObjectVariableStorage)); + log.LogError("{Method}: {Variable} is null", nameof(OnGameLoadedPrefix), nameof(mbObjectVariableStorage)); return; } if (mbObjectVariableStorage is not CampaignBehaviorBase storageBehavior) { - _log.LogError("{Method}: {Variable} is not a CampaignBehaviorBase", nameof(OnGameLoadedPrefix), nameof(mbObjectVariableStorage)); + log.LogError("{Method}: {Variable} is not a CampaignBehaviorBase", nameof(OnGameLoadedPrefix), nameof(mbObjectVariableStorage)); return; } - if (____campaignBehaviorDataStore is null) + if (AccessTools2.GetDelegate(____campaignBehaviorDataStore, ____campaignBehaviorDataStore.GetType(), "LoadBehaviorData") is not { } loadBehaviorData) { - _log.LogError("{Method}: {Variable} is null", nameof(OnGameLoadedPrefix), nameof(____campaignBehaviorDataStore)); + log.LogError("{Method}: {Variable} is not a SaveBehaviorDataDelegate", nameof(OnGameLoadedPrefix), nameof(loadBehaviorData)); return; } - var loadBehaviorData = AccessTools2.GetDelegate(____campaignBehaviorDataStore, LoadBehaviorDataMI!); - loadBehaviorData?.Invoke(storageBehavior); + try + { + loadBehaviorData(storageBehavior); + } + catch (Exception e) + { + log.LogError(e, "{Method}", nameof(OnGameLoadedPrefix)); + return; + } } [MethodImpl(MethodImplOptions.NoInlining)] private static void OnBeforeSavePostfix(object? ____campaignBehaviorDataStore) { - var mbObjectVariableStorage = ButterLibSubModule.Instance?.GetServiceProvider()?.GetService(); + var provider = ButterLibSubModule.Instance?.GetServiceProvider() ?? ButterLibSubModule.Instance?.GetTempServiceProvider(); + var log = provider?.GetService>() ?? NullLogger.Instance; - if (mbObjectVariableStorage is null) + if (____campaignBehaviorDataStore is null) + { + log.LogError("{Method}: {Variable} is null", nameof(OnBeforeSavePostfix), nameof(____campaignBehaviorDataStore)); + return; + } + + if (ButterLibSubModule.Instance?.GetServiceProvider()?.GetService() is not { } mbObjectVariableStorage) { - _log.LogError("{Method}: {Variable} is null", nameof(OnBeforeSavePostfix), nameof(mbObjectVariableStorage)); + log.LogError("{Method}: {Variable} is null", nameof(OnBeforeSavePostfix), nameof(mbObjectVariableStorage)); return; } if (mbObjectVariableStorage is not CampaignBehaviorBase storageBehavior) { - _log.LogError("{Method}: {Variable} is not a CampaignBehaviorBase", nameof(OnBeforeSavePostfix), nameof(mbObjectVariableStorage)); + log.LogError("{Method}: {Variable} is not a CampaignBehaviorBase", nameof(OnBeforeSavePostfix), nameof(mbObjectVariableStorage)); return; } - if (____campaignBehaviorDataStore is null) + if (AccessTools2.GetDelegate(____campaignBehaviorDataStore, ____campaignBehaviorDataStore.GetType(), "SaveBehaviorData") is not { } saveBehaviorData) { - _log.LogError("{Method}: {Variable} is null", nameof(OnBeforeSavePostfix), nameof(____campaignBehaviorDataStore)); + log.LogError("{Method}: {Variable} is not a SaveBehaviorDataDelegate", nameof(OnBeforeSavePostfix), nameof(saveBehaviorData)); return; } - var saveBehaviorData = AccessTools2.GetDelegate(____campaignBehaviorDataStore, SaveBehaviorDataMI!); - saveBehaviorData?.Invoke(storageBehavior); + try + { + saveBehaviorData(storageBehavior); + } + catch (Exception e) + { + log.LogError(e, "{Method}", nameof(OnBeforeSavePostfix)); + return; + } } } } \ No newline at end of file diff --git a/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/BehaviourNamePatch.cs b/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/BehaviourNamePatch.cs index 1e0e6b4c..5d6dca74 100644 --- a/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/BehaviourNamePatch.cs +++ b/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/BehaviourNamePatch.cs @@ -17,14 +17,14 @@ internal static bool Enable(Harmony harmony) { return harmony.TryPatch( AccessTools2.Constructor(typeof(CampaignBehaviorBase)), - postfix: AccessTools2.Method("Bannerlord.ButterLib.Implementation.SaveSystem.Patches.BehaviourNamePatch:CampaignBehaviorBaseCtorPostfix")); + postfix: SymbolExtensions2.GetMethodInfo((CampaignBehaviorBase x, string? y) => CampaignBehaviorBaseCtorPostfix(x, ref y))); } internal static bool Disable(Harmony harmony) { harmony.Unpatch( AccessTools2.Constructor(typeof(CampaignBehaviorBase)), - AccessTools2.Method("Bannerlord.ButterLib.Implementation.SaveSystem.Patches.BehaviourNamePatch:CampaignBehaviorBaseCtorPostfix")); + SymbolExtensions2.GetMethodInfo((CampaignBehaviorBase x, string? y) => CampaignBehaviorBaseCtorPostfix(x, ref y))); return true; } diff --git a/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/DefinitionContextPatch.cs b/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/DefinitionContextPatch.cs index 827bf90d..d6e5b4a6 100644 --- a/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/DefinitionContextPatch.cs +++ b/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/DefinitionContextPatch.cs @@ -77,7 +77,7 @@ internal static bool Disable(Harmony harmony) private static bool CanAddTypeDefinition(TypeDefinitionBase? typeDef, Dictionary typeDict) { - if (typeDef is null || typeDef.Type is null) + if (typeDef?.Type is null) return false; if (typeDict.ContainsKey(typeDef.Type)) diff --git a/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/TypeExtensionsPatch.cs b/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/TypeExtensionsPatch.cs index 6fb66d94..5fd5670c 100644 --- a/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/TypeExtensionsPatch.cs +++ b/src/Bannerlord.ButterLib.Implementation/SaveSystem/Patches/TypeExtensionsPatch.cs @@ -50,17 +50,17 @@ internal static bool Disable(Harmony harmony) return true; } - private static readonly Type? TargetType = typeof(MetaData).Assembly.GetType("TaleWorlds.SaveSystem.TypeExtensions"); + private static readonly Type? TargetType = AccessTools2.TypeByName("TaleWorlds.SaveSystem.TypeExtensions"); private static readonly Type[] TargetMethodParams = { typeof(Type), typeof(ContainerType).MakeByRefType() }; private static readonly MethodInfo? TargetMethod = AccessTools2.Method(TargetType!, "IsContainer", TargetMethodParams); - private static readonly MethodInfo? PatchMethod = AccessTools2.Method("Bannerlord.ButterLib.Implementation.SaveSystem.Patches.TypeExtensionsPatch:IsContainerPrefix"); + private static readonly MethodInfo? PatchMethod = SymbolExtensions2.GetMethodInfo((Type x, ContainerType y, bool z) => IsContainerPrefix(x, out y, ref z)); // ReSharper disable once RedundantAssignment private static bool IsContainerPrefix(Type type, out ContainerType containerType, ref bool __result) { containerType = ContainerType.None; - if (type.IsGenericType && !type.IsGenericTypeDefinition) + if (type is {IsGenericType: true, IsGenericTypeDefinition: false}) type = type.GetGenericTypeDefinition(); if (type.IsArray) diff --git a/src/Bannerlord.ButterLib/DelayedSubModule/DelayedSubModuleManager.cs b/src/Bannerlord.ButterLib/DelayedSubModule/DelayedSubModuleManager.cs index 11354b81..cdafd6d2 100644 --- a/src/Bannerlord.ButterLib/DelayedSubModule/DelayedSubModuleManager.cs +++ b/src/Bannerlord.ButterLib/DelayedSubModule/DelayedSubModuleManager.cs @@ -47,19 +47,19 @@ static DelayedSubModuleManager() var harmony = new Harmony("butterlib.delayedsubmoduleloader.static"); harmony.Patch( AccessTools2.DeclaredMethod("TaleWorlds.MountAndBlade.MBSubModuleBase:OnSubModuleLoad"), - postfix: new HarmonyMethod(typeof(DelayedSubModuleManager), nameof(BaseSubModuleLoadPostfix))); + postfix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => BaseSubModuleLoadPostfix(x)))); harmony.Patch( AccessTools2.DeclaredMethod("TaleWorlds.MountAndBlade.MBSubModuleBase:OnSubModuleUnloaded"), - postfix: new HarmonyMethod(typeof(DelayedSubModuleManager), nameof(BaseOnSubModuleUnloadedPostfix))); + postfix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => BaseOnSubModuleUnloadedPostfix(x)))); harmony.Patch( AccessTools2.DeclaredMethod("TaleWorlds.MountAndBlade.MBSubModuleBase:OnBeforeInitialModuleScreenSetAsRoot"), - postfix: new HarmonyMethod(typeof(DelayedSubModuleManager), nameof(BaseOnBeforeInitialModuleScreenSetAsRootPostfix))); + postfix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => BaseOnBeforeInitialModuleScreenSetAsRootPostfix(x)))); harmony.Patch( AccessTools2.DeclaredMethod("TaleWorlds.MountAndBlade.MBSubModuleBase:OnGameStart"), - postfix: new HarmonyMethod(typeof(DelayedSubModuleManager), nameof(BaseOnGameStartPostfix))); + postfix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => BaseOnGameStartPostfix(x)))); harmony.Patch( AccessTools2.DeclaredMethod("TaleWorlds.MountAndBlade.MBSubModuleBase:OnGameEnd"), - postfix: new HarmonyMethod(typeof(DelayedSubModuleManager), nameof(BaseOnGameEndPostfix))); + postfix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => BaseOnGameEndPostfix(x)))); } [MethodImpl(MethodImplOptions.NoInlining)] private static void BaseSubModuleLoadPostfix(MBSubModuleBase __instance) @@ -119,8 +119,8 @@ public static void Register(Type subModule, int priority, string[]? before, stri { harmony.Patch( onSubModuleLoad, - prefix: new HarmonyMethod(AccessTools2.DeclaredMethod("Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager:SubModuleLoadPrefix"), priority, before, after), - postfix: new HarmonyMethod(AccessTools2.DeclaredMethod("Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager:SubModuleLoadPostfix"), priority, before, after)); + prefix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => SubModuleLoadPrefix(x)), priority, before, after), + postfix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => SubModuleLoadPostfix(x)), priority, before, after)); } @@ -129,8 +129,8 @@ public static void Register(Type subModule, int priority, string[]? before, stri { harmony.Patch( AccessTools2.DeclaredMethod(subModule, "OnSubModuleUnloaded"), - prefix: new HarmonyMethod(AccessTools2.DeclaredMethod("Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager:OnSubModuleUnloadedPrefix"), priority, before, after), - postfix: new HarmonyMethod(AccessTools2.DeclaredMethod("Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager:OnSubModuleUnloadedPostfix"), priority, before, after)); + prefix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnSubModuleUnloadedPrefix(x)), priority, before, after), + postfix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnSubModuleUnloadedPostfix(x)), priority, before, after)); } @@ -139,8 +139,8 @@ public static void Register(Type subModule, int priority, string[]? before, stri { harmony.Patch( AccessTools2.DeclaredMethod(subModule, "OnBeforeInitialModuleScreenSetAsRoot"), - prefix: new HarmonyMethod(AccessTools2.DeclaredMethod("Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager:OnBeforeInitialModuleScreenSetAsRootPrefix"), priority, before, after), - postfix: new HarmonyMethod(AccessTools2.DeclaredMethod("Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager:OnBeforeInitialModuleScreenSetAsRootPostfix"), priority, before, after)); + prefix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnBeforeInitialModuleScreenSetAsRootPrefix(x)), priority, before, after), + postfix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnBeforeInitialModuleScreenSetAsRootPostfix(x)), priority, before, after)); } var onGameStart = AccessTools2.DeclaredMethod(subModule, "OnGameStart"); @@ -148,8 +148,8 @@ public static void Register(Type subModule, int priority, string[]? before, stri { harmony.Patch( AccessTools2.DeclaredMethod(subModule, "OnGameStart"), - prefix: new HarmonyMethod(AccessTools2.DeclaredMethod("Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager:OnGameStartPrefix"), priority, before, after), - postfix: new HarmonyMethod(AccessTools2.DeclaredMethod("Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager:OnGameStartPostfix"), priority, before, after)); + prefix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnGameStartPrefix(x)), priority, before, after), + postfix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnGameStartPostfix(x)), priority, before, after)); } @@ -158,8 +158,8 @@ public static void Register(Type subModule, int priority, string[]? before, stri { harmony.Patch( AccessTools2.DeclaredMethod(subModule, "OnGameEnd"), - prefix: new HarmonyMethod(AccessTools2.DeclaredMethod("Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager:OnGameEndPrefix"), priority, before, after), - postfix: new HarmonyMethod(AccessTools2.DeclaredMethod("Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager:OnGameEndPostfix"), priority, before, after)); + prefix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnGameEndPrefix(x)), priority, before, after), + postfix: new HarmonyMethod(SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnGameEndPostfix(x)), priority, before, after)); } } diff --git a/src/Bannerlord.ButterLib/ExceptionHandler/BEWPatch.cs b/src/Bannerlord.ButterLib/ExceptionHandler/BEWPatch.cs index 4b78a355..2c5afe7e 100644 --- a/src/Bannerlord.ButterLib/ExceptionHandler/BEWPatch.cs +++ b/src/Bannerlord.ButterLib/ExceptionHandler/BEWPatch.cs @@ -60,7 +60,7 @@ internal record ExceptionIdentifier(Type Type, string? StackTrace, string Messag private static readonly MethodInfo? ScreenManagerTickMethod = AccessTools2.Method("TaleWorlds.ScreenSystem.ScreenManager:Tick"); private static readonly MethodInfo? ManagedScriptHolderTickComponentsMethod = AccessTools2.Method("TaleWorlds.Engine.ManagedScriptHolder:TickComponents"); private static readonly MethodInfo? MissionTickMethod = AccessTools2.Method("TaleWorlds.MountAndBlade.Mission:Tick"); - public static readonly MethodInfo? FinalizerMethod = AccessTools2.Method(typeof(BEWPatch), nameof(Finalizer)); + public static readonly MethodInfo? FinalizerMethod = SymbolExtensions2.GetMethodInfo((Exception x) => Finalizer(x)); private static void Finalizer(Exception? __exception) { diff --git a/src/Bannerlord.ButterLib/ObjectSystem/IMBObjectExtensionDataStore.cs b/src/Bannerlord.ButterLib/ObjectSystem/IMBObjectExtensionDataStore.cs index c9edccba..d94cbeb1 100755 --- a/src/Bannerlord.ButterLib/ObjectSystem/IMBObjectExtensionDataStore.cs +++ b/src/Bannerlord.ButterLib/ObjectSystem/IMBObjectExtensionDataStore.cs @@ -49,7 +49,7 @@ internal interface IMBObjectExtensionDataStore /// A game object. /// The variable's name. /// The variable. - public bool TryGetVariable(MBObjectBase @object, string name, out T value); + public bool TryGetVariable(MBObjectBase @object, string name, out T? value); /**** F L A G S ****/ diff --git a/src/Bannerlord.ButterLib/SubModuleWrappers2/Patches/MBSubModuleBasePatch.cs b/src/Bannerlord.ButterLib/SubModuleWrappers2/Patches/MBSubModuleBasePatch.cs index ae05999e..2edcb60d 100644 --- a/src/Bannerlord.ButterLib/SubModuleWrappers2/Patches/MBSubModuleBasePatch.cs +++ b/src/Bannerlord.ButterLib/SubModuleWrappers2/Patches/MBSubModuleBasePatch.cs @@ -291,76 +291,76 @@ internal static bool Enable(Harmony harmony) return true & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnSubModuleLoad"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnSubModuleLoadPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnSubModuleLoadPostfix(x))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnSubModuleUnloaded"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnSubModuleUnloadedPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnSubModuleUnloadedPostfix(x))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnApplicationTick"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnApplicationTickPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, float y) => OnApplicationTickPostfix(x, ref y))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnBeforeInitialModuleScreenSetAsRoot"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnBeforeInitialModuleScreenSetAsRootPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnBeforeInitialModuleScreenSetAsRootPostfix(x))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnGameStart"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnGameStartPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Game y, IGameStarter z) => OnGameStartPostfix(x, y, z))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:InitializeGameStarter"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:InitializeGameStarterPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Game y, IGameStarter z) => InitializeGameStarterPostfix(x, y, z))) // TODO: Won't work & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnServiceRegistration", logErrorInTrace: false), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnServiceRegistrationPostfix", logErrorInTrace: false)) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnServiceRegistrationPostfix(x))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:DoLoading"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:DoLoadingPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, bool y, Game z) => DoLoadingPostfix(x, ref y, z))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnGameLoaded"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnGameLoadedPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Game y, object z) => OnGameLoadedPostfix(x, y, z))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnCampaignStart"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnCampaignStartPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Game y, object z) => OnCampaignStartPostfix(x, y, z))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:BeginGameStart"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:BeginGameStartPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Game y) => BeginGameStartPostfix(x, y))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnGameEnd"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnGameEndPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Game y) => OnGameEndPostfix(x, y))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnGameInitializationFinished"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnGameInitializationFinishedPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Game y) => OnGameInitializationFinishedPostfix(x, y))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnBeforeMissionBehaviorInitialize"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnBeforeMissionBehaviourInitializePostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Mission y) => OnBeforeMissionBehaviourInitializePostfix(x, y))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnMissionBehaviorInitialize"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnMissionBehaviourInitializePostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Mission y) => OnMissionBehaviourInitializePostfix(x, y))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnMultiplayerGameStart"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnMultiplayerGameStartPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Game y, object z) => OnMultiplayerGameStartPostfix(x, y, z))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnNewGameCreated"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnNewGameCreatedPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Game y, object z) => OnNewGameCreatedPostfix(x, y, z))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:RegisterSubModuleObjects"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:RegisterSubModuleObjectsPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, bool y) => RegisterSubModuleObjectsPostfix(x, y))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:AfterRegisterSubModuleObjects"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:AfterRegisterSubModuleObjectsPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, bool y) => AfterRegisterSubModuleObjectsPostfix(x, y))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnAfterGameInitializationFinished"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnAfterGameInitializationFinishedPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, Game y, object z) => OnAfterGameInitializationFinishedPostfix(x, y, z))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnConfigChanged"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnConfigChangedPostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnConfigChangedPostfix(x))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:OnInitialState"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:OnInitialStatePostfix")) + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x) => OnInitialStatePostfix(x))) & harmony.TryPatch( AccessTools2.Method("TaleWorlds.MountAndBlade.MBSubModuleBase:AfterAsyncTickTick"), - postfix: AccessTools2.Method("Bannerlord.ButterLib.SubModuleWrappers2.Patches.MBSubModuleBasePatch:AfterAsyncTickTickPostfix")); + postfix: SymbolExtensions2.GetMethodInfo((MBSubModuleBase x, float y) => AfterAsyncTickTickPostfix(x, y))); #pragma warning restore format // @formatter:on } }