From d57df7a1c2446ea4951d76c46fd41d45d7fce6c3 Mon Sep 17 00:00:00 2001 From: thakyZ <950594+thakyZ@users.noreply.github.com> Date: Thu, 10 Apr 2025 18:16:58 -0700 Subject: [PATCH] fix: a issue with hash conflicts and fixes erdelf/MinifyEverything#17 --- Source/MinifyEverything/MinifyEverything.cs | 63 ++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/Source/MinifyEverything/MinifyEverything.cs b/Source/MinifyEverything/MinifyEverything.cs index a17cd07..3191dd1 100644 --- a/Source/MinifyEverything/MinifyEverything.cs +++ b/Source/MinifyEverything/MinifyEverything.cs @@ -57,6 +57,13 @@ public MinifyMod(ModContentPack content) : base(content) harmony.Patch(AccessTools.Method(typeof(WorkGiver_ConstructDeliverResourcesToBlueprints), nameof(WorkGiver_Scanner.JobOnThing)), new HarmonyMethod(typeof(MinifyEverything), nameof(MinifyEverything.JobOnThingPrefix))); harmony.Patch(AccessTools.EnumeratorMoveNext(AccessTools.Method(typeof(ThingDef), nameof(ThingDef.ConfigErrors))), transpiler: new HarmonyMethod(typeof(MinifyEverything), nameof(MinifyEverything.ConfigErrorTranspiler))); + harmony.Patch(typeof(ShortHashGiver).FindIncludingInnerTypes((Type type) => + AccessTools.FirstMethod(type, (MethodInfo method) => + method.Name.Contains(nameof(ShortHashGiver.GiveAllShortHashes)) && + !method.Name.Equals(nameof(ShortHashGiver.GiveAllShortHashes)) && + method.GetParameters().Length == 1 && + method.GetParameters()[0].ParameterType.IsEquivalentTo(typeof(ValueTuple>)))), + transpiler: new HarmonyMethod(typeof(MinifyEverything), nameof(MinifyEverything.GiveAllShortHashesTranspiler))); } internal MinifySettings Settings => this.settings ??= this.GetSettings(); @@ -178,7 +185,12 @@ public static class MinifyEverything AccessTools.StaticFieldRefAccess>>(AccessTools.Field(typeof(ShortHashGiver), "takenHashesPerDeftype")); private static readonly AccessTools.FieldRef cachedGraphic = AccessTools.FieldRefAccess("cachedGraphic"); - + + // We collect a set of names of ThingDefs we create. + private static HashSet thisModsDefNames = []; + + private static Func testIfOurDef = TestIfOurDef; + public static bool MinifiedThingGetGraphic(MinifiedThing __instance, ref Graphic __result) { ref var cache = ref cachedGraphic(__instance); @@ -206,8 +218,13 @@ public static void AddMinifiedFor(ThingDef def, bool hash = true) def.minifiedDef = minified; if (def.blueprintDef == null) + { blueprintGen(def, false); + // the blueprintGen method creates a new def as well. + thisModsDefNames.Add(def.defName); + } + //AddCategoriesIfNeeded(def, true); ThingDef minifiedDef = blueprintGen(def, true, def.blueprintDef); @@ -216,6 +233,7 @@ public static void AddMinifiedFor(ThingDef def, bool hash = true) minifiedDef.PostLoad(); if(hash) giveShortHash(minifiedDef, typeof(ThingDef), takenShortHashes()[typeof(ThingDef)]); + thisModsDefNames.Add(minifiedDef.defName); //Log.Message(minifiedDef.defName); DefDatabase.Add(minifiedDef); } @@ -320,6 +338,49 @@ public static bool JobOnThingPrefix(Pawn pawn, Thing t) return true; } + public static bool TestIfOurDef(Def def) + { + return thisModsDefNames.Contains(def.defName); + } + + public static IEnumerable GiveAllShortHashesTranspiler(IEnumerable instructions) + { + var method1 = AccessTools.GetDeclaredMethods(typeof(GenCollection)).FirstOrDefault((MethodInfo x) => + x.Name.Equals(nameof(GenCollection.SortBy)) && + x.GetGenericArguments().Length == 2 && + x.GetParameters().Length == 2 + )?.MakeGenericMethod([typeof(Def), typeof(string)]); + + if (method1 == null) + { + Log.Error($"Failed to find the method GenCollection.SortBy(this List, Func)"); + return instructions; + } + + var method2 = AccessTools.GetDeclaredMethods(typeof(GenCollection)).FirstOrDefault((MethodInfo x) => + x.Name.Equals(nameof(GenCollection.SortBy)) && + x.GetGenericArguments().Length == 3 && + x.GetParameters().Length == 3 + )?.MakeGenericMethod([typeof(Def), typeof(bool), typeof(string)]); + + if (method2 == null) + { + Log.Error($"Failed to find the method GenCollection.SortBy(this List, Func, Func)"); + return instructions; + } + + var codeMatcher = new CodeMatcher(instructions) + .MatchStartForward([CodeMatch.Calls(method1)]) + .ThrowIfNotMatch($"Failed to match in match pattern #1 of transpiler {nameof(GiveAllShortHashesTranspiler)}."); + var labels = codeMatcher.Instruction.ExtractLabels(); + return codeMatcher.SetInstruction(new CodeInstruction(OpCodes.Call, method2).WithLabels(labels)) + .MatchStartBackwards([CodeMatch.WithOpcodes([OpCodes.Ldloc_3])]) + .ThrowIfNotMatch($"Failed to match in match pattern #2 of transpiler {nameof(GiveAllShortHashesTranspiler)}.") + .Advance(1) + .Insert([CodeInstruction.LoadField(typeof(MinifyEverything), nameof(testIfOurDef))]) + .Instructions(); + } + public static IEnumerable DesignateSingleCellTranspiler(IEnumerable instructions) { MethodInfo placeBlueprint = AccessTools.Method(typeof(GenConstruct), nameof(GenConstruct.PlaceBlueprintForBuild));