diff options
author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2021-07-30 00:34:53 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2021-07-30 00:34:53 -0400 |
commit | aa65b2e2f6ae2578f9d1f81d6fc1f4c5a261d90f (patch) | |
tree | faccc161af30557a38c80d266f257124af068af7 | |
parent | 737a434ad6704d22776f463c192b9a9748ce2a21 (diff) | |
download | SMAPI-aa65b2e2f6ae2578f9d1f81d6fc1f4c5a261d90f.tar.gz SMAPI-aa65b2e2f6ae2578f9d1f81d6fc1f4c5a261d90f.tar.bz2 SMAPI-aa65b2e2f6ae2578f9d1f81d6fc1f4c5a261d90f.zip |
split patch classes which target multiple types
-rw-r--r-- | src/SMAPI.Mods.ErrorHandler/ModEntry.cs | 3 | ||||
-rw-r--r-- | src/SMAPI.Mods.ErrorHandler/Patches/DialogueErrorPatch.cs | 21 | ||||
-rw-r--r-- | src/SMAPI.Mods.ErrorHandler/Patches/IClickableMenuPatcher.cs | 44 | ||||
-rw-r--r-- | src/SMAPI.Mods.ErrorHandler/Patches/ObjectErrorPatch.cs | 19 | ||||
-rw-r--r-- | src/SMAPI.Mods.ErrorHandler/Patches/ScheduleErrorPatch.cs | 21 | ||||
-rw-r--r-- | src/SMAPI/Framework/SCore.cs | 3 | ||||
-rw-r--r-- | src/SMAPI/Patches/LoadContextPatch.cs | 15 | ||||
-rw-r--r-- | src/SMAPI/Patches/TitleMenuPatcher.cs | 56 |
8 files changed, 124 insertions, 58 deletions
diff --git a/src/SMAPI.Mods.ErrorHandler/ModEntry.cs b/src/SMAPI.Mods.ErrorHandler/ModEntry.cs index b1081218..f6f9a150 100644 --- a/src/SMAPI.Mods.ErrorHandler/ModEntry.cs +++ b/src/SMAPI.Mods.ErrorHandler/ModEntry.cs @@ -1,8 +1,6 @@ using System; using System.Reflection; using StardewModdingAPI.Events; -using StardewModdingAPI.Framework; -using StardewModdingAPI.Framework.Logging; using StardewModdingAPI.Framework.Patching; using StardewModdingAPI.Mods.ErrorHandler.Patches; using StardewValley; @@ -35,6 +33,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler new DictionaryPatches(this.Helper.Reflection), new EventPatches(monitorForGame), new GameLocationPatches(monitorForGame), + new IClickablePatcher(), new ObjectErrorPatch(), new LoadErrorPatch(this.Monitor, this.OnSaveContentRemoved), new ScheduleErrorPatch(monitorForGame), diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/DialogueErrorPatch.cs b/src/SMAPI.Mods.ErrorHandler/Patches/DialogueErrorPatch.cs index a065e3d7..ca5bb0bf 100644 --- a/src/SMAPI.Mods.ErrorHandler/Patches/DialogueErrorPatch.cs +++ b/src/SMAPI.Mods.ErrorHandler/Patches/DialogueErrorPatch.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using HarmonyLib; using StardewModdingAPI.Framework; @@ -43,10 +42,6 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches original: AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) }), finalizer: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Finalize_Dialogue_Constructor)) ); - harmony.Patch( - original: AccessTools.Property(typeof(NPC), nameof(NPC.CurrentDialogue)).GetMethod, - finalizer: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Finalize_NPC_CurrentDialogue)) - ); } @@ -76,21 +71,5 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches return null; } - - /// <summary>The method to call after <see cref="NPC.CurrentDialogue"/>.</summary> - /// <param name="__instance">The instance being patched.</param> - /// <param name="__result">The return value of the original method.</param> - /// <param name="__exception">The exception thrown by the wrapped method, if any.</param> - /// <returns>Returns the exception to throw, if any.</returns> - private static Exception Finalize_NPC_CurrentDialogue(NPC __instance, ref Stack<Dialogue> __result, Exception __exception) - { - if (__exception == null) - return null; - - DialogueErrorPatch.MonitorForGame.Log($"Failed loading current dialogue for NPC {__instance.Name}:\n{__exception.GetLogSummary()}", LogLevel.Error); - __result = new Stack<Dialogue>(); - - return null; - } } } diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/IClickableMenuPatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/IClickableMenuPatcher.cs new file mode 100644 index 00000000..a5a90db2 --- /dev/null +++ b/src/SMAPI.Mods.ErrorHandler/Patches/IClickableMenuPatcher.cs @@ -0,0 +1,44 @@ +using System.Diagnostics.CodeAnalysis; +using HarmonyLib; +using StardewModdingAPI.Framework.Patching; +using StardewValley; +using StardewValley.Menus; +using SObject = StardewValley.Object; + +namespace StardewModdingAPI.Mods.ErrorHandler.Patches +{ + /// <summary>A Harmony patch for <see cref="IClickableMenu"/> which intercepts crashes due to invalid items.</summary> + /// <remarks>Patch methods must be static for Harmony to work correctly. See the Harmony documentation before renaming patch arguments.</remarks> + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony and methods are named for clarity.")] + [SuppressMessage("ReSharper", "IdentifierTypo", Justification = "Argument names are defined by Harmony and methods are named for clarity.")] + internal class IClickablePatcher : IHarmonyPatch + { + /********* + ** Public methods + *********/ + /// <inheritdoc /> + public void Apply(Harmony harmony) + { + harmony.Patch( + original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawToolTip)), + prefix: new HarmonyMethod(this.GetType(), nameof(IClickablePatcher.Before_IClickableMenu_DrawTooltip)) + ); + } + + + /********* + ** Private methods + *********/ + /// <summary>The method to call instead of <see cref="IClickableMenu.drawToolTip"/>.</summary> + /// <param name="hoveredItem">The item for which to draw a tooltip.</param> + /// <returns>Returns whether to execute the original method.</returns> + private static bool Before_IClickableMenu_DrawTooltip(Item hoveredItem) + { + // invalid edible item cause crash when drawing tooltips + if (hoveredItem is SObject obj && obj.Edibility != -300 && !Game1.objectInformation.ContainsKey(obj.ParentSheetIndex)) + return false; + + return true; + } + } +} diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/ObjectErrorPatch.cs b/src/SMAPI.Mods.ErrorHandler/Patches/ObjectErrorPatch.cs index a68e359c..7a4b3cfa 100644 --- a/src/SMAPI.Mods.ErrorHandler/Patches/ObjectErrorPatch.cs +++ b/src/SMAPI.Mods.ErrorHandler/Patches/ObjectErrorPatch.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; using HarmonyLib; using StardewModdingAPI.Framework.Patching; using StardewValley; -using StardewValley.Menus; using SObject = StardewValley.Object; namespace StardewModdingAPI.Mods.ErrorHandler.Patches @@ -32,12 +31,6 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches original: AccessTools.Method(typeof(SObject), "loadDisplayName"), finalizer: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Finalize_Object_loadDisplayName)) ); - - // IClickableMenu.drawToolTip - harmony.Patch( - original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawToolTip)), - prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Before_IClickableMenu_DrawTooltip)) - ); } @@ -74,17 +67,5 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches return __exception; } - - /// <summary>The method to call instead of <see cref="IClickableMenu.drawToolTip"/>.</summary> - /// <param name="hoveredItem">The item for which to draw a tooltip.</param> - /// <returns>Returns whether to execute the original method.</returns> - private static bool Before_IClickableMenu_DrawTooltip(Item hoveredItem) - { - // invalid edible item cause crash when drawing tooltips - if (hoveredItem is SObject obj && obj.Edibility != -300 && !Game1.objectInformation.ContainsKey(obj.ParentSheetIndex)) - return false; - - return true; - } } } diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/ScheduleErrorPatch.cs b/src/SMAPI.Mods.ErrorHandler/Patches/ScheduleErrorPatch.cs index d2e332b4..b8ab9361 100644 --- a/src/SMAPI.Mods.ErrorHandler/Patches/ScheduleErrorPatch.cs +++ b/src/SMAPI.Mods.ErrorHandler/Patches/ScheduleErrorPatch.cs @@ -35,6 +35,11 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches public void Apply(Harmony harmony) { harmony.Patch( + original: AccessTools.Property(typeof(NPC), nameof(NPC.CurrentDialogue)).GetMethod, + finalizer: new HarmonyMethod(this.GetType(), nameof(ScheduleErrorPatch.Finalize_NPC_CurrentDialogue)) + ); + + harmony.Patch( original: AccessTools.Method(typeof(NPC), nameof(NPC.parseMasterSchedule)), finalizer: new HarmonyMethod(this.GetType(), nameof(ScheduleErrorPatch.Finalize_NPC_parseMasterSchedule)) ); @@ -44,6 +49,22 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches /********* ** Private methods *********/ + /// <summary>The method to call after <see cref="NPC.CurrentDialogue"/>.</summary> + /// <param name="__instance">The instance being patched.</param> + /// <param name="__result">The return value of the original method.</param> + /// <param name="__exception">The exception thrown by the wrapped method, if any.</param> + /// <returns>Returns the exception to throw, if any.</returns> + private static Exception Finalize_NPC_CurrentDialogue(NPC __instance, ref Stack<Dialogue> __result, Exception __exception) + { + if (__exception == null) + return null; + + ScheduleErrorPatch.MonitorForGame.Log($"Failed loading current dialogue for NPC {__instance.Name}:\n{__exception.GetLogSummary()}", LogLevel.Error); + __result = new Stack<Dialogue>(); + + return null; + } + /// <summary>The method to call instead of <see cref="NPC.parseMasterSchedule"/>.</summary> /// <param name="rawData">The raw schedule data to parse.</param> /// <param name="__instance">The instance being patched.</param> diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index b607f95d..419afd4b 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -255,7 +255,8 @@ namespace StardewModdingAPI.Framework // apply game patches MiniMonoModHotfix.Apply(); new GamePatcher(this.Monitor).Apply( - new LoadContextPatch(this.Reflection, this.OnLoadStageChanged) + new LoadContextPatch(this.Reflection, this.OnLoadStageChanged), + new TitleMenuPatcher(this.OnLoadStageChanged) ); // add exit handler diff --git a/src/SMAPI/Patches/LoadContextPatch.cs b/src/SMAPI/Patches/LoadContextPatch.cs index 721cf53d..c7f7d986 100644 --- a/src/SMAPI/Patches/LoadContextPatch.cs +++ b/src/SMAPI/Patches/LoadContextPatch.cs @@ -44,12 +44,6 @@ namespace StardewModdingAPI.Patches /// <inheritdoc /> public void Apply(Harmony harmony) { - // detect CreatedBasicInfo - harmony.Patch( - original: AccessTools.Method(typeof(TitleMenu), nameof(TitleMenu.createdNewCharacter)), - prefix: new HarmonyMethod(this.GetType(), nameof(LoadContextPatch.Before_TitleMenu_CreatedNewCharacter)) - ); - // detect CreatedInitialLocations and SaveAddedLocations harmony.Patch( original: AccessTools.Method(typeof(Game1), nameof(Game1.AddModNPCs)), @@ -74,15 +68,6 @@ namespace StardewModdingAPI.Patches /********* ** Private methods *********/ - /// <summary>Called before <see cref="TitleMenu.createdNewCharacter"/>.</summary> - /// <returns>Returns whether to execute the original method.</returns> - /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> - private static bool Before_TitleMenu_CreatedNewCharacter() - { - LoadContextPatch.OnStageChanged(LoadStage.CreatedBasicInfo); - return true; - } - /// <summary>Called before <see cref="Game1.AddModNPCs"/>.</summary> /// <returns>Returns whether to execute the original method.</returns> /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> diff --git a/src/SMAPI/Patches/TitleMenuPatcher.cs b/src/SMAPI/Patches/TitleMenuPatcher.cs new file mode 100644 index 00000000..a889adfc --- /dev/null +++ b/src/SMAPI/Patches/TitleMenuPatcher.cs @@ -0,0 +1,56 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using HarmonyLib; +using StardewModdingAPI.Enums; +using StardewModdingAPI.Framework.Patching; +using StardewValley.Menus; + +namespace StardewModdingAPI.Patches +{ + /// <summary>Harmony patches which notify SMAPI for save creation load stages.</summary> + /// <remarks>Patch methods must be static for Harmony to work correctly. See the Harmony documentation before renaming patch arguments.</remarks> + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony and methods are named for clarity.")] + [SuppressMessage("ReSharper", "IdentifierTypo", Justification = "Argument names are defined by Harmony and methods are named for clarity.")] + internal class TitleMenuPatcher : IHarmonyPatch + { + /********* + ** Fields + *********/ + /// <summary>A callback to invoke when the load stage changes.</summary> + private static Action<LoadStage> OnStageChanged; + + + /********* + ** Public methods + *********/ + /// <summary>Construct an instance.</summary> + /// <param name="onStageChanged">A callback to invoke when the load stage changes.</param> + public TitleMenuPatcher(Action<LoadStage> onStageChanged) + { + TitleMenuPatcher.OnStageChanged = onStageChanged; + } + + /// <inheritdoc /> + public void Apply(Harmony harmony) + { + // detect CreatedBasicInfo + harmony.Patch( + original: AccessTools.Method(typeof(TitleMenu), nameof(TitleMenu.createdNewCharacter)), + prefix: new HarmonyMethod(this.GetType(), nameof(TitleMenuPatcher.Before_TitleMenu_CreatedNewCharacter)) + ); + } + + + /********* + ** Private methods + *********/ + /// <summary>Called before <see cref="TitleMenu.createdNewCharacter"/>.</summary> + /// <returns>Returns whether to execute the original method.</returns> + /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> + private static bool Before_TitleMenu_CreatedNewCharacter() + { + TitleMenuPatcher.OnStageChanged(LoadStage.CreatedBasicInfo); + return true; + } + } +} |