diff --git a/1.2/Assemblies/VisualExceptions.dll b/1.2/Assemblies/VisualExceptions.dll new file mode 100644 index 0000000..c37d4b2 Binary files /dev/null and b/1.2/Assemblies/VisualExceptions.dll differ diff --git a/1.3/Assemblies/VisualExceptions.dll b/1.3/Assemblies/VisualExceptions.dll new file mode 100644 index 0000000..eee635a Binary files /dev/null and b/1.3/Assemblies/VisualExceptions.dll differ diff --git a/About/Manifest.xml b/About/Manifest.xml index ea0b768..db66b0e 100644 --- a/About/Manifest.xml +++ b/About/Manifest.xml @@ -1,7 +1,7 @@  net.pardeike.rimworld.mod.visualexceptions - 1.0.4.0 + 1.1.0.0
  • 1.2.0
  • 1.3.0
  • diff --git a/Current/Assemblies/0Harmony.dll b/Current/Assemblies/0Harmony.dll deleted file mode 100644 index 779798c..0000000 Binary files a/Current/Assemblies/0Harmony.dll and /dev/null differ diff --git a/Current/Assemblies/VisualExceptions.dll b/Current/Assemblies/VisualExceptions.dll deleted file mode 100644 index 2ba8fdc..0000000 Binary files a/Current/Assemblies/VisualExceptions.dll and /dev/null differ diff --git a/LoadFolders.xml b/LoadFolders.xml index a484219..923c000 100644 --- a/LoadFolders.xml +++ b/LoadFolders.xml @@ -1,10 +1,10 @@
  • /
  • -
  • Current
  • +
  • 1.2
  • /
  • -
  • Current
  • +
  • 1.3
  • \ No newline at end of file diff --git a/Source/Patcher.cs b/Source/Patcher.cs index fdc7700..f9a1c0b 100644 --- a/Source/Patcher.cs +++ b/Source/Patcher.cs @@ -18,7 +18,7 @@ static class Patcher internal static void Apply() { var harmony = new Harmony(harmony_id); - _ = new PatchClassProcessor(harmony, typeof(RunloopExceptionHandler)).Patch(); + _ = new PatchClassProcessor(harmony, typeof(ExceptionsAndActivatorHandler)).Patch(); _ = new PatchClassProcessor(harmony, typeof(ShowLoadingExceptions)).Patch(); _ = new PatchClassProcessor(harmony, typeof(AddHarmonyTabWhenNecessary)).Patch(); _ = new PatchClassProcessor(harmony, typeof(RememberHarmonyIDs)).Patch(); @@ -29,16 +29,82 @@ internal static void Apply() // adds exception handlers // [HarmonyPatch] - static class RunloopExceptionHandler + static class ExceptionsAndActivatorHandler { static readonly MethodInfo Handle = SymbolExtensions.GetMethodInfo(() => ExceptionState.Handle(null)); + static readonly Dictionary createInstanceMethods = new Dictionary + { + { SymbolExtensions.GetMethodInfo(() => Activator.CreateInstance(typeof(void))), SymbolExtensions.GetMethodInfo(() => PatchedActivator.CreateInstance(typeof(void), null)) }, + { SymbolExtensions.GetMethodInfo(() => Activator.CreateInstance(typeof(void), new object[0])), SymbolExtensions.GetMethodInfo(() => PatchedActivator.CreateInstance(typeof(void), new object[0], null)) }, + }; + + class PatchedActivator + { + static object GetInfo(object obj) + { + if (obj == null) return null; + var def = obj as Def; + if (def != null) return def; + var fields = AccessTools.GetDeclaredFields(def.GetType()); + foreach (var field in fields) + if (typeof(Def).IsAssignableFrom(field.FieldType)) + { + def = field.GetValue(obj) as Def; + if (def != null) return def; + } + return obj; + } + + internal static object CreateInstance(Type type, object obj) + { + if (type != null) return Activator.CreateInstance(type); + var info = GetInfo(obj); + var message = "Activator.CreateInstance(type) called with a null type"; + if (info != null) message += $", possible context={info}"; + throw new ArgumentNullException(message); + } + + internal static object CreateInstance(Type type, object[] objects, object me) + { + if (type != null) return Activator.CreateInstance(type, objects); + var info = GetInfo(me); + var message = $"Activator.CreateInstance(type, object[]) called with a null type, objects=[{objects.Join(o => o?.ToString() ?? "null")}]"; + if (info != null) message += $", possible context={info}"; + throw new ArgumentNullException(message); + } + } + [HarmonyPriority(int.MaxValue)] - internal static IEnumerable Transpiler(IEnumerable instructions) + internal static IEnumerable Transpiler(IEnumerable instructions, MethodBase original) { var list = instructions.ToList(); - var idx = 0; + var found = false; + for (var i = 0; i < list.Count; i++) + if (list[i].opcode == OpCodes.Call) + if (list[i].operand is MethodInfo methodInfo && createInstanceMethods.TryGetValue(methodInfo, out var replacement)) + { + if (original.IsStatic) + { + var parameters = original.GetParameters(); + var defIndex = parameters.Select(p => p.ParameterType).FirstIndexOf(type => type.IsGenericType == false && type.IsByRef == false && typeof(Def).IsAssignableFrom(type)); + if (defIndex >= 0 && defIndex < parameters.Length) + { + list.Insert(i, new CodeInstruction(OpCodes.Ldarg, defIndex)); + list[++i].operand = replacement; + found = true; + } + } + else + { + list.Insert(i, new CodeInstruction(OpCodes.Ldarg_0)); + list[++i].operand = replacement; + found = true; + } + } + + var idx = 0; try { while (true) @@ -62,6 +128,7 @@ internal static IEnumerable Transpiler(IEnumerable block.blockType == ExceptionBlockType.BeginCatchBlock && block.catchType == typeof(Exception)); } + static bool HasCreateInstance(CodeInstruction code) + { + return code.operand is MethodInfo methodInfo && createInstanceMethods.ContainsKey(methodInfo); + } + static bool HasCatch(MethodBase method) { try { - var result = PatchProcessor.GetOriginalInstructions(method).Any(IsCatchException); - return result; + if (PatchProcessor.GetOriginalInstructions(method).Any(code => IsCatchException(code) || HasCreateInstance(code))) + return true; } catch { - return false; } + return false; } } diff --git a/Source/VisualExceptions.csproj b/Source/VisualExceptions.csproj index a0ba577..b54212b 100644 --- a/Source/VisualExceptions.csproj +++ b/Source/VisualExceptions.csproj @@ -7,10 +7,10 @@ net472 8.0 x64 - ..\Current\Assemblies\ + ..\1.3\Assemblies\ true false - 1.0.4.0 + 1.1.0.0 Copyright Andreas Pardeike @@ -30,9 +30,10 @@ - + - + runtime + all @@ -84,7 +85,7 @@ ModBuilder XMLPut -file "$(MSBuildProjectDirectory)\..\About\Manifest.xml" -xpath /Manifest/version -value "{{$(MSBuildProjectName)-version}}" ) if defined INSTALL_MOD ( - "%INSTALL_MOD%" "$(Configuration)" "$(MSBuildProjectDirectory)\..\" "$(MSBuildProjectName)" "About Current Sounds Textures" "LoadFolders.xml" + "%INSTALL_MOD%" "$(Configuration)" "$(MSBuildProjectDirectory)\..\" "$(MSBuildProjectName)" "About 1.2 1.3 Sounds Textures" "LoadFolders.xml" ) Brrainz