tutorial:commands
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
tutorial:commands [2019/08/13 15:02] – Add line numbers to code, clarify issue with redirects. Add another Command example i509vcb | tutorial:commands [2020/05/07 20:12] – Amend to use new API i509vcb | ||
---|---|---|---|
Line 8: | Line 8: | ||
If you just want to see how to register commands you've come to the right place here. | If you just want to see how to register commands you've come to the right place here. | ||
- | Registering commands is done through '' | + | Registering commands is done by registering a new listener in the '' |
- | + | The event should be registered | |
- | The '' | + | |
- | + | ||
- | The dedicated flag if set to true will tell Fabric to only register the command on a '' | + | |
+ | The dedicated parameter if true will tell event listeners that the server commands are being registered on is a '' | ||
Below are a few examples of how the commands can be registered. | Below are a few examples of how the commands can be registered. | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
- | CommandRegistry.INSTANCE.register(false, dispatcher -> TutorialCommands.register(dispatcher)); // All commands are registered in a single class that references | + | // The actual registration of commands can be delegated to another class via a method reference |
- | + | CommandRegistrationCallback.EVENT.register(TutorialCommands::register); | |
- | CommandRegistry.INSTANCE.register(false, | + | |
- | | + | // Or you can define |
- | | + | CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) |
+ | TutorialCommand.register(dispatcher); | ||
+ | | ||
+ | TutorialHelpCommand.register(dispatcher); | ||
+ | | ||
+ | IntegratedTutorialHelpCommand.register(dispatcher); | ||
+ | } | ||
}); | }); | ||
- | CommandRegistry.INSTANCE.register(true, dispatcher -> { // Or directly registering the command to the dispatcher. | + | CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) |
dispatcher.register(LiteralArgumentBuilder.literal(" | dispatcher.register(LiteralArgumentBuilder.literal(" | ||
}); | }); | ||
Line 35: | Line 39: | ||
<code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
// The root of the command. This must be a literal argument. | // The root of the command. This must be a literal argument. | ||
- | dispatcher.register(LiteralArgumentBuilder.literal(" | + | dispatcher.register(CommandManager.literal(" |
// Then add an argument named bar that is an integer | // Then add an argument named bar that is an integer | ||
- | .then(RequiredArgumentBuilder.argument(" | + | .then(CommandManager.argument(" |
// The command to be executed if the command " | // The command to be executed if the command " | ||
.executes(ctx -> { | .executes(ctx -> { | ||
Line 211: | Line 215: | ||
Redirects do not work in shortened aliases such as ''/ | Redirects do not work in shortened aliases such as ''/ | ||
+ | |||
+ | ==== Redirects (Chainable Commands) ==== | ||
+ | Commands such as ''/ | ||
+ | |||
+ | <code java [enable_line_numbers=" | ||
+ | LiteralCommandNode< | ||
+ | LiteralCommandNode< | ||
+ | // You can register under the same literal more than once, it will just register new parts of the branch as shown below if you register a duplicate branch an error will popup in console warning of conflicting commands but one will still work. | ||
+ | .then(literal(" | ||
+ | .then(literal(" | ||
+ | .redirect(root)) // Return to root for chaining | ||
+ | .then(literal(" | ||
+ | .redirect(root))) // Return to root for chaining | ||
+ | .then(literal(" | ||
+ | .executes(ctx -> { | ||
+ | ctx.getSource().sendFeedback(new LiteralText(" | ||
+ | return Command.SINGLE_SUCCESS; | ||
+ | }))); | ||
+ | </ | ||
+ | The redirect can also modify the CommandSource. | ||
+ | |||
+ | <code java [enable_line_numbers=" | ||
+ | .redirect(rootNode, | ||
+ | return ((ServerCommandSource) commandContext_1x.getSource()).withLookingAt(Vec3ArgumentType.getVec3(commandContext_1x, | ||
+ | }) | ||
+ | </ | ||
===== ServerCommandSource ===== | ===== ServerCommandSource ===== | ||
Line 413: | Line 443: | ||
</ | </ | ||
+ | ===== Custom Arguments ===== | ||
+ | |||
+ | Brigadier has support for custom argument types and this section goes into showing how to create a simple argument type. | ||
+ | |||
+ | Warning: Custom arguments require client mod installation to be registered correctly! If you are making a server plugin, consider using existing argument type and a custom suggestions provider instead. | ||
+ | |||
+ | For this example we will create a UUIDArgumentType. | ||
+ | |||
+ | First create a class which extends '' | ||
+ | |||
+ | <code java [enable_line_numbers=" | ||
+ | public class UUIDArgumentType implements ArgumentType< | ||
+ | </ | ||
+ | |||
+ | ArgumentType requires you to implement the '' | ||
+ | <code java> | ||
+ | @Override | ||
+ | public UUID parse(StringReader reader) throws CommandSyntaxException { | ||
+ | </ | ||
+ | |||
+ | This method is where all of your parsing will occur. Either this method will return the object based on the arguments provided in the command line or throw a CommandSyntaxException and parsing will fail. | ||
+ | |||
+ | Next you will store the current position of the cursor, this is so you can substring out only the specific argument. This will always be at the beginning of where your argument appears on the command line. | ||
+ | |||
+ | <code java [enable_line_numbers=" | ||
+ | int argBeginning = reader.getCursor(); | ||
+ | if (!reader.canRead()) { | ||
+ | reader.skip(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Now we grab the entire argument. Depending on your argument type, you may have a different criteria or be similar to some arguments where detecting a '' | ||
+ | |||
+ | <code java [enable_line_numbers=" | ||
+ | while (reader.canRead() && reader.peek() != ' ') { // peek provides the character at the current cursor position. | ||
+ | reader.skip(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Then we will ask the StringReader what the current position of the cursor is an substring our argument out of the command line. | ||
+ | |||
+ | <code java [enable_line_numbers=" | ||
+ | |||
+ | Now finally we check if our argument is correct and parse the specific argument to our liking, and throwing an exception if the parsing fails. | ||
+ | |||
+ | <code java [enable_line_numbers=" | ||
+ | try { | ||
+ | UUID uuid = UUID.fromString(uuidString); | ||
+ | return uuid; // And we return our type, in this case the parser will consider this argument to have parsed properly and then move on. | ||
+ | } catch (Exception ex) { | ||
+ | // UUIDs can throw an exception when made by a string, so we catch the exception and repackage it into a CommandSyntaxException type. | ||
+ | // Create with context tells Brigadier to supply some context to tell the user where the command failed at. | ||
+ | // Though normal create method could be used. | ||
+ | throw new SimpleCommandExceptionType(new LiteralText(ex.getMessage())).createWithContext(reader); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The ArgumentType is done, however your client will refuse the parse the argument and throw an error. To fix this we need to register an ArgumentSerializer. | ||
+ | Within your ModInitializer (Not only client or server) you will add this so the client can recognize the argument when the command tree is sent. For more complex argument types, you may need to create your own ArgumentSerializer. | ||
+ | |||
+ | <code java [enable_line_numbers=" | ||
+ | ArgumentTypes.register(" | ||
+ | // The argument should be what will create the ArgumentType. | ||
+ | </ | ||
+ | |||
+ | And here is the whole ArgumentType: | ||
+ | |||
+ | <file java UUIDArgumentType.java [enable_line_numbers=" | ||
+ | |||
+ | import com.mojang.brigadier.StringReader; | ||
+ | import com.mojang.brigadier.arguments.ArgumentType; | ||
+ | import com.mojang.brigadier.context.CommandContext; | ||
+ | import com.mojang.brigadier.exceptions.CommandSyntaxException; | ||
+ | import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; | ||
+ | import net.minecraft.text.LiteralText; | ||
+ | import net.minecraft.util.SystemUtil; | ||
+ | |||
+ | import java.util.ArrayList; | ||
+ | import java.util.Collection; | ||
+ | import java.util.UUID; | ||
+ | |||
+ | /** | ||
+ | * Represents an ArgumentType that will return a UUID. | ||
+ | */ | ||
+ | public class UUIDArgumentType implements ArgumentType< | ||
+ | // This method exists for convince and you could just initialize the class. | ||
+ | public static UUIDArgumentType uuid() { | ||
+ | return new UUIDArgumentType(); | ||
+ | } | ||
+ | |||
+ | // This is also for convince and you could always just grab the argument from the CommandContext. | ||
+ | public static <S> UUID getUuid(String name, CommandContext< | ||
+ | // Note that you should assume the CommandSource wrapped inside of the CommandContext will always be a generic type. | ||
+ | // If you access the ServerCommandSource make sure you verify the source is an instanceof ServerCommandSource before dangerous casting. | ||
+ | return context.getArgument(name, | ||
+ | } | ||
+ | |||
+ | private static final Collection< | ||
+ | list.add(" | ||
+ | list.add(" | ||
+ | list.add(" | ||
+ | }); | ||
+ | |||
+ | @Override | ||
+ | public UUID parse(StringReader reader) throws CommandSyntaxException { | ||
+ | int argBeginning = reader.getCursor(); | ||
+ | if (!reader.canRead()) { | ||
+ | reader.skip(); | ||
+ | } | ||
+ | |||
+ | // Now we check the contents of the argument till either we hit the end of the command line (When canRead becomes false) | ||
+ | // Otherwise we go till reach reach a space, which signifies the next argument | ||
+ | while (reader.canRead() && reader.peek() != ' ') { // peek provides the character at the current cursor position. | ||
+ | reader.skip(); | ||
+ | } | ||
+ | |||
+ | // Now we substring the specific part we want to see using the starting cursor position and the ends where the next argument starts. | ||
+ | String uuidString = reader.getString().substring(argBeginning, | ||
+ | try { | ||
+ | UUID uuid = UUID.fromString(uuidString); | ||
+ | return uuid; // And we return our type, in this case the parser will consider this argument to have parsed properly and then move on. | ||
+ | } catch (Exception ex) { | ||
+ | // UUIDs can throw an exception when made by a string, so we catch the exception and repackage it into a CommandSyntaxException type. | ||
+ | // Create with context tells Brigadier to supply some context to tell the user where the command failed at. | ||
+ | // Though normal create method could be used. | ||
+ | throw new SimpleCommandExceptionType(new LiteralText(ex.getMessage())).createWithContext(reader); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public Collection< | ||
+ | return EXAMPLES; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
===== FAQ ===== | ===== FAQ ===== | ||
tutorial/commands.txt · Last modified: 2024/02/23 14:22 by allen1210