/// <summary> /// Transpiles the IsAreaClear method to modify the check for attachment points. /// </summary> /// <param name="name">The method patched.</param> /// <param name="method">The original method body.</param> /// <returns>The new transpiled method body.</returns> internal static IEnumerable <CodeInstruction> TranspileAreaClear(string name, IEnumerable <CodeInstruction> method) { var instructions = new List <CodeInstruction>(method); var powerMethod = typeof(BuildingDef).GetMethodSafe( "ArePowerPortsInValidPositions", false, PPatchTools.AnyArguments); var targetMethod = typeof(BuildStraightUpPatches).GetMethodSafe( nameof(CheckVirtualAttachments), true, typeof(bool), typeof(BuildingDef), typeof(int)); bool hasAnchor = false; // Find call to power port check if (powerMethod == null) { PUtil.LogWarning("Could not transpile {0} - no method found!".F(name)); } else { // Go back for branch instruction for (int i = instructions.Count - 1; i > 0; i--) { var instr = instructions[i]; var code = instr.opcode; if ((code == OpCodes.Call || code == OpCodes.Callvirt) && powerMethod == (instr.operand as MethodInfo)) { hasAnchor = true; #if DEBUG PUtil.LogDebug("Power method offset: {0:D}".F(i)); #endif } else if (hasAnchor && code.IsConditionalBranchInstruction()) { #if DEBUG PUtil.LogDebug("Branch offset: {0:D}".F(i)); #endif var store = PPatchTools.GetMatchingStoreInstruction( instructions[i - 1]); // Stack has "flag" on it, pass it to our method instructions.InsertRange(i, new List <CodeInstruction>(5) { // this new CodeInstruction(OpCodes.Ldarg_0), // cell new CodeInstruction(OpCodes.Ldarg_2), // Call new CodeInstruction(OpCodes.Call, targetMethod), // Duplicate new CodeInstruction(OpCodes.Dup), // Store store }); // Stack now has altered flag value PUtil.LogDebug("Patched " + name); break; } } if (!hasAnchor) { PUtil.LogWarning("Could not transpile {0} - no anchor found!".F(name)); } } return(instructions); }