summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2021-07-30 00:34:53 -0400
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2021-07-30 00:34:53 -0400
commitaa65b2e2f6ae2578f9d1f81d6fc1f4c5a261d90f (patch)
treefaccc161af30557a38c80d266f257124af068af7
parent737a434ad6704d22776f463c192b9a9748ce2a21 (diff)
downloadSMAPI-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.cs3
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/DialogueErrorPatch.cs21
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/IClickableMenuPatcher.cs44
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/ObjectErrorPatch.cs19
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/ScheduleErrorPatch.cs21
-rw-r--r--src/SMAPI/Framework/SCore.cs3
-rw-r--r--src/SMAPI/Patches/LoadContextPatch.cs15
-rw-r--r--src/SMAPI/Patches/TitleMenuPatcher.cs56
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;
+ }
+ }
+}