Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orion Framework: Command service #32

Closed
tylerjwatson opened this issue Aug 13, 2016 · 2 comments
Closed

Orion Framework: Command service #32

tylerjwatson opened this issue Aug 13, 2016 · 2 comments
Assignees

Comments

@tylerjwatson
Copy link
Member

tylerjwatson commented Aug 13, 2016

implement a command service which handles commands with parameters that are either invoked by players, the console, or any UI frontend running in Orion.

The basic spec is as follows:

  1. Design an ICommandStreamService (shared) whose job it is to keep the list of commands, and facilitate the insertion of command handlers at any place in the handler stack, handle the deserialisation of command parameters, and invoke each handler in the list
  2. Design an ICommandService whose job it is to yield commands from their method (up to the implementation), and yield the delegates to to the ICommandStreamService

A command service implementation idea is listed below:

  • AttributeCommandService: Yields command from attributes placed on instance methods:

    [Command("/invsee {player} {-restore:flag}")]
    public CommandResult InvseeCommand(IPlayer player, bool? restore = null)
    {
    }

ObjectStream output

Commands must not write to Console or Player, instead must write to an object stream passed to the command in its parameters. This is to ensure that objects written as output from the commands are always formatted in a consistent manner.

A command may choose to output any object to the output stream, and they are formatted according to the rules of the UI environment which invokes the command. A command may output more than one object to the output stream, which may include one or more exceptions.

For example, a plugin may output an IEnumerable<>, which will format as a text table in the console, comma-separated list in the game itself, a HTML table in the web UI, or a JSON array as a REST call. An exception written to the object stream may format as red text in the console, or a callout in HTML, etc.

Any .NET type may be written to the object stream, however complex types will be coalesced to string before output; implement .ToString() if you want to summarize a human-friendly representation of a custom object.

@tylerjwatson tylerjwatson added this to the Orion 1.0 Milestone 1 milestone Aug 13, 2016
@tylerjwatson tylerjwatson self-assigned this Aug 13, 2016
@QuiCM
Copy link
Member

QuiCM commented Sep 3, 2016

I've implemented a class-based command system in another project. An example command is as follows:

public class TestCommand : ICommand
{
    public IEnumerable<string> Aliases => new[] { "t2" };

    public string Description => "A test command.";

    public bool Hidden => false;

    public string Name => "test2";

    public IEnumerable<Parameter> Parameters => new[]
    {
        new Parameter("RequiredMultiple", ParameterType.MultiRequired, typeof(int[]), 4),
        new Parameter("Optional", ParameterType.Optional, typeof(string))
    };

    public Response Execute(CommandContext context)
    {
        Console.WriteLine("TEST COMMAND DEFAULT FALLBACK");
        return new Response("TEST COMMAND DEFAULT FALLBACK");
    }

    public Response Execute(CommandContext context, int[] required, string optional = null)
    {
        Console.WriteLine("TEST COMMAND REAL CALLBACK");
        Console.WriteLine($"{string.Join(" ", required)} {optional ?? "null"}");
        return new Response("TEST COMMAND REAL CALLBACK");
    }
}

ICommand requires one Execute(CommandContext context) method to be present. Further execute methods must be manually added to match the parameter types specified in the command's Parameters enumerable.
When the command is run, the handler converts the provided string arguments into the required types for the command.
Eg test 1 2 3 4 test1 would output '1 2 3 4 test1' to the console.
test 1 2 3 4 would output '1 2 3 4 null' to the console.
test a 1 b 2 test would cause an error.

@kevzhao2
Copy link
Member

kevzhao2 commented Jun 1, 2020

Closing this -- we will revisit this in TShock.

@kevzhao2 kevzhao2 closed this as completed Jun 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants