fix command errors logged as SMAPI instead of the affected mod
This commit is contained in:
parent
91b3344fea
commit
c531acb659
|
@ -16,6 +16,7 @@
|
|||
* Fixed transparency issues on Linux/Mac for some mod images.
|
||||
* Fixed translation issues not shown as warnings.
|
||||
* Fixed dependencies not correctly enforced if the dependency is installed but failed to load.
|
||||
* Fixed some errors logged as SMAPI instead of the affected mod.
|
||||
* Updated compatibility list.
|
||||
|
||||
* For modders:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
|
||||
namespace StardewModdingAPI.Framework
|
||||
{
|
||||
|
@ -8,8 +8,8 @@ namespace StardewModdingAPI.Framework
|
|||
/*********
|
||||
** Accessor
|
||||
*********/
|
||||
/// <summary>The friendly name for the mod that registered the command.</summary>
|
||||
public string ModName { get; }
|
||||
/// <summary>The mod that registered the command (or <c>null</c> if registered by SMAPI).</summary>
|
||||
public IModMetadata Mod { get; }
|
||||
|
||||
/// <summary>The command name, which the user must type to trigger it.</summary>
|
||||
public string Name { get; }
|
||||
|
@ -25,13 +25,13 @@ namespace StardewModdingAPI.Framework
|
|||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="modName">The friendly name for the mod that registered the command.</param>
|
||||
/// <param name="mod">The mod that registered the command (or <c>null</c> if registered by SMAPI).</param>
|
||||
/// <param name="name">The command name, which the user must type to trigger it.</param>
|
||||
/// <param name="documentation">The human-readable documentation shown when the player runs the built-in 'help' command.</param>
|
||||
/// <param name="callback">The method to invoke when the command is triggered. This method is passed the command name and arguments submitted by the user.</param>
|
||||
public Command(string modName, string name, string documentation, Action<string, string[]> callback)
|
||||
public Command(IModMetadata mod, string name, string documentation, Action<string, string[]> callback)
|
||||
{
|
||||
this.ModName = modName;
|
||||
this.Mod = mod;
|
||||
this.Name = name;
|
||||
this.Documentation = documentation;
|
||||
this.Callback = callback;
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace StardewModdingAPI.Framework
|
|||
** Public methods
|
||||
*********/
|
||||
/// <summary>Add a console command.</summary>
|
||||
/// <param name="modName">The friendly mod name for this instance.</param>
|
||||
/// <param name="mod">The mod adding the command (or <c>null</c> for a SMAPI command).</param>
|
||||
/// <param name="name">The command name, which the user must type to trigger it.</param>
|
||||
/// <param name="documentation">The human-readable documentation shown when the player runs the built-in 'help' command.</param>
|
||||
/// <param name="callback">The method to invoke when the command is triggered. This method is passed the command name and arguments submitted by the user.</param>
|
||||
|
@ -27,7 +27,7 @@ namespace StardewModdingAPI.Framework
|
|||
/// <exception cref="ArgumentNullException">The <paramref name="name"/> or <paramref name="callback"/> is null or empty.</exception>
|
||||
/// <exception cref="FormatException">The <paramref name="name"/> is not a valid format.</exception>
|
||||
/// <exception cref="ArgumentException">There's already a command with that name.</exception>
|
||||
public void Add(string modName, string name, string documentation, Action<string, string[]> callback, bool allowNullCallback = false)
|
||||
public void Add(IModMetadata mod, string name, string documentation, Action<string, string[]> callback, bool allowNullCallback = false)
|
||||
{
|
||||
name = this.GetNormalisedName(name);
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace StardewModdingAPI.Framework
|
|||
throw new ArgumentException(nameof(callback), $"Can't register the '{name}' command because there's already a command with that name.");
|
||||
|
||||
// add command
|
||||
this.Commands.Add(name, new Command(modName, name, documentation, callback));
|
||||
this.Commands.Add(name, new Command(mod, name, documentation, callback));
|
||||
}
|
||||
|
||||
/// <summary>Get a command by its unique name.</summary>
|
||||
|
@ -65,19 +65,30 @@ namespace StardewModdingAPI.Framework
|
|||
.OrderBy(p => p.Name);
|
||||
}
|
||||
|
||||
/// <summary>Trigger a command.</summary>
|
||||
/// <param name="input">The raw command input.</param>
|
||||
/// <returns>Returns whether a matching command was triggered.</returns>
|
||||
public bool Trigger(string input)
|
||||
/// <summary>Try to parse a raw line of user input into an executable command.</summary>
|
||||
/// <param name="input">The raw user input.</param>
|
||||
/// <param name="name">The parsed command name.</param>
|
||||
/// <param name="args">The parsed command arguments.</param>
|
||||
/// <param name="command">The command which can handle the input.</param>
|
||||
/// <returns>Returns true if the input was successfully parsed and matched to a command; else false.</returns>
|
||||
public bool TryParse(string input, out string name, out string[] args, out Command command)
|
||||
{
|
||||
// ignore if blank
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
name = null;
|
||||
args = null;
|
||||
command = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
string[] args = this.ParseArgs(input);
|
||||
string name = args[0];
|
||||
// parse input
|
||||
args = this.ParseArgs(input);
|
||||
name = this.GetNormalisedName(args[0]);
|
||||
args = args.Skip(1).ToArray();
|
||||
|
||||
return this.Trigger(name, args);
|
||||
// get command
|
||||
return this.Commands.TryGetValue(name, out command);
|
||||
}
|
||||
|
||||
/// <summary>Trigger a command.</summary>
|
||||
|
|
|
@ -8,8 +8,8 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>The friendly mod name for this instance.</summary>
|
||||
private readonly string ModName;
|
||||
/// <summary>The mod using this instance.</summary>
|
||||
private readonly IModMetadata Mod;
|
||||
|
||||
/// <summary>Manages console commands.</summary>
|
||||
private readonly CommandManager CommandManager;
|
||||
|
@ -19,13 +19,12 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="modID">The unique ID of the relevant mod.</param>
|
||||
/// <param name="modName">The friendly mod name for this instance.</param>
|
||||
/// <param name="mod">The mod using this instance.</param>
|
||||
/// <param name="commandManager">Manages console commands.</param>
|
||||
public CommandHelper(string modID, string modName, CommandManager commandManager)
|
||||
: base(modID)
|
||||
public CommandHelper(IModMetadata mod, CommandManager commandManager)
|
||||
: base(mod?.Manifest?.UniqueID ?? "SMAPI")
|
||||
{
|
||||
this.ModName = modName;
|
||||
this.Mod = mod;
|
||||
this.CommandManager = commandManager;
|
||||
}
|
||||
|
||||
|
@ -38,7 +37,7 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
|||
/// <exception cref="ArgumentException">There's already a command with that name.</exception>
|
||||
public ICommandHelper Add(string name, string documentation, Action<string, string[]> callback)
|
||||
{
|
||||
this.CommandManager.Add(this.ModName, name, documentation, callback);
|
||||
this.CommandManager.Add(this.Mod, name, documentation, callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -427,8 +427,8 @@ namespace StardewModdingAPI.Framework
|
|||
{
|
||||
// prepare console
|
||||
this.Monitor.Log("Type 'help' for help, or 'help <cmd>' for a command's usage", LogLevel.Info);
|
||||
this.GameInstance.CommandManager.Add("SMAPI", "help", "Lists command documentation.\n\nUsage: help\nLists all available commands.\n\nUsage: help <cmd>\n- cmd: The name of a command whose documentation to display.", this.HandleCommand);
|
||||
this.GameInstance.CommandManager.Add("SMAPI", "reload_i18n", "Reloads translation files for all mods.\n\nUsage: reload_i18n", this.HandleCommand);
|
||||
this.GameInstance.CommandManager.Add(null, "help", "Lists command documentation.\n\nUsage: help\nLists all available commands.\n\nUsage: help <cmd>\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);
|
||||
|
||||
// start handling command line input
|
||||
Thread inputThread = new Thread(() =>
|
||||
|
@ -973,7 +973,7 @@ namespace StardewModdingAPI.Framework
|
|||
IModHelper modHelper;
|
||||
{
|
||||
IModEvents events = new ModEvents(mod, this.EventManager);
|
||||
ICommandHelper commandHelper = new CommandHelper(manifest.UniqueID, mod.DisplayName, this.GameInstance.CommandManager);
|
||||
ICommandHelper commandHelper = new CommandHelper(mod, this.GameInstance.CommandManager);
|
||||
IContentHelper contentHelper = new ContentHelper(contentCore, mod.DirectoryPath, manifest.UniqueID, mod.DisplayName, monitor);
|
||||
IDataHelper dataHelper = new DataHelper(manifest.UniqueID, mod.DirectoryPath, jsonHelper);
|
||||
IReflectionHelper reflectionHelper = new ReflectionHelper(manifest.UniqueID, mod.DisplayName, this.Reflection, this.DeprecationManager);
|
||||
|
@ -1216,15 +1216,15 @@ namespace StardewModdingAPI.Framework
|
|||
if (result == null)
|
||||
this.Monitor.Log("There's no command with that name.", LogLevel.Error);
|
||||
else
|
||||
this.Monitor.Log($"{result.Name}: {result.Documentation}\n(Added by {result.ModName}.)", LogLevel.Info);
|
||||
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<string, string>[] groups = (from command in this.GameInstance.CommandManager.GetAll() orderby command.ModName, command.Name group command.Name by command.ModName).ToArray();
|
||||
IGrouping<string, string>[] 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;
|
||||
string modName = group.Key ?? "SMAPI";
|
||||
string[] commandNames = group.ToArray();
|
||||
message += $"{modName}:\n {string.Join("\n ", commandNames)}\n\n";
|
||||
}
|
||||
|
|
|
@ -268,14 +268,32 @@ namespace StardewModdingAPI.Framework
|
|||
*********/
|
||||
while (this.CommandQueue.TryDequeue(out string rawInput))
|
||||
{
|
||||
// parse command
|
||||
string name;
|
||||
string[] args;
|
||||
Command command;
|
||||
try
|
||||
{
|
||||
if (!this.CommandManager.Trigger(rawInput))
|
||||
if (!this.CommandManager.TryParse(rawInput, out name, out args, out command))
|
||||
this.Monitor.Log("Unknown command; type 'help' for a list of available commands.", LogLevel.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Monitor.Log($"The handler registered for that command failed:\n{ex.GetLogSummary()}", LogLevel.Error);
|
||||
this.Monitor.Log($"Failed parsing that command:\n{ex.GetLogSummary()}", LogLevel.Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
// execute command
|
||||
try
|
||||
{
|
||||
command.Callback.Invoke(name, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (command.Mod != null)
|
||||
command.Mod.LogAsMod($"Mod failed handling that command:\n{ex.GetLogSummary()}", LogLevel.Error);
|
||||
else
|
||||
this.Monitor.Log($"Failed handling that command:\n{ex.GetLogSummary()}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue