Using Chimera Commands - Pante/chimera GitHub Wiki
This guide provides a walkthrough of the creation of a tell command using Chimera's Builder
s. If you prefer to use annotations, please view using annotations instead.
⚠️ Do not define commands in theplugin.yml
: Due to changes in Spigot 1.19, doing so will cause commands to be unregistered
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.
To use Chimera, include the commons
library in your project's pom.xml
<repositories>
<repository>
<id>chimera-releases</id>
<url>https://repo.karuslabs.com/repository/chimera-releases/</url>
</repository>
<repository>
<id>minecraft-libraries</id>
<url>https://libraries.minecraft.net</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>brigadier</artifactId>
<version>1.0.17</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.karuslabs</groupId>
<artifactId>commons</artifactId>
<version>5.1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
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();
WARNING: It is recommended to use
WordType.word()
instead ofStringArgument.word()
, andReaders.unquoted(StringReader)
instead ofStringReader.readUnquoted()
. See the FAQ for more information.
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
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());
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();
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();
We have completed creating our tell command and it's time to test it.
Entering /tell
in-game yields:
Entering /tell "@r, PanteLegacy" "Hello World!"
in-game yields: