Skip to content

Commit 6e441f9

Browse files
committed
handle Find.CurrentMap
1 parent 1cfbc5c commit 6e441f9

File tree

1 file changed

+24
-17
lines changed

1 file changed

+24
-17
lines changed

Source/Client/Patches/Determinism.cs

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -123,31 +123,38 @@ static void Postfix(ref FloodUnfogResult __result)
123123
__result.allOnScreen = false;
124124
}
125125
}
126-
126+
127127
[HarmonyPatch]
128-
static class UnnaturalCorpsePatch // v1.5
128+
static class UnnaturalCorpsePatch
129129
{
130130
static IEnumerable<MethodBase> TargetMethods()
131131
{
132+
// both of these actually combine "is valid" semantics with "is unseen"
132133
yield return AccessTools.DeclaredMethod(typeof(AnomalyUtility), nameof(AnomalyUtility.IsValidUnseenCell));
133134
yield return AccessTools.DeclaredMethod(typeof(UnnaturalCorpse), nameof(UnnaturalCorpse.IsOutsideView));
134135
}
135136

136-
static MethodInfo CellRectContains = AccessTools.Method(typeof(CellRect), nameof(CellRect.Contains));
137-
138-
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> insts)
139-
{
140-
foreach (var inst in insts)
141-
{
142-
yield return inst;
143-
144-
// consider it always outside view (not contained in CurrentViewRect)
145-
if (inst.operand == CellRectContains)
146-
{
147-
yield return new CodeInstruction(OpCodes.Ldc_I4_0);
148-
yield return new CodeInstruction(OpCodes.And);
149-
}
150-
}
137+
// primarily for `IsValidUnseenCell()` but works fine for `IsOutsideView()` as well (maybe others)
138+
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> insts, ILGenerator gen)
139+
{
140+
var cm = new CodeMatcher(insts, gen);
141+
142+
cm.MatchStartForward(Code.Call[AccessTools.DeclaredPropertyGetter(typeof(Find), nameof(Find.CurrentMap))]);
143+
cm.SearchForward(inst => inst.Branches(out _));
144+
// consider it always on current map, so we can proceed (with finding a nice walkable cell etc.)
145+
// keeping `Beq` and `Bne` avoids needing `[Code.Pop, Code.Pop]`
146+
if (cm.Opcode == OpCodes.Beq_S)
147+
cm.Advance(1).Insert(Code.Br_S[cm.InstructionAt(-1).operand]); // force jump as if equal
148+
else if (cm.Opcode == OpCodes.Bne_Un_S)
149+
cm.CreateLabelWithOffsets(1, out var label).Operand = label; // not-equal jump goes nowhere
150+
else
151+
cm.ThrowIfFalse("Couldn't find equality branch opcode following `Find.CurrentMap`", _ => false);
152+
153+
cm.MatchStartForward(Code.Call[AccessTools.DeclaredMethod(typeof(CellRect), nameof(CellRect.Contains))]);
154+
// consider it always outside view (not contained in `CurrentViewRect`) so we can proceed
155+
cm.Advance(1).Insert([Code.Ldc_I4_0, Code.And]);
156+
157+
return cm.Instructions();
151158
}
152159
}
153160

0 commit comments

Comments
 (0)