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); }
/// <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); }