Beispiel #1
0
        /// <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);
        }