Ejemplo n.º 1
0
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            List <CodeInstruction> codes             = TranspilerUtil.ToCodeList(instructions);
            MethodInfo             calcStopPosAndDir = typeof(NetLane).GetMethod(nameof(NetLane.CalculateStopPositionAndDirection));

            CodeInstruction searchInstr = new CodeInstruction(OpCodes.Call, calcStopPosAndDir);
            int             index       = codes.FindIndex(instr => TranspilerUtil.IsSameInstruction(instr, searchInstr));

            if (index > -1)
            {
                int targetIndex     = index + 1;
                int replace1stIndex = targetIndex + 3;
                if (codes[replace1stIndex].opcode.Equals(OpCodes.Ldarg_2))
                {
                    codes.RemoveRange(replace1stIndex + 1, 6);
                    codes.Insert(replace1stIndex + 1, new CodeInstruction(OpCodes.Ldloc_3));
                }
                else
                {
                    throw new Exception("Could not find Ldarg.2 instruction or instructions has been patched");
                }
                codes.InsertRange(targetIndex, GetInstructions());
            }
            else
            {
                throw new Exception("Could not find CalculateStopPositionAndDirection call or instructions has been patched");
            }

            return(codes);
        }
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            List <CodeInstruction> codes = TranspilerUtil.ToCodeList(instructions);

            int minus1OpIndex = TranspilerUtil.SearchInstruction(codes, new CodeInstruction(OpCodes.Ldc_I4_M1), 0);

            //check index and previous instruction
            if (minus1OpIndex != -1 && codes[minus1OpIndex + 1].opcode.Equals(OpCodes.Bne_Un))
            {
                int ldArg0Index = TranspilerUtil.SearchInstruction(codes, new CodeInstruction(OpCodes.Ldarg_0), minus1OpIndex);
                //check index and previous instruction
                if (ldArg0Index != -1 && codes[ldArg0Index - 1].opcode.Equals(OpCodes.Stfld))
                {
                    int targetIndex = minus1OpIndex + 2;//move index to first item to remove
                    // replace all instruction between targetIndex and Ldarg_0
                    codes.RemoveRange(targetIndex, ldArg0Index - targetIndex);

                    var newInstructions = new[] {
                        new CodeInstruction(OpCodes.Ldarg_1), // load node id
                        new CodeInstruction(OpCodes.Call, typeof(ClickNodeButtonPatch).GetMethod(nameof(ClickNodeButtonPatch.ToggleTrafficLight))),
                    };
                    codes.InsertRange(targetIndex, newInstructions);
                }
                else
                {
                    throw new Exception("Could not found Ldarg_0 Instruction or instruction was already patched!");
                }
            }
            else
            {
                throw new Exception("Could not found Ldc_I4_M1 Instruction or previous instruction was already patched!");
            }

            return(codes);
        }
        // code from: https://github.com/Strdate/SmartIntersections/blob/master/SmartIntersections/Patch/LoadPathsPatch.cs
        public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions)
        {
            var fTempNodeBuffer = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempNodeBuffer))
                                  ?? throw new Exception("cound not find NetManager.m_tempNodeBuffer");
            var mClear = AccessTools.DeclaredMethod(fTempNodeBuffer.FieldType, nameof(FastList <ushort> .Clear))
                         ?? throw new Exception("cound not find m_tempNodeBuffer.Clear");
            var mAfterIntersectionBuilt = AccessTools.DeclaredMethod(
                typeof(LoadPathsPatch), nameof(AfterIntersectionBuilt))
                                          ?? throw new Exception("cound not find AfterIntersectionBuilt()");

            List <CodeInstruction> codes = TranspilerUtil.ToCodeList(instructions);

            bool comp(int i) =>
            codes[i].opcode == OpCodes.Ldfld && codes[i].operand == fTempNodeBuffer &&
            codes[i + 1].opcode == OpCodes.Callvirt && codes[i + 1].operand == mClear;

            int index = TranspilerUtil.SearchGeneric(codes, comp, index: 0, counter: 2);

            index -= 1; // index to insert instructions.

            var newInstructions = new[] {
                new CodeInstruction(OpCodes.Ldarg_0), // load argument info
                new CodeInstruction(OpCodes.Call, mAfterIntersectionBuilt),
            };

            TranspilerUtil.InsertInstructions(codes, newInstructions, index);
            return(codes);
        }
Ejemplo n.º 4
0
        public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions)
        {
            var fTempSegmentBuffer = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempSegmentBuffer))
                                     ?? throw new Exception("Could not find NetManager.m_tempSegmentBuffer");
            var mSize = AccessTools.DeclaredField(fTempSegmentBuffer.FieldType, nameof(FastList <ushort> .m_size))
                        ?? throw new Exception("Could not find m_tempSegmentBuffer.m_size");
            var mAfterIntersectionBuilt = AccessTools.DeclaredMethod(
                typeof(LoadPathsPatch), nameof(AfterIntersectionBuilt))
                                          ?? throw new Exception("Could not find AfterIntersectionBuilt()");

            List <CodeInstruction> codes = TranspilerUtil.ToCodeList(instructions);

            bool predicate(int i) =>
            codes[i].opcode == OpCodes.Blt &&
            codes[i - 1].opcode == OpCodes.Ldfld && codes[i - 1].operand == mSize &&
            codes[i - 2].opcode == OpCodes.Ldfld && codes[i - 2].operand == fTempSegmentBuffer;

            int index = TranspilerUtil.SearchGeneric(codes, predicate, index: 0, counter: 1);

            index += 1; // index to insert instructions. (end of the loop)

            var newInstructions = new[] {
                new CodeInstruction(OpCodes.Ldarg_0), // load argument info
                new CodeInstruction(OpCodes.Call, mAfterIntersectionBuilt),
            };

            TranspilerUtil.InsertInstructions(codes, newInstructions, index);
            return(codes);
        }
Ejemplo n.º 5
0
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            List <CodeInstruction> codes = TranspilerUtil.ToCodeList(instructions);

            int minus1OpIndex = TranspilerUtil.SearchInstruction(codes, new CodeInstruction(OpCodes.Ldc_I4_M1), 0);

            //check index and previous instruction
            if (minus1OpIndex != -1 && codes[minus1OpIndex + 1].opcode.Equals(OpCodes.Bne_Un))
            {
                int ldArg0Index = TranspilerUtil.SearchInstruction(codes, new CodeInstruction(OpCodes.Ldarg_0), minus1OpIndex);
                //check index and previous instruction
                if (ldArg0Index != -1 && codes[ldArg0Index - 1].opcode.Equals(OpCodes.Stfld))
                {
                    int targetIndex = minus1OpIndex + 2;//move index to first item to remove
                    // replace all instruction between targetIndex and Ldarg_0
                    codes.RemoveRange(targetIndex, ldArg0Index - targetIndex);
                    codes.InsertRange(targetIndex, GetReplacementInstructions());
                }
                else
                {
                    throw new Exception("Could not found Ldarg_0 Instruction or instruction was already patched!");
                }
            }
            else
            {
                throw new Exception("Could not found Ldc_I4_M1 Instruction or previous instruction was already patched!");
            }

            return(codes);
        }
Ejemplo n.º 6
0
        public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions)
        {
            List <CodeInstruction> codes = TranspilerUtil.ToCodeList(instructions);
            int searchInstruction        = TranspilerUtil.SearchInstruction(codes, new CodeInstruction(OpCodes.Call, CheckSegmentProblemsMethod()), 0, 1, 3);

            if (searchInstruction != -1 &&
                codes[searchInstruction + 1].opcode.Equals(OpCodes.Ldc_I4_1) &&
                codes[searchInstruction + 2].opcode.Equals(OpCodes.Ret))
            {
                int startTarget         = searchInstruction + 3; //first instruction to remove, contains labels to copy
                int createPathCallIndex = TranspilerUtil.SearchInstruction(codes, new CodeInstruction(OpCodes.Callvirt, CreatePathMethod()), startTarget);

                if (createPathCallIndex != -1 && codes[createPathCallIndex + 1].opcode.Equals(OpCodes.Brfalse))
                {
                    List <Label> labels = codes[startTarget].labels;
                    codes.RemoveRange(startTarget, createPathCallIndex + 1 - startTarget);
                    codes.InsertRange(startTarget, GetInjectInstructions(labels));
                }
                else
                {
                    throw new Exception("Could not find CreatePath call or instructions has been patched");
                }
            }
            else
            {
                throw new Exception("Could not find 3rd. CheckSegmentProblems call or instructions has been patched");
            }

            return(codes);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Inserts MayDespawn call into the instruction chain
        /// </summary>
        /// <param name="instructions"></param>
        /// <returns></returns>
        public static IEnumerable <CodeInstruction> ReplaceSimulationStepIsCongestedCheck(IEnumerable <CodeInstruction> instructions)
        {
            List <CodeInstruction> codes = TranspilerUtil.ToCodeList(instructions);

            bool found = false;

            foreach (CodeInstruction instruction in codes)
            {
                if (!found && (instruction.opcode.Equals(OpCodes.Brfalse_S) || instruction.opcode.Equals(OpCodes.Brfalse)))
                {
                    found = true;
                    yield return(instruction);                                                                // return found instruction

                    yield return(new CodeInstruction(OpCodes.Ldsfld, _vehicleBehaviourManagerInstanceField)); // loadInstFiled

                    yield return(new CodeInstruction(OpCodes.Ldarg_1));                                       // vehicleID

                    yield return(new CodeInstruction(OpCodes.Ldarg_2));                                       // loadVehicleData

                    yield return(new CodeInstruction(OpCodes.Callvirt, _mayDespawnMethod));                   // callMayDespawn

                    yield return(instruction.Clone());                                                        //brfalse_s || brfalse - clone including label!
                }
                else
                {
                    yield return(instruction);
                }
            }

            /*
             * -----------------------------------------------------------------------------------
             * SimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos)
             * -----------------------------------------------------------------------------------
             *
             * IL_0000: ldarg.2      // vehicleData
             * IL_0001: ldfld        valuetype ['Assembly-CSharp']Vehicle/Flags ['Assembly-CSharp']Vehicle::m_flags
             * IL_0006: ldc.i4       67108864 // 0x04000000
             * IL_000b: and
             * IL_000c: brfalse.s    IL_0027
             *
             * // NON-STOCK CODE START
             * IL_000e: ldsfld       class TrafficManager.Manager.Impl.VehicleBehaviorManager TrafficManager.Manager.Impl.VehicleBehaviorManager::Instance
             * IL_0013: ldarg.1     // vehicleID
             * IL_0013: ldarg.2      // vehicleData
             * IL_0014: callvirt     instance bool TrafficManager.Manager.Impl.VehicleBehaviorManager::MayDespawn(valuetype ['Assembly-CSharp']Vehicle&)
             * IL_0019: brfalse.s    IL_0027
             * // NON-STOCK CODE STOP
             *
             * ...
             */
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Revrites instructions adding necessary TMPE calls
        /// </summary>
        /// <param name="il"> Il Generator</param>
        /// <param name="instructions">List of instructions</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static IEnumerable <CodeInstruction> TranspileTramTrainSimulationStep(ILGenerator il, IEnumerable <CodeInstruction> instructions)
        {
            List <CodeInstruction> codes = TranspilerUtil.ToCodeList(instructions);

            MethodBase trySpawnCall = TranspilerUtil.DeclaredMethod <TrySpawnDelegate>(typeof(VehicleAI), "TrySpawn");

            CodeInstruction searchInstruction = new CodeInstruction(OpCodes.Callvirt, trySpawnCall);
            int             index             = codes.FindIndex(instruction => TranspilerUtil.IsSameInstruction(instruction, searchInstruction));

            if (index > -1)
            {
                int          target1   = index + 2;
                Label        label     = il.DefineLabel();
                List <Label> oldLabels = codes[target1].labels.ToList();
                codes[target1].labels.Clear();                 // clear labels -> they are moved to new instruction
                codes[target1].labels.Add(label);              //add label to next instruction (if() false jump)
                List <CodeInstruction> newInstructions = GetUpdatePositionInstructions(label);
                newInstructions[0].labels.AddRange(oldLabels); // add old labels to redirect here
                codes.InsertRange(target1, newInstructions);   // insert new instructions

                CodeInstruction searchInstruction2 = new CodeInstruction(OpCodes.Ldfld, typeof(Vehicle).GetField(nameof(Vehicle.m_blockCounter)));
                int             index2             = codes.FindIndex(instruction => TranspilerUtil.IsSameInstruction(instruction, searchInstruction2));
                if (index2 > -1 && codes[index2 + 1].opcode.Equals(OpCodes.Ldc_I4) && codes[index2 + 2].opcode.Equals(OpCodes.Bne_Un))
                {
                    int   target2  = index2 + 2;
                    Label retLabel = (Label)codes[target2].operand;
                    codes.InsertRange(target2 + 1, GetModifiedBlockCounterInstructions(retLabel));
                }
                else
                {
                    throw new Exception("Could not find m_blockCounter field usage or instructions has been patched");
                }
            }
            else
            {
                throw new Exception("Could not find TrySpawn call or instructions has been patched");
            }

            return(codes);
        }