From 6e441f95c59ac4b3cffd5cc40fe08d3d68bed7fd Mon Sep 17 00:00:00 2001 From: Christopher Galpin <52485+CodeOptimist@users.noreply.github.com> Date: Sat, 4 May 2024 19:10:53 -0600 Subject: [PATCH] handle `Find.CurrentMap` --- Source/Client/Patches/Determinism.cs | 41 ++++++++++++++++------------ 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/Source/Client/Patches/Determinism.cs b/Source/Client/Patches/Determinism.cs index e6c6df24..24dacbef 100644 --- a/Source/Client/Patches/Determinism.cs +++ b/Source/Client/Patches/Determinism.cs @@ -123,31 +123,38 @@ static void Postfix(ref FloodUnfogResult __result) __result.allOnScreen = false; } } - + [HarmonyPatch] - static class UnnaturalCorpsePatch // v1.5 + static class UnnaturalCorpsePatch { static IEnumerable TargetMethods() { + // both of these actually combine "is valid" semantics with "is unseen" yield return AccessTools.DeclaredMethod(typeof(AnomalyUtility), nameof(AnomalyUtility.IsValidUnseenCell)); yield return AccessTools.DeclaredMethod(typeof(UnnaturalCorpse), nameof(UnnaturalCorpse.IsOutsideView)); } - static MethodInfo CellRectContains = AccessTools.Method(typeof(CellRect), nameof(CellRect.Contains)); - - static IEnumerable Transpiler(IEnumerable insts) - { - foreach (var inst in insts) - { - yield return inst; - - // consider it always outside view (not contained in CurrentViewRect) - if (inst.operand == CellRectContains) - { - yield return new CodeInstruction(OpCodes.Ldc_I4_0); - yield return new CodeInstruction(OpCodes.And); - } - } + // primarily for `IsValidUnseenCell()` but works fine for `IsOutsideView()` as well (maybe others) + static IEnumerable Transpiler(IEnumerable insts, ILGenerator gen) + { + var cm = new CodeMatcher(insts, gen); + + cm.MatchStartForward(Code.Call[AccessTools.DeclaredPropertyGetter(typeof(Find), nameof(Find.CurrentMap))]); + cm.SearchForward(inst => inst.Branches(out _)); + // consider it always on current map, so we can proceed (with finding a nice walkable cell etc.) + // keeping `Beq` and `Bne` avoids needing `[Code.Pop, Code.Pop]` + if (cm.Opcode == OpCodes.Beq_S) + cm.Advance(1).Insert(Code.Br_S[cm.InstructionAt(-1).operand]); // force jump as if equal + else if (cm.Opcode == OpCodes.Bne_Un_S) + cm.CreateLabelWithOffsets(1, out var label).Operand = label; // not-equal jump goes nowhere + else + cm.ThrowIfFalse("Couldn't find equality branch opcode following `Find.CurrentMap`", _ => false); + + cm.MatchStartForward(Code.Call[AccessTools.DeclaredMethod(typeof(CellRect), nameof(CellRect.Contains))]); + // consider it always outside view (not contained in `CurrentViewRect`) so we can proceed + cm.Advance(1).Insert([Code.Ldc_I4_0, Code.And]); + + return cm.Instructions(); } }