//Insert FilterForUrgentHediffs when counting needed medicine
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            MethodInfo SortByTendPriorityInfo = AccessTools.Method(
                typeof(TendUtility), nameof(TendUtility.SortByTendPriority));
            MethodInfo filterMethodInfo = AccessTools.Method(
                typeof(GetMedicineCountToFullyHeal_Patch), nameof(FilterInjuriesForMedCount));
            FieldInfo filterMethodParameter = AccessTools.Field(typeof(Medicine), "tendableHediffsInTendPriorityOrder");

            List <CodeInstruction> instructionList = instructions.ToList();

            for (int i = 0; i < instructionList.Count; i++)
            {
                CodeInstruction instruction = instructionList[i];
                if (instruction.LoadsField(filterMethodParameter))
                {
                    i++;
                    CodeInstruction nextInstruction = instructionList[i];
                    if (nextInstruction.Calls(SortByTendPriorityInfo))
                    {
                        //insert before the sort call
                        yield return(new CodeInstruction(OpCodes.Ldsfld, filterMethodParameter));

                        yield return(new CodeInstruction(OpCodes.Call, filterMethodInfo));
                    }
                    yield return(instruction);

                    yield return(nextInstruction);
                }
                else
                {
                    yield return(instruction);
                }
            }
        }
Пример #2
0
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            FieldInfo buildingInfo = AccessTools.Field(typeof(ThingDef), nameof(ThingDef.building));

            List <CodeInstruction> instList = instructions.ToList();

            for (int i = 0; i < instList.Count(); i++)
            {
                CodeInstruction inst = instList[i];

                if (inst.LoadsField(buildingInfo))
                {
                    //IL_0015: ldarg.0      // this
                    //IL_0016: ldfld        class RimWorld.BuildingProperties Verse.ThingDef::building

                    //replace the this.building code with the end return true:

                    instList[i - 1].opcode = OpCodes.Ldc_I4_1;                    //preserve label here
                    instList[i]            = new CodeInstruction(OpCodes.Ret);

                    //chop off rest of the code that checks rock and smooth ezpz, we can corner touch rocks now!
                    return(instList.Take(i + 1));
                }
            }
            Verse.Log.Warning("Replace Stuff failed to patch CanInteractThroughCorners");
            return(instructions);
        }
Пример #3
0
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            //		public static void BeginGroup(Rect position);
            MethodInfo BeginGroupInfo = AccessTools.Method(typeof(GUI), nameof(GUI.BeginGroup), new Type[] { typeof(Rect) });

            //class Verse.ThingFilter RimWorld.StorageSettings::'filter'
            FieldInfo filterInfo = AccessTools.Field(typeof(StorageSettings), "filter");
            int       count      = 0;

            bool firstTopAreaHeight         = true;
            List <CodeInstruction> instList = instructions.ToList();

            for (int i = 0; i < instList.Count; i++)
            {
                CodeInstruction inst = instList[i];

                //replace
                //  settings.filter
                //with
                //  RankComp.GetFilter(settings.filter, FillTab.curRank)
                //but there's another .filter that is Parent filter so check for .settings

                //IL_01f0: ldfld        class RimWorld.StorageSettings RimWorld.ITab_Storage/'<>c__DisplayClass12_0'::settings
                //IL_01f5: ldfld        class Verse.ThingFilter RimWorld.StorageSettings::'filter'

                //What why the ITab_Storage.\u003C\u003Ec__DisplayClass12_0 really

                //Soo I guess just skip it for the first call to filter in the method
                if (inst.LoadsField(filterInfo) && count++ > 0)
                {
                    //instead of settings.filter, do RankComp.GetFilter(settings, curRank)
                    yield return(new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(FillTab), "curRank")));

                    yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(RankComp), "GetFilter")));
                }
                else
                {
                    yield return(inst);
                }

                if (firstTopAreaHeight &&
                    inst.Calls(GetTopAreaHeight))
                {
                    firstTopAreaHeight = false;
                    yield return(new CodeInstruction(OpCodes.Ldc_R4, TopAreaHeight.rankHeight));

                    yield return(new CodeInstruction(OpCodes.Sub));
                }

                if (inst.Calls(BeginGroupInfo))
                {
                    yield return(new CodeInstruction(OpCodes.Ldarg_0));                   //ITab_Storage this

                    yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(FillTab), nameof(DrawRanking))));
                }
            }
        }
        //AllowsPlacing(BuildableDef checkingDef, IntVec3 loc, Rot4 rot, Map map, Thing thingToIgnore = null)
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            FieldInfo entityDefInfo = AccessTools.Field(typeof(ThingDef), "entityDefToBuild");

            //need to find loop continue label
            object continueLabel = null;

            //just easier to find the 3-line code to get thingList[i]
            bool foundLdLoc = false;
            List <CodeInstruction> currentThing = new List <CodeInstruction>();

            List <CodeInstruction> iList = instructions.ToList();

            for (int k = 0; k < iList.Count(); k++)
            {
                CodeInstruction i = iList[k];
                if (!foundLdLoc && i.opcode == OpCodes.Ldloc_0)
                {
                    foundLdLoc = true;
                    currentThing.AddRange(iList.GetRange(k, 3));
                }
                if (i.LoadsField(entityDefInfo))
                {
                    continueLabel = iList[k + 1].operand;
                    break;
                }
            }

            foundLdLoc = false;
            foreach (CodeInstruction i in instructions)
            {
                if (!foundLdLoc && i.opcode == OpCodes.Ldloc_0)
                {
                    foundLdLoc = true;

                    yield return(new CodeInstruction(OpCodes.Nop)
                    {
                        labels = i.labels
                    });                                                                                     //start of loop label

                    i.labels = new List <Label>();
                    foreach (CodeInstruction ci in currentThing)
                    {
                        yield return(new CodeInstruction(ci.opcode, ci.operand));            //thingList[i]
                    }
                    yield return(new CodeInstruction(OpCodes.Ldarg_S, 5));                   //thingToIgnore

                    yield return(new CodeInstruction(OpCodes.Beq, continueLabel));           //continue
                }
                yield return(i);
            }
        }
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            var codes = new List <CodeInstruction>(instructions);

            for (int i = 0; i < codes.Count; ++i)
            {
                CodeInstruction inst = codes[i];
                if (inst.LoadsField(f_ToolTier))
                {
                    codes[i - 1]    = new CodeInstruction(OpCodes.Call, m_GetToolTier);
                    codes[i].opcode = OpCodes.Nop;
                    break;
                }
                else if (inst.LoadsField(f_MiningSpeed))
                {
                    codes[i - 1] = new CodeInstruction(OpCodes.Ldarg_3);
                    codes[i]     = new CodeInstruction(OpCodes.Call, m_GetMiningSpeed);
                }
            }

            return(codes.AsEnumerable());
        }
Пример #6
0
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator generator)
        {
            FieldInfo allowOpportunisticPrefix_Field = AccessTools.Field(typeof(JobDef), "allowOpportunisticPrefix");
            List <CodeInstruction> instuctionList    = instructions.ToList();

            for (int i = 0; i < instuctionList.Count; i++)
            {
                CodeInstruction instruction = instuctionList[i];
                if (instruction.LoadsField(allowOpportunisticPrefix_Field))
                {
                    while (!instuctionList[i].IsLdarg(1))
                    {
                        i--;
                    }
                    // i -= 2;
                    Label        brLabel  = generator.DefineLabel();
                    Label        oldLabel = instuctionList[i].labels.First();
                    LocalBuilder localVar = generator.DeclareLocal(typeof(Job));
                    instuctionList[i].labels[0] = brLabel;
                    List <CodeInstruction> insertedInstructions = new List <CodeInstruction>()
                    {
                        new CodeInstruction(OpCodes.Ldarg_0, null)
                        {
                            labels = new List <Label>()
                            {
                                oldLabel
                            }
                        },
                        new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(Pawn_JobTracker), "pawn")),
                        new CodeInstruction(OpCodes.Ldarg_1, null),
                        new CodeInstruction(OpCodes.Ldloca_S, localVar),
                        new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Patch_Pawn_JobTracker_TryOpportunisticJob), "CheckOportunisticToolJob")),
                        new CodeInstruction(OpCodes.Brfalse_S, brLabel),
                        new CodeInstruction(OpCodes.Ldloc_S, localVar),
                        new CodeInstruction(OpCodes.Ret, null)
                    };
                    instuctionList.InsertRange(i, insertedInstructions);
                    break;
                }
            }
            return(instuctionList);
        }
Пример #7
0
        private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator ilg)
        {
            List <CodeInstruction> instructionList = instructions.ToList();

            for (int i = 0; i < instructionList.Count; i++)
            {
                CodeInstruction instruction = instructionList[i];

                if (instruction.opcode == OpCodes.Ldfld && instruction.LoadsField(AccessTools.Field(typeof(Pawn), nameof(Pawn.mindState))))
                {
                    yield return(new CodeInstruction(opcode: OpCodes.Pop));

                    yield return(new CodeInstruction(opcode: OpCodes.Dup));

                    yield return(new CodeInstruction(opcode: OpCodes.Ldarg_0));

                    yield return(new CodeInstruction(opcode: OpCodes.Call, operand: AccessTools.Method(typeof(GenerateQualityCreatedByPawn_Patch), nameof(GenerateQualityCreatedByPawn_Patch.Notify_Progress))));

                    yield return(new CodeInstruction(opcode: OpCodes.Ldarg_0));
                }
                yield return(instruction);
            }
        }
Пример #8
0
        /// <summary>
        /// Add FloatMenuOption(s) for Pawns towards Vehicles
        /// </summary>
        /// <param name="instructions"></param>
        /// <param name="ilg"></param>
        public static IEnumerable <CodeInstruction> AddHumanLikeOrdersLoadVehiclesTranspiler(IEnumerable <CodeInstruction> instructions, ILGenerator ilg)
        {
            List <CodeInstruction> instructionList = instructions.ToList();

            for (int i = 0; i < instructionList.Count; i++)
            {
                CodeInstruction instruction = instructionList[i];
                if (instruction.LoadsField(AccessTools.Field(typeof(JobDefOf), nameof(JobDefOf.GiveToPackAnimal))))
                {
                    yield return(instruction);                    //Ldsfld : JobDefOf::GiveToPackAnimal

                    instruction = instructionList[++i];
                    Label jobLabel = ilg.DefineLabel();

                    yield return(new CodeInstruction(opcode: OpCodes.Ldsfld, operand: AccessTools.Field(typeof(FloatMenuMakerMap), nameof(FloatMenuMakerMap.makingFor))));

                    yield return(new CodeInstruction(opcode: OpCodes.Call, operand: AccessTools.Method(typeof(Ext_Vehicles), nameof(Ext_Vehicles.HasVehicleInCaravan))));

                    yield return(new CodeInstruction(opcode: OpCodes.Brfalse, jobLabel));

                    yield return(new CodeInstruction(opcode: OpCodes.Pop));

                    yield return(new CodeInstruction(opcode: OpCodes.Ldsfld, AccessTools.Field(typeof(JobDefOf_Vehicles), nameof(JobDefOf_Vehicles.CarryItemToVehicle))));

                    int j = i;
                    while (j < instructionList.Count)
                    {
                        j++;
                        if (instructionList[j].opcode == OpCodes.Stfld)
                        {
                            instructionList[j].labels.Add(jobLabel);
                            break;
                        }
                    }
                }
                if (instruction.Calls(AccessTools.Property(typeof(Lord), nameof(Lord.LordJob)).GetGetMethod()))
                {
                    yield return(instruction);

                    instruction = instructionList[++i];
                    Label label  = ilg.DefineLabel();
                    Label label2 = ilg.DefineLabel();

                    yield return(new CodeInstruction(opcode: OpCodes.Dup));

                    yield return(new CodeInstruction(opcode: OpCodes.Isinst, operand: typeof(LordJob_FormAndSendVehicles)));

                    yield return(new CodeInstruction(opcode: OpCodes.Brtrue, label));

                    yield return(instruction);                    //CASTCLASS : LordJob_FormAndSendCaravan

                    instruction = instructionList[++i];
                    yield return(instruction);                    //STLOC_S : 50

                    instruction = instructionList[++i];
                    yield return(instruction);                    //LDLOC_S : 49

                    instruction = instructionList[++i];
                    yield return(instruction);                    //LDLOC_S : 50

                    instruction = instructionList[++i];
                    yield return(instruction);                    //CALL : CapacityLeft

                    instruction = instructionList[++i];
                    yield return(new CodeInstruction(opcode: OpCodes.Br, label2));

                    yield return(new CodeInstruction(opcode: OpCodes.Pop)
                    {
                        labels = new List <Label> {
                            label
                        }
                    });

                    yield return(new CodeInstruction(opcode: OpCodes.Ldloc_S, operand: 49));

                    yield return(new CodeInstruction(opcode: OpCodes.Ldarg_1));

                    yield return(new CodeInstruction(opcode: OpCodes.Call, operand: AccessTools.Method(typeof(LordUtility), "GetLord", new Type[] { typeof(Pawn) })));

                    yield return(new CodeInstruction(opcode: OpCodes.Callvirt, operand: AccessTools.Property(typeof(Lord), nameof(Lord.LordJob)).GetGetMethod()));

                    yield return(new CodeInstruction(opcode: OpCodes.Castclass, operand: typeof(LordJob_FormAndSendVehicles)));

                    yield return(new CodeInstruction(opcode: OpCodes.Call, operand: AccessTools.Method(typeof(CaravanHelper), nameof(CaravanHelper.CapacityLeft))));

                    instruction.labels.Add(label2);
                    yield return(instruction);                    //STFLD : capacityLeft

                    instruction = instructionList[++i];
                }
                yield return(instruction);
            }
        }
Пример #9
0
        public static IEnumerable <CodeInstruction> SetControlsTranspiler(IEnumerable <CodeInstruction> instructions)
        {
            bool            foundCancelCrouch           = false;
            bool            foundAutoRunCondition       = false;
            bool            foundMoveDirCondition       = false;
            bool            foundCancelAutorunCondition = false;
            bool            foundMoveDirAssignment      = false;
            CodeInstruction branchEndAutoRun            = null;

            List <CodeInstruction> codes = new List <CodeInstruction>(instructions);

            //DumpIL(codes);
            for (int i = 0; i < codes.Count(); i++)
            {
                CodeInstruction code = codes[i];

                if (!foundCancelCrouch &&
                    codes[i + 0].opcode == OpCodes.Ldarg_0 &&
                    codes[i + 1].opcode == OpCodes.Ldc_I4_0 &&
                    codes[i + 2].Calls(AccessTools.Method(typeof(Character), nameof(Character.SetCrouch))))
                {
                    //Debug.Log("foundit0 " + i);
                    // Nop out the call to "this.SetCrouch(false)"
                    codes[i + 0].opcode = OpCodes.Nop; codes[i + 0].operand = null;
                    codes[i + 1].opcode = OpCodes.Nop; codes[i + 1].operand = null;
                    codes[i + 2].opcode = OpCodes.Nop; codes[i + 2].operand = null;

                    foundCancelCrouch = true;
                }

                // We're looking for a ldfld of m_autoRun followed by a brfalse: "if(this.m_autoRun)"
                if (!foundAutoRunCondition &&
                    code.opcode == OpCodes.Ldfld &&
                    code.LoadsField(AccessTools.DeclaredField(typeof(Player), nameof(Player.m_autoRun))) &&
                    codes[i + 1].opcode == OpCodes.Brfalse)
                {
                    //Debug.Log("foundit1 " + i);
                    foundAutoRunCondition = true;
                }

                // Nop out the "jump || crouch || movedir != Vector3.zero" conditions
                if (foundAutoRunCondition &&
                    codes[i - 5].opcode == OpCodes.Ldarg_S &&
                    codes[i - 4].opcode == OpCodes.Or &&
                    codes[i - 3].opcode == OpCodes.Ldarg_S &&
                    codes[i - 2].opcode == OpCodes.Or &&
                    codes[i - 1].Branches(out Label? asdfasdfasdsa) &&
                    codes[i + 0].opcode == OpCodes.Ldarg_1 &&
                    codes[i + 1].opcode == OpCodes.Call)
                {
                    //Debug.Log("foundit3 " + i);
                    codes[i - 5].opcode = OpCodes.Nop; codes[i - 5].operand = null;
                    codes[i - 4].opcode = OpCodes.Nop; codes[i - 4].operand = null;
                    codes[i - 3].opcode = OpCodes.Nop; codes[i - 3].operand = null;
                    codes[i - 2].opcode = OpCodes.Nop; codes[i - 2].operand = null;
                    // Leave codes[i - 1] alone since it's the branching instruction for the very first condition
                    codes[i + 0].opcode = OpCodes.Nop; codes[i + 0].operand = null;
                    codes[i + 1].opcode = OpCodes.Nop; codes[i + 1].operand = null;
                    codes[i + 2].opcode = OpCodes.Nop; codes[i + 2].operand = null;
                    codes[i + 3].opcode = OpCodes.Nop; codes[i + 3].operand = null;

                    // Add in our own autorun canceling conditions: if either forwards or backwards are pressed.
                    branchEndAutoRun = codes[i - 1];
                    codes.InsertRange(i, new List <CodeInstruction>()
                    {
                        new CodeInstruction(OpCodes.Ldstr, "Forward"),
                        CodeInstruction.Call(typeof(ZInput), nameof(ZInput.GetButton)),
                        branchEndAutoRun.Clone(),
                        new CodeInstruction(OpCodes.Ldstr, "Backward"),
                        CodeInstruction.Call(typeof(ZInput), nameof(ZInput.GetButton)),
                        branchEndAutoRun.Clone()
                    });

                    foundCancelAutorunCondition = true;
                }

                // Convert "else if (autoRun || blockHold)" into "else"
                if (foundCancelAutorunCondition &&
                    codes[i + 0].opcode == OpCodes.Ldarg_S && //&& codes[i + 0].operand as string == "10"
                    codes[i + 1].opcode == OpCodes.Ldarg_S && //&& codes[i + 1].operand as string == "6"
                    codes[i + 2].opcode == OpCodes.Or &&
                    codes[i + 3].Branches(out Label? asdfasdfsad))
                {
                    //Debug.Log("foundit4 " + i);
                    codes[i + 0].opcode = OpCodes.Nop; codes[i + 0].operand = null;
                    codes[i + 1].opcode = OpCodes.Nop; codes[i + 1].operand = null;
                    codes[i + 2].opcode = OpCodes.Nop; codes[i + 2].operand = null;
                    codes[i + 3].opcode = OpCodes.Nop; codes[i + 3].operand = null;

                    foundMoveDirCondition = true;
                }

                // Lastly, add "movedir.x * Vector3.Cross(Vector3.up, this.m_lookDir)" to the player's movedir so that they can strafe while autorunning
                if (foundMoveDirCondition &&
                    codes[i - 3].opcode == OpCodes.Ldarg_0 &&
                    codes[i - 2].opcode == OpCodes.Ldarg_0 &&
                    codes[i - 1].LoadsField(AccessTools.Field(typeof(Character), nameof(Character.m_lookDir))) &&
                    codes[i - 0].StoresField(AccessTools.Field(typeof(Character), nameof(Character.m_moveDir))))
                {
                    //Debug.Log("foundit5 " + i);
                    codes.InsertRange(i, new List <CodeInstruction>()
                    {
                        new CodeInstruction(OpCodes.Ldarg_1),
                        CodeInstruction.LoadField(typeof(Vector3), nameof(Vector3.x)),
                        new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(Vector3), nameof(Vector3.up))),
                        new CodeInstruction(OpCodes.Ldarg_0),
                        CodeInstruction.LoadField(typeof(Player), nameof(Player.m_lookDir)),
                        CodeInstruction.Call(typeof(Vector3), nameof(Vector3.Cross)),
                        new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Vector3), "op_Multiply", new Type[] { typeof(float), typeof(Vector3) })),
                        new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Vector3), "op_Addition", new Type[] { typeof(Vector3), typeof(Vector3) }))
                    });

                    foundMoveDirAssignment = true;
                    break; // we done
                }
            }

            //DumpIL(codes);

            //Debug.Log(string.Format("{0} {1} {2} {3} {4}", foundAutoRunCondition, branchEndAutoRun != null, foundCancelAutorunCondition, foundMoveDirCondition, foundMoveDirAssignment));
            if (!foundAutoRunCondition || branchEndAutoRun == null || !foundCancelAutorunCondition || !foundMoveDirCondition || !foundMoveDirAssignment)
            {
                throw new Exception("BetterAutoRun injection point NOT found!! Game has most likely updated and broken this mod!");
            }

            if (!foundCancelCrouch)
            {
                Main.log.LogWarning("One of the BetterAutoRun injection points were not found, game has most likely updated and broken this mod.");
                Main.log.LogWarning("Autorun while crouching will not work but everything else should be fine.");
            }

            return(codes.AsEnumerable());
        }