From a9fcbc686d203b20f8e4b127e213b7028b3a9ae1 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 8 Sep 2021 19:01:40 -0400 Subject: fix error when loading corrupted translation files --- src/SMAPI/Framework/SCore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 5913430e..df6cd129 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -1891,9 +1891,9 @@ namespace StardewModdingAPI.Framework string locale = Path.GetFileNameWithoutExtension(file.Name.ToLower().Trim()); try { - if (!jsonHelper.ReadJsonFileIfExists(file.FullName, out IDictionary data)) + if (!jsonHelper.ReadJsonFileIfExists(file.FullName, out IDictionary data) || data == null) { - errors.Add($"{file.Name} file couldn't be read"); // should never happen, since we're iterating files that exist + errors.Add($"{file.Name} file couldn't be read"); // mainly happens when the file is corrupted or empty continue; } -- cgit From 54a7c1f9bde0f98d9f81aa9dcd7bd4c18e409877 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 18 Sep 2021 11:07:06 -0400 Subject: add more visible log output for players during early startup --- docs/release-notes.md | 1 + src/SMAPI/Framework/SCore.cs | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/docs/release-notes.md b/docs/release-notes.md index c51dec39..ab120994 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -3,6 +3,7 @@ # Release notes ## Upcoming release * For players: + * Added more progress updates in the log during startup. * Fixed crash loading mods with corrupted translation files. * For mod authors: diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index df6cd129..86b69239 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -289,7 +289,7 @@ namespace StardewModdingAPI.Framework this.UpdateWindowTitles(); // start game - this.Monitor.Log("Starting game...", LogLevel.Debug); + this.Monitor.Log("Waiting for game to launch...", LogLevel.Debug); try { this.IsGameRunning = true; @@ -377,7 +377,7 @@ namespace StardewModdingAPI.Framework // load mods { - this.Monitor.Log("Loading mod metadata..."); + this.Monitor.Log("Loading mod metadata...", LogLevel.Debug); ModResolver resolver = new ModResolver(); // log loose files @@ -1487,7 +1487,7 @@ namespace StardewModdingAPI.Framework /// Handles access to SMAPI's internal mod metadata list. private void LoadMods(IModMetadata[] mods, JsonHelper jsonHelper, ContentCoordinator contentCore, ModDatabase modDatabase) { - this.Monitor.Log("Loading mods..."); + this.Monitor.Log("Loading mods...", LogLevel.Debug); // load mods IList skippedMods = new List(); @@ -1523,6 +1523,7 @@ namespace StardewModdingAPI.Framework this.ReloadTranslations(loaded); // initialize loaded non-content-pack mods + this.Monitor.Log("Launching mods...", LogLevel.Debug); foreach (IModMetadata metadata in loadedMods) { // add interceptors @@ -1572,6 +1573,8 @@ namespace StardewModdingAPI.Framework // unlock mod integrations this.ModRegistry.AreAllModsInitialized = true; + + this.Monitor.Log("Mods loaded and ready!", LogLevel.Debug); } /// Raised after a mod adds or removes asset interceptors. -- cgit From 8a117744608dfff970855defbffb1f40466ab755 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 18 Sep 2021 11:48:20 -0400 Subject: add simpler error when an asset isn't found --- docs/release-notes.md | 1 + .../ContentManagers/GameContentManager.cs | 44 +++++++++++++--------- 2 files changed, 27 insertions(+), 18 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/docs/release-notes.md b/docs/release-notes.md index ab120994..f330c677 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -4,6 +4,7 @@ ## Upcoming release * For players: * Added more progress updates in the log during startup. + * Simplified common asset load error message. * Fixed crash loading mods with corrupted translation files. * For mod authors: diff --git a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs index 63cd1759..38bcf153 100644 --- a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Reflection; using Microsoft.Xna.Framework.Content; @@ -205,28 +206,35 @@ namespace StardewModdingAPI.Framework.ContentManagers /// Derived from . private T RawLoad(string assetName, LanguageCode language, bool useCache) { - // use cached key - if (language == this.Language && this.LocalizedAssetNames.TryGetValue(assetName, out string cachedKey)) - return base.RawLoad(cachedKey, useCache); - - // try translated key - if (language != LocalizedContentManager.LanguageCode.en) + try { - string translatedKey = $"{assetName}.{this.GetLocale(language)}"; - try - { - T obj = base.RawLoad(translatedKey, useCache); - this.LocalizedAssetNames[assetName] = translatedKey; - return obj; - } - catch (ContentLoadException) + // use cached key + if (language == this.Language && this.LocalizedAssetNames.TryGetValue(assetName, out string cachedKey)) + return base.RawLoad(cachedKey, useCache); + + // try translated key + if (language != LocalizedContentManager.LanguageCode.en) { - this.LocalizedAssetNames[assetName] = assetName; + string translatedKey = $"{assetName}.{this.GetLocale(language)}"; + try + { + T obj = base.RawLoad(translatedKey, useCache); + this.LocalizedAssetNames[assetName] = translatedKey; + return obj; + } + catch (ContentLoadException) + { + this.LocalizedAssetNames[assetName] = assetName; + } } - } - // try base asset - return base.RawLoad(assetName, useCache); + // try base asset + return base.RawLoad(assetName, useCache); + } + catch (ContentLoadException ex) when (ex.InnerException is FileNotFoundException innerEx && innerEx.InnerException == null) + { + throw new SContentLoadException($"Error loading \"{assetName}\": it isn't in the Content folder and no mod provided it."); + } } /// Parse an asset key that contains an explicit language into its asset name and language, if applicable. -- cgit From 6ac5ca090da088e96b0c6508866cebe7eedc439d Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 18 Sep 2021 12:43:31 -0400 Subject: simplify exception logs --- docs/release-notes.md | 3 +- src/SMAPI.Internal/ExceptionExtensions.cs | 48 ------------------ src/SMAPI.Internal/ExceptionHelper.cs | 76 +++++++++++++++++++++++++++++ src/SMAPI.Internal/SMAPI.Internal.projitems | 2 +- src/SMAPI/Framework/Logging/LogManager.cs | 4 ++ 5 files changed, 83 insertions(+), 50 deletions(-) delete mode 100644 src/SMAPI.Internal/ExceptionExtensions.cs create mode 100644 src/SMAPI.Internal/ExceptionHelper.cs (limited to 'src/SMAPI/Framework') diff --git a/docs/release-notes.md b/docs/release-notes.md index f330c677..f619623f 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -4,7 +4,8 @@ ## Upcoming release * For players: * Added more progress updates in the log during startup. - * Simplified common asset load error message. + * Simplified asset load error message. + * Simplified exception logs. * Fixed crash loading mods with corrupted translation files. * For mod authors: diff --git a/src/SMAPI.Internal/ExceptionExtensions.cs b/src/SMAPI.Internal/ExceptionExtensions.cs deleted file mode 100644 index d8189048..00000000 --- a/src/SMAPI.Internal/ExceptionExtensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Reflection; - -namespace StardewModdingAPI.Internal -{ - /// Provides extension methods for handling exceptions. - internal static class ExceptionExtensions - { - /********* - ** Public methods - *********/ - /// Get a string representation of an exception suitable for writing to the error log. - /// The error to summarize. - public static string GetLogSummary(this Exception exception) - { - try - { - switch (exception) - { - case TypeLoadException ex: - return $"Failed loading type '{ex.TypeName}': {exception}"; - - case ReflectionTypeLoadException ex: - string summary = ex.ToString(); - foreach (Exception childEx in ex.LoaderExceptions ?? new Exception[0]) - summary += $"\n\n{childEx?.GetLogSummary()}"; - return summary; - - default: - return exception?.ToString() ?? $"\n{Environment.StackTrace}"; - } - } - catch (Exception ex) - { - throw new InvalidOperationException($"Failed handling {exception?.GetType().FullName} (original message: {exception?.Message})", ex); - } - } - - /// Get the lowest exception in an exception stack. - /// The exception from which to search. - public static Exception GetInnermostException(this Exception exception) - { - while (exception.InnerException != null) - exception = exception.InnerException; - return exception; - } - } -} diff --git a/src/SMAPI.Internal/ExceptionHelper.cs b/src/SMAPI.Internal/ExceptionHelper.cs new file mode 100644 index 00000000..4bc55f95 --- /dev/null +++ b/src/SMAPI.Internal/ExceptionHelper.cs @@ -0,0 +1,76 @@ +using System; +using System.Reflection; +using System.Text.RegularExpressions; + +namespace StardewModdingAPI.Internal +{ + /// Provides extension methods for handling exceptions. + internal static class ExceptionHelper + { + /********* + ** Public methods + *********/ + /// Get a string representation of an exception suitable for writing to the error log. + /// The error to summarize. + public static string GetLogSummary(this Exception exception) + { + try + { + string message; + switch (exception) + { + case TypeLoadException ex: + message = $"Failed loading type '{ex.TypeName}': {exception}"; + break; + + case ReflectionTypeLoadException ex: + string summary = ex.ToString(); + foreach (Exception childEx in ex.LoaderExceptions ?? new Exception[0]) + summary += $"\n\n{childEx?.GetLogSummary()}"; + message = summary; + break; + + default: + message = exception?.ToString() ?? $"\n{Environment.StackTrace}"; + break; + } + + return ExceptionHelper.SimplifyExtensionMessage(message); + } + catch (Exception ex) + { + throw new InvalidOperationException($"Failed handling {exception?.GetType().FullName} (original message: {exception?.Message})", ex); + } + } + + /// Get the lowest exception in an exception stack. + /// The exception from which to search. + public static Exception GetInnermostException(this Exception exception) + { + while (exception.InnerException != null) + exception = exception.InnerException; + return exception; + } + + /// Simplify common patterns in exception log messages that don't convey useful info. + /// The log message to simplify. + public static string SimplifyExtensionMessage(string message) + { + // remove namespace for core exception types + message = Regex.Replace( + message, + @"(?:StardewModdingAPI\.Framework\.Exceptions|Microsoft\.Xna\.Framework|System|System\.IO)\.([a-zA-Z]+Exception):", + "$1:" + ); + + // remove unneeded root build paths for SMAPI and Stardew Valley + message = message + .Replace(@"C:\source\_Stardew\SMAPI\src\", "") + .Replace(@"C:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\", ""); + + // remove placeholder info in Linux/macOS stack traces + return message + .Replace(@":0", ""); + } + } +} diff --git a/src/SMAPI.Internal/SMAPI.Internal.projitems b/src/SMAPI.Internal/SMAPI.Internal.projitems index 0ee94a5b..41d356c0 100644 --- a/src/SMAPI.Internal/SMAPI.Internal.projitems +++ b/src/SMAPI.Internal/SMAPI.Internal.projitems @@ -14,6 +14,6 @@ - + \ No newline at end of file diff --git a/src/SMAPI/Framework/Logging/LogManager.cs b/src/SMAPI/Framework/Logging/LogManager.cs index 6fe44d98..f2876146 100644 --- a/src/SMAPI/Framework/Logging/LogManager.cs +++ b/src/SMAPI/Framework/Logging/LogManager.cs @@ -406,6 +406,10 @@ namespace StardewModdingAPI.Framework.Logging } } + // simplify exception messages + if (level == LogLevel.Error) + message = ExceptionHelper.SimplifyExtensionMessage(message); + // forward to monitor gameMonitor.Log(message, level); } -- cgit