summaryrefslogtreecommitdiff
path: root/src/SMAPI.Mods.ErrorHandler/Patches
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2021-07-30 00:54:15 -0400
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2021-07-30 00:54:15 -0400
commit948c800a98f00b1bdcfd05ee6228e3423f9eb465 (patch)
treeb958b3cdb4428fa8788a5698a207a45912923de7 /src/SMAPI.Mods.ErrorHandler/Patches
parent4074f697d73f5cac6699836550b144fd0c4e2803 (diff)
downloadSMAPI-948c800a98f00b1bdcfd05ee6228e3423f9eb465.tar.gz
SMAPI-948c800a98f00b1bdcfd05ee6228e3423f9eb465.tar.bz2
SMAPI-948c800a98f00b1bdcfd05ee6228e3423f9eb465.zip
migrate to the new Harmony patch pattern used in my mods
That improves validation and error-handling.
Diffstat (limited to 'src/SMAPI.Mods.ErrorHandler/Patches')
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/DialoguePatcher.cs18
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatcher.cs28
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/EventPatcher.cs12
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/GameLocationPatcher.cs24
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/IClickableMenuPatcher.cs14
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/NpcPatcher.cs24
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/ObjectPatcher.cs16
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/SaveGamePatcher.cs15
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/SpriteBatchPatcher.cs20
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/UtilityPatcher.cs14
10 files changed, 89 insertions, 96 deletions
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/DialoguePatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/DialoguePatcher.cs
index 7b730ee5..7a3af39c 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/DialoguePatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/DialoguePatcher.cs
@@ -1,17 +1,17 @@
using System;
using System.Diagnostics.CodeAnalysis;
using HarmonyLib;
-using StardewModdingAPI.Framework;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
{
- /// <summary>A Harmony patch for the <see cref="Dialogue"/> constructor which intercepts invalid dialogue lines and logs an error instead of crashing.</summary>
+ /// <summary>Harmony patches for <see cref="Dialogue"/> which intercept invalid dialogue lines and logs an error instead of crashing.</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 DialoguePatcher : IHarmonyPatch
+ internal class DialoguePatcher : BasePatcher
{
/*********
** Fields
@@ -36,11 +36,11 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
}
/// <inheritdoc />
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
- original: AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) }),
- finalizer: new HarmonyMethod(this.GetType(), nameof(DialoguePatcher.Finalize_Dialogue_Constructor))
+ original: this.RequireConstructor<Dialogue>(typeof(string), typeof(NPC)),
+ finalizer: this.GetHarmonyMethod(nameof(DialoguePatcher.Finalize_Constructor))
);
}
@@ -48,13 +48,13 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
/*********
** Private methods
*********/
- /// <summary>The method to call after the Dialogue constructor.</summary>
+ /// <summary>The method to call when the Dialogue constructor throws an exception.</summary>
/// <param name="__instance">The instance being patched.</param>
/// <param name="masterDialogue">The dialogue being parsed.</param>
/// <param name="speaker">The NPC for which the dialogue is being parsed.</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_Dialogue_Constructor(Dialogue __instance, string masterDialogue, NPC speaker, Exception __exception)
+ private static Exception Finalize_Constructor(Dialogue __instance, string masterDialogue, NPC speaker, Exception __exception)
{
if (__exception != null)
{
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatcher.cs
index 3c5240b6..6ad64e16 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatcher.cs
@@ -2,18 +2,18 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using HarmonyLib;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley.GameData;
using StardewValley.GameData.HomeRenovations;
using StardewValley.GameData.Movies;
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
{
- /// <summary>A Harmony patch for <see cref="Dictionary{TKey,TValue}"/> which adds the accessed key to <see cref="KeyNotFoundException"/> exceptions.</summary>
+ /// <summary>Harmony patches for <see cref="Dictionary{TKey,TValue}"/> which add the accessed key to <see cref="KeyNotFoundException"/> exceptions.</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 DictionaryPatcher : IHarmonyPatch
+ internal class DictionaryPatcher : BasePatcher
{
/*********
** Fields
@@ -33,7 +33,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
}
/// <inheritdoc />
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
Type[] keyTypes = { typeof(int), typeof(string) };
Type[] valueTypes = { typeof(int), typeof(string), typeof(HomeRenovation), typeof(MovieData), typeof(SpecialOrderData) };
@@ -45,8 +45,8 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
Type dictionaryType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
harmony.Patch(
- original: AccessTools.Method(dictionaryType, "get_Item"),
- finalizer: new HarmonyMethod(this.GetType(), nameof(DictionaryPatcher.Finalize_GetItem))
+ original: AccessTools.Method(dictionaryType, "get_Item") ?? throw new InvalidOperationException($"Can't find method {PatchHelper.GetMethodString(dictionaryType, "get_Item")} to patch."),
+ finalizer: this.GetHarmonyMethod(nameof(DictionaryPatcher.Finalize_GetItem))
);
}
}
@@ -63,19 +63,13 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
private static Exception Finalize_GetItem(object key, Exception __exception)
{
if (__exception is KeyNotFoundException)
- AddKeyTo(__exception, key?.ToString());
+ {
+ DictionaryPatcher.Reflection
+ .GetField<string>(__exception, "_message")
+ .SetValue($"{__exception.Message}\nkey: '{key}'");
+ }
return __exception;
}
-
- /// <summary>Add the accessed key to an exception message.</summary>
- /// <param name="exception">The exception to modify.</param>
- /// <param name="key">The dictionary key.</param>
- private static void AddKeyTo(Exception exception, string key)
- {
- DictionaryPatcher.Reflection
- .GetField<string>(exception, "_message")
- .SetValue($"{exception.Message}\nkey: '{key}'");
- }
}
}
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/EventPatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/EventPatcher.cs
index 9a7b34d8..1b706147 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/EventPatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/EventPatcher.cs
@@ -1,7 +1,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using HarmonyLib;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
@@ -10,7 +10,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
/// <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 EventPatcher : IHarmonyPatch
+ internal class EventPatcher : BasePatcher
{
/*********
** Fields
@@ -30,11 +30,11 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
}
/// <inheritdoc />
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
- original: AccessTools.Method(typeof(Event), nameof(Event.LogErrorAndHalt)),
- postfix: new HarmonyMethod(this.GetType(), nameof(EventPatcher.After_Event_LogErrorAndHalt))
+ original: this.RequireMethod<Event>(nameof(Event.LogErrorAndHalt)),
+ postfix: this.GetHarmonyMethod(nameof(EventPatcher.After_LogErrorAndHalt))
);
}
@@ -44,7 +44,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
*********/
/// <summary>The method to call after <see cref="Event.LogErrorAndHalt"/>.</summary>
/// <param name="e">The exception being logged.</param>
- private static void After_Event_LogErrorAndHalt(Exception e)
+ private static void After_LogErrorAndHalt(Exception e)
{
EventPatcher.MonitorForGame.Log(e.ToString(), LogLevel.Error);
}
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/GameLocationPatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/GameLocationPatcher.cs
index 7427fe48..7df6b0a2 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/GameLocationPatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/GameLocationPatcher.cs
@@ -1,17 +1,17 @@
using System;
using System.Diagnostics.CodeAnalysis;
using HarmonyLib;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
using xTile;
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
{
- /// <summary>Harmony patches for <see cref="GameLocation.checkEventPrecondition"/> and <see cref="GameLocation.updateSeasonalTileSheets"/> which intercept errors instead of crashing.</summary>
+ /// <summary>Harmony patches for <see cref="GameLocation"/> which intercept errors instead of crashing.</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 GameLocationPatcher : IHarmonyPatch
+ internal class GameLocationPatcher : BasePatcher
{
/*********
** Fields
@@ -31,15 +31,15 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
}
/// <inheritdoc />
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
- original: AccessTools.Method(typeof(GameLocation), nameof(GameLocation.checkEventPrecondition)),
- finalizer: new HarmonyMethod(this.GetType(), nameof(GameLocationPatcher.Finalize_GameLocation_CheckEventPrecondition))
+ original: this.RequireMethod<GameLocation>(nameof(GameLocation.checkEventPrecondition)),
+ finalizer: this.GetHarmonyMethod(nameof(GameLocationPatcher.Finalize_CheckEventPrecondition))
);
harmony.Patch(
- original: AccessTools.Method(typeof(GameLocation), nameof(GameLocation.updateSeasonalTileSheets)),
- finalizer: new HarmonyMethod(this.GetType(), nameof(GameLocationPatcher.Before_GameLocation_UpdateSeasonalTileSheets))
+ original: this.RequireMethod<GameLocation>(nameof(GameLocation.updateSeasonalTileSheets)),
+ finalizer: this.GetHarmonyMethod(nameof(GameLocationPatcher.Finalize_UpdateSeasonalTileSheets))
);
}
@@ -47,12 +47,12 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
/*********
** Private methods
*********/
- /// <summary>The method to call instead of GameLocation.checkEventPrecondition.</summary>
+ /// <summary>The method to call when <see cref="GameLocation.checkEventPrecondition"/> throws an exception.</summary>
/// <param name="__result">The return value of the original method.</param>
/// <param name="precondition">The precondition to be parsed.</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_GameLocation_CheckEventPrecondition(ref int __result, string precondition, Exception __exception)
+ private static Exception Finalize_CheckEventPrecondition(ref int __result, string precondition, Exception __exception)
{
if (__exception != null)
{
@@ -63,12 +63,12 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
return null;
}
- /// <summary>The method to call instead of <see cref="GameLocation.updateSeasonalTileSheets"/>.</summary>
+ /// <summary>The method to call when <see cref="GameLocation.updateSeasonalTileSheets"/> throws an exception.</summary>
/// <param name="__instance">The instance being patched.</param>
/// <param name="map">The map whose tilesheets to update.</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 Before_GameLocation_UpdateSeasonalTileSheets(GameLocation __instance, Map map, Exception __exception)
+ private static Exception Finalize_UpdateSeasonalTileSheets(GameLocation __instance, Map map, Exception __exception)
{
if (__exception != null)
GameLocationPatcher.MonitorForGame.Log($"Failed updating seasonal tilesheets for location '{__instance.NameOrUniqueName}': \n{__exception}", LogLevel.Error);
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/IClickableMenuPatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/IClickableMenuPatcher.cs
index d6f9fbf4..b65a695a 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/IClickableMenuPatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/IClickableMenuPatcher.cs
@@ -1,27 +1,27 @@
using System.Diagnostics.CodeAnalysis;
using HarmonyLib;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.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>
+ /// <summary>Harmony patches for <see cref="IClickableMenu"/> which intercept 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 IClickableMenuPatcher : IHarmonyPatch
+ internal class IClickableMenuPatcher : BasePatcher
{
/*********
** Public methods
*********/
/// <inheritdoc />
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
- original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawToolTip)),
- prefix: new HarmonyMethod(this.GetType(), nameof(IClickableMenuPatcher.Before_IClickableMenu_DrawTooltip))
+ original: this.RequireMethod<IClickableMenu>(nameof(IClickableMenu.drawToolTip)),
+ prefix: this.GetHarmonyMethod(nameof(IClickableMenuPatcher.Before_DrawTooltip))
);
}
@@ -32,7 +32,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
/// <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)
+ private static bool Before_DrawTooltip(Item hoveredItem)
{
// invalid edible item cause crash when drawing tooltips
if (hoveredItem is SObject obj && obj.Edibility != -300 && !Game1.objectInformation.ContainsKey(obj.ParentSheetIndex))
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/NpcPatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/NpcPatcher.cs
index 4a07ea1d..275bb5bf 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/NpcPatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/NpcPatcher.cs
@@ -2,17 +2,17 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using HarmonyLib;
-using StardewModdingAPI.Framework;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
{
- /// <summary>A Harmony patch for <see cref="NPC.parseMasterSchedule"/> which intercepts crashes due to invalid schedule data.</summary>
+ /// <summary>Harmony patches for <see cref="NPC"/> which intercept crashes due to invalid schedule data.</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 NpcPatcher : IHarmonyPatch
+ internal class NpcPatcher : BasePatcher
{
/*********
** Fields
@@ -32,16 +32,16 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
}
/// <inheritdoc />
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
- original: AccessTools.Property(typeof(NPC), nameof(NPC.CurrentDialogue)).GetMethod,
- finalizer: new HarmonyMethod(this.GetType(), nameof(NpcPatcher.Finalize_NPC_CurrentDialogue))
+ original: this.RequireMethod<NPC>($"get_{nameof(NPC.CurrentDialogue)}"),
+ finalizer: this.GetHarmonyMethod(nameof(NpcPatcher.Finalize_CurrentDialogue))
);
harmony.Patch(
- original: AccessTools.Method(typeof(NPC), nameof(NPC.parseMasterSchedule)),
- finalizer: new HarmonyMethod(this.GetType(), nameof(NpcPatcher.Finalize_NPC_parseMasterSchedule))
+ original: this.RequireMethod<NPC>(nameof(NPC.parseMasterSchedule)),
+ finalizer: this.GetHarmonyMethod(nameof(NpcPatcher.Finalize_ParseMasterSchedule))
);
}
@@ -49,12 +49,12 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
/*********
** Private methods
*********/
- /// <summary>The method to call after <see cref="NPC.CurrentDialogue"/>.</summary>
+ /// <summary>The method to call when <see cref="NPC.CurrentDialogue"/> throws an exception.</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)
+ private static Exception Finalize_CurrentDialogue(NPC __instance, ref Stack<Dialogue> __result, Exception __exception)
{
if (__exception == null)
return null;
@@ -71,7 +71,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
/// <param name="__result">The patched method's return value.</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_parseMasterSchedule(string rawData, NPC __instance, ref Dictionary<int, SchedulePathDescription> __result, Exception __exception)
+ private static Exception Finalize_ParseMasterSchedule(string rawData, NPC __instance, ref Dictionary<int, SchedulePathDescription> __result, Exception __exception)
{
if (__exception != null)
{
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/ObjectPatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/ObjectPatcher.cs
index c4b25b96..fd4ea35c 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/ObjectPatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/ObjectPatcher.cs
@@ -2,34 +2,34 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using HarmonyLib;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
using SObject = StardewValley.Object;
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
{
- /// <summary>A Harmony patch for <see cref="SObject.getDescription"/> which intercepts crashes due to the item no longer existing.</summary>
+ /// <summary>Harmony patches for <see cref="SObject"/> which intercept 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 ObjectPatcher : IHarmonyPatch
+ internal class ObjectPatcher : BasePatcher
{
/*********
** Public methods
*********/
/// <inheritdoc />
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
// object.getDescription
harmony.Patch(
- original: AccessTools.Method(typeof(SObject), nameof(SObject.getDescription)),
- prefix: new HarmonyMethod(this.GetType(), nameof(ObjectPatcher.Before_Object_GetDescription))
+ original: this.RequireMethod<SObject>(nameof(SObject.getDescription)),
+ prefix: this.GetHarmonyMethod(nameof(ObjectPatcher.Before_Object_GetDescription))
);
// object.getDisplayName
harmony.Patch(
- original: AccessTools.Method(typeof(SObject), "loadDisplayName"),
- finalizer: new HarmonyMethod(this.GetType(), nameof(ObjectPatcher.Finalize_Object_loadDisplayName))
+ original: this.RequireMethod<SObject>("loadDisplayName"),
+ finalizer: this.GetHarmonyMethod(nameof(ObjectPatcher.Finalize_Object_loadDisplayName))
);
}
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/SaveGamePatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/SaveGamePatcher.cs
index ef165831..8945e4f3 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/SaveGamePatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/SaveGamePatcher.cs
@@ -4,18 +4,18 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using HarmonyLib;
using Microsoft.Xna.Framework.Content;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
using StardewValley.Buildings;
using StardewValley.Locations;
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
{
- /// <summary>A Harmony patch for <see cref="SaveGame"/> which prevents some errors due to broken save data.</summary>
+ /// <summary>Harmony patches for <see cref="SaveGame"/> which prevent some errors due to broken save data.</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 SaveGamePatcher : IHarmonyPatch
+ internal class SaveGamePatcher : BasePatcher
{
/*********
** Fields
@@ -39,13 +39,12 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
SaveGamePatcher.OnContentRemoved = onContentRemoved;
}
-
/// <inheritdoc />
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
- original: AccessTools.Method(typeof(SaveGame), nameof(SaveGame.loadDataToLocations)),
- prefix: new HarmonyMethod(this.GetType(), nameof(SaveGamePatcher.Before_SaveGame_LoadDataToLocations))
+ original: this.RequireMethod<SaveGame>(nameof(SaveGame.loadDataToLocations)),
+ prefix: this.GetHarmonyMethod(nameof(SaveGamePatcher.Before_LoadDataToLocations))
);
}
@@ -56,7 +55,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
/// <summary>The method to call instead of <see cref="SaveGame.loadDataToLocations"/>.</summary>
/// <param name="gamelocations">The game locations being loaded.</param>
/// <returns>Returns whether to execute the original method.</returns>
- private static bool Before_SaveGame_LoadDataToLocations(List<GameLocation> gamelocations)
+ private static bool Before_LoadDataToLocations(List<GameLocation> gamelocations)
{
bool removedAny =
SaveGamePatcher.RemoveBrokenBuildings(gamelocations)
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/SpriteBatchPatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/SpriteBatchPatcher.cs
index 1099afee..6860a4ec 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/SpriteBatchPatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/SpriteBatchPatcher.cs
@@ -2,27 +2,27 @@ using System;
using System.Diagnostics.CodeAnalysis;
using HarmonyLib;
using Microsoft.Xna.Framework.Graphics;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
{
- /// <summary>Harmony patch for <see cref="SpriteBatch"/> to validate textures earlier.</summary>
+ /// <summary>Harmony patches for <see cref="SpriteBatch"/> which validate textures earlier.</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 SpriteBatchPatcher : IHarmonyPatch
+ internal class SpriteBatchPatcher : BasePatcher
{
/*********
** Public methods
*********/
/// <inheritdoc />
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
original: Constants.GameFramework == GameFramework.Xna
- ? AccessTools.Method(typeof(SpriteBatch), "InternalDraw")
- : AccessTools.Method(typeof(SpriteBatch), "CheckValid", new[] { typeof(Texture2D) }),
- postfix: new HarmonyMethod(this.GetType(), nameof(SpriteBatchPatcher.After_SpriteBatch_CheckValid))
+ ? this.RequireMethod<SpriteBatch>("InternalDraw")
+ : this.RequireMethod<SpriteBatch>("CheckValid", new[] { typeof(Texture2D) }),
+ postfix: this.GetHarmonyMethod(nameof(SpriteBatchPatcher.After_CheckValid))
);
}
@@ -31,13 +31,13 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
** Private methods
*********/
#if SMAPI_FOR_XNA
- /// <summary>The method to call instead of <see cref="SpriteBatch.InternalDraw"/>.</summary>
+ /// <summary>The method to call after <see cref="SpriteBatch.InternalDraw"/>.</summary>
/// <param name="texture">The texture to validate.</param>
#else
- /// <summary>The method to call instead of <see cref="SpriteBatch.CheckValid"/>.</summary>
+ /// <summary>The method to call after <see cref="SpriteBatch.CheckValid"/>.</summary>
/// <param name="texture">The texture to validate.</param>
#endif
- private static void After_SpriteBatch_CheckValid(Texture2D texture)
+ private static void After_CheckValid(Texture2D texture)
{
if (texture?.IsDisposed == true)
throw new ObjectDisposedException("Cannot draw this texture because it's disposed.");
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/UtilityPatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/UtilityPatcher.cs
index e29e3030..ce85d0c2 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/UtilityPatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/UtilityPatcher.cs
@@ -1,7 +1,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using HarmonyLib;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
@@ -10,17 +10,17 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
/// <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 UtilityPatcher : IHarmonyPatch
+ internal class UtilityPatcher : BasePatcher
{
/*********
** Public methods
*********/
/// <inheritdoc />
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
- original: AccessTools.Method(typeof(Utility), nameof(Utility.getItemFromStandardTextDescription)),
- finalizer: new HarmonyMethod(this.GetType(), nameof(UtilityPatcher.Finalize_Utility_GetItemFromStandardTextDescription))
+ original: this.RequireMethod<Utility>(nameof(Utility.getItemFromStandardTextDescription)),
+ finalizer: this.GetHarmonyMethod(nameof(UtilityPatcher.Finalize_GetItemFromStandardTextDescription))
);
}
@@ -28,12 +28,12 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
/*********
** Private methods
*********/
- /// <summary>The method to call instead of <see cref="Utility.getItemFromStandardTextDescription"/>.</summary>
+ /// <summary>The method to call when <see cref="Utility.getItemFromStandardTextDescription"/> throws an exception.</summary>
/// <param name="description">The item text description to parse.</param>
/// <param name="delimiter">The delimiter by which to split the text description.</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_Utility_GetItemFromStandardTextDescription(string description, char delimiter, ref Exception __exception)
+ private static Exception Finalize_GetItemFromStandardTextDescription(string description, char delimiter, ref Exception __exception)
{
return __exception != null
? new FormatException($"Failed to parse item text description \"{description}\" with delimiter \"{delimiter}\".", __exception)