using System; using Svelto.ECS; using GamecraftModdingAPI.Utility; namespace GamecraftModdingAPI.Commands { /// <summary> /// Custom Command builder. /// </summary> public class CommandBuilder { private string name; private string description; private short parameterCount; private ICustomCommandEngine commandEngine; private bool fromExisting = false; /// <summary> /// Create a new command builder. /// </summary> public CommandBuilder() { name = ""; description = null; parameterCount = -1; } /// <summary> /// Create and return a command builder. /// </summary> /// <returns>The builder.</returns> public static CommandBuilder Builder() { return new CommandBuilder(); } /// <summary> /// Create a new command builder. /// </summary> /// <param name="name">The command name.</param> /// <param name="description">The command description (shown in help).</param> public CommandBuilder(string name, string description = null) { this.name = name; this.description = description; parameterCount = -1; } /// <summary> /// Create and return a command builder. /// If name and description are provided, this is equivalent to <code>Builder().Name(name).Description(description)</code> /// </summary> /// <param name="name">The command name.</param> /// <param name="description">The command description (shown in help).</param> /// <returns>The builder.</returns> public static CommandBuilder Builder(string name, string description = null) { return new CommandBuilder(name, description); } /// <summary> /// Name the command. /// </summary> /// <returns>The builder.</returns> /// <param name="name">The command name.</param> public CommandBuilder Name(string name) { this.name = name; return this; } /// <summary> /// Describe the command. /// </summary> /// <returns>The builder.</returns> /// <param name="description">The command description (shown in help).</param> public CommandBuilder Description(string description) { this.description = description; return this; } /// <summary> /// Set the action the command performs. /// </summary> /// <returns>The builder.</returns> /// <param name="action">The action to perform when the command is called.</param> public CommandBuilder Action(Action action) { parameterCount = 0; commandEngine = new SimpleCustomCommandEngine(action, name, description); return this; } /// <summary> /// Set the action the command performs. /// </summary> /// <returns>The builder.</returns> /// <param name="action">The action to perform when the command is called.</param> /// <typeparam name="A">The 1st parameter's type.</typeparam> public CommandBuilder Action<A>(Action<A> action) { parameterCount = 1; commandEngine = new SimpleCustomCommandEngine<A>(action, name, description); return this; } /// <summary> /// Set the action the command performs. /// </summary> /// <returns>The builder.</returns> /// <param name="action">The action to perform when the command is called.</param> /// <typeparam name="A">The 1st parameter's type.</typeparam> /// <typeparam name="B">The 2nd parameter's type.</typeparam> public CommandBuilder Action<A,B>(Action<A,B> action) { parameterCount = 2; commandEngine = new SimpleCustomCommandEngine<A,B>(action, name, description); return this; } /// <summary> /// Set the action the command performs. /// </summary> /// <returns>The builder.</returns> /// <param name="action">The action to perform when the command is called.</param> /// <typeparam name="A">The 1st parameter's type.</typeparam> /// <typeparam name="B">The 2nd parameter's type.</typeparam> /// <typeparam name="C">The 3rd parameter's type.</typeparam> public CommandBuilder Action<A,B,C>(Action<A,B,C> action) { parameterCount = 3; commandEngine = new SimpleCustomCommandEngine<A,B,C>(action, name, description); return this; } /// <summary> /// Build the command from an existing command. /// </summary> /// <returns>The command. Use Invoke() to execute it.</returns> public SimpleCustomCommandEngine FromExisting() { if (string.IsNullOrWhiteSpace(name)) { throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called"); } if (!ExistingCommands.Exists(name)) { throw new CommandNotFoundException("Command cannot be built from existing because it does not exist."); } fromExisting = true; return new SimpleCustomCommandEngine( () => { ExistingCommands.Call(name); }, name, description); } /// <summary> /// Build the command from an existing command. /// </summary> /// <returns>The command. Use Invoke() to execute it.</returns> /// <typeparam name="A">The 1st parameter's type.</typeparam> public SimpleCustomCommandEngine<A> FromExisting<A>() { if (string.IsNullOrWhiteSpace(name)) { throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called"); } if (!ExistingCommands.Exists(name)) { throw new CommandNotFoundException("Command cannot be built from existing because it does not exist."); } fromExisting = true; return new SimpleCustomCommandEngine<A>( (A a) => { ExistingCommands.Call<A>(name, a); }, name, description); } /// <summary> /// Build the command from an existing command. /// </summary> /// <returns>The command. Use Invoke() to execute it.</returns> /// <typeparam name="A">The 1st parameter's type.</typeparam> /// <typeparam name="B">The 2nd parameter's type.</typeparam> public SimpleCustomCommandEngine<A,B> FromExisting<A,B>() { if (string.IsNullOrWhiteSpace(name)) { throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called"); } if (!ExistingCommands.Exists(name)) { throw new CommandNotFoundException("Command cannot be built from existing because it does not exist."); } fromExisting = true; return new SimpleCustomCommandEngine<A,B>( (A a, B b) => { ExistingCommands.Call<A,B>(name, a, b); }, name, description); } /// <summary> /// Build the command from an existing command. /// </summary> /// <returns>The command. Use Invoke() to execute it.</returns> /// <typeparam name="A">The 1st parameter's type.</typeparam> /// <typeparam name="B">The 2nd parameter's type.</typeparam> /// <typeparam name="C">The 3rd parameter's type.</typeparam> public SimpleCustomCommandEngine<A,B,C> FromExisting<A,B,C>() { if (string.IsNullOrWhiteSpace(name)) { throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called"); } if (!ExistingCommands.Exists(name)) { throw new CommandNotFoundException("Command cannot be built from existing because it does not exist."); } fromExisting = true; return new SimpleCustomCommandEngine<A,B,C>( (A a, B b, C c) => { ExistingCommands.Call<A,B,C>(name, a, b, c); }, name, description); } /// <summary> /// Build the command. /// </summary> /// <returns>The built command.</returns> /// <param name="register">Automatically register the command with CommandManager.AddCommand()?</param> public ICustomCommandEngine Build(bool register = true) { if (string.IsNullOrWhiteSpace(name)) { throw new CommandParameterMissingException("Command name must be defined before Build() is called"); } if (fromExisting) { throw new CommandAlreadyBuiltException("Command was already built by FromExisting()"); } if (commandEngine == null) { throw new CommandParameterMissingException("Command action must be defined before Build() is called"); } if (string.IsNullOrWhiteSpace(description)) { Logging.LogWarning($"Command {FullName()} was built without a description"); } if (register) { CommandManager.AddCommand(commandEngine); Logging.MetaDebugLog($"Command {FullName()} was automatically registered"); } return commandEngine; } /// <summary> /// Get the full command name, in the form [name]::[description]::[# of parameters] /// </summary> /// <returns>The name.</returns> public string FullName() { if (string.IsNullOrWhiteSpace(description)) { return name + "::" + parameterCount; } return name + "::" + description + "::" + parameterCount; } } }