Esempio n. 1
0
        public static IEnumerable <CodeInstruction> TestTranspiler(IEnumerable <CodeInstruction> instructions)
        {
            savedInstructions = new CodeInstruction[instructions.Count()];
            instructions.ToList().CopyTo(savedInstructions);

            foreach (var instruction in instructions)
            {
                if (instruction.opcode == insertLoc)
                {
                    var blocks = instruction.blocks;
                    instruction.blocks = new List <ExceptionBlock>();

                    var log    = AccessTools.DeclaredField(typeof(Class3), "log");
                    var tst    = typeof(string);
                    var concat = AccessTools.Method(typeof(string), nameof(string.Concat), new Type[] { tst, tst });
                    yield return(new CodeInstruction(OpCodes.Ldarg_0)
                    {
                        blocks = blocks
                    });

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

                    yield return(new CodeInstruction(OpCodes.Ldfld, log));

                    yield return(new CodeInstruction(OpCodes.Ldstr, ",patch"));

                    yield return(new CodeInstruction(OpCodes.Call, concat));

                    yield return(new CodeInstruction(OpCodes.Stfld, log));
                }

                yield return(instruction);
            }
        }
        // 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);
        }
Esempio n. 3
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);
        }
Esempio n. 4
0
 private static IEnumerable <CodeInstruction> FilterDrops(IEnumerable <CodeInstruction> instructions)
 {
     return(new CodeMatcher(instructions)
            .MatchForward(false, new CodeMatch(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(CharacterDrop), nameof(CharacterDrop.m_drops))))
            .SetInstructionAndAdvance(Transpilers.EmitDelegate(ConditionChecker.FilterOnDeath))
            .InstructionEnumeration());
 }
Esempio n. 5
0
        public void Test_AccessTools_Field2()
        {
            var classType = typeof(AccessToolsClass);

            Assert.NotNull(AccessTools.Field(classType, "field1"));
            Assert.NotNull(AccessTools.DeclaredField(classType, "field1"));
            Assert.Null(AccessTools.Field(classType, "unknown"));
            Assert.Null(AccessTools.DeclaredField(classType, "unknown"));

            var subclassType = typeof(AccessToolsSubClass);

            Assert.NotNull(AccessTools.Field(subclassType, "field1"));
            Assert.Null(AccessTools.DeclaredField(subclassType, "field1"));
            Assert.Null(AccessTools.Field(subclassType, "unknown"));
            Assert.Null(AccessTools.DeclaredField(subclassType, "unknown"));

            var structType = typeof(AccessToolsStruct);

            Assert.NotNull(AccessTools.Field(structType, "structField1"));
            Assert.NotNull(AccessTools.DeclaredField(structType, "structField1"));
            Assert.Null(AccessTools.Field(structType, "unknown"));
            Assert.Null(AccessTools.DeclaredField(structType, "unknown"));

            var interfaceType = typeof(IAccessToolsType);

            Assert.Throws(typeof(NullReferenceException), () => AccessTools.Field(interfaceType, "unknown"));             // TODO: should return null, not throw NRE
            Assert.Null(AccessTools.DeclaredField(interfaceType, "unknown"));
        }
Esempio n. 6
0
        public void Test_AccessTools_Field2()
        {
            var classType = typeof(AccessToolsClass);

            Assert.NotNull(AccessTools.Field(classType, "field1"));
            Assert.NotNull(AccessTools.DeclaredField(classType, "field1"));
            Assert.Null(AccessTools.Field(classType, "unknown"));
            Assert.Null(AccessTools.DeclaredField(classType, "unknown"));

            var subclassType = typeof(AccessToolsSubClass);

            Assert.NotNull(AccessTools.Field(subclassType, "field1"));
            Assert.Null(AccessTools.DeclaredField(subclassType, "field1"));
            Assert.Null(AccessTools.Field(subclassType, "unknown"));
            Assert.Null(AccessTools.DeclaredField(subclassType, "unknown"));

            var structType = typeof(AccessToolsStruct);

            Assert.NotNull(AccessTools.Field(structType, "structField1"));
            Assert.NotNull(AccessTools.DeclaredField(structType, "structField1"));
            Assert.Null(AccessTools.Field(structType, "unknown"));
            Assert.Null(AccessTools.DeclaredField(structType, "unknown"));

            var interfaceType = typeof(IAccessToolsType);

            Assert.Null(AccessTools.Field(interfaceType, "unknown"));
            Assert.Null(AccessTools.DeclaredField(interfaceType, "unknown"));
        }
Esempio n. 7
0
 public static void AssertIsEmpty(Traverse trv)
 {
     foreach (var name in fieldNames)
     {
         Assert.AreEqual(null, AccessTools.DeclaredField(typeof(Traverse), name).GetValue(trv));
     }
 }
Esempio n. 8
0
 public void Traverse_Has_Expected_Internal_Fields()
 {
     foreach (var name in fieldNames)
     {
         var fInfo = AccessTools.DeclaredField(typeof(Traverse), name);
         Assert.IsNotNull(fInfo);
     }
 }
Esempio n. 9
0
        public static IEnumerable <CodeInstruction> GetDataToUseTranspiler(IEnumerable <CodeInstruction> instructions, ILGenerator ilGenerator)
        {
            var list = instructions.ToList();

            var firstReturnNull       = ilGenerator.DefineLabel();
            var secondExpressionStart = ilGenerator.DefineLabel();
            var originalEntry         = ilGenerator.DefineLabel();

            list[0].labels.Add(originalEntry);

            // if (SavedMemberType == SavedMemberType.Enum && (_typeDefinition == null || _typeDefinition.Type == typeof(object))) return null;
            list.InsertRange(0, new[]
            {
                new CodeInstruction(OpCodes.Ldarg_0),
                new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "SavedMemberType")),
                new CodeInstruction(OpCodes.Ldc_I4_5),
                new CodeInstruction(OpCodes.Bne_Un_S, secondExpressionStart),
                new CodeInstruction(OpCodes.Ldarg_0),
                new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")),
                new CodeInstruction(OpCodes.Brfalse_S, firstReturnNull),
                new CodeInstruction(OpCodes.Ldarg_0),
                new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")),
                new CodeInstruction(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(TypeDefinitionBase), "Type")),
                new CodeInstruction(OpCodes.Ldtoken, typeof(object)),
                new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Type), nameof(Type.GetTypeFromHandle))),
                new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Type), "op_Equality")),
                new CodeInstruction(OpCodes.Brfalse_S, secondExpressionStart),

                new CodeInstruction(OpCodes.Ldnull)
                {
                    labels = { firstReturnNull }
                },
                new CodeInstruction(OpCodes.Ret),
            });
            //

            // if (_typeDefinition is NullTypeDefinition) return null;
            list.InsertRange(16, new[]
            {
                new CodeInstruction(OpCodes.Ldarg_0)
                {
                    labels = { secondExpressionStart }
                },
                new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")),
                new CodeInstruction(OpCodes.Isinst, typeof(NullTypeDefinition)), // Basic
                new CodeInstruction(OpCodes.Brfalse_S, originalEntry),

                new CodeInstruction(OpCodes.Ldnull),
                new CodeInstruction(OpCodes.Ret)
            });
            //

            return(list);
        }
Esempio n. 10
0
        public void Test_AccessTools_Field2()
        {
            var type = typeof(AccessToolsClass);

            Assert.NotNull(AccessTools.Field(type, "field1"));
            Assert.NotNull(AccessTools.DeclaredField(type, "field1"));

            var subtype = typeof(AccessToolsSubClass);

            Assert.NotNull(AccessTools.Field(subtype, "field1"));
            Assert.Null(AccessTools.DeclaredField(subtype, "field1"));
        }
Esempio n. 11
0
        public static RectTransform TopLevelWindow(Transform parent)
        {
            GameObject obj = new GameObject("ToyBox.TopLevelWindow");

            ToyBox.Main.Objects.Add(obj);
            crUI.obj = obj;

            RectTransform transform = obj.AddComponent <RectTransform>();

            transform.SetParent(parent, false);
            transform.anchorMin = new Vector2(0.0f, 0.0f);
            transform.anchorMax = new Vector2(1.0f, 1.0f);
            transform.pivot     = new Vector2(0.5f, 0.5f);
            transform.offsetMin = new Vector2(0.0f, 0.0f);
            transform.offsetMax = new Vector2(0.0f, 0.0f);

            VerticalLayoutGroupWorkaround group = obj.AddComponent <VerticalLayoutGroupWorkaround>();

            group.SetLayoutVertical();
            group.childControlWidth      = true;
            group.childControlHeight     = true;
            group.childForceExpandWidth  = false;
            group.childForceExpandHeight = false;
            group.childScaleWidth        = false;
            group.childScaleHeight       = false;
            group.childAlignment         = TextAnchor.UpperLeft;
            group.spacing = DefaultSpacing;
            group.padding = DefaultPadding;

            LayoutElement layout = obj.AddComponent <LayoutElement>();

            layout.minWidth        = -1.0f;
            layout.minHeight       = -1.0f;
            layout.preferredWidth  = -1.0f;
            layout.preferredHeight = -1.0f;
            layout.flexibleWidth   = 1.0f;
            layout.flexibleHeight  = 1.0f;

            CanvasGroup canvas = obj.AddComponent <CanvasGroup>();

            ContentSizeFitterExtended fitter = obj.AddComponent <ContentSizeFitterExtended>();

            AccessTools
            .DeclaredField(typeof(ContentSizeFitterExtended), "m_HorizontalFit")
            .SetValue(fitter, ContentSizeFitterExtended.FitMode.PreferredSize);
            AccessTools
            .DeclaredField(typeof(ContentSizeFitterExtended), "m_VerticalFit")
            .SetValue(fitter, ContentSizeFitterExtended.FitMode.PreferredSize);
            fitter.SetLayoutVertical();

            return(transform);
        }
Esempio n. 12
0
 internal FieldInfo GetFieldInfo(Type type, string name)
 {
     if (fields.TryGetValue(type, out var fieldsByType) == false)
     {
         fieldsByType = new Dictionary <string, FieldInfo>();
         fields.Add(type, fieldsByType);
     }
     if (fieldsByType.TryGetValue(name, out var field) == false)
     {
         field = AccessTools.DeclaredField(type, name);
         fieldsByType.Add(name, field);
     }
     return(field);
 }
Esempio n. 13
0
        public void Test_AccessTools_Field1()
        {
            var type = typeof(AccessToolsClass);

            Assert.Null(AccessTools.DeclaredField(null, null));
            Assert.Null(AccessTools.DeclaredField(type, null));
            Assert.Null(AccessTools.DeclaredField(null, "field1"));
            Assert.Null(AccessTools.DeclaredField(type, "unknown"));

            var field = AccessTools.DeclaredField(type, "field1");

            Assert.NotNull(field);
            Assert.AreEqual(type, field.DeclaringType);
            Assert.AreEqual("field1", field.Name);
        }
Esempio n. 14
0
        public void AccessTools_Field1()
        {
            var type = typeof(AccessToolsClass);

            Assert.Throws <ArgumentNullException>(() => AccessTools.DeclaredField(null, null));
            Assert.Throws <ArgumentNullException>(() => AccessTools.DeclaredField(type, null));
            Assert.Throws <ArgumentNullException>(() => AccessTools.DeclaredField(null, "field1"));
            Assert.IsNull(AccessTools.DeclaredField(type, "unknown"));

            var field = AccessTools.DeclaredField(type, "field1");

            Assert.IsNotNull(field);
            Assert.AreEqual(type, field.DeclaringType);
            Assert.AreEqual("field1", field.Name);
        }
Esempio n. 15
0
        public static void Init()
        {
            // there's definitely a better way to get sprites and images
            // but don't know how
            crUI.CommonPCView = AccessTools
                                .DeclaredField(typeof(RootUIContext), "m_CommonView")?
                                .GetValue(Game.Instance?.RootUiContext) as MonoBehaviour;

            crUI.FrameBackgroundImage = crUI.CommonPCView.transform
                                        .Find("FadeCanvas/InfoWindow/Window/Background")?
                                        .gameObject?.GetComponent <Image>();

            Transform owlcat_checkbox = null;

            foreach (GameObject obj in Resources.FindObjectsOfTypeAll <GameObject>())
            {
                if (obj.name == "ShowHelmContainer")
                {
                    owlcat_checkbox = obj.transform.Find("ToggleOwlcatMultiSelectable");
                    if (owlcat_checkbox != null)
                    {
                        break;
                    }
                }
            }

            crUI.CheckboxBackgroundImage = owlcat_checkbox?.Find("Background")?
                                           .GetComponent <Image>();

            crUI.CheckboxCheckmarkImage = owlcat_checkbox?.Find("Background/Checkmark")?
                                          .GetComponent <Image>();

            crUI.CheckboxLayerParts = AccessTools.DeclaredField(typeof(OwlcatSelectable), "m_CommonLayer")
                                      .GetValue(owlcat_checkbox?.GetComponent <OwlcatMultiButton>()) as List <OwlcatSelectableLayerPart>;

            Transform owlcat_save_button = crUI.CommonPCView.gameObject.transform
                                           .Find("FadeCanvas/EscMenuView/Window/ButtonBlock/SaveButton");

            crUI.ButtonBackgroundImage = owlcat_save_button?.GetComponent <Image>();

            List <OwlcatSelectableLayerPart> button_layer_parts = AccessTools.DeclaredField(typeof(OwlcatSelectable), "m_CommonLayer")
                                                                  .GetValue(owlcat_save_button?.GetComponent <OwlcatButton>()) as List <OwlcatSelectableLayerPart>;

            crUI.ButtonBackgroundSpriteState = button_layer_parts[0].SpriteState;
        }
Esempio n. 16
0
        public static IEnumerable <CodeInstruction> ReadTranspiler(IEnumerable <CodeInstruction> instructions, ILGenerator ilGenerator)
        {
            var list = instructions.ToList();

            // if (_typeDefinition is NullTypeDefinition) return;
            var label = ilGenerator.DefineLabel();

            list.InsertRange(92, new[]
            {
                new CodeInstruction(OpCodes.Ldarg_0),
                new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")),
                new CodeInstruction(OpCodes.Isinst, typeof(NullTypeDefinition)), // Basic
                new CodeInstruction(OpCodes.Brfalse_S, label),

                new CodeInstruction(OpCodes.Ret)
            });
            list[97].labels.Add(label);
            //

            return(list);
        }
Esempio n. 17
0
        public static RectTransform Frame(RectTransform parent)
        {
            GameObject obj = new GameObject("ToyBox.Frame");

            RectTransform transform = obj.AddComponent <RectTransform>();

            transform.SetParent(parent, false);
            transform.anchorMin = new Vector2(0.0f, 0.0f);
            transform.anchorMax = new Vector2(1.0f, 1.0f);
            transform.pivot     = new Vector2(0.5f, 0.5f);
            transform.offsetMin = new Vector2(-16.0f, -16.0f);
            transform.offsetMax = new Vector2(16.0f, 16.0f);

            HorizontalLayoutGroupWorkaround group = obj.AddComponent <HorizontalLayoutGroupWorkaround>();

            group.SetLayoutHorizontal();
            group.childControlWidth      = true;
            group.childControlHeight     = true;
            group.childForceExpandWidth  = false;
            group.childForceExpandHeight = false;
            group.childScaleWidth        = false;
            group.childScaleHeight       = false;
            group.childAlignment         = TextAnchor.UpperRight;
            group.spacing = DefaultSpacing;
            group.padding = new RectOffset(left: 0, bottom: 0, right: 16, top: 8);

            LayoutElement layout = obj.AddComponent <LayoutElement>();

            layout.ignoreLayout    = true;
            layout.minWidth        = -1.0f;
            layout.minHeight       = -1.0f;
            layout.preferredWidth  = -1.0f;
            layout.preferredHeight = -1.0f;
            layout.flexibleWidth   = 1.0f;
            layout.flexibleHeight  = 1.0f;

            CanvasRenderer renderer = obj.AddComponent <CanvasRenderer>();

            Image image = obj.AddComponent <Image>();

            image.sprite = crUI.FrameBackgroundImage?.sprite;

            DraggbleWindow drag = obj.AddComponent <DraggbleWindow>();

            AccessTools
            .DeclaredField(typeof(DraggbleWindow), "m_OwnRectTransform")
            .SetValue(drag, parent);
            AccessTools
            .DeclaredField(typeof(DraggbleWindow), "m_ParentRectTransform")
            .SetValue(drag, parent.parent);

            RectTransform close = crUI.Button(transform, "Close");

            LayoutElement close_layout = close.GetComponent <LayoutElement>();

            close_layout.minWidth        = 64.0f;
            close_layout.minHeight       = 32.0f;
            close_layout.preferredWidth  = close_layout.minWidth;
            close_layout.preferredHeight = close_layout.minHeight;
            close_layout.flexibleWidth   = 0.0f;
            close_layout.flexibleHeight  = 0.0f;

            OwlcatButton button = close.GetComponent <OwlcatButton>();

            Button.ButtonClickedEvent evt = AccessTools
                                            .DeclaredField(typeof(OwlcatButton), "m_OnLeftClick").GetValue(button) as Button.ButtonClickedEvent;

            evt.AddListener(() => {
                parent.gameObject.SetActive(false);
            });

            return(transform);
        }
Esempio n. 18
0
        public static RectTransform Checkbox(RectTransform parent)
        {
            GameObject obj = new GameObject("ToyBox.Checkbox");

            RectTransform transform = obj.AddComponent <RectTransform>();

            transform.SetParent(parent, false);
            transform.anchorMin = new Vector2(0.0f, 0.0f);
            transform.anchorMax = new Vector2(1.0f, 1.0f);
            transform.pivot     = new Vector2(0.5f, 0.5f);
            transform.offsetMin = new Vector2(0.0f, 0.0f);
            transform.offsetMax = new Vector2(0.0f, 0.0f);

            HorizontalLayoutGroupWorkaround group = obj.AddComponent <HorizontalLayoutGroupWorkaround>();

            group.SetLayoutHorizontal();
            group.childControlWidth      = true;
            group.childControlHeight     = true;
            group.childForceExpandWidth  = false;
            group.childForceExpandHeight = false;
            group.childScaleWidth        = false;
            group.childScaleHeight       = false;
            group.childAlignment         = TextAnchor.UpperLeft;
            group.spacing = DefaultSpacing;
            group.padding = DefaultPadding;

            LayoutElement layout = obj.AddComponent <LayoutElement>();

            layout.minWidth        = 32.0f;
            layout.minHeight       = 32.0f;
            layout.preferredWidth  = -1.0f;
            layout.preferredHeight = -1.0f;
            layout.flexibleWidth   = 0.0f;
            layout.flexibleHeight  = 0.0f;

            OwlcatMultiButton button = obj.AddComponent <OwlcatMultiButton>();

            button.ClickSoundType = -1;
            //button.HoverSoundType = 1;

            // background
            GameObject background_obj = new GameObject("ToyBox.Checkbox.Background");

            RectTransform background_transform = background_obj.AddComponent <RectTransform>();

            background_transform.SetParent(transform, false);
            background_transform.anchorMin = new Vector2(0.0f, 0.0f);
            background_transform.anchorMax = new Vector2(1.0f, 1.0f);
            background_transform.pivot     = new Vector2(0.5f, 0.5f);
            background_transform.offsetMin = new Vector2(0.0f, 0.0f);
            background_transform.offsetMax = new Vector2(0.0f, 0.0f);

            HorizontalLayoutGroupWorkaround background_group = background_obj.AddComponent <HorizontalLayoutGroupWorkaround>();

            background_group.SetLayoutHorizontal();
            background_group.childControlWidth      = true;
            background_group.childControlHeight     = true;
            background_group.childForceExpandWidth  = false;
            background_group.childForceExpandHeight = false;
            background_group.childScaleWidth        = false;
            background_group.childScaleHeight       = false;
            background_group.childAlignment         = TextAnchor.UpperLeft;
            background_group.spacing = DefaultSpacing;
            background_group.padding = new RectOffset(
                (int)(layout.minWidth * 0.2f),
                (int)(layout.minHeight * 0.2f),
                (int)(layout.minWidth * 0.2f),
                (int)(layout.minHeight * 0.2f)
                );

            LayoutElement background_layout = background_obj.AddComponent <LayoutElement>();

            background_layout.minWidth        = -1.0f;
            background_layout.minHeight       = -1.0f;
            background_layout.preferredWidth  = -1.0f;
            background_layout.preferredHeight = -1.0f;
            background_layout.flexibleWidth   = 0.0f;
            background_layout.flexibleHeight  = 0.0f;

            CanvasRenderer background_renderer = background_obj.AddComponent <CanvasRenderer>();

            Image background_image = background_obj.AddComponent <Image>();

            background_image.sprite = crUI.CheckboxBackgroundImage?.sprite;

            // checkmark
            GameObject checkmark_obj = new GameObject("ToyBox.Checkbox.Checkmark");

            RectTransform checkmark_transform = checkmark_obj.AddComponent <RectTransform>();

            checkmark_transform.SetParent(background_transform, false);
            checkmark_transform.anchorMin = new Vector2(0.0f, 0.0f);
            checkmark_transform.anchorMax = new Vector2(1.0f, 1.0f);
            checkmark_transform.pivot     = new Vector2(0.5f, 0.5f);
            checkmark_transform.offsetMin = new Vector2(0.0f, 0.0f);
            checkmark_transform.offsetMax = new Vector2(0.0f, 0.0f);

            LayoutElement checkmark_layout = checkmark_obj.AddComponent <LayoutElement>();

            checkmark_layout.minWidth        = -1.0f;
            checkmark_layout.minHeight       = -1.0f;
            checkmark_layout.preferredWidth  = -1.0f;
            checkmark_layout.preferredHeight = -1.0f;
            checkmark_layout.flexibleWidth   = 1.0f;
            checkmark_layout.flexibleHeight  = 1.0f;

            CanvasRenderer checkmark_renderer = checkmark_obj.AddComponent <CanvasRenderer>();

            Image checkmark_image = checkmark_obj.AddComponent <Image>();

            checkmark_image.sprite = crUI.CheckboxCheckmarkImage?.sprite;

            SpriteState sprite_state = crUI.CheckboxLayerParts[0].SpriteState;

            OwlcatSelectableLayerPart layer0 = new OwlcatSelectableLayerPart();

            layer0.Image       = background_image;
            layer0.Transition  = OwlcatTransition.SpriteSwap;
            layer0.SpriteState = sprite_state;
            button.AddLayerToMainPart(layer0);

            button.AddMultiLayer();
            button.AddMultiLayer();

            List <OwlcatMultiLayer> layers = AccessTools.DeclaredField(typeof(OwlcatMultiSelectable), "m_MultiLayers")
                                             .GetValue(button) as List <OwlcatMultiLayer>;

            layers[0].LayerName = "Unchecked";

            OwlcatMultiLayer layer1 = layers[1];

            layer1.LayerName = "Checked";
            layer1.AddPart();
            layer1.Parts[0].Transition = OwlcatTransition.Activate;
            AccessTools.DeclaredField(typeof(OwlcatSelectableLayerPart), "m_TargetGameObject")
            .SetValue(layer1.Parts[0], checkmark_obj);

            AccessTools.DeclaredMethod(typeof(OwlcatMultiSelectable), "DoSetLayers").Invoke(button, new object[] {});

            Button.ButtonClickedEvent evt = AccessTools
                                            .DeclaredField(typeof(OwlcatMultiButton), "m_OnLeftClick").GetValue(button) as Button.ButtonClickedEvent;

            evt.AddListener(() => {
                List <OwlcatMultiLayer> layers = AccessTools.DeclaredField(typeof(OwlcatMultiSelectable), "m_MultiLayers")
                                                 .GetValue(button) as List <OwlcatMultiLayer>;
                button.SetActiveLayer((button.ActiveLayerIndex + 1) % layers.Count);
            });

            return(transform);
        }
Esempio n. 19
0
        private static void EmitCallParameter(ILEmitter il, MethodBase original, MethodInfo patch,
                                              Dictionary <string, VariableDefinition> variables,
                                              bool allowFirsParamPassthrough)
        {
            var isInstance             = original.IsStatic == false;
            var originalParameters     = original.GetParameters();
            var originalParameterNames = originalParameters.Select(p => p.Name).ToArray();

            // check for passthrough using first parameter (which must have same type as return type)
            var parameters = patch.GetParameters().ToList();

            if (allowFirsParamPassthrough && patch.ReturnType != typeof(void) && parameters.Count > 0 &&
                parameters[0].ParameterType == patch.ReturnType)
            {
                parameters.RemoveRange(0, 1);
            }

            foreach (var patchParam in parameters)
            {
                if (patchParam.Name == ORIGINAL_METHOD_PARAM)
                {
                    if (original is MethodInfo method)
                    {
                        il.Emit(OpCodes.Ldtoken, method);
                    }
                    else if (original is ConstructorInfo constructor)
                    {
                        il.Emit(OpCodes.Ldtoken, constructor);
                    }
                    else
                    {
                        il.Emit(OpCodes.Ldnull);
                        continue;
                    }

                    var type = original.ReflectedType;
                    if (type != null && type.IsGenericType)
                    {
                        il.Emit(OpCodes.Ldtoken, type);
                    }
                    il.Emit(OpCodes.Call, type != null && type.IsGenericType ? GetMethodFromHandle2 : GetMethodFromHandle1);
                    continue;
                }

                if (patchParam.Name == INSTANCE_PARAM)
                {
                    if (original.IsStatic)
                    {
                        il.Emit(OpCodes.Ldnull);
                    }
                    else
                    {
                        var instanceIsRef  = original.DeclaringType != null && AccessTools.IsStruct(original.DeclaringType);
                        var parameterIsRef = patchParam.ParameterType.IsByRef;
                        if (instanceIsRef == parameterIsRef)
                        {
                            il.Emit(OpCodes.Ldarg_0);
                        }
                        if (instanceIsRef && parameterIsRef == false)
                        {
                            il.Emit(OpCodes.Ldarg_0);
                            il.Emit(OpCodes.Ldobj, original.DeclaringType);
                        }

                        if (instanceIsRef == false && parameterIsRef)
                        {
                            il.Emit(OpCodes.Ldarga, 0);
                        }
                    }

                    continue;
                }

                if (patchParam.Name.StartsWith(INSTANCE_FIELD_PREFIX, StringComparison.Ordinal))
                {
                    var       fieldName = patchParam.Name.Substring(INSTANCE_FIELD_PREFIX.Length);
                    FieldInfo fieldInfo;
                    if (fieldName.All(char.IsDigit))
                    {
                        fieldInfo = AccessTools.DeclaredField(original.DeclaringType, int.Parse(fieldName));
                        if (fieldInfo == null)
                        {
                            throw new ArgumentException(
                                      $"No field found at given index in class {original.DeclaringType.FullName}", fieldName);
                        }
                    }
                    else
                    {
                        fieldInfo = AccessTools.DeclaredField(original.DeclaringType, fieldName);
                        if (fieldInfo == null)
                        {
                            throw new ArgumentException(
                                      $"No such field defined in class {original.DeclaringType.FullName}", fieldName);
                        }
                    }

                    if (fieldInfo.IsStatic)
                    {
                        il.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldsflda : OpCodes.Ldsfld, fieldInfo);
                    }
                    else
                    {
                        il.Emit(OpCodes.Ldarg_0);
                        il.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldflda : OpCodes.Ldfld, fieldInfo);
                    }

                    continue;
                }

                // state is special too since each patch has its own local var
                if (patchParam.Name == STATE_VAR)
                {
                    if (variables.TryGetValue(patch.DeclaringType?.FullName ?? string.Empty, out var stateVar))
                    {
                        il.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc, stateVar);
                    }
                    else
                    {
                        il.Emit(OpCodes.Ldnull);
                    }
                    continue;
                }

                // treat __result var special
                if (patchParam.Name == RESULT_VAR)
                {
                    var returnType = AccessTools.GetReturnedType(original);
                    if (returnType == typeof(void))
                    {
                        throw new InvalidHarmonyPatchArgumentException($"Cannot get result from void method", original, patch);
                    }
                    var resultType = patchParam.ParameterType;
                    if (resultType.IsByRef)
                    {
                        resultType = resultType.GetElementType();
                    }
                    if (resultType.IsAssignableFrom(returnType) == false)
                    {
                        throw new InvalidHarmonyPatchArgumentException(
                                  $"Cannot assign method return type {returnType.FullName} to {RESULT_VAR} type {resultType.FullName}", original, patch);
                    }
                    il.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc, variables[RESULT_VAR]);
                    continue;
                }

                // any other declared variables
                if (variables.TryGetValue(patchParam.Name, out var localBuilder))
                {
                    il.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc, localBuilder);
                    continue;
                }

                int idx;
                if (patchParam.Name.StartsWith(PARAM_INDEX_PREFIX, StringComparison.Ordinal))
                {
                    var val = patchParam.Name.Substring(PARAM_INDEX_PREFIX.Length);
                    if (!int.TryParse(val, out idx))
                    {
                        throw new InvalidHarmonyPatchArgumentException($"Parameter {patchParam.Name} does not contain a valid index", original, patch);
                    }
                    if (idx < 0 || idx >= originalParameters.Length)
                    {
                        throw new InvalidHarmonyPatchArgumentException($"No parameter found at index {idx}", original, patch);
                    }
                }
                else
                {
                    idx = GetArgumentIndex(patch, originalParameterNames, patchParam);
                    if (idx == -1)
                    {
                        throw new InvalidHarmonyPatchArgumentException(
                                  $"Parameter \"{patchParam.Name}\" not found", original, patch);
                    }
                }

                //   original -> patch     opcode
                // --------------------------------------
                // 1 normal   -> normal  : LDARG
                // 2 normal   -> ref/out : LDARGA
                // 3 ref/out  -> normal  : LDARG, LDIND_x
                // 4 ref/out  -> ref/out : LDARG
                //
                var originalIsNormal = originalParameters[idx].IsOut == false &&
                                       originalParameters[idx].ParameterType.IsByRef == false;
                var patchIsNormal = patchParam.IsOut == false && patchParam.ParameterType.IsByRef == false;
                var patchArgIndex = idx + (isInstance ? 1 : 0);

                // Case 1 + 4
                if (originalIsNormal == patchIsNormal)
                {
                    il.Emit(OpCodes.Ldarg, patchArgIndex);
                    continue;
                }

                // Case 2
                if (originalIsNormal && patchIsNormal == false)
                {
                    il.Emit(OpCodes.Ldarga, patchArgIndex);
                    continue;
                }

                // Case 3
                il.Emit(OpCodes.Ldarg, patchArgIndex);
                il.Emit(GetIndOpcode(originalParameters[idx].ParameterType));
            }
        }
Esempio n. 20
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());
        }
Esempio n. 21
0
        public static IEnumerable <CodeInstruction> FindPath(IEnumerable <CodeInstruction> instructions, ILGenerator iLGenerator)
        {
            //Type nodeFastType = AccessTools.TypeByName("Verse.AI.PathFinder+PathFinderNodeFast");
            Type         nodeFastType                      = typeof(PathFinderNodeFast);
            Type         nodeFastTypeArray                 = nodeFastType.MakeArrayType();
            LocalBuilder local_calcGrid                    = iLGenerator.DeclareLocal(nodeFastTypeArray);
            LocalBuilder local_statusOpenValue             = iLGenerator.DeclareLocal(typeof(ushort));
            LocalBuilder local_statusClosedValue           = iLGenerator.DeclareLocal(typeof(ushort));
            LocalBuilder local_regionCostCalculatorWrapper = iLGenerator.DeclareLocal(typeof(RegionCostCalculatorWrapper));
            Type         costNodeType                      = AccessTools.TypeByName("Verse.AI.PathFinder+CostNode");
            Type         costNodeType2                     = typeof(CostNode2);
            Type         icomparerCostNodeType1            = typeof(IComparer <>).MakeGenericType(costNodeType);
            Type         icomparerCostNodeType2            = typeof(IComparer <>).MakeGenericType(costNodeType2);
            Type         fastPriorityQueueCostNodeType1    = typeof(FastPriorityQueue <>).MakeGenericType(costNodeType);
            Type         fastPriorityQueueCostNodeType2    = typeof(FastPriorityQueue <>).MakeGenericType(costNodeType2);
            LocalBuilder local_openList                    = iLGenerator.DeclareLocal(fastPriorityQueueCostNodeType2);
            //LocalBuilder tID = iLGenerator.DeclareLocal(typeof(int));
            //LocalBuilder size = iLGenerator.DeclareLocal(typeof(int));

            List <CodeInstruction> instructionsList = instructions.ToList();
            int i = 0;

            // int managedThreadId = Thread.CurrentThread.ManagedThreadId;
            //IL_0000: call class [mscorlib]System.Threading.Thread[mscorlib] System.Threading.Thread::get_CurrentThread()
            //IL_0005: callvirt instance int32[mscorlib] System.Threading.Thread::get_ManagedThreadId()
            //IL_000a: stloc.0
            //yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Thread), "get_CurrentThread"));
            //yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Thread), "get_ManagedThreadId"));
            //yield return new CodeInstruction(OpCodes.Stloc, tID.LocalIndex);

            // PathFinderNodeFast[] calcGrid = getCalcGrid(managedThreadId, __instance);
            //IL_000b: ldloc.0
            //IL_000c: ldarg.0
            //IL_000d: call valuetype RimThreaded.PathFinder_Patch / PathFinderNodeFast[] RimThreaded.PathFinder_Patch::getCalcGrid(int32, class ['Assembly-CSharp'] Verse.AI.PathFinder)
            //IL_0012: stloc.1
            //yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
            yield return(new CodeInstruction(OpCodes.Ldarg_0));

            yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "getCalcGrid")));

            yield return(new CodeInstruction(OpCodes.Stloc, local_calcGrid.LocalIndex));

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

            yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "getRegionCostCalculatorWrapper")));

            yield return(new CodeInstruction(OpCodes.Stloc, local_regionCostCalculatorWrapper.LocalIndex));

            // FastPriorityQueue<CostNode2> openList = getOpenList(managedThreadId);
            //IL_0013: ldloc.0
            //IL_0014: call class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2> RimThreaded.PathFinder_Patch::getOpenList(int32)
            //IL_0019: stloc.2
            //yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
            yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "getOpenList")));

            yield return(new CodeInstruction(OpCodes.Stloc, local_openList.LocalIndex));

            // ushort local_statusOpenValue = getOpenValue(managedThreadId);
            //IL_001a: ldloc.0
            //IL_001b: call uint16 RimThreaded.PathFinder_Patch::getOpenValue(int32)
            //IL_0020: stloc.3
            //yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
            yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "getOpenValue")));

            yield return(new CodeInstruction(OpCodes.Stloc, local_statusOpenValue.LocalIndex));

            // ushort local_statusClosedValue = getClosedValue(managedThreadId);
            //IL_0021: ldloc.0
            //IL_0022: call uint16 RimThreaded.PathFinder_Patch::getClosedValue(int32)
            //IL_0027: stloc.s 4
            //yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
            yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "getClosedValue")));

            yield return(new CodeInstruction(OpCodes.Stloc, local_statusClosedValue.LocalIndex));

            /*
             * // int num = mapSizeXField(__instance) * mapSizeZField(__instance);
             * yield return new CodeInstruction(OpCodes.Ldarg_0);
             * yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), "mapSizeX"));
             * yield return new CodeInstruction(OpCodes.Ldarg_0);
             * yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), "mapSizeZ"));
             * yield return new CodeInstruction(OpCodes.Mul);
             * yield return new CodeInstruction(OpCodes.Stloc, size.LocalIndex);
             *
             * // if (!calcGrids.TryGetValue(managedThreadId, out PathFinderNodeFast[] value) || value.Length < num)
             *
             * //IL_0025: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<int32, valuetype RimThreaded.PathFinder_Patch/PathFinderNodeFast[]> RimThreaded.PathFinder_Patch::calcGrids
             * //IL_002a: ldloc.0
             * //IL_002b: ldloca.s 2
             * //IL_002d: callvirt instance bool class [mscorlib]System.Collections.Generic.Dictionary`2<int32, valuetype RimThreaded.PathFinder_Patch/PathFinderNodeFast[]>::TryGetValue(!0, !1&)
             * //IL_0032: brfalse.s IL_003a
             * //IL_0034: ldloc.2
             * //IL_0035: ldlen
             * //IL_0036: conv.i4
             * //IL_0037: ldloc.1
             * //IL_0038: bge.s IL_004d
             *
             * yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "calcGrids"));
             * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Ldloca, local_calcGrid.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, PathFinder_Patch.PathFinderNodeFast[]>), "TryGetValue"));
             * Label il_003a = iLGenerator.DefineLabel();
             * yield return new CodeInstruction(OpCodes.Brfalse_S, il_003a);
             *
             * yield return new CodeInstruction(OpCodes.Ldloc, local_calcGrid.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Ldlen);
             * yield return new CodeInstruction(OpCodes.Conv_I4);
             * yield return new CodeInstruction(OpCodes.Ldloc, size.LocalIndex);
             * Label il_004d = iLGenerator.DefineLabel();
             * yield return new CodeInstruction(OpCodes.Bge_S, il_004d);
             *
             * // value = new PathFinderNodeFast[num];
             * //IL_003a: ldloc.1
             * //IL_003b: newarr RimThreaded.PathFinder_Patch / PathFinderNodeFast
             * //IL_0040: stloc.2
             * CodeInstruction ci_003a = new CodeInstruction(OpCodes.Ldloc, size.LocalIndex);
             * ci_003a.labels.Add(il_003a);
             * yield return ci_003a;
             *
             * yield return new CodeInstruction(OpCodes.Newarr, nodeFastType);
             * yield return new CodeInstruction(OpCodes.Stloc, local_calcGrid.LocalIndex);
             *
             * // calcGrids[managedThreadId] = value;
             * //IL_0041: ldsfld class [mscorlib] System.Collections.Generic.Dictionary`2<int32, valuetype RimThreaded.PathFinder_Patch/PathFinderNodeFast[]> RimThreaded.PathFinder_Patch::calcGrids
             * //IL_0046: ldloc.0
             * //IL_0047: ldloc.2
             * //IL_0048: callvirt instance void class [mscorlib] System.Collections.Generic.Dictionary`2<int32, valuetype RimThreaded.PathFinder_Patch/PathFinderNodeFast[]>::set_Item(!0, !1)
             * yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "calcGrids"));
             * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Ldloc, local_calcGrid.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Callvirt,
             *      AccessTools.Method(typeof(Dictionary<int, PathFinder_Patch.PathFinderNodeFast[]>), "set_Item"));
             *
             *
             * // if (!openLists.TryGetValue(managedThreadId, out FastPriorityQueue<CostNode2> value2))
             * //IL_004d: ldsfld class [mscorlib] System.Collections.Generic.Dictionary`2<int32, class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2>> RimThreaded.PathFinder_Patch::openLists
             * //IL_0052: ldloc.0
             * //IL_0053: ldloca.s 3
             * //IL_0055: callvirt instance bool class [mscorlib] System.Collections.Generic.Dictionary`2<int32, class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2>>::TryGetValue(!0, !1&)
             * //IL_005a: brtrue.s IL_0073
             * CodeInstruction ci_004d = new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "openLists"));
             * ci_004d.labels.Add(il_004d);
             * yield return ci_004d;
             *
             * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Ldloca, local_statusOpenValue);
             * yield return new CodeInstruction(OpCodes.Callvirt,
             *      AccessTools.Method(typeof(Dictionary<int, FastPriorityQueue<PathFinder_Patch.CostNode2>>), "TryGetValue"));
             * Label il_0073 = iLGenerator.DefineLabel();
             * yield return new CodeInstruction(OpCodes.Brtrue, il_0073);
             *
             * // value2 = new FastPriorityQueue<CostNode2>(new CostNodeComparer2());
             * //IL_005c: newobj instance void RimThreaded.PathFinder_Patch / CostNodeComparer2::.ctor()
             * //IL_0061: newobj instance void class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2>::.ctor(class [mscorlib] System.Collections.Generic.IComparer`1<!0>)
             * //IL_0066: stloc.3
             * yield return new CodeInstruction(OpCodes.Newobj, typeof(CostNodeComparer2).GetConstructor(Type.EmptyTypes));
             * yield return new CodeInstruction(OpCodes.Newobj, fastPriorityQueueCostNodeType2.GetConstructor(new Type[] { icomparerCostNodeType2 }));
             * yield return new CodeInstruction(OpCodes.Stloc, local_openList.LocalIndex);
             *
             * // openLists[managedThreadId] = value2;
             * //IL_0067: ldsfld class [mscorlib] System.Collections.Generic.Dictionary`2<int32, class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2>> RimThreaded.PathFinder_Patch::openLists
             * //IL_006c: ldloc.0
             * //IL_006d: ldloc.3
             * //IL_006e: callvirt instance void class [mscorlib] System.Collections.Generic.Dictionary`2<int32, class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2>>::set_Item(!0, !1)
             * yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "openLists"));
             * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Ldloc, local_openList.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, FastPriorityQueue<PathFinder_Patch.CostNode2>>), "set_Item"));
             *
             * // if (!openValues.TryGetValue(managedThreadId, out ushort value3))
             * //IL_0073: ldsfld class [mscorlib] System.Collections.Generic.Dictionary`2<int32, uint16> RimThreaded.PathFinder_Patch::openValues
             * //IL_0078: ldloc.0
             * //IL_0079: ldloca.s 4
             * //IL_007b: callvirt instance bool class [mscorlib] System.Collections.Generic.Dictionary`2<int32, uint16>::TryGetValue(!0, !1&)
             * //IL_0080: brtrue.s IL_0085
             * CodeInstruction ci_0073 = new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "openValues"));
             * ci_0073.labels.Add(il_0073);
             * yield return ci_0073;
             * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Ldloca, local_statusOpenValue.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, ushort>), "TryGetValue"));
             * Label il_0085 = iLGenerator.DefineLabel();
             * yield return new CodeInstruction(OpCodes.Brtrue, il_0085);
             *
             * // value3 = 1;
             * //IL_0082: ldc.i4.1
             * //IL_0083: stloc.s 4
             * yield return new CodeInstruction(OpCodes.Ldc_I4_1);
             * yield return new CodeInstruction(OpCodes.Stloc, local_statusOpenValue.LocalIndex);
             *
             * // if (!closedValues.TryGetValue(managedThreadId, out ushort value4))
             * //IL_0085: ldsfld class [mscorlib] System.Collections.Generic.Dictionary`2<int32, uint16> RimThreaded.PathFinder_Patch::closedValues
             * //IL_008a: ldloc.0
             * //IL_008b: ldloca.s 5
             * //IL_008d: callvirt instance bool class [mscorlib] System.Collections.Generic.Dictionary`2<int32, uint16>::TryGetValue(!0, !1&)
             * //IL_0092: brtrue.s IL_0097
             * CodeInstruction ci__0085 = new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "closedValues"));
             * ci__0085.labels.Add(il_0085);
             * yield return ci__0085;
             * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Ldloca, local_statusClosedValue.LocalIndex);
             * yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, ushort>), "TryGetValue"));
             * Label il_0097 = iLGenerator.DefineLabel();
             * yield return new CodeInstruction(OpCodes.Brtrue, il_0097);
             *
             * // value4 = 2;
             * //IL_0094: ldc.i4.2
             * //IL_0095: stloc.s 5
             * yield return new CodeInstruction(OpCodes.Ldc_I4_2);
             * yield return new CodeInstruction(OpCodes.Stloc, local_statusClosedValue.LocalIndex);
             * instructionsList[0].labels.Add(il_0097);
             *
             * //yield return new CodeInstruction(OpCodes.Newobj, costNodeType2.GetConstructor(Type.EmptyTypes));
             * //yield return new CodeInstruction(OpCodes.Newobj, fastPriorityQueueCostNodeType2.GetConstructor(new Type[] { icomparerCostNodeType2 }));
             * //yield return new CodeInstruction(OpCodes.Stloc, local_openList.LocalIndex);
             */

            while (i < instructionsList.Count)
            {
                // InitStatusesAndPushStartNode(ref curIndex, start);
                //IL_0363: ldarg.0
                //IL_0364: ldloca.s 3
                //IL_0366: ldarg.1
                //IL_0367: call instance void Verse.AI.PathFinder::InitStatusesAndPushStartNode(int32 &, valuetype Verse.IntVec3)
                if (
                    i + 3 < instructionsList.Count &&
                    instructionsList[i + 3].opcode == OpCodes.Call &&
                    instructionsList[i + 3].operand.ToString().Equals("Void InitStatusesAndPushStartNode(Int32 ByRef, Verse.IntVec3)")
                    )
                {
                    //IL_043b: ldsfld class ['0Harmony'] HarmonyLib.AccessTools/FieldRef`2<class ['Assembly-CSharp'] Verse.AI.PathFinder, class ['Assembly-CSharp'] Verse.CellIndices> RimThreaded.PathFinder_Patch::cellIndicesField
                    //IL_0440: ldarg.0
                    //IL_0441: callvirt instance !1& class ['0Harmony'] HarmonyLib.AccessTools/FieldRef`2<class ['Assembly-CSharp'] Verse.AI.PathFinder, class ['Assembly-CSharp'] Verse.CellIndices>::Invoke(!0)
                    //IL_0446: ldind.ref
                    //IL_0447: ldloca.s 7
                    //IL_0449: ldarg.2
                    //IL_044a: ldloc.0
                    //IL_044b: ldloc.3
                    //IL_044c: ldloca.s 1
                    //IL_044e: ldloca.s 2
                    //IL_0450: call void RimThreaded.PathFinder_Patch::InitStatusesAndPushStartNode2(class ['Assembly-CSharp'] Verse.CellIndices, int32&, valuetype['Assembly-CSharp'] Verse.IntVec3, valuetype RimThreaded.PathFinder_Patch/PathFinderNodeFast[], class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode>, uint16&, uint16&)

                    instructionsList[i].opcode = OpCodes.Nop;
                    yield return(instructionsList[i]);

                    i++;
                    yield return(instructionsList[i]);

                    i++;
                    yield return(instructionsList[i]);

                    i += 2;
                    yield return(new CodeInstruction(OpCodes.Ldarg_0));

                    yield return(new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), "cellIndices")));

                    yield return(new CodeInstruction(OpCodes.Ldloc, local_calcGrid.LocalIndex));

                    //yield return new CodeInstruction(OpCodes.Ldarg_0);
                    //yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), "openList"));
                    yield return(new CodeInstruction(OpCodes.Ldloca, local_statusOpenValue.LocalIndex));

                    yield return(new CodeInstruction(OpCodes.Ldloca, local_statusClosedValue.LocalIndex));

                    yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "InitStatusesAndPushStartNode3")));

                    // openList.Clear();
                    // fastPriorityQueue.Clear();
                    //IL_0502: ldloc.3
                    //IL_0503: callvirt instance void class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype Verse.AI.PathFinder_Target/CostNode>::Clear()
                    yield return(new CodeInstruction(OpCodes.Ldloc_S, local_openList.LocalIndex));

                    yield return(new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(fastPriorityQueueCostNodeType2, "Clear")));

                    // openList.Push(new CostNode(curIndex, 0));
                    // fastPriorityQueue.Push(new CostNode(num3, 0));
                    //IL_0508: ldloc.3
                    //IL_0509: ldloc.s 9
                    //IL_050b: ldc.i4.0
                    //IL_050c: newobj instance void Verse.AI.PathFinder_Target / CostNode::.ctor(int32, int32)
                    //IL_0511: callvirt instance void class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype Verse.AI.PathFinder_Target/CostNode>::Push(!0)
                    yield return(new CodeInstruction(OpCodes.Ldloc_S, local_openList.LocalIndex));

                    yield return(new CodeInstruction(OpCodes.Ldloc_3));                    //curIndex

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

                    Log.Message(costNodeType2.GetConstructor(new Type[] { typeof(Int32), typeof(Int32) }).ToString());
                    yield return(new CodeInstruction(OpCodes.Newobj, costNodeType2.GetConstructor(new Type[] { typeof(Int32), typeof(Int32) })));

                    yield return(new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(fastPriorityQueueCostNodeType2, "Push")));
                    //yield return new CodeInstruction(OpCodes.Ldloc_S, openList.LocalIndex);
                }
                //call instance class ['Assembly-CSharp']Verse.AI.PawnPath Verse.AI.PathFinder_Original::FinalizedPath(int32, bool)
                else if (
                    i + 3 < instructionsList.Count &&
                    instructionsList[i + 3].opcode == OpCodes.Call &&
                    instructionsList[i + 3].operand.ToString().Equals("Verse.AI.PawnPath FinalizedPath(Int32, Boolean)")
                    )
                {
                    // PawnPath pawnPath = new PawnPath();
                    //IL_0535: newobj instance void ['Assembly-CSharp']Verse.AI.PawnPath::.ctor()
                    //IL_0545: stloc.s 39   (emptyPawnPath.LocalIndex)
                    // int num13 = curIndex;
                    //IL_0547: ldloc.3   (curIndex)
                    //IL_0549: stloc.s 40   (num1.LocalIndex)
                    instructionsList[i].opcode = OpCodes.Nop;
                    yield return(instructionsList[i]);

                    i++;
                    yield return(instructionsList[i]);

                    i++;
                    yield return(instructionsList[i]);

                    i += 2;
                    yield return(new CodeInstruction(OpCodes.Ldarg_0));

                    yield return(new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), "cellIndices")));

                    yield return(new CodeInstruction(OpCodes.Ldloc, local_calcGrid.LocalIndex));

                    yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "FinalizedPath2")));
                }

                //ldsfld valuetype Verse.AI.PathFinder_Original/PathFinderNodeFast[] Verse.AI.PathFinder_Original::calcGrid
                else if (
                    instructionsList[i].opcode == OpCodes.Ldsfld && instructionsList[i].operand.ToString().Equals("Verse.AI.PathFinder+PathFinderNodeFast[] calcGrid")
                    )
                {
                    //ldloc.0   (local_calcGrid.LocalIndex)
                    instructionsList[i].opcode  = OpCodes.Ldloc;
                    instructionsList[i].operand = local_calcGrid.LocalIndex;
                    yield return(instructionsList[i]);

                    i++;
                }

                //ldsfld uint16 Verse.AI.PathFinder_Original::statusOpenValue
                else if (
                    instructionsList[i].opcode == OpCodes.Ldsfld && instructionsList[i].operand.ToString().Equals("System.UInt16 statusOpenValue")
                    )
                {
                    //ldloc.1   (local_statusOpenValue.LocalIndex)
                    instructionsList[i].opcode  = OpCodes.Ldloc;
                    instructionsList[i].operand = local_statusOpenValue.LocalIndex;
                    yield return(instructionsList[i]);

                    i++;
                }

                //ldsfld uint16 Verse.AI.PathFinder_Original::statusClosedValue
                else if (
                    instructionsList[i].opcode == OpCodes.Ldsfld && instructionsList[i].operand.ToString().Equals("System.UInt16 statusClosedValue")
                    )
                {
                    //ldloc.2(local_statusClosedValue.LocalIndex)
                    instructionsList[i].opcode  = OpCodes.Ldloc;
                    instructionsList[i].operand = local_statusClosedValue.LocalIndex;
                    yield return(instructionsList[i]);

                    i++;
                }
                // ldarg.0
                // ldfld class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype Verse.AI.PathFinder_Target/CostNode> Verse.AI.PathFinder_Target::openList
                else if (
                    i + 1 < instructionsList.Count &&
                    instructionsList[i].opcode == OpCodes.Ldarg_0 &&
                    instructionsList[i + 1].opcode == OpCodes.Ldfld && instructionsList[i + 1].operand.ToString().Equals("Verse.FastPriorityQueue`1[Verse.AI.PathFinder+CostNode] openList")
                    )
                {
                    // ldloc.3 (openlist)
                    instructionsList[i].opcode  = OpCodes.Ldloc;
                    instructionsList[i].operand = local_openList.LocalIndex;
                    yield return(instructionsList[i]);

                    i += 2;
                }
                else if (
                    instructionsList[i].opcode == OpCodes.Callvirt &&
                    (MethodInfo)instructionsList[i].operand == AccessTools.Method(fastPriorityQueueCostNodeType1, "get_Count")
                    )
                {
                    instructionsList[i].operand = AccessTools.Method(fastPriorityQueueCostNodeType2, "get_Count");
                    yield return(instructionsList[i]);

                    i++;
                }
                else if (
                    instructionsList[i].opcode == OpCodes.Callvirt &&
                    (MethodInfo)instructionsList[i].operand == AccessTools.Method(fastPriorityQueueCostNodeType1, "Pop")
                    )
                {
                    instructionsList[i].operand = AccessTools.Method(fastPriorityQueueCostNodeType2, "Pop");
                    yield return(instructionsList[i]);

                    i++;
                }
                else if (
                    instructionsList[i].opcode == OpCodes.Callvirt &&
                    (MethodInfo)instructionsList[i].operand == AccessTools.Method(fastPriorityQueueCostNodeType1, "Push")
                    )
                {
                    instructionsList[i].operand = AccessTools.Method(fastPriorityQueueCostNodeType2, "Push");
                    yield return(instructionsList[i]);

                    i++;
                }

                else if (
                    instructionsList[i].opcode == OpCodes.Ldfld &&
                    (FieldInfo)instructionsList[i].operand == AccessTools.Field(costNodeType, "index")
                    )
                {
                    instructionsList[i].operand = AccessTools.Field(costNodeType2, "index");
                    yield return(instructionsList[i]);

                    i++;
                }
                else if (
                    instructionsList[i].opcode == OpCodes.Ldfld &&
                    (FieldInfo)instructionsList[i].operand == AccessTools.Field(costNodeType, "cost")
                    )
                {
                    instructionsList[i].operand = AccessTools.Field(costNodeType2, "cost");
                    yield return(instructionsList[i]);

                    i++;
                }
                else if (
                    instructionsList[i].opcode == OpCodes.Newobj &&
                    (ConstructorInfo)instructionsList[i].operand == costNodeType.GetConstructor(new Type[] { typeof(int), typeof(int) })
                    )
                {
                    instructionsList[i].operand = costNodeType2.GetConstructor(new Type[] { typeof(int), typeof(int) });
                    yield return(instructionsList[i]);

                    i++;
                }
                else if (
                    instructionsList[i].opcode == OpCodes.Newobj &&
                    (ConstructorInfo)instructionsList[i].operand == fastPriorityQueueCostNodeType1.GetConstructor(new Type[] { icomparerCostNodeType1 })
                    )
                {
                    instructionsList[i].operand = fastPriorityQueueCostNodeType2.GetConstructor(new Type[] { icomparerCostNodeType2 });
                    yield return(instructionsList[i]);

                    i++;
                }
                else if (i + 1 < instructionsList.Count &&
                         instructionsList[i + 1].opcode == OpCodes.Ldfld &&
                         (FieldInfo)instructionsList[i + 1].operand == AccessTools.DeclaredField(typeof(PathFinder), "regionCostCalculator")
                         )
                {
                    instructionsList[i].opcode  = OpCodes.Ldloc;
                    instructionsList[i].operand = local_regionCostCalculatorWrapper.LocalIndex;
                    yield return(instructionsList[i++]);

                    i++;
                }

                /*
                 * else if (i == instructionsList.Count - 1)
                 * {
                 *      // openValues[managedThreadId] = value3;
                 *      //IL_0c30: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<int32, uint16> RimThreaded.PathFinder_Patch::openValues
                 *      //IL_0c35: ldloc.0
                 *      //IL_0c36: ldloc.s 4
                 *      //IL_0c38: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32, uint16>::set_Item(!0, !1)
                 *      yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "openValues"));
                 *      yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
                 *      yield return new CodeInstruction(OpCodes.Ldloc, local_statusOpenValue);
                 *      yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, ushort>), "set_Item"));
                 *
                 *      // closedValues[managedThreadId] = value4;
                 *      //IL_0c3d: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<int32, uint16> RimThreaded.PathFinder_Patch::closedValues
                 *      //IL_0c42: ldloc.0
                 *      //IL_0c43: ldloc.s 5
                 *      //IL_0c45: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32, uint16>::set_Item(!0, !1)
                 *      yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "closedValues"));
                 *      yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex);
                 *      yield return new CodeInstruction(OpCodes.Ldloc, local_statusClosedValue);
                 *      yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, ushort>), "set_Item"));
                 *      yield return instructionsList[i];
                 *      i++;
                 * }
                 */
                else
                {
                    yield return(instructionsList[i]);

                    i++;
                }
            }
        }
Esempio n. 22
0
        public static void WriteSyncObject(ByteWriter data, object obj, SyncType syncType)
        {
            MpContext context = data.MpContext();
            Type      type    = syncType.type;

            var log = (data as LoggingByteWriter)?.Log;

            log?.Enter($"{type.FullName}: {obj ?? "null"}");

            if (obj != null && !type.IsAssignableFrom(obj.GetType()))
            {
                throw new SerializationException($"Serializing with type {type} but got object of type {obj.GetType()}");
            }

            try
            {
                if (typeof(object) == type)
                {
                    return;
                }

                if (type.IsByRef)
                {
                    return;
                }

                if (SyncDictFast.syncWorkers.TryGetValue(type, out var syncWorkerEntryEarly))
                {
                    syncWorkerEntryEarly.Invoke(new WritingSyncWorker(data), ref obj);

                    return;
                }

                if (syncType.expose)
                {
                    if (!typeof(IExposable).IsAssignableFrom(type))
                    {
                        throw new SerializationException($"Type {type} can't be exposed because it isn't IExposable");
                    }

                    IExposable exposable = obj as IExposable;
                    byte[]     xmlData   = ScribeUtil.WriteExposable(exposable);
                    LogXML(log, xmlData);
                    data.WritePrefixedBytes(xmlData);

                    return;
                }

                if (typeof(ISynchronizable).IsAssignableFrom(type))
                {
                    ((ISynchronizable)obj).Sync(new WritingSyncWorker(data));
                    return;
                }

                if (type.IsEnum)
                {
                    Type enumType = Enum.GetUnderlyingType(type);
                    WriteSyncObject(data, Convert.ChangeType(obj, enumType), enumType);
                    return;
                }

                if (type.IsArray)
                {
                    if (type.GetArrayRank() != 1)
                    {
                        throw new SerializationException("Multi dimensional arrays aren't supported.");
                    }

                    Type  elementType = type.GetElementType();
                    Array arr         = (Array)obj;

                    if (arr == null)
                    {
                        data.WriteUShort(ushort.MaxValue);
                        return;
                    }

                    if (arr.Length >= ushort.MaxValue)
                    {
                        throw new SerializationException($"Tried to serialize a {elementType}[] with too many ({arr.Length}) items.");
                    }

                    data.WriteUShort((ushort)arr.Length);
                    foreach (object e in arr)
                    {
                        WriteSyncObject(data, e, elementType);
                    }

                    return;
                }

                if (type.IsGenericType)
                {
                    Type genericTypeDefinition = type.GetGenericTypeDefinition();

                    if (genericTypeDefinition == typeof(List <>))
                    {
                        IList list        = (IList)obj;
                        Type  listObjType = type.GetGenericArguments()[0];

                        if (list == null)
                        {
                            data.WriteUShort(ushort.MaxValue);
                            return;
                        }

                        if (list.Count >= ushort.MaxValue)
                        {
                            throw new SerializationException($"Tried to serialize a {type} with too many ({list.Count}) items.");
                        }

                        data.WriteUShort((ushort)list.Count);
                        foreach (object e in list)
                        {
                            WriteSyncObject(data, e, listObjType);
                        }

                        return;
                    }

                    if (genericTypeDefinition == typeof(IEnumerable <>))
                    {
                        IEnumerable e           = (IEnumerable)obj;
                        Type        elementType = type.GetGenericArguments()[0];
                        var         listType    = typeof(List <>).MakeGenericType(elementType);

                        if (e == null)
                        {
                            WriteSyncObject(data, null, listType);
                            return;
                        }

                        IList list = (IList)Activator.CreateInstance(listType);

                        foreach (var o in e)
                        {
                            list.Add(o);
                        }

                        WriteSyncObject(data, list, listType);

                        return;
                    }

                    if (genericTypeDefinition == typeof(Nullable <>))
                    {
                        bool isNull = obj == null;
                        data.WriteBool(isNull);
                        if (isNull)
                        {
                            return;
                        }

                        WriteSyncObject(data, obj, Nullable.GetUnderlyingType(type));

                        return;
                    }

                    if (genericTypeDefinition == typeof(Dictionary <,>))
                    {
                        IDictionary dictionary = (IDictionary)obj;
                        Type[]      arguments  = type.GetGenericArguments();

                        if (dictionary == null)
                        {
                            WriteSyncObject(data, null, arguments[0].MakeArrayType());
                            return;
                        }

                        Array keyArray = Array.CreateInstance(arguments[0], dictionary.Count);
                        dictionary.Keys.CopyTo(keyArray, 0);

                        Array valueArray = Array.CreateInstance(arguments[1], dictionary.Count);
                        dictionary.Values.CopyTo(valueArray, 0);

                        WriteSyncObject(data, keyArray, keyArray.GetType());
                        WriteSyncObject(data, valueArray, valueArray.GetType());

                        return;
                    }

                    if (genericTypeDefinition == typeof(Pair <,>))
                    {
                        Type[] arguments = type.GetGenericArguments();

                        WriteSyncObject(data, AccessTools.DeclaredField(type, "first").GetValue(obj), arguments[0]);
                        WriteSyncObject(data, AccessTools.DeclaredField(type, "second").GetValue(obj), arguments[1]);

                        return;
                    }

                    if (typeof(ITuple).IsAssignableFrom(genericTypeDefinition)) // ValueTuple or Tuple
                    {
                        Type[] arguments = type.GetGenericArguments();
                        ITuple tuple     = (ITuple)obj;

                        data.WriteInt32(tuple.Length);

                        for (int i = 0; i < tuple.Length; i++)
                        {
                            WriteSyncObject(data, tuple[i], arguments[i]);
                        }

                        return;
                    }
                }

                if (typeof(ISyncSimple).IsAssignableFrom(type))
                {
                    foreach (var field in AccessTools.GetDeclaredFields(type))
                    {
                        WriteSyncObject(data, field.GetValue(obj), field.FieldType);
                    }
                    return;
                }

                // Special case
                if (typeof(Def).IsAssignableFrom(type))
                {
                    if (obj is not Def def)
                    {
                        data.WriteUShort(ushort.MaxValue);
                        return;
                    }

                    var defTypeIndex = Array.IndexOf(DefSerialization.DefTypes, def.GetType());
                    if (defTypeIndex == -1)
                    {
                        throw new SerializationException($"Unknown def type {def.GetType()}");
                    }

                    data.WriteUShort((ushort)defTypeIndex);
                    data.WriteUShort(def.shortHash);

                    return;
                }

                // Special case for Designators to change the type
                if (typeof(Designator).IsAssignableFrom(type))
                {
                    data.WriteUShort((ushort)Array.IndexOf(ImplSerialization.designatorTypes, obj.GetType()));
                }

                // Where the magic happens
                if (SyncDict.syncWorkers.TryGetValue(type, out var syncWorkerEntry))
                {
                    syncWorkerEntry.Invoke(new WritingSyncWorker(data), ref obj);

                    return;
                }

                log?.Node("No writer for " + type);
                throw new SerializationException("No writer for type " + type);
            }
            catch
            {
                Log.Error($"Multiplayer: Error writing type: {type}, obj: {obj}, obj type: {obj?.GetType()}");
                throw;
            }
            finally
            {
                log?.Exit();
            }
        }
        private static IEnumerable <CodeInstruction> InitializeTranspiler(IEnumerable <CodeInstruction> instructions, MethodBase method)
        {
            var instructionsList = instructions.ToList();

            IEnumerable <CodeInstruction> ReturnDefault(string place)
            {
                Utils.DisplayUserWarning("Failed to patch WidgetPrefab.LoadFrom! {0}", place);
                return(instructionsList.AsEnumerable());
            }

            var locals    = method.GetMethodBody()?.LocalVariables;
            var typeLocal = locals?.FirstOrDefault(x => x.LocalType == typeof(Type));

            if (typeLocal is null)
            {
                return(ReturnDefault("Local not found"));
            }

            var startIndex = -1;
            var endIndex   = -1;

            for (var i = 0; i < instructionsList.Count - 5; i++)
            {
                if (!instructionsList[i + 0].IsLdarg(0))
                {
                    continue;
                }

                if (!instructionsList[i + 1].LoadsField(AccessTools.DeclaredField(typeof(WidgetFactory), "_builtinTypes")))
                {
                    continue;
                }

                if (!instructionsList[i + 2].IsLdloc())
                {
                    continue;
                }

                if (!instructionsList[i + 3].Calls(AccessTools.DeclaredPropertyGetter(typeof(MemberInfo), nameof(MemberInfo.Name))))
                {
                    continue;
                }

                if (!instructionsList[i + 4].IsLdloc())
                {
                    continue;
                }

                if (!instructionsList[i + 5].Calls(SymbolExtensions.GetMethodInfo((Dictionary <string, Type> d) => d.Add(null !, null !))))
                {
                    continue;
                }

                startIndex = i;
                endIndex   = i + 5;
                break;
            }

            if (startIndex == -1)
            {
                return(ReturnDefault("Pattern not found"));
            }

            if (instructionsList[endIndex + 1].labels.Count == 0)
            {
                return(ReturnDefault("Jmp was not found"));
            }

            var jmpEnumerator = instructionsList[endIndex + 1].labels.FirstOrDefault();

            // if (!this._builtinTypes.ContainsKey(type.Name))
            instructionsList.InsertRange(startIndex, new List <CodeInstruction>
            {
                new(OpCodes.Ldarg_0),
                new(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(WidgetFactory), "_builtinTypes")),
                new(OpCodes.Ldloc, typeLocal.LocalIndex),
                new(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(MemberInfo), nameof(MemberInfo.Name))),
                new(OpCodes.Callvirt, SymbolExtensions.GetMethodInfo((Dictionary <string, Type> d) => d.ContainsKey(null !))),
                new(OpCodes.Brtrue_S, jmpEnumerator)
            });
Esempio n. 24
0
            static void Prefix(Hud __instance)
            {
                if (!modEnabled.Value || !Player.m_localPlayer)
                {
                    return;
                }

                float angle;

                if (usePlayerDirection.Value)
                {
                    angle = Player.m_localPlayer.transform.eulerAngles.y;
                }
                else
                {
                    angle = GameCamera.instance.transform.eulerAngles.y;
                }

                if (angle > 180)
                {
                    angle -= 360;
                }

                angle *= -Mathf.Deg2Rad;

                Rect  rect       = compassObject.GetComponent <Image>().sprite.rect;
                float imageScale = GameObject.Find("GUI").GetComponent <CanvasScaler>().scaleFactor;

                compassObject.GetComponent <RectTransform>().localPosition = Vector3.right * (rect.width / 2) * angle / (2f * Mathf.PI) - new Vector3(rect.width * 0.125f, 0, 0);

                compassObject.GetComponent <Image>().color = compassColor.Value;
                compassObject.transform.parent.GetComponent <RectTransform>().localScale       = Vector3.one * compassScale.Value;
                compassObject.transform.parent.GetComponent <RectTransform>().anchoredPosition = new Vector2(0f, (Screen.height / imageScale - compassObject.GetComponent <Image>().sprite.texture.height *compassScale.Value) / 2) - Vector2.up * compassYOffset.Value;

                centerObject.GetComponent <Image>().color = centerColor.Value;
                centerObject.SetActive(showCenterMarker.Value);

                int           count   = pinsObject.transform.childCount;
                List <string> oldPins = new List <string>();

                for (int i = 0; i < count; i++)
                {
                    oldPins.Add(pinsObject.transform.GetChild(i).name);
                }

                var pinList = new List <Minimap.PinData>(AccessTools.DeclaredField(typeof(Minimap), "m_pins").GetValue(Minimap.instance) as List <Minimap.PinData>);

                pinList.AddRange((AccessTools.DeclaredField(typeof(Minimap), "m_locationPins").GetValue(Minimap.instance) as Dictionary <Vector3, Minimap.PinData>).Values);

                if (showPlayerMarkers.Value)
                {
                    pinList.AddRange((AccessTools.DeclaredField(typeof(Minimap), "m_playerPins").GetValue(Minimap.instance) as List <Minimap.PinData>));
                }

                Minimap.PinData deathPin = AccessTools.DeclaredField(typeof(Minimap), "m_deathPin").GetValue(Minimap.instance) as Minimap.PinData;

                if (deathPin != null)
                {
                    pinList.Add(deathPin);
                }

                string[] ignoredNames = ignoredMarkerNames.Value.Split(',');
                //string[] unlimitedRangeMarkerNamesList = unlimitedRangeMarkerNames.Value.Split(',');
                Transform pt = Player.m_localPlayer.transform;
                float     zeroScaleDistance = maxMarkerDistance.Value / (1 - minMarkerScale.Value);

                foreach (Minimap.PinData pin in pinList)
                {
                    string name = pin.m_pos.ToString();
                    oldPins.Remove(name);

                    var t = pinsObject.transform.Find(name);

                    if (ignoredNames.Contains(pin.m_name) || Array.Exists(ignoredNames, s => s.EndsWith("*") && name.StartsWith(s.Substring(0, s.Length - 1))) || Vector3.Distance(pt.position, pin.m_pos) > maxMarkerDistance.Value || Vector3.Distance(pt.position, pin.m_pos) < minMarkerDistance.Value)
                    {
                        if (t)
                        {
                            t.gameObject.SetActive(false);
                        }
                        continue;
                    }
                    if (t)
                    {
                        t.gameObject.SetActive(true);
                    }

                    Vector3 offset;
                    if (usePlayerDirection.Value)
                    {
                        offset = pt.InverseTransformPoint(pin.m_pos);
                    }
                    else
                    {
                        offset = GameCamera.instance.transform.InverseTransformPoint(pin.m_pos);
                    }

                    angle = Mathf.Atan2(offset.x, offset.z);

                    GameObject    po;
                    RectTransform rt;
                    Image         img;

                    if (!t)
                    {
                        po      = new GameObject();
                        po.name = pin.m_pos.ToString();
                        rt      = po.AddComponent <RectTransform>();
                        rt.SetParent(pinsObject.transform);
                        rt.anchoredPosition = Vector2.zero;
                        img = po.AddComponent <Image>();
                    }
                    else
                    {
                        po  = t.gameObject;
                        rt  = t.GetComponent <RectTransform>();
                        img = t.GetComponent <Image>();
                    }

                    float distanceScale = minMarkerScale.Value < 1 ? (zeroScaleDistance - Vector3.Distance(pt.position, pin.m_pos)) / zeroScaleDistance : 1;
                    rt.localScale    = Vector3.one * distanceScale * 0.5f * markerScale.Value;
                    img.color        = markerColor.Value;
                    img.sprite       = pin.m_icon;
                    rt.localPosition = Vector3.right * (rect.width / 2) * angle / (2f * Mathf.PI);
                }
                foreach (string name in oldPins)
                {
                    Destroy(pinsObject.transform.Find(name).gameObject);
                }
            }
Esempio n. 25
0
        public static IEnumerable <CodeInstruction> BuildingDecorationLoadPathsTranspiler <TypeExtension>(IEnumerable <CodeInstruction> instructions)
            where TypeExtension : IBaseNetAssetDataExtension
        {
            var segmentBufferField = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempSegmentBuffer));
            var nodeBufferField    = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempNodeBuffer));
            var clearMethod        = AccessTools.DeclaredMethod(nodeBufferField.FieldType, nameof(FastList <ushort> .Clear));

            var matchCount          = 0;
            var inserted            = false;
            var enumerator          = instructions.GetEnumerator();
            var prevPrevInstruction = (CodeInstruction)null;
            var prevInstruction     = (CodeInstruction)null;

            while (enumerator.MoveNext())
            {
                var instruction = enumerator.Current;

                if (prevInstruction != null && prevInstruction.opcode == OpCodes.Ldfld && prevInstruction.operand == nodeBufferField && instruction.opcode == OpCodes.Callvirt && instruction.operand == clearMethod)
                {
                    matchCount += 1;
                }

                if (!inserted && matchCount == 2)
                {
                    yield return(new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(SingletonItem <TypeExtension>), nameof(SingletonItem <TypeExtension> .Instance))));

                    yield return(new CodeInstruction(OpCodes.Box, typeof(TypeExtension)));

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

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

                    yield return(new CodeInstruction(OpCodes.Ldfld, segmentBufferField));

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

                    yield return(new CodeInstruction(OpCodes.Ldfld, nodeBufferField));

                    yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(TypeExtension), nameof(IBaseNetAssetDataExtension.OnPlaceAsset))));

                    inserted = true;
                }

                if (prevPrevInstruction != null)
                {
                    yield return(prevPrevInstruction);
                }

                prevPrevInstruction = prevInstruction;
                prevInstruction     = instruction;
            }

            if (prevPrevInstruction != null)
            {
                yield return(prevPrevInstruction);
            }

            if (prevInstruction != null)
            {
                yield return(prevInstruction);
            }
        }
        public static bool InitMenuItemScript(SceneEdit.SMenuItem mi, string f_strMenuFileName, bool f_bMan, out string IconTex)
        {
            var fetchedField = AccessTools.DeclaredField(typeof(SceneEdit), "m_byItemFileBuffer");
            var fetchedVal   = fetchedField.GetValue(@this) as byte[];

            IconTex = null;

            if (f_strMenuFileName.IndexOf("mod_") == 0)
            {
                string modPathFileName = Menu.GetModPathFileName(f_strMenuFileName);
                return(!string.IsNullOrEmpty(modPathFileName) && SceneEdit.InitModMenuItemScript(mi, modPathFileName));
            }
            try
            {
                using (AFileBase afileBase = GameUty.FileOpen(f_strMenuFileName, null))
                {
                    NDebug.Assert(afileBase.IsValid(), "メニューファイルが存在しません。 :" + f_strMenuFileName);
                    if (fetchedVal == null)
                    {
                        fetchedVal = new byte[System.Math.Max(500000, afileBase.GetSize())];
                    }
                    else if (fetchedVal.Length < afileBase.GetSize())
                    {
                        fetchedVal = new byte[afileBase.GetSize()];
                    }
                    afileBase.Read(ref fetchedVal, afileBase.GetSize());
                }
            }
            catch (Exception ex)
            {
                Main.logger.LogError(string.Concat(new string[]
                {
                    "メニューファイルがが読み込めませんでした。 : ",
                    f_strMenuFileName,
                    " : ",
                    ex.Message,
                    " : StackTrace :\n",
                    ex.StackTrace
                }));
                throw ex;
            }
            BinaryReader binaryReader = new BinaryReader(new MemoryStream(fetchedVal), Encoding.UTF8);
            string       text         = binaryReader.ReadString();

            NDebug.Assert(text == "CM3D2_MENU", "ProcScriptBin 例外 : ヘッダーファイルが不正です。" + text);
            int    num   = binaryReader.ReadInt32();
            string path  = binaryReader.ReadString();
            string text2 = binaryReader.ReadString();
            string text3 = binaryReader.ReadString();
            string text4 = binaryReader.ReadString();
            long   num2  = (long)binaryReader.ReadInt32();
            int    num3  = 0;
            string text5 = null;
            string text6 = string.Empty;
            string text7 = string.Empty;

            try
            {
                for (; ;)
                {
                    int num4 = (int)binaryReader.ReadByte();
                    text7 = text6;
                    text6 = string.Empty;
                    if (num4 == 0)
                    {
                        break;
                    }
                    for (int i = 0; i < num4; i++)
                    {
                        text6 = text6 + "\"" + binaryReader.ReadString() + "\" ";
                    }
                    if (!(text6 == string.Empty))
                    {
                        string   stringCom  = UTY.GetStringCom(text6);
                        string[] stringList = UTY.GetStringList(text6);
                        if (stringCom == "name")
                        {
                            string text8 = stringList[1];
                            string text9 = string.Empty;
                            string arg   = string.Empty;
                            int    j     = 0;
                            while (j < text8.Length && text8[j] != '\u3000' && text8[j] != ' ')
                            {
                                text9 += text8[j];
                                j++;
                            }
                            while (j < text8.Length)
                            {
                                arg += text8[j];
                                j++;
                            }
                            mi.m_strMenuName = text9;
                        }
                        else if (stringCom == "setumei")
                        {
                            mi.m_strInfo = stringList[1];
                            mi.m_strInfo = mi.m_strInfo.Replace("《改行》", "\n");
                        }
                        else if (stringCom == "category")
                        {
                            string strCateName = stringList[1].ToLower();
                            mi.m_strCateName = strCateName;
                            try
                            {
                                mi.m_mpn = (MPN)Enum.Parse(typeof(MPN), mi.m_strCateName);
                            }
                            catch
                            {
                                Main.logger.LogWarning("カテゴリがありません。" + mi.m_strCateName);
                                mi.m_mpn = MPN.null_mpn;
                            }
                        }
                        else if (stringCom == "color_set")
                        {
                            try
                            {
                                mi.m_eColorSetMPN = (MPN)Enum.Parse(typeof(MPN), stringList[1].ToLower());
                            }
                            catch
                            {
                                Main.logger.LogWarning("カテゴリがありません。" + mi.m_strCateName);
                            }
                            if (stringList.Length >= 3)
                            {
                                mi.m_strMenuNameInColorSet = stringList[2].ToLower();
                            }
                        }
                        else if (stringCom == "tex" || stringCom == "テクスチャ変更")
                        {
                            MaidParts.PARTS_COLOR pcMultiColorID = MaidParts.PARTS_COLOR.NONE;
                            if (stringList.Length == 6)
                            {
                                string text10 = stringList[5];
                                try
                                {
                                    pcMultiColorID = (MaidParts.PARTS_COLOR)Enum.Parse(typeof(MaidParts.PARTS_COLOR), text10.ToUpper());
                                }
                                catch
                                {
                                    NDebug.Assert("無限色IDがありません。" + text10, false);
                                }
                                mi.m_pcMultiColorID = pcMultiColorID;
                            }
                        }
                        else if (stringCom == "icon" || stringCom == "icons")
                        {
                            text5 = stringList[1];
                        }
                        else if (!(stringCom == "iconl"))
                        {
                            if (!(stringCom == "setstr"))
                            {
                                if (!(stringCom == "アイテムパラメータ"))
                                {
                                    if (stringCom == "saveitem")
                                    {
                                        string text11 = stringList[1];
                                        if (text11 == string.Empty)
                                        {
                                            Main.logger.LogError("err SaveItem \"" + text11);
                                        }
                                        if (text11 == null)
                                        {
                                            Main.logger.LogError("err SaveItem null=\"" + text11);
                                        }
                                        if (text11 != string.Empty)
                                        {
                                        }
                                    }
                                    else if (!(stringCom == "catno"))
                                    {
                                        if (stringCom == "additem")
                                        {
                                            num3++;
                                        }
                                        else if (stringCom == "unsetitem")
                                        {
                                            mi.m_boDelOnly = true;
                                        }
                                        else if (stringCom == "priority")
                                        {
                                            mi.m_fPriority = float.Parse(stringList[1]);
                                        }
                                        else if (stringCom == "メニューフォルダ" && stringList[1].ToLower() == "man")
                                        {
                                            mi.m_bMan = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex2)
            {
                Main.logger.LogError(string.Concat(new string[]
                {
                    "Exception ",
                    Path.GetFileName(path),
                    " 現在処理中だった行 = ",
                    text6,
                    " 以前の行 = ",
                    text7,
                    "   ",
                    ex2.Message,
                    "StackTrace:\n",
                    ex2.StackTrace
                }));
                throw ex2;
            }
            if (text5 != null && text5 != string.Empty)
            {
                try
                {
                    IconTex = text5;
                    //mi.m_texIcon = ImportCM.CreateTexture(text5);
                }
                catch (Exception)
                {
                    Main.logger.LogError("Error:");
                }
            }
            binaryReader.Close();
            return(true);
        }
                static IEnumerable <CodeInstruction> OpportunisticJobs(IEnumerable <CodeInstruction> _codes, ILGenerator generator, MethodBase __originalMethod)
                {
                    var t = new Transpiler(_codes, __originalMethod);
                    var listerHaulablesIdx = t.TryFindCodeIndex(code => code.LoadsField(AccessTools.DeclaredField(typeof(Map), nameof(Map.listerHaulables))));
                    var skipMod            = generator.DefineLabel();

                    t.TryInsertCodes(
                        -3,
                        (i, codes) => i == listerHaulablesIdx,
                        (i, codes) => new List <CodeInstruction> {
                        new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(Pawn_JobTracker_TryOpportunisticJob_Patch), nameof(IsEnabled))),
                        new CodeInstruction(OpCodes.Brfalse_S, skipMod),

                        new CodeInstruction(OpCodes.Ldarg_0),
                        new CodeInstruction(OpCodes.Ldarg_1),
                        new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(Patch_TryOpportunisticJob), nameof(TryOpportunisticJob))),
                        new CodeInstruction(OpCodes.Ret),
                    }, true);

                    t.codes[t.MatchIdx - 3].labels.Add(skipMod);
                    return(t.GetFinalCodes());
                }