Пример #1
0
        static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            var             codes        = new List <CodeInstruction>(instructions);
            ConstructorInfo rivermaker   = AccessTools.Constructor(typeof(RiverMaker), new Type[] { typeof(Vector3), typeof(float), typeof(RiverDef) });
            int             riverIndex   = -1;
            int             replaceIndex = -1;

            for (int i = 0; i < codes.Count; i++)
            {
                if (codes[i].opcode == OpCodes.Newobj)
                {
                    if (codes[i].OperandIs(rivermaker))
                    {
                        riverIndex = i;
                        break;
                    }
                }
                if (codes[i].opcode == OpCodes.Ldloc_1)
                {
                    replaceIndex = i;
                }
            }
            codes.Insert(replaceIndex + 1, new CodeInstruction(opcode: OpCodes.Call, operand: AccessTools.Method(type: typeof(HelperMethods), name: nameof(HelperMethods.GetRiverDirection))));

            return(codes.AsEnumerable());
        }
Пример #2
0
        private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            var newInstructions = ListPool <CodeInstruction> .Shared.Rent(instructions);

            var index = newInstructions.FindLastIndex(op => op.opcode == OpCodes.Blt);

            newInstructions.InsertRange(++index, new[]
            {
                // Player.Get(ConsumableAndWearableItems._hub)
                new CodeInstruction(OpCodes.Ldloc_2),
                new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(ConsumableAndWearableItems), nameof(ConsumableAndWearableItems._hub))),
                new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),

                // ConsumableAndWearableItems.usableItems[mid].inventoryID
                new CodeInstruction(OpCodes.Ldloc_2),
                new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(ConsumableAndWearableItems), nameof(ConsumableAndWearableItems.usableItems))),
                new CodeInstruction(OpCodes.Ldarg_0),
                new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(type, "mid")),
                new CodeInstruction(OpCodes.Ldelem, typeof(ConsumableAndWearableItems.UsableItem)),
                new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(ConsumableAndWearableItems.UsableItem), nameof(ConsumableAndWearableItems.UsableItem.inventoryID))),

                // Player.OnMedicalItemDequipped(new UsedMedicalItemEventArgs(arg1, arg2))
                new CodeInstruction(OpCodes.Newobj, AccessTools.Constructor(typeof(UsedMedicalItemEventArgs), new[] { typeof(Player), typeof(ItemType) })),
                new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Handlers.Player), nameof(Handlers.Player.OnMedicalItemUsed))),
            });

            for (int z = 0; z < newInstructions.Count; z++)
            {
                yield return(newInstructions[z]);
            }

            ListPool <CodeInstruction> .Shared.Return(newInstructions);
        }
Пример #3
0
        /*********
        ** Private methods
        *********/
        /// <summary>Raised after the game is launched, right before the first update tick. This happens once per game session (unrelated to loading saves). All mods are loaded and initialised at this point, so this is a good time to set up mod integrations.</summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event data.</param>
        private void OnGameLaunched(object sender, GameLaunchedEventArgs e)
        {
            new DataLoader(Helper);

            var harmony = HarmonyInstance.Create("Digus.CustomCaskMod");

            harmony.Patch(
                original: AccessTools.Method(typeof(Cask), nameof(Cask.performObjectDropInAction)),
                prefix: new HarmonyMethod(typeof(CaskOverrides), nameof(CaskOverrides.PerformObjectDropInAction))
                );

            if (!DataLoader.ModConfig.DisableAutomateCompatibility && Helper.ModRegistry.IsLoaded("Pathoschild.Automate"))
            {
                ModMonitor.Log("Automated detected, patching it to work with configured items and aging rates.", LogLevel.Info);
                try
                {
                    Assembly automateAssembly = AppDomain.CurrentDomain.GetAssemblies().First(a => a.FullName.StartsWith("Automate,"));
                    harmony.Patch(
                        original: AccessTools.Constructor(automateAssembly.GetType("Pathoschild.Stardew.Automate.Framework.Machines.Objects.CaskMachine"), new Type[] { typeof(Cask), typeof(GameLocation), typeof(Vector2) }),
                        postfix: new HarmonyMethod(typeof(CaskOverrides), nameof(CaskOverrides.CaskMachine))
                        );
                }
                catch (Exception ex)
                {
                    ModMonitor.Log("Error trying to patch Automate. Configured items and aging rates will not work with Automate.", LogLevel.Warn);
                    ModMonitor.Log(ex.Message, LogLevel.Trace);
                    ModMonitor.Log(ex.StackTrace, LogLevel.Trace);
                }
            }
        }
Пример #4
0
                        public static IEnumerable <CodeInstruction> TranspilerPatchFor_OpenMenu(IEnumerable <CodeInstruction> instructions)
                        {
                            var orgCtor = AccessTools.Constructor(typeof(ItemGrabMenu),
                                                                  new Type[] { typeof(IList <StardewValley.Item>), typeof(Boolean), typeof(Boolean), typeof(InventoryMenu.highlightThisItem), typeof(ItemGrabMenu.behaviorOnItemSelect), typeof(String), typeof(ItemGrabMenu.behaviorOnItemSelect), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Int32), typeof(StardewValley.Item), typeof(Int32), typeof(Object) });
                            var newCtor = AccessTools.Constructor(typeof(Types.CustomTypes.ChestExMenu.MainMenu),
                                                                  new Type[] { typeof(IList <StardewValley.Item>), typeof(Boolean), typeof(Boolean), typeof(InventoryMenu.highlightThisItem), typeof(ItemGrabMenu.behaviorOnItemSelect), typeof(String), typeof(ItemGrabMenu.behaviorOnItemSelect), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Int32), typeof(StardewValley.Item), typeof(Int32), typeof(Object) });
                            Boolean patched = false;

                            foreach (var instruction in instructions)
                            {
                                if (instruction.opcode == OpCodes.Newobj)
                                {
                                    // ItemGrabMenu.ctor[2]
                                    if ((ConstructorInfo)instruction.operand == orgCtor)
                                    {
                                        yield return(new CodeInstruction(OpCodes.Newobj, newCtor));

                                        patched = true;
                                        continue;
                                    }
                                }
                                yield return(instruction);
                            }

                            if (patched)
                            {
                                GlobalVars.SMAPIMonitor.Log("Successfully patched 'ChestsAnywhere.ChestContainer.OpenMenu'.", LogLevel.Info);
                            }
                            else
                            {
                                GlobalVars.SMAPIMonitor.Log("Could not patch 'ChestsAnywhere.ChestContainer.OpenMenu' to redirect 'ItemGrabMenu.ctor' to 'ChestExMenu.MainMenu.ctor'!", LogLevel.Error);
                            }
                        }
        public override void Entry(IModHelper helper)
        {
            Instance = this;

            Config = helper.ReadConfig <ModConfig>();

            helper.Events.GameLoop.GameLaunched += OnGameLaunched;

            var harmony = new Harmony(ModManifest.UniqueID);

            try
            {
                harmony.Patch(
                    original: AccessTools.Constructor(typeof(HoeDirt)),
                    postfix: new HarmonyMethod(typeof(PredictableRetainingSoil), nameof(HoeDirt_ctor_Postfix))
                    );
                harmony.Patch(
                    original: AccessTools.Method(typeof(HoeDirt), nameof(HoeDirt.dayUpdate)),
                    prefix: new HarmonyMethod(typeof(PredictableRetainingSoil), nameof(HoeDirt_dayUpdate_Prefix)),
                    postfix: new HarmonyMethod(typeof(PredictableRetainingSoil), nameof(HoeDirt_dayUpdate_Postfix))
                    );
                harmony.Patch(
                    original: AccessTools.Method(typeof(HoeDirt), nameof(HoeDirt.plant)),
                    postfix: new HarmonyMethod(typeof(PredictableRetainingSoil), nameof(HoeDirt_plant_Postfix))
                    );
                harmony.Patch(
                    original: AccessTools.Method(typeof(SObject), nameof(SObject.getDescription)),
                    postfix: new HarmonyMethod(typeof(PredictableRetainingSoil), nameof(Object_getDescription_postfix))
                    );
            }
            catch (Exception e)
            {
                Monitor.Log($"Could not patch methods - Predictable Retaining Soil probably won't work.\nReason: {e}", LogLevel.Error);
            }
        }
        /*********
        ** Private methods
        *********/
        /// <summary>Raised after the game is launched, right before the first update tick. This happens once per game session (unrelated to loading saves). All mods are loaded and initialised at this point, so this is a good time to set up mod integrations.</summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event data.</param>
        private void OnGameLaunched(object sender, GameLaunchedEventArgs e)
        {
            DataLoader = new DataLoader(Helper);

            var harmony = HarmonyInstance.Create("Digus.InfiniteBaitAndLureMod");

            harmony.Patch(
                original: AccessTools.Method(typeof(FishingRod), "doDoneFishing"),
                prefix: new HarmonyMethod(typeof(GameOverrides), nameof(GameOverrides.DoDoneFishing))
                );

            harmony.Patch(
                original: AccessTools.Method(typeof(CraftingRecipe), nameof(CraftingRecipe.createItem)),
                prefix: new HarmonyMethod(typeof(GameOverrides), nameof(GameOverrides.CreateItem))
                );

            harmony.Patch(
                original: AccessTools.Method(typeof(CraftingPage), "clickCraftingRecipe"),
                prefix: new HarmonyMethod(typeof(GameOverrides), nameof(GameOverrides.ClickCraftingRecipe))
                );

            harmony.Patch(
                original: AccessTools.Method(typeof(NPC), nameof(NPC.tryToReceiveActiveObject)),
                prefix: new HarmonyMethod(typeof(GameOverrides), nameof(GameOverrides.TryToReceiveActiveObject))
                );


            if (!DataLoader.ModConfig.DisableIridiumQualityFish)
            {
                harmony.Patch(
                    original: AccessTools.Constructor(typeof(BobberBar), new[] { typeof(int), typeof(float), typeof(bool), typeof(int) }),
                    postfix: new HarmonyMethod(typeof(GameOverrides), nameof(GameOverrides.BobberBar))
                    );
            }
        }
Пример #7
0
 public static void ApplyAll(HarmonyInstance harmony)
 {
     // Force skip ItemGrabMenu ctor when called from ChestExMenu
     harmony.Patch(
         AccessTools.Constructor(typeof(ItemGrabMenu), new Type[] { typeof(IList <StardewValley.Item>), typeof(Object) }),
         null, null, new HarmonyMethod(typeof(PatchesFor_ItemGrabMenu).GetMethod("TranspilerPatchFor_ctor")));
 }
Пример #8
0
            public static void Postfix(List <KIconToggleMenu.ToggleInfo> ___overlayToggleInfos)
            {
                var constructor = AccessTools.Constructor(
                    AccessTools.Inner(typeof(OverlayMenu), "OverlayToggleInfo"),
                    new[]
                {
                    typeof(string),
                    typeof(string),
                    typeof(HashedString),
                    typeof(string),
                    typeof(Action),
                    typeof(string),
                    typeof(string),
                }
                    );

                var obj = constructor.Invoke(
                    new object[]
                {
                    "Info Overlay",
                    "overlay_info",
                    InfoOverlay.ID,
                    "",
                    Action.NumActions,
                    "Displays various information about tiles",
                    "Info Overlay",
                }
                    );

                ___overlayToggleInfos.Add((KIconToggleMenu.ToggleInfo)obj);
            }
 /// <inheritdoc/>
 public override void Apply(HarmonyInstance harmony)
 {
     harmony.Patch(
         original: AccessTools.Constructor(typeof(TemporaryAnimatedSprite), new[] { typeof(int), typeof(float), typeof(int), typeof(int), typeof(Vector2), typeof(bool), typeof(bool), typeof(GameLocation), typeof(Farmer) }),
         postfix: new HarmonyMethod(GetType(), nameof(TemporaryAnimatedSpriteCtorPostfix))
         );
 }
        public static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            var from = AccessTools.Constructor(typeof(IntVec3), new Type[] { typeof(int), typeof(int), typeof(int) });
            var to   = AccessTools.Method(typeof(Patch_Game_InitNewGame), nameof(CreateMyCustomVector));

            // I could not, for the life of me, figure out how to target the correct Ldloca_S with the operand.
            // The "correct" way would be to find the one with operand == 1, but that doesn't work.
            // If you know of the way, feel free to PR/tell me about it!
            var encounteredFirstLdloca_S = false;

            var replacedInstructions = instructions.MethodReplacer(from, to);

            foreach (var instruction in replacedInstructions)
            {
                // First Ldloca_S is our vector allocation.
                // We have replaced the constructor call with a static metho, so we should get rid of this.
                // We will set it after our static call.
                if (instruction.opcode == OpCodes.Ldloca_S && !encounteredFirstLdloca_S)
                {
                    encounteredFirstLdloca_S = true;
                    continue;
                }
                yield return(instruction);

                // If this instruction is our static call, we should set the result to the correct local variable.
                if (instruction.opcode == OpCodes.Call && (MethodInfo)instruction.operand == to)
                {
                    yield return(new CodeInstruction(OpCodes.Stloc_1));
                }
            }
        }
Пример #11
0
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides simplified APIs for writing mods.</param>
        public override void Entry(IModHelper helper)
        {
            instance    = this;
            Log.Monitor = Monitor;

            helper.Events.Player.Warped += onWarped;
            helper.Events.Display.RenderedActiveMenu += onRenderedActiveMenu;
            helper.Events.GameLoop.DayStarted        += onDayStarted;
            helper.Events.GameLoop.DayEnding         += onDayEnding;
            helper.Events.GameLoop.GameLaunched      += onGameLaunched;

            SpaceEvents.ChooseNightlyFarmEvent += changeFarmEvent;

            try
            {
                var harmony = HarmonyInstance.Create(ModManifest.UniqueID);
                Log.trace("Doing harmony patches...");
                harmony.Patch(AccessTools.Method(typeof(Farmer), nameof(Farmer.getProfessionForSkill)), postfix: new HarmonyMethod(AccessTools.Method(typeof(FarmerGetProfessionHook), nameof(LevelUpMenuProfessionNameHook.Postfix))));
                harmony.Patch(AccessTools.Method(typeof(Farmer), nameof(Farmer.gainExperience)), prefix: new HarmonyMethod(AccessTools.Method(typeof(OverpoweredGeodeFix), nameof(OverpoweredGeodeFix.Prefix))));
                harmony.Patch(AccessTools.Method(typeof(Farmer), nameof(Farmer.gainExperience)), transpiler: new HarmonyMethod(AccessTools.Method(typeof(ExperienceGainFix), nameof(ExperienceGainFix.Transpiler))));
                harmony.Patch(AccessTools.Constructor(typeof(LevelUpMenu), new Type[] { typeof(int), typeof(int) }), transpiler: new HarmonyMethod(AccessTools.Method(typeof(LevelUpMenuLuckProfessionConstructorFix), nameof(LevelUpMenuLuckProfessionConstructorFix.Transpiler))));
                harmony.Patch(AccessTools.Method(typeof(LevelUpMenu), "getProfessionName"), postfix: new HarmonyMethod(AccessTools.Method(typeof(LevelUpMenuProfessionNameHook), nameof(LevelUpMenuProfessionNameHook.Postfix))));
                harmony.Patch(AccessTools.Method(typeof(LevelUpMenu), nameof(LevelUpMenu.AddMissedProfessionChoices)), transpiler: new HarmonyMethod(AccessTools.Method(typeof(LevelUpMenuMissedStuffPatch), nameof(LevelUpMenuMissedStuffPatch.Transpiler))));
                harmony.Patch(AccessTools.Method(typeof(LevelUpMenu), nameof(LevelUpMenu.AddMissedLevelRecipes)), transpiler: new HarmonyMethod(AccessTools.Method(typeof(LevelUpMenuMissedStuffPatch), nameof(LevelUpMenuMissedStuffPatch.Transpiler))));
            }
            catch (Exception e)
            {
                Log.trace("Exception doing harmony: " + e);
            }

            checkForAllProfessions();
        }
        //thx Brrainz
        private static IEnumerable <CodeInstruction> DebugWindowsOpener_ToggleDebugActionsMenu_Patch(IEnumerable <CodeInstruction> instructions)
        {
            ConstructorInfo from = AccessTools.Constructor(typeof(Dialog_DebugActionsMenu));
            ConstructorInfo to   = AccessTools.Constructor(typeof(Dialog_MFIDebugActionMenu));

            return(instructions.MethodReplacer(from: from, to: to));
        }
Пример #13
0
 public static void PatchLogMessage(Harmony harmony)
 {
     harmony.Patch(AccessTools.Constructor(typeof(LogMessage), new Type[] { typeof(string) }),
                   prefix: new HarmonyMethod(typeof(MiscFixes), nameof(MiscFixes.LogMessage_ctor_string_prefix)));
     harmony.Patch(AccessTools.Constructor(typeof(LogMessage), new Type[] { typeof(LogMessageType), typeof(string), typeof(string) }),
                   prefix: new HarmonyMethod(typeof(MiscFixes), nameof(MiscFixes.LogMessage_ctor_LogMessageType_string_string_prefix)));
 }
Пример #14
0
        internal static void SaveLoaded(string uniqueID, ModEntry entry, ModConfig config, IEnumerable <SpawnableItem> items)
        {
            Config   = config;
            modEntry = entry;
            var harmony = new Harmony(uniqueID);

            harmony.Patch(
                original: AccessTools.Constructor(typeof(InventoryMenu), new System.Type[] { typeof(int), typeof(int), typeof(bool), typeof(IList <Item>), typeof(InventoryMenu.highlightThisItem), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool) }),
                postfix: new HarmonyMethod(typeof(AedenthornInventory), nameof(AedenthornInventory.InventoryMenu_Ctor_Postfix))
                );
            harmony.Patch(
                original: AccessTools.Method(typeof(InventoryMenu), nameof(InventoryMenu.draw), new System.Type[] { typeof(SpriteBatch), typeof(int), typeof(int), typeof(int) }),
                prefix: new HarmonyMethod(typeof(AedenthornInventory), nameof(AedenthornInventory.InventoryMenu_draw_Prefix)),
                postfix: new HarmonyMethod(typeof(AedenthornInventory), nameof(AedenthornInventory.InventoryMenu_draw_Postfix))
                );
            harmony.Patch(
                original: AccessTools.Method(typeof(InventoryMenu), nameof(InventoryMenu.performHoverAction)),
                prefix: new HarmonyMethod(typeof(AedenthornInventory), nameof(AedenthornInventory.InventoryMenu_performHoverAction_Prefix))
                );

            AllItems = items.ToArray();

            entry.Helper.Events.Input.MouseWheelScrolled += Input_MouseWheelScrolled;
            entry.Helper.Events.Input.ButtonPressed      += Input_ButtonPressed;
        }
Пример #15
0
        /// <summary>Apply the Harmony patch.</summary>
        /// <param name="harmony">The Harmony instance.</param>
        public void Apply(HarmonyInstance harmony)
        {
            ConstructorInfo constructor = AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) });
            MethodInfo      prefix      = AccessTools.Method(this.GetType(), nameof(DialogueErrorPatch.Prefix));

            harmony.Patch(constructor, new HarmonyMethod(prefix), null);
        }
Пример #16
0
        public override void Entry(IModHelper helper)
        {
            DialoguePatches.Initialize(Monitor, helper);

            var harmony = HarmonyInstance.Create(ModManifest.UniqueID);

            HarmonyMethod hm = new HarmonyMethod(typeof(DialoguePatches), nameof(DialoguePatches.Dialogue_Prefix));

            hm.prioritiy = Priority.First;
            harmony.Patch(
                original: AccessTools.Constructor(typeof(Dialogue), new Type[] { typeof(string), typeof(NPC) }),
                prefix: hm
                );

            harmony.Patch(
                original: AccessTools.Method(typeof(LocalizedContentManager), nameof(LocalizedContentManager.LoadString), new Type[] { typeof(string) }),
                postfix: new HarmonyMethod(typeof(DialoguePatches), nameof(DialoguePatches.LocalizedContentManager_LoadString_Postfix))
                );
            harmony.Patch(
                original: AccessTools.Method(typeof(NPC), nameof(NPC.showTextAboveHead)),
                prefix: new HarmonyMethod(typeof(DialoguePatches), nameof(DialoguePatches.NPC_showTextAboveHead_Prefix))
                );
            harmony.Patch(
                original: AccessTools.Method(typeof(NPC), nameof(NPC.getHi)),
                postfix: new HarmonyMethod(typeof(DialoguePatches), nameof(DialoguePatches.NPC_getHi_Postfix))
                );
        }
        private static AbstractActor InitAbstractActor(AbstractActor actor)
        {
            // Init the combat ref for constants
            ConstructorInfo     constantsCI = AccessTools.Constructor(typeof(CombatGameConstants), new Type[] { });
            CombatGameConstants constants   = (CombatGameConstants)constantsCI.Invoke(new object[] { });

            CombatGameState cgs        = new CombatGameState();
            Traverse        constantsT = Traverse.Create(cgs).Property("Constants");

            constantsT.SetValue(constants);

            Traverse combatT = Traverse.Create(actor).Property("Combat");

            combatT.SetValue(cgs);

            // Init any required stats
            actor.StatCollection = new StatCollection();

            // ModStats
            //actor.StatCollection.AddStatistic<int>(ModStats.PunchAttackMod, 0);

            // Vanilla
            actor.StatCollection.AddStatistic <float>("SensorSignatureModifier", 1.0f);

            return(actor);
        }
Пример #18
0
 public static void ApplyPatch(Harmony harmony)
 {
     harmony.Patch(
         original: AccessTools.Constructor(typeof(FarmAnimal), new Type[] { typeof(string), typeof(long), typeof(long) }),
         prefix: new HarmonyMethod(typeof(FarmAnimalPatch), nameof(ctor_Prefix)),
         postfix: new HarmonyMethod(typeof(FarmAnimalPatch), nameof(ctor_Postfix)));
 }
Пример #19
0
        /****
        ** Methods
        ****/
        /// <summary>Apply the harmony patches for patching game code.</summary>
        private void ApplyHarmonyPatches()
        {
            // create a new harmony instance for patching source code
            HarmonyInstance harmony = HarmonyInstance.Create(this.ModManifest.UniqueID);

            // apply the patches
            harmony.Patch(
                original: AccessTools.Constructor(typeof(StardewValley.Menus.InventoryPage), new Type[] { typeof(int), typeof(int), typeof(int), typeof(int) }),
                postfix: new HarmonyMethod(AccessTools.Method(typeof(InventoryPagePatch), nameof(InventoryPagePatch.ConstructorPostFix)))
                );

            harmony.Patch(
                original: AccessTools.Method(typeof(StardewValley.Menus.InventoryPage), nameof(InventoryPage.receiveLeftClick)),
                postfix: new HarmonyMethod(AccessTools.Method(typeof(InventoryPagePatch), nameof(InventoryPagePatch.ReceiveLeftClickPostFix)))
                );

            harmony.Patch(
                original: AccessTools.Method(typeof(StardewValley.Menus.InventoryPage), nameof(InventoryPage.draw), new Type[] { typeof(SpriteBatch) }),
                postfix: new HarmonyMethod(AccessTools.Method(typeof(InventoryPagePatch), nameof(InventoryPagePatch.DrawPostFix)))
                );

            harmony.Patch(
                original: AccessTools.Method(typeof(StardewValley.FarmerRenderer), nameof(FarmerRenderer.draw), new Type[] { typeof(SpriteBatch), typeof(FarmerSprite.AnimationFrame), typeof(int), typeof(Rectangle), typeof(Vector2), typeof(Vector2), typeof(float), typeof(int), typeof(Color), typeof(float), typeof(float), typeof(Farmer) }),
                postfix: new HarmonyMethod(AccessTools.Method(typeof(FarmerRendererPatch), nameof(FarmerRendererPatch.DrawPostFix)))
                );
        }
Пример #20
0
        /// <summary>
        /// Applies the Harmony Patch to the game code
        /// </summary>
        /// <param name="harmony">The instance (targetted application) harmony will patch up.</param>
        public void Apply(HarmonyInstance harmony)
        {
            ConstructorInfo Constructor = null;
            MethodInfo      Original    = null;
            MethodInfo      Prefix      = (prefix) ? helper.Reflection.GetMethod(type, "Prefix").MethodInfo : null;
            MethodInfo      Transpile   = (transpiler) ? helper.Reflection.GetMethod(type, "Transpiler").MethodInfo : null;
            MethodInfo      Postfix     = (postfix) ? helper.Reflection.GetMethod(type, "Postfix").MethodInfo : null;

            if (patchType == PatchType.Constructor)
            {
                Constructor = AccessTools.Constructor(getTypeSDV(sdvType), parameters);
                harmony.Patch(Constructor, (prefix) ? new HarmonyMethod(Prefix) : null,
                              (postfix) ? new HarmonyMethod(Postfix) : null,
                              (transpiler) ? new HarmonyMethod(Transpile) : null);
            }
            else
            {
                Original = AccessTools.Method(getTypeSDV(sdvType), original, parameters);
                harmony.Patch(Original, (prefix) ? new HarmonyMethod(Prefix) : null,
                              (postfix) ? new HarmonyMethod(Postfix) : null,
                              (transpiler) ? new HarmonyMethod(Transpile) : null);
            }

            return;
        }
Пример #21
0
                    public static void ApplyAll(HarmonyInstance harmony)
                    {
                        if (GlobalVars.SMAPIHelper.ModRegistry.Get(CONST_UID) is IModInfo automateModInfo)
                        {
                            GlobalVars.SMAPIMonitor.Log("Automate is found, installing dynamic compatibility patches...", LogLevel.Info);
                            GlobalVars.SMAPIMonitor.Log($"The target version of Automate for the compatibility patch is '{CONST_VERSION}'.", LogLevel.Debug);

                            if (String.Equals(automateModInfo.Manifest.Version.ToString(), CONST_VERSION, StringComparison.OrdinalIgnoreCase))
                            {
                                // user is running the same version of Automate
                                GlobalVars.SMAPIMonitor.Log("ChestEx is fully compatible with this Automate version.", LogLevel.Info);
                            }
                            else if (automateModInfo.Manifest.Version.IsNewerThan(CONST_VERSION))
                            {
                                // user is running a newer version of Automate
                                GlobalVars.SMAPIMonitor.Log("You seem to be running a newer version of Automate! This warning can safely be ignored if you don't experience any issues. However, if you do experience any issues, please report it to me on Discord or on Nexus.", LogLevel.Warn);
                            }
                            else if (automateModInfo.Manifest.Version.IsOlderThan(CONST_VERSION))
                            {
                                // user is running an older version of Automate
                                GlobalVars.SMAPIMonitor.Log("You seem to be running an older version of Automate! There is a high chance that you will experience issues, please update your copy of Automate.", LogLevel.Warn);
                            }

                            harmony.Patch(
                                AccessTools.Constructor(
                                    Type.GetType("Pathoschild.Stardew.Automate.Framework.Storage.ChestContainer, Automate"),
                                    new Type[] { typeof(Chest), typeof(StardewValley.GameLocation), typeof(Microsoft.Xna.Framework.Vector2), typeof(IReflectionHelper) }),
                                null,
                                null,
                                new HarmonyMethod(typeof(PatchesFor_ChestContainer).GetMethod("TranspilerPatchFor_ctor")));
                        }
                    }
Пример #22
0
            public static void Postfix(List <KIconToggleMenu.ToggleInfo> ___overlayToggleInfos)
            {
                var constructor = AccessTools.Constructor(
                    AccessTools.Inner(typeof(OverlayMenu), "OverlayToggleInfo"),
                    new[] {
                    typeof(string),       // text
                    typeof(string),       // icon_name
                    typeof(HashedString), // sim_view
                    typeof(string),       // required_tech_item
                    typeof(Action),       // hotKey
                    typeof(string),       // tooltip
                    typeof(string)        // tooltip_header
                }
                    );

                var obj = constructor.Invoke(
                    new object[] {
                    MapOverlay.Name,
                    MapOverlay.Icon,
                    MapOverlay.ID,
                    "",
                    Action.NumActions,     // TODO: Should be MapOverlay.Hotkey, but Overlay15 already is used by Traffic Visualiser and possibly will be taken by Radiation Overlay, too
                    MapOverlay.Desc,
                    MapOverlay.Name
                }
                    );

                ___overlayToggleInfos.Add((KIconToggleMenu.ToggleInfo)obj);
            }
Пример #23
0
                    public static IEnumerable <CodeInstruction> TranspilerPatches_RedirectingToChestExMenu(IEnumerable <CodeInstruction> instructions)
                    {
                        var orgCtor = AccessTools.Constructor(typeof(ItemGrabMenu),
                                                              new Type[] { typeof(IList <StardewValley.Item>), typeof(Boolean), typeof(Boolean), typeof(InventoryMenu.highlightThisItem), typeof(ItemGrabMenu.behaviorOnItemSelect), typeof(String), typeof(ItemGrabMenu.behaviorOnItemSelect), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Int32), typeof(StardewValley.Item), typeof(Int32), typeof(Object) });
                        var newCtor = AccessTools.Constructor(typeof(Types.CustomTypes.ChestExMenu.MainMenu),
                                                              new Type[] { typeof(IList <StardewValley.Item>), typeof(Boolean), typeof(Boolean), typeof(InventoryMenu.highlightThisItem), typeof(ItemGrabMenu.behaviorOnItemSelect), typeof(String), typeof(ItemGrabMenu.behaviorOnItemSelect), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Boolean), typeof(Int32), typeof(StardewValley.Item), typeof(Int32), typeof(Object) });

                        foreach (var instruction in instructions)
                        {
                            if (instruction.opcode == OpCodes.Newobj)
                            {
                                // ItemGrabMenu.ctor[2]
                                if ((ConstructorInfo)instruction.operand == orgCtor)
                                {
                                    yield return(new CodeInstruction(OpCodes.Newobj, newCtor));

                                    continue;
                                }
                            }
                            // IsInst ItemGrabMenu
                            else if (instruction.opcode == OpCodes.Isinst &&
                                     (Type)instruction.operand == typeof(ItemGrabMenu))
                            {
                                yield return(new CodeInstruction(OpCodes.Isinst, typeof(Types.BaseTypes.ICustomItemGrabMenu)));

                                continue;
                            }
                            yield return(instruction);
                        }
                    }
Пример #24
0
        static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions)
        {
            var from = AccessTools.Constructor(typeof(DamageFlasher), new Type[] { typeof(Pawn) });
            var to   = AccessTools.Constructor(typeof(ZombieDamageFlasher), new Type[] { typeof(Pawn) });

            return(Transpilers.MethodReplacer(instructions, from, to));
        }
 /// <summary>Patches out <see cref="System.Random"/> calls using <see cref="FixRNG(IEnumerable{CodeInstruction})"/>, and optionally surrounds the method with <see cref="Rand.PushState"/> and <see cref="Rand.PopState"/>.</summary>
 /// <param name="type">Type with a constructors that needs patching</param>
 /// <param name="patchPushPop">Determines if the methods should be surrounded with push/pop calls</param>
 public static void PatchSystemRandCtor(string[] types, bool patchPushPop = true)
 {
     foreach (var method in types)
     {
         PatchSystemRand(AccessTools.Constructor(AccessTools.TypeByName(method)), patchPushPop);
     }
 }
Пример #26
0
        internal void Apply(Harmony harmony)
        {
            harmony.Patch(AccessTools.Method(_object, nameof(Object.draw), new[] { typeof(SpriteBatch), typeof(int), typeof(int), typeof(float) }), prefix: new HarmonyMethod(GetType(), nameof(DrawPrefix)));
            harmony.Patch(AccessTools.Method(_object, nameof(Object.drawPlacementBounds), new[] { typeof(SpriteBatch), typeof(GameLocation) }), prefix: new HarmonyMethod(GetType(), nameof(DrawPlacementBoundsPrefix)));
            harmony.Patch(AccessTools.Method(_object, nameof(Object.DayUpdate), new[] { typeof(GameLocation) }), postfix: new HarmonyMethod(GetType(), nameof(DayUpdatePostfix)));
            harmony.Patch(AccessTools.Method(_object, nameof(Object.rot), null), postfix: new HarmonyMethod(GetType(), nameof(RotPostfix)));
            harmony.Patch(AccessTools.Method(_object, nameof(Object.placementAction), new[] { typeof(GameLocation), typeof(int), typeof(int), typeof(Farmer) }), postfix: new HarmonyMethod(GetType(), nameof(PlacementActionPostfix)));

            harmony.Patch(AccessTools.Constructor(_object, new[] { typeof(Vector2), typeof(int), typeof(int) }), postfix: new HarmonyMethod(GetType(), nameof(ObjectPostfix)));

            if (PatchTemplate.IsDGAUsed())
            {
                try
                {
                    if (Type.GetType("DynamicGameAssets.Game.CustomObject, DynamicGameAssets") is Type dgaObjectType && dgaObjectType != null)
                    {
                        harmony.Patch(AccessTools.Method(dgaObjectType, nameof(Object.draw), new[] { typeof(SpriteBatch), typeof(int), typeof(int), typeof(float) }), prefix: new HarmonyMethod(GetType(), nameof(DrawPrefix)));
                        harmony.Patch(AccessTools.Method(dgaObjectType, nameof(Object.placementAction), new[] { typeof(GameLocation), typeof(int), typeof(int), typeof(Farmer) }), postfix: new HarmonyMethod(GetType(), nameof(PlacementActionPostfix)));
                    }

                    if (Type.GetType("DynamicGameAssets.Game.CustomBigCraftable, DynamicGameAssets") is Type dgaCraftableType && dgaCraftableType != null)
                    {
                        harmony.Patch(AccessTools.Method(dgaCraftableType, nameof(Object.draw), new[] { typeof(SpriteBatch), typeof(int), typeof(int), typeof(float) }), prefix: new HarmonyMethod(GetType(), nameof(DrawPrefix)));
                    }
                }
                catch (Exception ex)
                {
                    _monitor.Log($"Failed to patch Dynamic Game Assets in {this.GetType().Name}: AT may not be able to override certain DGA object types!", LogLevel.Warn);
                    _monitor.Log($"Patch for DGA failed in {this.GetType().Name}: {ex}", LogLevel.Trace);
                }
            }
        }
Пример #27
0
 public static ConstructorInfo Constructor(Type type, Type[] parameters = null)
 {
     // Harmony 1.x matched both static and instance constructors
     return
         (AccessTools.Constructor(type, parameters, searchForStatic: false)
          ?? AccessTools.Constructor(type, parameters, searchForStatic: true));
 }
Пример #28
0
        static Patch_RimHUDBase()
        {
            try
            {
                ((Action)(() =>
                {
                    if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "RimHUD"))
                    {
                        Log.Message("DInterests: RimHUD running, attempting to patch");
                        var harmony = new Harmony("io.github.dametri.interests");

                        hudPawnModel = AccessTools.TypeByName("RimHUD.Data.Models.PawnModel");
                        hudSkillModel = AccessTools.TypeByName("RimHUD.Data.Models.SkillModel");

                        var hudTarget1 = AccessTools.Constructor(hudSkillModel, new[] { hudPawnModel, typeof(SkillDef) });
                        var hudInvoke1 = AccessTools.Method(typeof(RimHUDPatches.Patch_SkillModelConstructor_Postfix), "Postfix");
                        if (hudTarget1 != null && hudInvoke1 != null)
                        {
                            harmony.Patch(hudTarget1, postfix: new HarmonyMethod(hudInvoke1));
                        }

                        var hudTarget2 = AccessTools.Method(hudSkillModel, "GetSkillPassionColor");
                        var hudInvoke2 = AccessTools.Method(typeof(RimHUDPatches.Patch_GetSkillPassionColor_Prefix), "Prefix");
                        if (hudTarget2 != null && hudInvoke2 != null)
                        {
                            harmony.Patch(hudTarget2, prefix: new HarmonyMethod(hudInvoke2));
                        }
                    }
                }))();
            }
            catch (TypeLoadException ex) { Log.Message(ex.ToString()); }
        }
Пример #29
0
        public CashRegister(ModContentPack mod)
        {
            var type = AccessTools.TypeByName("CashRegister.Shifts.ITab_Register_Shifts");

            MpCompat.RegisterLambdaMethod(type, "GetGizmos", 1).SetContext(SyncContext.MapSelected);
            MP.RegisterSyncWorker <object>(NoSync, type, shouldConstruct: true);
            MP.RegisterSyncMethod(typeof(CashRegister), nameof(SyncedSetShifts)).ExposeParameter(1).ExposeParameter(2).ExposeParameter(3).ExposeParameter(4).ExposeParameter(5).MinTime(100);
            MpCompat.harmony.Patch(AccessTools.Method(type, "FillTab"),
                                   prefix: new HarmonyMethod(typeof(CashRegister), nameof(PreFillTab)),
                                   postfix: new HarmonyMethod(typeof(CashRegister), nameof(PostFillTab)));

            type = AccessTools.TypeByName("CashRegister.Gizmo_Radius");
            gizmoRadiusConstructor = AccessTools.GetDeclaredConstructors(type).First(x => x.GetParameters().Length == 1);
            gizmoSelectionField    = AccessTools.FieldRefAccess <Building[]>(type, "selection");
            MP.RegisterSyncMethod(AccessTools.DeclaredMethod(type, "ButtonDown"));
            MP.RegisterSyncMethod(AccessTools.DeclaredMethod(type, "ButtonUp"));
            MP.RegisterSyncMethod(AccessTools.DeclaredMethod(type, "ButtonCenter"));
            MP.RegisterSyncWorker <Gizmo>(SyncGizmoRadius, type);

            type             = AccessTools.TypeByName("CashRegister.Building_CashRegister");
            cashRegisterType = type.MakeArrayType();
            shiftsListField  = AccessTools.FieldRefAccess <IList>(type, "shifts");

            type             = AccessTools.TypeByName("CashRegister.Shifts.Shift");
            shiftConstructor = AccessTools.Constructor(type);
            timetableField   = AccessTools.FieldRefAccess <object>(type, "timetable");
            assignedField    = AccessTools.FieldRefAccess <List <Pawn> >(type, "assigned");

            type       = AccessTools.TypeByName("CashRegister.Timetable.TimetableBool");
            timesField = AccessTools.FieldRefAccess <List <bool> >(type, "times");
        }
Пример #30
0
        /// <summary>
        /// Applies the Harmony Patch to the game code.
        /// </summary>
        /// <param name="h">The instance (targetted application) harmony will patch up.</param>
        public void Apply(HarmonyInstance h)
        {
            ConstructorInfo con;
            MethodInfo      orig;
            MethodInfo      prefix;
            MethodInfo      postfix;
            MethodInfo      transpiler;

            prefix     = (hasPrefix) ? Memory.instance.Helper.Reflection.GetMethod(type, "Prefix").MethodInfo : null;
            postfix    = (hasPostfix) ? Memory.instance.Helper.Reflection.GetMethod(type, "Postfix").MethodInfo : null;
            transpiler = (hasTranspiler) ? Memory.instance.Helper.Reflection.GetMethod(type, "Transpiler").MethodInfo : null;

            switch (infoType)
            {
            case 0:
                orig = AccessTools.Method(getTypeSDV(SDVType), original, constructorType);
                h.Patch(orig, (prefix != null) ? new HarmonyMethod(prefix) : null, (postfix != null) ? new HarmonyMethod(postfix) : null, (transpiler != null) ? new HarmonyMethod(transpiler) : null);;
                break;

            case 1:
                con = AccessTools.Constructor(getTypeSDV(SDVType), constructorType);
                h.Patch(con, (prefix != null) ? new HarmonyMethod(prefix) : null, (postfix != null) ? new HarmonyMethod(postfix) : null, (transpiler != null) ? new HarmonyMethod(transpiler) : null);
                break;
            }

            return;
        }