From d8d8cac2d89c27c6d28be444cebaabf0e2077a53 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 9 May 2020 10:43:05 -0400 Subject: simplify logged paranoid warnings --- src/SMAPI/Framework/SCore.cs | 133 ++++++++++++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 41 deletions(-) (limited to 'src/SMAPI/Framework/SCore.cs') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index de9c955d..8c9424c1 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -1129,67 +1129,118 @@ namespace StardewModdingAPI.Framework // log warnings if (modsWithWarnings.Any()) { - // issue block format logic - void LogWarningGroup(ModWarning warning, LogLevel logLevel, string heading, params string[] blurb) - { - IModMetadata[] matches = modsWithWarnings - .Where(mod => mod.HasUnsuppressWarning(warning)) - .ToArray(); - if (!matches.Any()) - return; - - this.Monitor.Log(" " + heading, logLevel); - this.Monitor.Log(" " + "".PadRight(50, '-'), logLevel); - foreach (string line in blurb) - this.Monitor.Log(" " + line, logLevel); - this.Monitor.Newline(); - foreach (IModMetadata match in matches) - this.Monitor.Log($" - {match.DisplayName}", logLevel); - this.Monitor.Newline(); - } - - // supported issues - LogWarningGroup(ModWarning.BrokenCodeLoaded, LogLevel.Error, "Broken mods", + // broken code + this.LogModWarningGroup(modsWithWarnings, ModWarning.BrokenCodeLoaded, LogLevel.Error, "Broken mods", "These mods have broken code, but you configured SMAPI to load them anyway. This may cause bugs,", "errors, or crashes in-game." ); - LogWarningGroup(ModWarning.ChangesSaveSerializer, LogLevel.Warn, "Changed save serializer", + + // changes serializer + this.LogModWarningGroup(modsWithWarnings, ModWarning.ChangesSaveSerializer, LogLevel.Warn, "Changed save serializer", "These mods change the save serializer. They may corrupt your save files, or make them unusable if", "you uninstall these mods." ); - if (this.Settings.ParanoidWarnings) - { - LogWarningGroup(ModWarning.AccessesConsole, LogLevel.Warn, "Accesses the console directly", - "These mods directly access the SMAPI console, and you enabled paranoid warnings. (Note that this may be", - "legitimate and innocent usage; this warning is meaningless without further investigation.)" - ); - LogWarningGroup(ModWarning.AccessesFilesystem, LogLevel.Warn, "Accesses filesystem directly", - "These mods directly access the filesystem, and you enabled paranoid warnings. (Note that this may be", - "legitimate and innocent usage; this warning is meaningless without further investigation.)" - ); - LogWarningGroup(ModWarning.AccessesShell, LogLevel.Warn, "Accesses shell/process directly", - "These mods directly access the OS shell or processes, and you enabled paranoid warnings. (Note that", - "this may be legitimate and innocent usage; this warning is meaningless without further investigation.)" - ); - } - LogWarningGroup(ModWarning.PatchesGame, LogLevel.Info, "Patched game code", + + // patched game code + this.LogModWarningGroup(modsWithWarnings, ModWarning.PatchesGame, LogLevel.Info, "Patched game code", "These mods directly change the game code. They're more likely to cause errors or bugs in-game; if", "your game has issues, try removing these first. Otherwise you can ignore this warning." ); - LogWarningGroup(ModWarning.UsesUnvalidatedUpdateTick, LogLevel.Info, "Bypassed safety checks", + + // unvalidated update tick + this.LogModWarningGroup(modsWithWarnings, ModWarning.UsesUnvalidatedUpdateTick, LogLevel.Info, "Bypassed safety checks", "These mods bypass SMAPI's normal safety checks, so they're more likely to cause errors or save", "corruption. If your game has issues, try removing these first." ); - LogWarningGroup(ModWarning.NoUpdateKeys, LogLevel.Debug, "No update keys", + + // paranoid warnings + if (this.Settings.ParanoidWarnings) + { + this.LogModWarningGroup( + modsWithWarnings, + match: mod => mod.HasUnsuppressedWarnings(ModWarning.AccessesConsole, ModWarning.AccessesFilesystem, ModWarning.AccessesShell), + level: LogLevel.Debug, + heading: "Direct system access", + blurb: new[] + { + "You enabled paranoid warnings and these mods directly access the filesystem, shells/processes, or", + "SMAPI console. (This is usually legitimate and innocent usage; this warning is only useful for", + "further investigation.)" + }, + modLabel: mod => + { + List labels = new List(); + if (mod.HasUnsuppressedWarnings(ModWarning.AccessesConsole)) + labels.Add("console"); + if (mod.HasUnsuppressedWarnings(ModWarning.AccessesFilesystem)) + labels.Add("files"); + if (mod.HasUnsuppressedWarnings(ModWarning.AccessesShell)) + labels.Add("shells/processes"); + + return $"{mod.DisplayName} ({string.Join(", ", labels)})"; + } + ); + } + + // no update keys + this.LogModWarningGroup(modsWithWarnings, ModWarning.NoUpdateKeys, LogLevel.Debug, "No update keys", "These mods have no update keys in their manifest. SMAPI may not notify you about updates for these", "mods. Consider notifying the mod authors about this problem." ); - LogWarningGroup(ModWarning.UsesDynamic, LogLevel.Debug, "Not crossplatform", + + // not crossplatform + this.LogModWarningGroup(modsWithWarnings, ModWarning.UsesDynamic, LogLevel.Debug, "Not crossplatform", "These mods use the 'dynamic' keyword, and won't work on Linux/Mac." ); } } + /// Write a mod warning group to the console and log. + /// The mods to search. + /// Matches mods to include in the warning group. + /// The log level for the logged messages. + /// A brief heading label for the group. + /// A detailed explanation of the warning, split into lines. + /// Formats the mod label, or null to use the . + private void LogModWarningGroup(IModMetadata[] mods, Func match, LogLevel level, string heading, string[] blurb, Func modLabel = null) + { + // get matching mods + IModMetadata[] matches = mods + .Where(match) + .ToArray(); + if (!matches.Any()) + return; + + // log header/blurb + this.Monitor.Log(" " + heading, level); + this.Monitor.Log(" " + "".PadRight(50, '-'), level); + foreach (string line in blurb) + this.Monitor.Log(" " + line, level); + this.Monitor.Newline(); + + // log mod list + foreach (IModMetadata modMatch in matches) + { + string label = modLabel != null + ? modLabel(modMatch) + : modMatch.DisplayName; + this.Monitor.Log($" - {label}", level); + } + + this.Monitor.Newline(); + } + + /// Write a mod warning group to the console and log. + /// The mods to search. + /// The mod warning to match. + /// The log level for the logged messages. + /// A brief heading label for the group. + /// A detailed explanation of the warning, split into lines. + void LogModWarningGroup(IModMetadata[] mods, ModWarning warning, LogLevel level, string heading, params string[] blurb) + { + this.LogModWarningGroup(mods, mod => mod.HasUnsuppressedWarnings(warning), level, heading, blurb); + } + /// Load a mod's entry class. /// The mod assembly. /// The loaded instance. -- cgit From 719831c15a74a4987496dc77a3caa6999940bf90 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 9 May 2020 10:58:10 -0400 Subject: sort mod warning lists --- src/SMAPI/Framework/SCore.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src/SMAPI/Framework/SCore.cs') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 8c9424c1..cd292bfc 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -1205,10 +1205,12 @@ namespace StardewModdingAPI.Framework private void LogModWarningGroup(IModMetadata[] mods, Func match, LogLevel level, string heading, string[] blurb, Func modLabel = null) { // get matching mods - IModMetadata[] matches = mods + string[] modLabels = mods .Where(match) + .Select(mod => modLabel?.Invoke(mod) ?? mod.DisplayName) + .OrderBy(p => p) .ToArray(); - if (!matches.Any()) + if (!modLabels.Any()) return; // log header/blurb @@ -1219,13 +1221,8 @@ namespace StardewModdingAPI.Framework this.Monitor.Newline(); // log mod list - foreach (IModMetadata modMatch in matches) - { - string label = modLabel != null - ? modLabel(modMatch) - : modMatch.DisplayName; + foreach (string label in modLabels) this.Monitor.Log($" - {label}", level); - } this.Monitor.Newline(); } -- cgit From 163eebd92e21075698986a843850f0850514e778 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 22 May 2020 19:57:22 -0400 Subject: move internal commands out of SCore --- src/SMAPI/Framework/SCore.cs | 54 ++++++++------------------------------------ 1 file changed, 10 insertions(+), 44 deletions(-) (limited to 'src/SMAPI/Framework/SCore.cs') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index cd292bfc..a89616a3 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -16,6 +16,7 @@ using System.Windows.Forms; #endif using Newtonsoft.Json; using StardewModdingAPI.Events; +using StardewModdingAPI.Framework.Commands; using StardewModdingAPI.Framework.Events; using StardewModdingAPI.Framework.Exceptions; using StardewModdingAPI.Framework.Logging; @@ -508,8 +509,9 @@ namespace StardewModdingAPI.Framework { // prepare console this.Monitor.Log("Type 'help' for help, or 'help ' for a command's usage", LogLevel.Info); - this.GameInstance.CommandManager.Add(null, "help", "Lists command documentation.\n\nUsage: help\nLists all available commands.\n\nUsage: help \n- cmd: The name of a command whose documentation to display.", this.HandleCommand); - this.GameInstance.CommandManager.Add(null, "reload_i18n", "Reloads translation files for all mods.\n\nUsage: reload_i18n", this.HandleCommand); + this.GameInstance.CommandManager + .Add(new HelpCommand(this.GameInstance.CommandManager), this.Monitor) + .Add(new ReloadI18nCommand(this.ReloadTranslations), this.Monitor); // start handling command line input Thread inputThread = new Thread(() => @@ -1273,6 +1275,12 @@ namespace StardewModdingAPI.Framework } /// Reload translations for all mods. + private void ReloadTranslations() + { + this.ReloadTranslations(this.ModRegistry.GetAll(contentPacks: false)); + } + + /// Reload translations for the given mods. /// The mods for which to reload translations. private void ReloadTranslations(IEnumerable mods) { @@ -1357,48 +1365,6 @@ namespace StardewModdingAPI.Framework return translations; } - /// The method called when the user submits a core SMAPI command in the console. - /// The command name. - /// The command arguments. - private void HandleCommand(string name, string[] arguments) - { - switch (name) - { - case "help": - if (arguments.Any()) - { - Command result = this.GameInstance.CommandManager.Get(arguments[0]); - if (result == null) - this.Monitor.Log("There's no command with that name.", LogLevel.Error); - else - this.Monitor.Log($"{result.Name}: {result.Documentation}{(result.Mod != null ? $"\n(Added by {result.Mod.DisplayName}.)" : "")}", LogLevel.Info); - } - else - { - string message = "The following commands are registered:\n"; - IGrouping[] groups = (from command in this.GameInstance.CommandManager.GetAll() orderby command.Mod?.DisplayName, command.Name group command.Name by command.Mod?.DisplayName).ToArray(); - foreach (var group in groups) - { - string modName = group.Key ?? "SMAPI"; - string[] commandNames = group.ToArray(); - message += $"{modName}:\n {string.Join("\n ", commandNames)}\n\n"; - } - message += "For more information about a command, type 'help command_name'."; - - this.Monitor.Log(message, LogLevel.Info); - } - break; - - case "reload_i18n": - this.ReloadTranslations(this.ModRegistry.GetAll(contentPacks: false)); - this.Monitor.Log("Reloaded translation files for all mods. This only affects new translations the mods fetch; if they cached some text, it may not be updated.", LogLevel.Info); - break; - - default: - throw new NotSupportedException($"Unrecognized core SMAPI command '{name}'."); - } - } - /// Redirect messages logged directly to the console to the given monitor. /// The monitor with which to log messages as the game. /// The message to log. -- cgit From b074eb279a649030e71ed2192bb6a528a9801fce Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 22 May 2020 20:00:33 -0400 Subject: add harmony_summary command --- src/SMAPI/Framework/SCore.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/SMAPI/Framework/SCore.cs') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index a89616a3..9d96bad1 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -511,6 +511,7 @@ namespace StardewModdingAPI.Framework this.Monitor.Log("Type 'help' for help, or 'help ' for a command's usage", LogLevel.Info); this.GameInstance.CommandManager .Add(new HelpCommand(this.GameInstance.CommandManager), this.Monitor) + .Add(new HarmonySummaryCommand(), this.Monitor) .Add(new ReloadI18nCommand(this.ReloadTranslations), this.Monitor); // start handling command line input -- cgit From fc29fe918a89623544b011c76217aa1ea1975d00 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 15 Jun 2020 18:58:05 -0400 Subject: refactor & optimize event code a bit, drop old support for unknown event handlers --- src/SMAPI/Framework/SCore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/SCore.cs') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index de9c955d..c6e69d4e 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -172,7 +172,7 @@ namespace StardewModdingAPI.Framework this.MonitorForGame = this.GetSecondaryMonitor("game"); SCore.PerformanceMonitor = new PerformanceMonitor(this.Monitor); - this.EventManager = new EventManager(this.Monitor, this.ModRegistry, SCore.PerformanceMonitor); + this.EventManager = new EventManager(this.ModRegistry, SCore.PerformanceMonitor); SCore.PerformanceMonitor.InitializePerformanceCounterCollections(this.EventManager); SCore.DeprecationManager = new DeprecationManager(this.Monitor, this.ModRegistry); -- cgit From dcd2c647a2abd836e8ee20f8ddad6568c9b4fbf2 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 15 Jun 2020 22:17:32 -0400 Subject: temporarily restore Harmony 1.x support with compile flag (#711) --- src/SMAPI/Framework/SCore.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/SMAPI/Framework/SCore.cs') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 530b6754..1a2c97f4 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -511,7 +511,9 @@ namespace StardewModdingAPI.Framework this.Monitor.Log("Type 'help' for help, or 'help ' for a command's usage", LogLevel.Info); this.GameInstance.CommandManager .Add(new HelpCommand(this.GameInstance.CommandManager), this.Monitor) +#if HARMONY_2 .Add(new HarmonySummaryCommand(), this.Monitor) +#endif .Add(new ReloadI18nCommand(this.ReloadTranslations), this.Monitor); // start handling command line input -- cgit From f63f14c70369541311bb5034894409a5170d56e9 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 16 Jun 2020 18:53:29 -0400 Subject: fix typo --- src/SMAPI/Framework/SCore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/SCore.cs') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 1a2c97f4..2794002c 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -994,7 +994,7 @@ namespace StardewModdingAPI.Framework } catch (SAssemblyLoadFailedException ex) { - errorReasonPhrase = $"it DLL couldn't be loaded: {ex.Message}"; + errorReasonPhrase = $"its DLL couldn't be loaded: {ex.Message}"; return false; } catch (Exception ex) -- cgit From aeab19f4aca366be3446b9f1ee097d51d21b5fde Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 19 Jun 2020 21:28:44 -0400 Subject: backport harmony_summary command to Harmony 1.x (#711) --- src/SMAPI/Framework/SCore.cs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/SMAPI/Framework/SCore.cs') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 2794002c..e1db563c 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -511,9 +511,7 @@ namespace StardewModdingAPI.Framework this.Monitor.Log("Type 'help' for help, or 'help ' for a command's usage", LogLevel.Info); this.GameInstance.CommandManager .Add(new HelpCommand(this.GameInstance.CommandManager), this.Monitor) -#if HARMONY_2 .Add(new HarmonySummaryCommand(), this.Monitor) -#endif .Add(new ReloadI18nCommand(this.ReloadTranslations), this.Monitor); // start handling command line input -- cgit From 067163da02c5a5993d88d80f04d379c22bc32cba Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 20 Jun 2020 00:50:23 -0400 Subject: make parallel rewriting optional --- src/SMAPI/Framework/SCore.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/SCore.cs') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index e1db563c..90435f54 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -337,6 +337,8 @@ namespace StardewModdingAPI.Framework // add headers if (this.Settings.DeveloperMode) this.Monitor.Log($"You have SMAPI for developers, so the console will be much more verbose. You can disable developer mode by installing the non-developer version of SMAPI, or by editing {Constants.ApiConfigPath}.", LogLevel.Info); + if (this.Settings.RewriteInParallel) + this.Monitor.Log($"You enabled experimental parallel rewriting. This may result in faster startup times, but intermittent startup errors. You can disable it by reinstalling SMAPI or editing {Constants.ApiConfigPath}.", LogLevel.Info); if (!this.Settings.CheckForUpdates) this.Monitor.Log($"You configured SMAPI to not check for updates. Running an old version of SMAPI is not recommended. You can enable update checks by reinstalling SMAPI or editing {Constants.ApiConfigPath}.", LogLevel.Warn); if (!this.Monitor.WriteToConsole) @@ -981,7 +983,7 @@ namespace StardewModdingAPI.Framework Assembly modAssembly; try { - modAssembly = assemblyLoader.Load(mod, assemblyPath, assumeCompatible: mod.DataRecord?.Status == ModStatus.AssumeCompatible); + modAssembly = assemblyLoader.Load(mod, assemblyPath, assumeCompatible: mod.DataRecord?.Status == ModStatus.AssumeCompatible, rewriteInParallel: this.Settings.RewriteInParallel); this.ModRegistry.TrackAssemblies(mod, modAssembly); } catch (IncompatibleInstructionException) // details already in trace logs -- cgit From e9b8df46181bc9996cb2690acbb98971454b5b2a Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 20 Jun 2020 12:29:08 -0400 Subject: fix reload_i18n not reloading content pack translations --- src/SMAPI/Framework/SCore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/SCore.cs') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 90435f54..2b04b1dc 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -1280,7 +1280,7 @@ namespace StardewModdingAPI.Framework /// Reload translations for all mods. private void ReloadTranslations() { - this.ReloadTranslations(this.ModRegistry.GetAll(contentPacks: false)); + this.ReloadTranslations(this.ModRegistry.GetAll()); } /// Reload translations for the given mods. -- cgit