Skip to content

Using Chimera Commands

Matthias Ngeo edited this page Jun 5, 2020 · 41 revisions

Overview

This guide provides a walkthrough of the creation of a tell command using Chimera's Builders. If you prefer to use annotations, please view using annotations instead.

Our tell command allows a player to send a message to one or more other players. It's syntax is /tell|t <players> <messages>. Suggestions are provided for each argument. For <player> and <players>, it's the names of visible, online players. For <messages>, it's Hello World!. Lastly, the message, Hello darkness my old friend is displayed if no arguments are given.

Creating the tell command

A command is represented by either a Literal or LiteralCommandNode. Both can contain an arbitrary number of arguments or child commands. It is recommended to use Literal as it may contain aliases and optional children.

A Literal can be created through a builder returned by Literal.<CommandSender>builder(name) or Literal.of(name).

import com.karuslabs.commons.command.tree.nodes.Literal;

Literal<CommandSender> tell = Literal.of("tell").alias("t")
                                     .then(arguments) // covered in the next section
                                     .build();

Creating the <player>, <players> and <message> arguments

An argument is represented by either a Argument or ArgumentCommandNode. Both contain an ArgumentType that is used to resolve a string to a type. An SuggestionProvider can also optionally be used to provide completion suggestions. It is recommended to use Argument.

An Argument can be created through a builder returned by Argument.<CommandSender>builder(name, type) or Argument.of(name, type).

<player> | <players>:

import com.karuslabs.commons.command.tree.nodes.Argument;
import com.karuslabs.commons.command.types.PlayersType;

// Inbuilt players type provided by Chimera
Argument.Builder<CommandSender, List<Player>> players = Argument.of("players", new PlayersType()); 

<message>:

import com.karuslabs.commons.command.tree.nodes.Argument;
import com.mojang.brigadier.arguments.StringArgumentType;

// Inbuilt string type provided by Mojang
Argument.Builder<CommandSender, String> message = Argument.of("message", StringArgumentType.string()) 
                                                          .suggests((c, builder) -> builder
                                                              .suggest("\"Hello World!\"").buildFuture()
                                                           );

Chaining the arguments:

Argument<CommandSender, List<Player>> arguments = players.then(message).build(); // Chains player and message

Defining a command's behaviour

Until now, nothing will happen if the tell command is executed since it does not contain any behaviour. To define a command's behaviour, we must use either an Execution<T> or Command. It is recommend to use Execution` since it allows optional arguments, and provides the source as a parameter.

The last literal or argument in a chain is always executed, e.g. given the input /tell Bob "I'm a banana", the Execution<T> bound to the Argument that represents <message> will be executed.

Editing the Literal in the previous section yields:

import com.karuslabs.commons.command.Execution;
        

Literal<CommandSender> tell = Literal.of("tell").alias("t")
                                     // Add the following
                                     .executes(context -> 
                                        context.getSource().sendMessage("Hello darkness my old friend")) 
                                     .then(message)
                                     .build();

Editing the Argument that represents in the previous section yields:

Argument.Builder<CommandSender, String> message = Argument.of("message", StringArgumentType.string())
                                                          .executes(context -> { // <-- Add this
                                                              CommandSender sender = context.getSource();
                                                              List<Player> recipents = context.getArgument("players", List.class);
                                                              String entered = context.getArgument("message", String.class);   
                                                              
                                                              recipents.forEach(p -> p.sendMessage(sender + " says: " + entered));
                                                           })
                                                          .suggests((context, builder) -> builder.suggest("\"Hello World!\"").buildFuture());

Registering a command

The final step after creating the command is to register it with a Disptcher. Commands not registered in either JavaPlugin.onLoad() or JavaPlugin.onEnable() will only be available after Dispatcher.update() is called.

import com.karuslabs.commons.command.dispatcher.Dispatcher;

Dispatcher dispatcher = Dispatcher.of(yourPlugin);
dispatcher.getRoot().addChild(tell);
// Only needed if called outside JavaPlugin.onLoad() or JavaPlugin.onEnable()
dispatcher.update(); 

Putting it together

In the end, our tell command should look like:

import com.karuslabs.commons.command.Exeuction;
import com.karuslabs.commons.command.dispatcher.Dispatcher;
import com.karuslabs.commons.command.tree.nodes.Literal;
import com.karuslabs.commons.command.tree.nodes.Argument;
import com.karuslabs.commons.command.types.PlayersType;
import com.mojang.brigadier.arguments.StringArgumentType;        
            
Argument.Builder<CommandSender, List<Player>> players = Argument.of("players", new PlayersType()); // Inbuilt players type provided by Chimera
Argument.Builder<CommandSender, String> message = Argument.of("message", StringArgumentType.string()) // Inbuilt string type provided by Mojang
                                                          .executes(context -> { 
                                                              CommandSender sender = context.getSource();
                                                              List<Player> recipents = context.getArgument("players", List.class);
                                                              String entered = context.getArgument("message", String.class);   
                                                              
                                                              recipents.forEach(p -> p.sendMessage(sender.getName() + " says: " + entered));
                                                           })
                                                          .suggests((context, builder) -> builder.suggest("\"Hello World!\"").buildFuture());
        
Argument<CommandSender, List<Player>> arguments = players.then(message).build();

Literal<CommandSender> tell = Literal.of("tell").alias("t")
                                     .executes(context -> context.getSource().sendMessage("Hello darkness my old friend"))
                                     .then(arguments)
                                     .build();

Dispatcher dispatcher = Dispatcher.of(yourPlugin);
dispatcher.getRoot().addChild(tell);
// Only needed if called outside JavaPlugin.onLoad() or JavaPlugin.onEnable()
dispatcher.update();

Taking the tell command for a spin

We have completed creating our tell command and it's time to test it.

Entering /tell in-game yields:

Partial Command Execution

Entering /tell "@r, PanteLegacy" "Hello World!" in-game yields:

Full Command Execution

Where to next?

Clone this wiki locally