summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/release-notes.md1
-rw-r--r--src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatcher.cs33
2 files changed, 29 insertions, 5 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 65a2e93b..a7a5e6dd 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -6,6 +6,7 @@
* Fixed mod edits to the farmhouse shifting the player down one tile in some cases.
* For mod authors:
+ * SMAPI now intercepts dictionary duplicate-key errors and adds the key to the error message to simplify troubleshooting. (Due to Harmony limitations, this only works for the dictionary types used by the game.)
* Fixed map tile rotations/flips not working for farmhands in split-screen mode.
* Fixed barn/coop exit warps being reset when you edit their interior map.
diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatcher.cs b/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatcher.cs
index 6ad64e16..8ceafcc5 100644
--- a/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatcher.cs
+++ b/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatcher.cs
@@ -48,6 +48,11 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
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))
);
+
+ harmony.Patch(
+ original: AccessTools.Method(dictionaryType, "Add") ?? throw new InvalidOperationException($"Can't find method {PatchHelper.GetMethodString(dictionaryType, "Add")} to patch."),
+ finalizer: this.GetHarmonyMethod(nameof(DictionaryPatcher.Finalize_Add))
+ );
}
}
}
@@ -63,13 +68,31 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
private static Exception Finalize_GetItem(object key, Exception __exception)
{
if (__exception is KeyNotFoundException)
- {
- DictionaryPatcher.Reflection
- .GetField<string>(__exception, "_message")
- .SetValue($"{__exception.Message}\nkey: '{key}'");
- }
+ DictionaryPatcher.AddKey(__exception, key);
return __exception;
}
+
+ /// <summary>The method to call after a dictionary insert throws an exception.</summary>
+ /// <param name="key">The dictionary key being inserted.</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_Add(object key, Exception __exception)
+ {
+ if (__exception is ArgumentException)
+ DictionaryPatcher.AddKey(__exception, key);
+
+ return __exception;
+ }
+
+ /// <summary>Add the dictionary key to an exception message.</summary>
+ /// <param name="exception">The exception whose message to edit.</param>
+ /// <param name="key">The dictionary key.</param>
+ private static void AddKey(Exception exception, object key)
+ {
+ DictionaryPatcher.Reflection
+ .GetField<string>(exception, "_message")
+ .SetValue($"{exception.Message}\nkey: '{key}'");
+ }
}
}