public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { MethodInfo AndIsNotRockInfo = AccessTools.Method(typeof(InteractionSpot), nameof(InteractionSpot.AndIsNotRock)); bool doneOnce = false; List <CodeInstruction> list = instructions.ToList(); for (int i = 0; i < list.Count; i++) { CodeInstruction inst = list[i]; yield return(inst); //if (thingList2[index].def.passability == Traversability.Impassable) //if (thingList2[index].def.passability == Traversability.Impassable && thingList2[index] is not rock) if (inst.LoadsConstant(2) && !doneOnce) //Traversability.Impassable { doneOnce = true; yield return(new CodeInstruction(list[i - 5].opcode, list[i - 5].operand)); //thingList2, but no labels yield return(list[i - 4]); //index yield return(list[i - 3]); //thingList[index] yield return(new CodeInstruction(OpCodes.Call, AndIsNotRockInfo)); i++; yield return(new CodeInstruction(OpCodes.Brtrue, list[i].operand) { labels = list[i].labels }); } } }
public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { MethodInfo SetFontInfo = AccessTools.Property(typeof(Text), "Font").GetSetMethod(); MethodInfo DrawSurgeryOptionInfo = AccessTools.Method(typeof(SurgergyUnlimitedPawnSettings), nameof(SurgergyUnlimitedPawnSettings.DrawSurgeryOption)); //Insert before //IL_0324: ldc.i4.1 //IL_0325: call void Verse.Text::set_Font(valuetype Verse.GameFont) List <CodeInstruction> list = instructions.ToList(); for (int i = 0; i < list.Count; i++) { CodeInstruction inst = list[i]; if (i + 1 < list.Count && inst.LoadsConstant(GameFont.Small) && list[i + 1].Calls(SetFontInfo)) //Text.Small { //Draw pawn surgery option //Rect leftRect, Pawn pawn, float curY yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Ldarg_1)); yield return(new CodeInstruction(OpCodes.Ldarga_S, 2)); yield return(new CodeInstruction(OpCodes.Call, DrawSurgeryOptionInfo)); } yield return(inst); } }
static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { // Put all the instructions in an array as we need to be able to peek forward CodeInstruction[] instructionArray = instructions.ToArray(); // Get the field info for the planetCount field in the StarData class FieldInfo starInfo_planetCount = AccessTools.Field(typeof(StarData), "planetCount"); // We have to skip the initializations for the following: // * Black hole // * Neutron Star // * White Dwarf // * Giant Star // This is due to them having fixed numbers of planets initialized and to fix would require more invasive changes int skipped = 0; // Loop through all the instructions for (int i = 0; i < instructionArray.Length; i++) { // Get the current instruction CodeInstruction instruction = instructionArray[i]; // Make sure it's not the last instruction and then check if it loads a constant if (i != (instructionArray.Length - 1) && instruction.LoadsConstant()) { // If a constant was loaded, then check if that constant is assigned to the planet count in the generator if (instructionArray[i + 1].StoresField(starInfo_planetCount)) { // We have to skip the first few assignements, detailed above with declaration of the variable if (skipped < 7) { skipped++; } else { // If this is not one of the special cases, override the opcode of the IL instruction // for the constant value to be 8 for every system instruction.opcode = OpCodes.Ldc_I4_8; } } } // Add the instruction to the iEnumerable to return, modified if required yield return(instruction); } }
/// <summary>Tests if the code instruction loads an enum constant</summary> /// <param name="code">The <see cref="CodeInstruction"/></param> /// <param name="e">The enum</param> /// <returns>True if the instruction loads the constant</returns> /// public static bool LoadsConstant(this CodeInstruction code, Enum e) { return(code.LoadsConstant(Convert.ToInt64(e))); }