Command API

Totally agree with you @Ranzdo! It shouldn’t be the target of sponge to handle everything! Just a abstraction layer. Commands and even configs shouldn’t be a part of sponge. Probably a default recommendation for an implementation to use would be good, but there are too many individual developers out there to support everyone’s needs.

plugin.yml will not exists in Sponge:
https://github.com/SpongePowered/SpongeAPI/blob/master/src/main/example/main/java/org/spongepowered/example/ExamplePlugin.java

Read more here:

2 Likes

I hope not! With Bukkit I hate to predefine all commands, the most time it is a repetitive work.
And then you have to register them again in your plugin if you used CommandExecutor.

I would propose just to overwrite the old command and log a warning. Simple but effective.

I didn’t like plugin.yml and I am happy that this project will take another approach, but that approach needs to solve the same problems that the plugin.yml solved. The approach to override the command in a state of conflict and tell the user through the console does not supply also a solution to make the plugins stop conflicting.

One solution I can think of is to tell the user that two plugins use the same command when they try to use the command. Then they get asked to rename one of the plugins commands so they don’t conflict anymore. That way it will be clear to the Server Admin what is wrong and a easy solution to fix the problem.

Or if there is a conflict in commands, when you try to run the command the server will bring this to your attention
'There is a conflict with this command by the plugins [plugin1, plugin2… etc]
‘Please suffix your command with the plugin name’
‘E.g /plugin1:command’

Something along those lines maybe

2 Likes

I agree, there are too many individuals out there! (me too)
But if plugins import their own config parser library you have big plugin files, so a “default” config library would be nice.
This default would help the lazy developers or newcomers who just want to throw together a new plugin.
I would suggest for migration a yaml based default config library.


Not good. As I know my server owner, he executes commands on players in his plugins.
Maybe another solution would be to blacklist commands in the server config?

commands:
  blacklist:
    myPlugin: [send, test]

Back to the topic: Where will be the commands registered / replaced / removed?
@sk89q Would there be with Intake in Sponge one “master” dispatcher?
Or had you another design in mind?

I like the annotations more than the concept of passing a context object to methods.
Passing down a context object may risk the type safety.

I like the idea of annotations, just not how it’s implemented here.

It was already decided to use HOCON as a config format, since it’s much more forgiving than YAML. It also has a few nifty features.

I think you meant HOCON :slight_smile:

It is implemented already though. I would like it to be a complete command API on the first run, because else a plugin dev would have to do more work early, and probably have to rewrite later.

I don’t see why everyone is against more features in this project. Give them time and we’ll have something awesome :slight_smile:

you’re right :stuck_out_tongue:

I’m the one who proposed http://www.reddit.com/r/spongeproject/comments/2g2b22/command_api_idea_use_of_annotations_and_dynamic/
I love the annotations, so please include them. I would like to see 2 or 3 ways of adding commands:

//class, description, aliases
//class uses String[] args
plugin.registerCommand(commandClass, "Worldedit Help", "/help", "worldedit help")


//class with annotated methods, annotation defines description, aliases, permissions
plugin.registerCommands(annotatedCommandsClass)

and the annotation looks like this:


//This argument could also be of type OnlinePlayer or ConsoleSender, for player/console-only commands
@Command(aliases=["mail send", "ms"], permissions=["perm.a", "perm.b"], "desc")
public void myCommand(
    CommandSender sender, 
    @Arg(name="player") Player receipient, 
    @Wilcard @Arg(name="message") String[] message
)
{ 
//command logic...
}

My Code is based on this implementation: Home · Ranzdo/MethodCommand Wiki · GitHub
More examples can be found there…

A nice idea, especially when there are muliple command aliases (/cmd1, /cmd2) and you want to know which one the player used.
(Let’s say for paging commands, the help text would say “Page 1 of x. Use /cmd2 ” instead of “/cmd1 ”)

It’s always an issue, and i think it’s quite important. Maybe something like gettext is a good solution: Localization support suggestion

Yeah, bring me more features by all means! I’m all for new and beneficial things :slight_smile:

  1. We will be registering commands dynamically most likely. Convention > configuration
  2. Intake is extremely modular:
    1. CommandCallable is an interface that (essentially) takes callable.execute(sender, arguments).
    2. Dispatcher (an interface) is also a CommandCallable, but it lets you register commands on it, so callable.execute(sender, "addmember") would call an “addmember” subcommand.
    3. If you want a “command manager,” you just use a Dispatcher at the top.
    4. If you want subcommands, then you use a Dispatcher somewhere below (commandManager.register(dispatcher, "region", "rg")).
    5. The annotation code builds CommandCallables. You basically give ParametricBuilder your .class file and it will give you a List<CommandCallable>. manager.registerCommands(YourClass.class) does not exist, which means the annotation implementation is 100% separate.
    6. Some of you want to use annotated methods to register commands but don’t want parametric injection (i.e. @Command void myCommand(Sender sender, CommandContext args)). The annotation library supports this 100% too because to it, all it is doing is injecting a Sender object and the arguments.
    7. Intake supports switches, flags, and quote handling (/mycommand -f -w world "hi there"). However, this is also 100% optional because Intake only gives you a String for arguments. (However, the annotation code does mandate this parser).
  3. If you use annotations, it still passes a context object underneath. Annotations are an abstraction on top of the simpler command code.

So basically Intake does everything* while letting you use almost nothing.

*besides one-command-per-class annotated commands.

8 Likes

API draft:

Overview from @Falkreon (thanks):

I can’t help but notice “String arguments” is a singular String, and “arguments” is a plural word. So does this mean all arguments will be strung together in a single String? Or is this an oops?

String arguments consists of a list of all arguments separated by a space following the main command.

Ex.
/tp jkmalan bdubz4552

This would break down into

String arguments = "jkmalan bdubz4552"
String[] parentCommands = ["tp"]

The arguments would need to be split at the spaces to be parsed one by one.

Yes. Makes it easier for commands like /msg and /mail.

I would argue that having them in a pre-separated array (because when we go to use them we will split them anyways) would be better, but then again it is as simple as args.split (" ");

1 Like