static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, MethodBase original)
        {
            var codes       = instructions.ToCodeList();
            var ldSegmentID = GetLDArg(original, "nodeSegment");

            // TODO aquire dynamically
            var ldSegmentIDA = new CodeInstruction(OpCodes.Ldloc_S, 20);
            var ldSegmentIDB = new CodeInstruction(OpCodes.Ldloc_S, 21);
            int index;

            // non-invert
            index = codes.Search(_c => _c.LoadsField(f_pavementWidth), count: 2); //A left
            codes.InsertInstructions(index + 1,                                   //after
                                     new[] {
                ldSegmentIDA.Clone(),
                ldSegmentID.Clone(),                   // does not matter
                new CodeInstruction(OpCodes.Ldc_I4_2), // occurance
                new CodeInstruction(OpCodes.Call, mModifyPavement),
            });

            index = codes.Search(_c => _c.LoadsField(f_pavementWidth), count: 3); //main right
            codes.InsertInstructions(index + 1,                                   //after
                                     new[] {
                ldSegmentID.Clone(),
                ldSegmentIDB.Clone(),
                new CodeInstruction(OpCodes.Ldc_I4_3),     // occurance
                new CodeInstruction(OpCodes.Call, mModifyPavement),
            });

            // invert
            index = codes.Search(_c => _c.LoadsField(f_pavementWidth), count: 1); //A left
            codes.InsertInstructions(index + 1,                                   //after
                                     new[] {
                ldSegmentID.Clone(),
                ldSegmentIDA.Clone(),
                new CodeInstruction(OpCodes.Ldc_I4_1),     // occurance
                new CodeInstruction(OpCodes.Call, mModifyPavement),
            });

            index = codes.Search(_c => _c.LoadsField(f_pavementWidth), count: 4); //main right
            codes.InsertInstructions(index + 1,                                   //after
                                     new[] {
                ldSegmentIDB.Clone(),
                ldSegmentID.Clone(),                   // does not matter
                new CodeInstruction(OpCodes.Ldc_I4_4), // occurance
                new CodeInstruction(OpCodes.Call, mModifyPavement),
            });
            return(codes);
        }
Ejemplo n.º 2
0
        public static IEnumerable <CodeInstruction> Transpiler(MethodBase original, IEnumerable <CodeInstruction> instructions)
        {
            CodeInstruction ldNodeID              = GetLDArg(original, "startNodeID");
            CodeInstruction ldSegmentID           = GetLDArg(original, "ignoreSegmentID");
            CodeInstruction callGetClipSegmentEnd = new CodeInstruction(OpCodes.Call, mGetClipSegmentEnd);

            int n = 0;

            foreach (var instruction in instructions)
            {
                yield return(instruction);

                if (instruction.LoadsField(f_clipSegmentEnds))
                {
                    n++;
                    yield return(ldNodeID.Clone());

                    yield return(ldSegmentID.Clone());

                    yield return(callGetClipSegmentEnd.Clone());
                }
            }

            Log.Succeeded($"patched {n} instances of {f_clipSegmentEnds} in {original}");
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Deep-copies the instruction, including labels and exception blocks.
        /// </summary>
        /// <param name="instruction">The instruction to fully clone.</param>
        /// <returns>Fully cloned instruction.</returns>
        public static CodeInstruction FullClone(this CodeInstruction instruction)
        {
            CodeInstruction clone = instruction.Clone();

            clone.labels = instruction.labels.ConvertAll(l => l); // TODO: Clone labels?
            clone.blocks = instruction.blocks.ConvertAll(b => b.Clone());

            return(clone);
        }
        public static IEnumerable <CodeInstruction> Transpiler(MethodBase original, IEnumerable <CodeInstruction> instructions)
        {
            CodeInstruction ldSegmentID             = GetLDArg(original, "segmentID");
            CodeInstruction callGetClipSegmentStart = new CodeInstruction(OpCodes.Call, mGetClipSegmentStart);
            CodeInstruction callGetClipSegmentEnd   = new CodeInstruction(OpCodes.Call, mGetClipSegmentEnd);

            int n = 0;

            foreach (var instruction in instructions)
            {
                yield return(instruction);

                if (instruction.LoadsField(f_clipSegmentEnds))
                {
                    yield return(ldSegmentID.Clone());

                    // first one is for start node and second one is for end node.
                    switch (n)
                    {
                    case 0:
                        yield return(callGetClipSegmentStart.Clone());

                        break;

                    case 1:
                        yield return(callGetClipSegmentEnd.Clone());

                        break;

                    default:
                        new Exception("expected only 2 occurrences").Log();
                        break;
                    }

                    n++;
                }
            }

            Log.Succeeded($"patched {n} instances of {f_clipSegmentEnds} in {original}");
        }
Ejemplo n.º 5
0
        public static List <CodeInstruction> ApplyPatch(
            List <CodeInstruction> codes,
            CodeInstruction ldSegmentID,
            CodeInstruction ldSegmentIDA,
            CodeInstruction ldSegmentIDB)
        {
            int index;

            /****************************************************
             * non-invert */
            index = codes.Search(_c => _c.LoadsField(f_pavementWidth), count: 2); //A left
            codes.InsertInstructions(index + 1,                                   //after
                                     new[] {
                ldSegmentIDA.Clone(),
                ldSegmentID.Clone(),                   // does not matter
                new CodeInstruction(OpCodes.Ldc_I4_2), // occurance
                new CodeInstruction(OpCodes.Call, mModifyPavement),
            });

            index = codes.Search(_c => _c.LoadsField(f_pavementWidth), count: 3); //main right
            codes.InsertInstructions(index + 1,                                   //after
                                     new[] {
                ldSegmentID.Clone(),
                ldSegmentIDB.Clone(),
                new CodeInstruction(OpCodes.Ldc_I4_3),     // occurance
                new CodeInstruction(OpCodes.Call, mModifyPavement),
            });

            /****************************************************
             * invert */
            index = codes.Search(_c => _c.LoadsField(f_pavementWidth), count: 1); //A left
            codes.InsertInstructions(index + 1,                                   //after
                                     new[] {
                ldSegmentID.Clone(),
                ldSegmentIDA.Clone(),
                new CodeInstruction(OpCodes.Ldc_I4_1),     // occurance
                new CodeInstruction(OpCodes.Call, mModifyPavement),
            });

            index = codes.Search(_c => _c.LoadsField(f_pavementWidth), count: 4); //main right
            codes.InsertInstructions(index + 1,                                   //after
                                     new[] {
                ldSegmentIDB.Clone(),
                ldSegmentID.Clone(),                   // does not matter
                new CodeInstruction(OpCodes.Ldc_I4_4), // occurance
                new CodeInstruction(OpCodes.Call, mModifyPavement),
            });

            /********************************
             * m_dataVector0 */
            index = codes.Search(_c => _c.LoadsField(f_pavementWidth), count: 5); //m_dataVector0.z
            codes.InsertInstructions(index + 1,                                   //after
                                     new[] {
                ldSegmentID.Clone(),
                ldSegmentID.Clone(),                   // does not matter
                new CodeInstruction(OpCodes.Ldc_I4_5), // occurance
                new CodeInstruction(OpCodes.Call, mModifyPavement),
            });

            index = codes.Search(_c => _c.LoadsField(f_pavementWidth), count: 6); //m_dataVector0.w
            codes.InsertInstructions(index + 1,                                   //after
                                     new[] {
                ldSegmentID.Clone(),
                ldSegmentID.Clone(),                   // does not matter
                new CodeInstruction(OpCodes.Ldc_I4_6), // occurance
                new CodeInstruction(OpCodes.Call, mModifyPavement),
            });
            return(codes);
        }
Ejemplo n.º 6
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());
        }
Ejemplo n.º 7
0
            private static IEnumerable <CodeInstruction> UpdateFood_Transpiler(IEnumerable <CodeInstruction> instructions)
            {
                bool            done     = false;
                CodeInstruction previous = null;

                foreach (CodeInstruction instruction in instructions)
                {
                    if (done)
                    {
                        yield return(instruction);

                        continue;
                    }

                    if (instruction.opcode == OpCodes.Ldfld && ((FieldInfo)instruction.operand).Name == nameof(Player.Food.m_health) && previous != null)
                    {
                        // (1.0f - Mathf.Pow(1.0f - food.m_health / food.m_item.m_shared.m_food, CurveExponent.Value)) * food.m_item.m_shared.m_food
                        yield return(new CodeInstruction(OpCodes.Ldc_R4, 1.0f));

                        yield return(new CodeInstruction(OpCodes.Ldc_R4, 1.0f));

                        yield return(previous);

                        yield return(instruction);

                        yield return(previous.Clone());

                        yield return(new CodeInstruction(OpCodes.Ldfld, typeof(Player.Food).GetField(nameof(Player.Food.m_item))));

                        yield return(new CodeInstruction(OpCodes.Ldfld, typeof(ItemDrop.ItemData).GetField(nameof(ItemDrop.ItemData.m_shared))));

                        yield return(new CodeInstruction(OpCodes.Ldfld, typeof(ItemDrop.ItemData.SharedData).GetField(nameof(ItemDrop.ItemData.SharedData.m_food))));

                        yield return(new CodeInstruction(OpCodes.Div));

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

                        yield return(new CodeInstruction(OpCodes.Ldc_R4, HealthCurveExponent.Value));

                        yield return(new CodeInstruction(OpCodes.Call, typeof(Mathf).GetMethod(nameof(Mathf.Pow))));

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

                        yield return(previous.Clone());

                        yield return(new CodeInstruction(OpCodes.Ldfld, typeof(Player.Food).GetField(nameof(Player.Food.m_item))));

                        yield return(new CodeInstruction(OpCodes.Ldfld, typeof(ItemDrop.ItemData).GetField(nameof(ItemDrop.ItemData.m_shared))));

                        yield return(new CodeInstruction(OpCodes.Ldfld, typeof(ItemDrop.ItemData.SharedData).GetField(nameof(ItemDrop.ItemData.SharedData.m_food))));

                        yield return(new CodeInstruction(OpCodes.Mul));

                        done = true;
                    }
                    else
                    {
                        if (previous != null)
                        {
                            yield return(previous);

                            previous = null;
                        }

                        if (instruction.opcode == OpCodes.Ldloc_S)
                        {
                            previous = instruction;
                        }
                        else
                        {
                            yield return(instruction);
                        }
                    }
                }
            }