using System; using System.Collections.Generic; using System.Linq; using StardewModdingAPI.Events; using StardewModdingAPI.Framework; namespace StardewModdingAPI { /// A command that can be submitted through the SMAPI console to interact with SMAPI. public class Command { /********* ** Properties *********/ /**** ** SMAPI ****/ /// The commands registered with SMAPI. internal static List RegisteredCommands = new List(); /// The event raised when this command is submitted through the console. public event EventHandler CommandFired; /**** ** Command ****/ /// The name of the command. public string CommandName; /// A human-readable description of what the command does. public string CommandDesc; /// A human-readable list of accepted arguments. public string[] CommandArgs; /// The actual submitted argument values. public string[] CalledArgs; /********* ** Public methods *********/ /**** ** Command ****/ /// Construct an instance. /// The name of the command. /// A human-readable description of what the command does. /// A human-readable list of accepted arguments. public Command(string name, string description, string[] args = null) { this.CommandName = name; this.CommandDesc = description; if (args == null) args = new string[0]; this.CommandArgs = args; } /// Trigger this command. public void Fire() { if (this.CommandFired == null) throw new InvalidOperationException($"Can't run command '{this.CommandName}' because it has no registered handler."); this.CommandFired.Invoke(this, new EventArgsCommand(this)); } /**** ** SMAPI ****/ /// Parse a command string and invoke it if valid. /// The command to run, including the command name and any arguments. [Obsolete("Use the overload which passes in your mod's monitor")] public static void CallCommand(string input) { Program.DeprecationManager.Warn($"an old version of {nameof(Command)}.{nameof(Command.CallCommand)}", "1.1", DeprecationLevel.Notice); Command.CallCommand(input, Program.GetLegacyMonitorForMod()); } /// Parse a command string and invoke it if valid. /// The command to run, including the command name and any arguments. /// Encapsulates monitoring and logging. public static void CallCommand(string input, IMonitor monitor) { // normalise input input = input?.Trim(); if (string.IsNullOrWhiteSpace(input)) return; // tokenise input string[] args = input.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string commandName = args[0]; args = args.Skip(1).ToArray(); // get command Command command = Command.FindCommand(commandName); if (command == null) { monitor.Log("Unknown command", LogLevel.Error); return; } // fire command command.CalledArgs = args; command.Fire(); } /// Register a command with SMAPI. /// The name of the command. /// A human-readable description of what the command does. /// A human-readable list of accepted arguments. public static Command RegisterCommand(string name, string description, string[] args = null) { var command = new Command(name, description, args); if (Command.RegisteredCommands.Contains(command)) throw new InvalidOperationException($"The '{command.CommandName}' command is already registered!"); Command.RegisteredCommands.Add(command); return command; } /// Find a command with the given name. /// The command name to find. public static Command FindCommand(string name) { return Command.RegisteredCommands.Find(x => x.CommandName.Equals(name)); } } }