Skip to content

Commit f29ea4b

Browse files
Hinterhaeltigerpowercasgamerzlataovceolijeffers0nDerEchtePilz
authored
feat: Improved brigadier documentation (#436)
Co-authored-by: powercas_gamer <cas@mizule.dev> Co-authored-by: Matouš Kučera <mk@kcra.me> Co-authored-by: Ollie <69084614+olijeffers0n@users.noreply.github.com> Co-authored-by: DerEchtePilz <81232921+DerEchtePilz@users.noreply.github.com>
1 parent fc73d5c commit f29ea4b

7 files changed

Lines changed: 190 additions & 56 deletions

File tree

_redirects

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
/paper/per-world-configuration /paper/configuration
88
/paper/configuration /paper/reference/configuration
99
/paper/reference/vanilla-command-permissions /paper/reference/permissions
10+
/paper/dev/commands /paper/dev/commands-api/commands

config/sidebar.paper.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ const paper: SidebarsConfig = {
127127
"dev/api/event-api/chat-event",
128128
],
129129
},
130+
{
131+
type: "category",
132+
label: "Brigadier Command API",
133+
collapsed: true,
134+
items: ["dev/api/command-api/commands", "dev/api/command-api/arguments"],
135+
},
130136
{
131137
type: "category",
132138
label: "Entity API",
@@ -145,7 +151,6 @@ const paper: SidebarsConfig = {
145151
},
146152
"dev/api/pdc",
147153
"dev/api/custom-inventory-holder",
148-
"dev/api/commands",
149154
"dev/api/scheduler",
150155
"dev/api/plugin-messaging",
151156
"dev/api/plugin-configs",
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
---
2+
slug: /dev/command-api/arguments
3+
description: A guide to arguments in Paper's Brigadier command API.
4+
---
5+
6+
# Arguments
7+
8+
Argument types are datatypes that we can use instead of strings.
9+
10+
:::danger[Experimental]
11+
12+
Paper's command system is still experimental and may change in the future.
13+
14+
:::
15+
16+
## Basic usage of arguments
17+
18+
You can add arguments to a command by doing the following:
19+
```java title="YourPluginClass.java"
20+
public class YourPluginClass extends JavaPlugin {
21+
@Override
22+
public void onEnable() {
23+
LifecycleEventManager<Plugin> manager = this.getLifecycleManager();
24+
manager.registerEventHandler(LifecycleEvents.COMMANDS, event -> {
25+
final Commands commands = event.registrar();
26+
commands.register(
27+
Commands.literal("enchantmentargumentcommand")
28+
.then(
29+
Commands.argument("enchantmentargument", ArgumentTypes.resource(RegistryKey.ENCHANTMENT))
30+
.executes(ctx -> {
31+
ctx.getSource().getSender().sendPlainMessage(
32+
ctx.getArgument("enchantmentargument", Enchantment.class).getKey().asString()
33+
);
34+
return Command.SINGLE_SUCCESS;
35+
})
36+
).build()
37+
);
38+
});
39+
}
40+
}
41+
```
42+
43+
This command has one argument of the `Enchantment` datatype. When the command is executed, the command
44+
sender will get a message containing the key of the enchantment they selected.
45+
46+
## Advantages over string-based arguments
47+
48+
- Direct conversion to usable type
49+
- Client-side error handling
50+
- Custom types
51+
- Non alphanumerical sorting
52+
53+
## Enchantment types
54+
55+
By default, you can use [the registry API](../registries) to get simple argument types like
56+
blocks, items, potions and many more. In the example above, we used the Enchantment
57+
Argument type, but there are many others:
58+
59+
### Predefined types (Registry)
60+
61+
| Registry key name | Return datatype class | Description |
62+
|---------------------|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
63+
| GAME_EVENT | GameEvent | Events in the game (eating, flying with an elytra etc.) |
64+
| STRUCTURE_TYPE | StructureType | [Structures](https://minecraft.wiki/w/Structure#Overworld)
65+
| INSTRUMENT | CraftMusicInstrument | [Note block instrument](https://minecraft.wiki/w/Note_Block) |
66+
| ENCHANTMENT | Enchantment | [Enchantment type](https://minecraft.wiki/w/Enchanting#Summary_of_enchantments) |
67+
| MOB_EFFECT | PotionEffectType | [Potion effect](https://minecraft.wiki/w/Effect#List) |
68+
| BLOCK | BlockType | [Block type - not modifiable](https://minecraft.wiki/w/Block#List_of_blocks) |
69+
| ITEM | ItemType | [Item type - not modifiable](https://minecraft.wiki/w/Item#List_of_items) |
70+
| BIOME | Biome | [Biome type](https://minecraft.wiki/w/Biome#Biome_types) |
71+
| TRIM_MATERIAL | TrimMaterial | [Materials used to trim armor](https://minecraft.wiki/w/Smithing#Material) |
72+
| TRIM_PATTERN | TrimPattern | [Trim patterns](https://minecraft.wiki/w/Smithing#Trimming) |
73+
| DAMAGE_TYPE | DamageType | [All types of damage dealt to an entity](https://minecraft.wiki/w/Damage_type) |
74+
| WOLF_VARIANT | Wolf.Variant | [Wolf variants since 1.20.5](https://minecraft.wiki/w/Wolf#Variants) |
75+
| PAINTING_VARIANT | Art | [All paintings](https://minecraft.wiki/w/Painting#Canvases) |
76+
| ATTRIBUTE | Attribute | [Entity attribute](https://minecraft.wiki/w/Attribute) |
77+
| BANNER_PATTERN | PatternType | [Armor Pattern type](https://minecraft.wiki/w/Banner_Pattern#Variants) |
78+
| CAT_VARIANT | Cat.Type | [Cat variants](https://minecraft.wiki/w/Cat#Appearance) |
79+
| ENTITY_TYPE | EntityType | [Every entity type](https://minecraft.wiki/w/Entity#Types_of_entities) |
80+
| PARTICLE_TYPE | Particle | [Every particle type](https://minecraft.wiki/w/Particles_(Java_Edition)#Types_of_particles) |
81+
| POTION | PotionType | [Every potion type](https://minecraft.wiki/w/Potion#Effect_potions) |
82+
| SOUND_EVENT | Sound | [Events that trigger sound effects](https://minecraft.wiki/w/Sounds.json#Sound_events) |
83+
| VILLAGER_PROFESSION | Villager.Profession | [Villager professions](https://minecraft.wiki/w/Villager#Professions) |
84+
| VILLAGER_TYPE | Villager.Type | [Villager biome specific type](https://minecraft.wiki/w/Villager#Professions) |
85+
| MEMORY_MODULE_TYPE | MemoryKey | Keys for saving per-entity data |
86+
| FROG_VARIANT | Frog.Variant | [Frog variants](https://minecraft.wiki/w/Frog) |
87+
| MAP_DECORATION_TYPE | MapCursor.Type | [Types of sprites displayed on a map](https://minecraft.wiki/w/Map#Map_icons) |
88+
| FLUID | Fluid | [Fluid types](https://minecraft.wiki/w/Fluid)
89+
90+
Minecraft itself also specifies many argument types. For more information on them, see <Javadoc name={"io.papermc.paper.command.brigadier.argument.ArgumentTypes"}>ArgumentTypes</Javadoc>
91+
92+
### Custom types
93+
94+
Custom arguments can be created by implementing the <Javadoc name={"io.papermc.paper.command.brigadier.argument.CustomArgumentType"}>CustomArgumentType</Javadoc>
95+
interface.
96+
97+
Now, let's say that we want to implement a command which lets you order ice cream. For that,
98+
we add an enum that specifies all available values for our custom type.
99+
100+
```java
101+
public enum IceCreamType {
102+
VANILLA,
103+
CHOCOLATE,
104+
STRAWBERRY,
105+
MINT,
106+
COOKIES
107+
}
108+
```
109+
Now, we have to define the argument itself. We do this by implementing the <Javadoc name={"io.papermc.paper.command.brigadier.argument.CustomArgumentType$Converted"}>CustomArgumentType.Converted</Javadoc> interface:
110+
111+
```java
112+
public class IceCreamTypeArgument implements CustomArgumentType.Converted<IceCreamType, String> {
113+
114+
@Override
115+
public @NotNull IceCreamType convert(String nativeType) throws CommandSyntaxException {
116+
try {
117+
return IceCreamType.valueOf(nativeType.toUpperCase());
118+
} catch (Exception e) {
119+
Message message = MessageComponentSerializer.message().serialize(Component.text("Invalid flavor %s!".formatted(nativeType), NamedTextColor.RED));
120+
121+
throw new CommandSyntaxException(new SimpleCommandExceptionType(message), message);
122+
}
123+
}
124+
125+
@Override
126+
public @NotNull ArgumentType<String> getNativeType() {
127+
return StringArgumentType.word();
128+
}
129+
130+
@Override
131+
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
132+
for (IceCreamType flavor : IceCreamType.values()) {
133+
builder.suggest(flavor.name(), MessageComponentSerializer.message().serialize(Component.text("look at this cool green tooltip!", NamedTextColor.GREEN)));
134+
}
135+
136+
return CompletableFuture.completedFuture(
137+
builder.build()
138+
);
139+
}
140+
}
141+
```
142+
143+
We implemented the <Javadoc name={"io.papermc.paper.command.brigadier.argument.CustomArgumentType$Converted"}>CustomArgumentType.Converted</Javadoc>
144+
interface. This interface takes two type arguments: our custom enum, T, and a native Java type called N.
145+
146+
- `convert()` converts the native type (in this case `String`) into our custom type.
147+
148+
- `getNativeType()` returns the type of string that our command argument uses. This uses a single word, so we return `StringArgumentType.word()`.
149+
150+
- `listSuggestions()` returns `CompletableFuture<Suggestions>` so that the client
151+
can suggest all available options. We can even add tooltips to the suggestions to explain them in greater
152+
detail.
153+
154+
We then need to register the command:
155+
156+
```java
157+
public void onEnable() {
158+
LifecycleEventManager manager = this.getLifecycleManager();
159+
manager.registerEventHandler(LifecycleEvents.COMMANDS, event -> {
160+
final Commands commands = event.registrar();
161+
commands.register(Commands.literal("ordericecream")
162+
.then(
163+
Commands.argument("flavor", new IceCreamTypeArgument()).executes((commandContext -> {
164+
IceCreamType argumentResponse = commandContext.getArgument("flavor", IceCreamType.class);
165+
commandContext.getSource().getSender().sendMessage(Component.text("You ordered: " + argumentResponse));
166+
return 1;
167+
}))
168+
).build()
169+
);
170+
});
171+
}
172+
```
173+
174+
Now that we have registered the command, we can execute it ingame:
175+
176+
![command with suggestions](./assets/icecreamargument.gif)
177+
Look, we can even see our tooltip and if we execute the command, we get the message we specified
178+
179+
![executed command](./assets/command-executed.gif)
116 KB
Loading
55.5 KB
Loading

docs/paper/dev/api/commands.mdx renamed to docs/paper/dev/api/command-api/commands.mdx

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
2-
slug: /dev/commands
2+
slug: /dev/command-api/commands
33
description: A guide to Paper's Brigadier command API.
44
---
55

6-
# Command API
6+
# Commands
77

88
Paper's command system is built on top of Minecraft's Brigadier command system. This system is a
99
powerful and flexible way to define commands and arguments.
@@ -19,7 +19,7 @@ Paper's command system is still experimental and may change in the future.
1919
:::note
2020

2121
This uses the <Javadoc name={"io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager"}>LifecycleEventManager</Javadoc>
22-
to register the command. See the [Lifecycle Events](./lifecycle.mdx) page for more information.
22+
to register the command. See the [Lifecycle Events](../lifecycle.mdx) page for more information.
2323

2424
:::
2525

@@ -109,57 +109,6 @@ class FunCommand implements BasicCommand {
109109
}
110110
```
111111

112-
## Arguments
113-
114-
### Built-in arguments
115-
116-
Vanilla has lots of built-in arguments that the client also supports. These can provide better
117-
syntax and error-checking before even executing the commands. <Javadoc name={"io.papermc.paper.command.brigadier.argument.ArgumentTypes"}>ArgumentTypes</Javadoc>
118-
has all the argument types available to the API.
119-
120-
For now, you can find specific examples of arguments, among other things, on the [Fabric Wiki](https://fabricmc.net/wiki/tutorial:commands).
121-
122-
### Custom arguments
123-
124-
Custom arguments can be created by implementing the <Javadoc name={"io.papermc.paper.command.brigadier.argument.CustomArgumentType"}>CustomArgumentType</Javadoc>
125-
interface. See the Javadocs for more information on how they work.
126-
127-
### Command suggestions
128-
129-
Custom command suggestions can be supplied by either overriding the
130-
<Javadoc name={"io.papermc.paper.command.brigadier.argument.CustomArgumentType#listSuggestions(com.mojang.brigadier.context.CommandContext,com.mojang.brigadier.suggestion.SuggestionsBuilder)"}>listSuggestions</Javadoc>
131-
method in `CustomArgumentType`, or using the `suggests(SuggestionProvider)` method to define a `SuggestionProvider` for the argument.
132-
133-
An example suggestion provider might look like this:
134-
```java
135-
Commands.argument("count", IntegerArgumentType.integer())
136-
.suggests((ctx, builder) -> {
137-
builder.suggest(1);
138-
builder.suggest(10);
139-
return builder.buildFuture();
140-
})
141-
```
142-
143-
Suggestions can also be contextual since they have access to the `CommandContext`.
144-
145-
:::note
146-
147-
To access other arguments when building suggestions, make sure the correct `CommandContext`
148-
is obtained with `CommandContext.getLastChild()`.
149-
150-
:::
151-
152-
An example contextual suggestion provider:
153-
```java
154-
Commands.argument("min", IntegerArgumentType.integer())
155-
.then(Commands.argument("max", IntegerArgumentType.integer())
156-
.suggests((ctx, builder) -> {
157-
int min = ctx.getLastChild().getArgument("min", Integer.class);
158-
builder.suggest(min + 1);
159-
return builder.buildFuture();
160-
}))
161-
```
162-
163112
## Lifecycle
164113

165114
Commands are not just registered once at the start, but anytime a reload happens. This can be

docs/paper/dev/getting-started/paper-plugins.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ See [declaring dependencies](#dependency-declaration) for more information on ho
187187
### Commands
188188
Paper plugins do not use the `commands` field to register commands. This means that you do not need to include all
189189
of your commands in the `paper-plugin.yml` file. Instead, you can register commands using the
190-
[Brigadier Command API](../api/commands.mdx).
190+
[Brigadier Command API](../api/command-api/commands.mdx).
191191

192192
### Cyclic plugin loading
193193

0 commit comments

Comments
 (0)