From 05bfd33ac4d4d089ed88fddcc8f8304ffb99f1f4 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 14 Apr 2019 21:17:51 -0400 Subject: fix formatting and code style (#636) --- src/SMAPI/Patches/DialogueErrorPatch.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI/Patches/DialogueErrorPatch.cs') diff --git a/src/SMAPI/Patches/DialogueErrorPatch.cs b/src/SMAPI/Patches/DialogueErrorPatch.cs index d8905fd1..5af6ceef 100644 --- a/src/SMAPI/Patches/DialogueErrorPatch.cs +++ b/src/SMAPI/Patches/DialogueErrorPatch.cs @@ -13,7 +13,7 @@ namespace StardewModdingAPI.Patches internal class DialogueErrorPatch : IHarmonyPatch { /********* - ** Private methods + ** Fields *********/ /// Writes messages to the console and log file on behalf of the game. private static IMonitor MonitorForGame; -- cgit From e43f01ffce7238d40d275c47615c24b9134b4954 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 14 Apr 2019 22:14:43 -0400 Subject: tweak patch code style --- src/SMAPI/Patches/CheckEventPreconditionErrorPatch.cs | 2 +- src/SMAPI/Patches/DialogueErrorPatch.cs | 8 ++++---- src/SMAPI/Patches/LoadForNewGamePatch.cs | 15 +++++++-------- src/SMAPI/Patches/ObjectErrorPatch.cs | 4 ++-- 4 files changed, 14 insertions(+), 15 deletions(-) (limited to 'src/SMAPI/Patches/DialogueErrorPatch.cs') diff --git a/src/SMAPI/Patches/CheckEventPreconditionErrorPatch.cs b/src/SMAPI/Patches/CheckEventPreconditionErrorPatch.cs index 74cfbfb0..c2a16391 100644 --- a/src/SMAPI/Patches/CheckEventPreconditionErrorPatch.cs +++ b/src/SMAPI/Patches/CheckEventPreconditionErrorPatch.cs @@ -42,7 +42,7 @@ namespace StardewModdingAPI.Patches { harmony.Patch( original: AccessTools.Method(typeof(GameLocation), "checkEventPrecondition"), - prefix: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(CheckEventPreconditionErrorPatch.Prefix))) + prefix: new HarmonyMethod(this.GetType(), nameof(CheckEventPreconditionErrorPatch.Prefix)) ); } diff --git a/src/SMAPI/Patches/DialogueErrorPatch.cs b/src/SMAPI/Patches/DialogueErrorPatch.cs index 5af6ceef..7d57464c 100644 --- a/src/SMAPI/Patches/DialogueErrorPatch.cs +++ b/src/SMAPI/Patches/DialogueErrorPatch.cs @@ -46,10 +46,10 @@ namespace StardewModdingAPI.Patches /// The Harmony instance. 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); + harmony.Patch( + original: AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) }), + prefix: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Prefix)) + ); } diff --git a/src/SMAPI/Patches/LoadForNewGamePatch.cs b/src/SMAPI/Patches/LoadForNewGamePatch.cs index f4ce2023..def7134d 100644 --- a/src/SMAPI/Patches/LoadForNewGamePatch.cs +++ b/src/SMAPI/Patches/LoadForNewGamePatch.cs @@ -1,7 +1,6 @@ using System; using System.Collections.ObjectModel; using System.Collections.Specialized; -using System.Reflection; using Harmony; using StardewModdingAPI.Enums; using StardewModdingAPI.Framework.Patching; @@ -28,7 +27,7 @@ namespace StardewModdingAPI.Patches private static bool IsCreating; /// The number of times that has been cleared since started. - private static int TimesLocationsCleared = 0; + private static int TimesLocationsCleared; /********* @@ -54,11 +53,11 @@ namespace StardewModdingAPI.Patches /// The Harmony instance. public void Apply(HarmonyInstance harmony) { - MethodInfo method = AccessTools.Method(typeof(Game1), nameof(Game1.loadForNewGame)); - MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Prefix)); - MethodInfo postfix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Postfix)); - - harmony.Patch(method, new HarmonyMethod(prefix), new HarmonyMethod(postfix)); + harmony.Patch( + original: AccessTools.Method(typeof(Game1), nameof(Game1.loadForNewGame)), + prefix: new HarmonyMethod(this.GetType(), nameof(LoadForNewGamePatch.Prefix)), + postfix: new HarmonyMethod(this.GetType(), nameof(LoadForNewGamePatch.Postfix)) + ); } @@ -89,7 +88,7 @@ namespace StardewModdingAPI.Patches if (LoadForNewGamePatch.IsCreating) { // clean up - ObservableCollection locations = (ObservableCollection) Game1.locations; + ObservableCollection locations = (ObservableCollection)Game1.locations; locations.CollectionChanged -= LoadForNewGamePatch.OnLocationListChanged; // raise stage changed diff --git a/src/SMAPI/Patches/ObjectErrorPatch.cs b/src/SMAPI/Patches/ObjectErrorPatch.cs index d72201c3..0b17b101 100644 --- a/src/SMAPI/Patches/ObjectErrorPatch.cs +++ b/src/SMAPI/Patches/ObjectErrorPatch.cs @@ -27,13 +27,13 @@ namespace StardewModdingAPI.Patches // object.getDescription harmony.Patch( original: AccessTools.Method(typeof(SObject), nameof(SObject.getDescription)), - prefix: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(ObjectErrorPatch.Object_GetDescription_Prefix))) + prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Object_GetDescription_Prefix)) ); // IClickableMenu.drawToolTip harmony.Patch( original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawToolTip)), - prefix: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(ObjectErrorPatch.IClickableMenu_DrawTooltip_Prefix))) + prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.IClickableMenu_DrawTooltip_Prefix)) ); } -- cgit From 6285c7954843557eec06cbae406c8ae436512803 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 12 Jul 2019 20:01:38 -0400 Subject: prevent mods from crashing the game with invalid dialogue in more cases --- docs/release-notes.md | 1 + src/SMAPI/Patches/DialogueErrorPatch.cs | 41 +++++++++++++++++++++++++++++++-- src/SMAPI/Patches/EventErrorPatch.cs | 4 ++-- src/SMAPI/Patches/LoadContextPatch.cs | 8 +++---- src/SMAPI/Patches/ObjectErrorPatch.cs | 8 +++---- 5 files changed, 50 insertions(+), 12 deletions(-) (limited to 'src/SMAPI/Patches/DialogueErrorPatch.cs') diff --git a/docs/release-notes.md b/docs/release-notes.md index 87b142bc..3addb2d0 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -5,6 +5,7 @@ These changes have not been released yet. * For players: * SMAPI now prevents invalid items from breaking menus on hover. * SMAPI now prevents invalid event preconditions from crashing the game (thanks to berkayylmao!). + * SMAPI now prevents more invalid dialogues from crashing the game. * Fixed errors during early startup not shown before exit. * For the web UI: diff --git a/src/SMAPI/Patches/DialogueErrorPatch.cs b/src/SMAPI/Patches/DialogueErrorPatch.cs index 7d57464c..f1c25c05 100644 --- a/src/SMAPI/Patches/DialogueErrorPatch.cs +++ b/src/SMAPI/Patches/DialogueErrorPatch.cs @@ -21,6 +21,9 @@ namespace StardewModdingAPI.Patches /// Simplifies access to private code. private static Reflector Reflection; + /// Whether the getter is currently being intercepted. + private static bool IsInterceptingCurrentDialogue; + /********* ** Accessors @@ -48,7 +51,11 @@ namespace StardewModdingAPI.Patches { harmony.Patch( original: AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) }), - prefix: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Prefix)) + prefix: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Before_Dialogue_Constructor)) + ); + harmony.Patch( + original: AccessTools.Property(typeof(NPC), nameof(NPC.CurrentDialogue)).GetMethod, + prefix: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Before_NPC_CurrentDialogue)) ); } @@ -63,7 +70,7 @@ namespace StardewModdingAPI.Patches /// Returns whether to execute the original method. /// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments. [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")] - private static bool Prefix(Dialogue __instance, string masterDialogue, NPC speaker) + private static bool Before_Dialogue_Constructor(Dialogue __instance, string masterDialogue, NPC speaker) { // get private members bool nameArraysTranslated = DialogueErrorPatch.Reflection.GetField(typeof(Dialogue), "nameArraysTranslated").GetValue(); @@ -96,5 +103,35 @@ namespace StardewModdingAPI.Patches return false; } + + /// The method to call instead of . + /// The instance being patched. + /// The return value of the original method. + /// The method being wrapped. + /// Returns whether to execute the original method. + /// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments. + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")] + private static bool Before_NPC_CurrentDialogue(NPC __instance, ref Stack __result, MethodInfo __originalMethod) + { + if (DialogueErrorPatch.IsInterceptingCurrentDialogue) + return true; + + try + { + DialogueErrorPatch.IsInterceptingCurrentDialogue = true; + __result = (Stack)__originalMethod.Invoke(__instance, new object[0]); + return false; + } + catch (TargetInvocationException ex) + { + DialogueErrorPatch.MonitorForGame.Log($"Failed loading current dialogue for NPC {__instance.Name}:\n{ex.InnerException ?? ex}", LogLevel.Error); + __result = new Stack(); + return false; + } + finally + { + DialogueErrorPatch.IsInterceptingCurrentDialogue = false; + } + } } } diff --git a/src/SMAPI/Patches/EventErrorPatch.cs b/src/SMAPI/Patches/EventErrorPatch.cs index b0074356..cd530616 100644 --- a/src/SMAPI/Patches/EventErrorPatch.cs +++ b/src/SMAPI/Patches/EventErrorPatch.cs @@ -42,7 +42,7 @@ namespace StardewModdingAPI.Patches { harmony.Patch( original: AccessTools.Method(typeof(GameLocation), "checkEventPrecondition"), - prefix: new HarmonyMethod(this.GetType(), nameof(EventErrorPatch.Prefix)) + prefix: new HarmonyMethod(this.GetType(), nameof(EventErrorPatch.Before_GameLocation_CheckEventPrecondition)) ); } @@ -58,7 +58,7 @@ namespace StardewModdingAPI.Patches /// Returns whether to execute the original method. /// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments. [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")] - private static bool Prefix(GameLocation __instance, ref int __result, string precondition, MethodInfo __originalMethod) + private static bool Before_GameLocation_CheckEventPrecondition(GameLocation __instance, ref int __result, string precondition, MethodInfo __originalMethod) { if (EventErrorPatch.IsIntercepted) return true; diff --git a/src/SMAPI/Patches/LoadContextPatch.cs b/src/SMAPI/Patches/LoadContextPatch.cs index 43e09573..3f86c9a9 100644 --- a/src/SMAPI/Patches/LoadContextPatch.cs +++ b/src/SMAPI/Patches/LoadContextPatch.cs @@ -55,8 +55,8 @@ namespace StardewModdingAPI.Patches { harmony.Patch( original: AccessTools.Method(typeof(Game1), nameof(Game1.loadForNewGame)), - prefix: new HarmonyMethod(this.GetType(), nameof(LoadContextPatch.Prefix)), - postfix: new HarmonyMethod(this.GetType(), nameof(LoadContextPatch.Postfix)) + prefix: new HarmonyMethod(this.GetType(), nameof(LoadContextPatch.Before_Game1_LoadForNewGame)), + postfix: new HarmonyMethod(this.GetType(), nameof(LoadContextPatch.After_Game1_LoadForNewGame)) ); } @@ -67,7 +67,7 @@ namespace StardewModdingAPI.Patches /// The method to call instead of . /// Returns whether to execute the original method. /// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments. - private static bool Prefix() + private static bool Before_Game1_LoadForNewGame() { LoadContextPatch.IsCreating = Game1.activeClickableMenu is TitleMenu menu && LoadContextPatch.Reflection.GetField(menu, "transitioningCharacterCreationMenu").GetValue(); LoadContextPatch.TimesLocationsCleared = 0; @@ -83,7 +83,7 @@ namespace StardewModdingAPI.Patches /// The method to call instead after . /// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments. - private static void Postfix() + private static void After_Game1_LoadForNewGame() { if (LoadContextPatch.IsCreating) { diff --git a/src/SMAPI/Patches/ObjectErrorPatch.cs b/src/SMAPI/Patches/ObjectErrorPatch.cs index 0b17b101..5b918d39 100644 --- a/src/SMAPI/Patches/ObjectErrorPatch.cs +++ b/src/SMAPI/Patches/ObjectErrorPatch.cs @@ -27,13 +27,13 @@ namespace StardewModdingAPI.Patches // object.getDescription harmony.Patch( original: AccessTools.Method(typeof(SObject), nameof(SObject.getDescription)), - prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Object_GetDescription_Prefix)) + prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Before_Object_GetDescription)) ); // IClickableMenu.drawToolTip harmony.Patch( original: AccessTools.Method(typeof(IClickableMenu), nameof(IClickableMenu.drawToolTip)), - prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.IClickableMenu_DrawTooltip_Prefix)) + prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Before_IClickableMenu_DrawTooltip)) ); } @@ -47,7 +47,7 @@ namespace StardewModdingAPI.Patches /// Returns whether to execute the original method. /// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments. [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")] - private static bool Object_GetDescription_Prefix(SObject __instance, ref string __result) + private static bool Before_Object_GetDescription(SObject __instance, ref string __result) { // invalid bigcraftables crash instead of showing '???' like invalid non-bigcraftables if (!__instance.IsRecipe && __instance.bigCraftable.Value && !Game1.bigCraftablesInformation.ContainsKey(__instance.ParentSheetIndex)) @@ -65,7 +65,7 @@ namespace StardewModdingAPI.Patches /// Returns whether to execute the original method. /// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments. [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")] - private static bool IClickableMenu_DrawTooltip_Prefix(IClickableMenu __instance, Item hoveredItem) + private static bool Before_IClickableMenu_DrawTooltip(IClickableMenu __instance, Item hoveredItem) { // invalid edible item cause crash when drawing tooltips if (hoveredItem is SObject obj && obj.Edibility != -300 && !Game1.objectInformation.ContainsKey(obj.ParentSheetIndex)) -- cgit