Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved brigadier documentation #436

Open
wants to merge 42 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
213e7a0
Added note that the docs are incomplete
Hinterhaeltiger Jun 25, 2024
aa91be2
added more documentation for brigadier arguments
Hinterhaeltiger Jun 26, 2024
38e6065
further explaination about arguments
Hinterhaeltiger Jun 26, 2024
1fa5fe3
Merge pull request #1 from PaperMC/main
Hinterhaeltiger Jun 26, 2024
d1a8a3e
further explaination about arguments
Hinterhaeltiger Jun 26, 2024
a803edf
Merge branch 'main' of https://github.com/Hinterhaeltiger/paperdocs
Hinterhaeltiger Jun 26, 2024
ddf2de5
Further explanation about arguments
Hinterhaeltiger Jun 26, 2024
3ad576b
Merge branch 'main' of https://github.com/Hinterhaeltiger/paperdocs
Hinterhaeltiger Jun 26, 2024
0ded485
remove empty line
Hinterhaeltiger Jun 26, 2024
9e1d02c
fixed typo
Hinterhaeltiger Jun 26, 2024
154bc14
fixed typo + slug
Hinterhaeltiger Jun 26, 2024
6879701
Merge branch 'main' of https://github.com/Hinterhaeltiger/paperdocs
Hinterhaeltiger Jun 26, 2024
d45921f
added redirect
Hinterhaeltiger Jun 26, 2024
1a3eb61
fixed links
Hinterhaeltiger Jun 26, 2024
a27d760
added redirect + fixed formatting
Hinterhaeltiger Jun 26, 2024
da18661
name change + gitignore fix
Hinterhaeltiger Jun 26, 2024
9dd908f
fixed formatting
Hinterhaeltiger Jun 27, 2024
a6e0d14
fixed formatting
Hinterhaeltiger Jun 27, 2024
517513c
Merge branch 'main' of https://github.com/Hinterhaeltiger/paperdocs
Hinterhaeltiger Jun 27, 2024
b5d882d
fixed formatting (again)
Hinterhaeltiger Jun 27, 2024
079ee2c
Merge branch 'main' of https://github.com/Hinterhaeltiger/paperdocs
Hinterhaeltiger Jun 27, 2024
99bb901
Fixed nested interface reference
Hinterhaeltiger Jun 27, 2024
57136e1
Fixed cut off sentence
Hinterhaeltiger Jun 27, 2024
cd6bac6
Simplified advantages paragraph
Hinterhaeltiger Jun 29, 2024
e19aac3
Apply suggestions from code review (mostly typos)
Hinterhaeltiger Jun 29, 2024
b5d9e42
Merge branch 'main' into main
Hinterhaeltiger Jul 1, 2024
38d29d4
added javadoc reference + deleted code comment
Hinterhaeltiger Jul 1, 2024
baaed29
fixed typo
Hinterhaeltiger Jul 2, 2024
b8372ad
Fixed slugs + page descriptions
Hinterhaeltiger Jul 3, 2024
594dae6
Merge branch 'main' of https://github.com/Hinterhaeltiger/paperdocs
Hinterhaeltiger Jul 3, 2024
3de5676
fixed command api folder name
Hinterhaeltiger Jul 3, 2024
498a592
renamed link
Hinterhaeltiger Jul 4, 2024
1497b53
fixed typo
Hinterhaeltiger Jul 4, 2024
b205c1e
fixed wrong reference name
Hinterhaeltiger Jul 4, 2024
2807e1a
fixed typo
Hinterhaeltiger Jul 4, 2024
7fd6bf9
Merge branch 'main' into main
Hinterhaeltiger Jul 4, 2024
1fbbefb
fixed reference
Hinterhaeltiger Jul 4, 2024
13a99a9
Merge branch 'main' of https://github.com/Hinterhaeltiger/paperdocs
Hinterhaeltiger Jul 4, 2024
fe76545
Merge branch 'main' into main
Hinterhaeltiger Jul 7, 2024
6c04f35
committed suggestion
Hinterhaeltiger Jul 15, 2024
5c21bfc
Update docs/paper/dev/api/command-api/arguments.mdx
Hinterhaeltiger Jul 21, 2024
2fcb850
Shorter code explaination
Hinterhaeltiger Jul 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions _redirects
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
/paper/per-world-configuration /paper/configuration
/paper/configuration /paper/reference/configuration
/paper/reference/vanilla-command-permissions /paper/reference/permissions
/paper/dev/commands /paper/dev/commands-api/commands
7 changes: 6 additions & 1 deletion config/sidebar.paper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ const paper: SidebarsConfig = {
"dev/api/event-api/chat-event",
],
},
{
type: "category",
label: "Brigadier Command API",
Hinterhaeltiger marked this conversation as resolved.
Show resolved Hide resolved
collapsed: true,
items: ["dev/api/command-api/commands", "dev/api/command-api/arguments"],
},
{
type: "category",
label: "Entity API",
Expand All @@ -144,7 +150,6 @@ const paper: SidebarsConfig = {
},
"dev/api/pdc",
"dev/api/custom-inventory-holder",
"dev/api/commands",
Hinterhaeltiger marked this conversation as resolved.
Show resolved Hide resolved
"dev/api/scheduler",
"dev/api/plugin-messaging",
"dev/api/plugin-configs",
Expand Down
186 changes: 186 additions & 0 deletions docs/paper/dev/api/command-api/arguments.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
---
slug: /dev/command-api/arguments
description: A guide to arguments in Paper's Brigadier command API.
---

# Arguments

Argument types are datatypes that we can use instead of strings.

:::danger[Experimental]

Paper's command system is still experimental and may change in the future.

:::

## Basic usage of arguments

You can add arguments to a command by doing the following:
```java title="YourPluginClass.java"
public class YourPluginClass extends JavaPlugin {
@Override
public void onEnable() {
LifecycleEventManager<Plugin> manager = this.getLifecycleManager();
manager.registerEventHandler(LifecycleEvents.COMMANDS, event -> {
final Commands commands = event.registrar();
commands.register(
Commands.literal("enchantmentargumentcommand")
.then(
Commands.argument("enchantmentargument", ArgumentTypes.resource(RegistryKey.ENCHANTMENT))
.executes(ctx -> {
ctx.getSource().getSender().sendPlainMessage(
ctx.getArgument("enchantmentargument", Enchantment.class).getKey().asString()
);
return Command.SINGLE_SUCCESS;
})
).build()
);
});
}
}
```

This command has one argument of the `Enchantment` datatype. When the command is executed, the command
sender will get a message containing the key of the enchantment they selected.

## Advantage over string-based arguments
Hinterhaeltiger marked this conversation as resolved.
Show resolved Hide resolved

- Direct conversion to usable type
- Client-side error handling
- Custom types
- Non alphanumerical sorting

## Enchantment types

By default, you can use [the registry API](../registries) to get simple argument types like
blocks, items, potions and many more. In the example above, we used the Enchantment
Argument type, but there are many others:

### Predefined types (Registry)

| Registry key name | Return datatype class | Description |
|---------------------|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| GAME_EVENT | GameEvent | Events in the game (eating, flying with an elytra etc.) |
| STRUCTURE_TYPE | StructureType | [Structures](https://minecraft.wiki/w/Structure#Overworld)
| INSTRUMENT | CraftMusicInstrument | [Note block instrument](https://minecraft.wiki/w/Note_Block) |
| ENCHANTMENT | Enchantment | [Enchantment type](https://minecraft.wiki/w/Enchanting#Summary_of_enchantments) |
| MOB_EFFECT | PotionEffectType | [Potion effect](https://minecraft.wiki/w/Effect#List) |
| BLOCK | BlockType | [Block type - not modifiable](https://minecraft.wiki/w/Block#List_of_blocks) |
| ITEM | ItemType | [Item type - not modifiable](https://minecraft.wiki/w/Item#List_of_items) |
| BIOME | Biome | [Biome type](https://minecraft.wiki/w/Biome#Biome_types) |
| TRIM_MATERIAL | TrimMaterial | [Materials used to trim armor](https://minecraft.wiki/w/Smithing#Material) |
| TRIM_PATTERN | TrimPattern | [Trim patterns](https://minecraft.wiki/w/Smithing#Trimming) |
| DAMAGE_TYPE | DamageType | [All types of damage dealt to an entity](https://minecraft.wiki/w/Damage_type) |
| WOLF_VARIANT | Wolf.Variant | [Wolf variants since 1.20.5](https://minecraft.wiki/w/Wolf#Variants) |
| PAINTING_VARIANT | Art | [All paintings](https://minecraft.wiki/w/Painting#Canvases) |
| ATTRIBUTE | Attribute | [Entity attribute](https://minecraft.wiki/w/Attribute) |
| BANNER_PATTERN | PatternType | [Armor Pattern type](https://minecraft.wiki/w/Banner_Pattern#Variants) |
| CAT_VARIANT | Cat.Type | [Cat variants](https://minecraft.wiki/w/Cat#Appearance) |
| ENTITY_TYPE | EntityType | [Every entity type](https://minecraft.wiki/w/Entity#Types_of_entities) |
| PARTICLE_TYPE | Particle | [Every particle type](https://minecraft.wiki/w/Particles_(Java_Edition)#Types_of_particles) |
| POTION | PotionType | [Every potion type](https://minecraft.wiki/w/Potion#Effect_potions) |
| SOUND_EVENT | Sound | [Events that trigger sound effects](https://minecraft.wiki/w/Sounds.json#Sound_events) |
| VILLAGER_PROFESSION | Villager.Profession | [Villager professions](https://minecraft.wiki/w/Villager#Professions) |
| VILLAGER_TYPE | Villager.Type | [Villager biome specific type](https://minecraft.wiki/w/Villager#Professions) |
| MEMORY_MODULE_TYPE | MemoryKey | Keys for saving per-entity data |
| FROG_VARIANT | Frog.Variant | [Frog variants](https://minecraft.wiki/w/Frog) |
| MAP_DECORATION_TYPE | MapCursor.Type | [Types of sprites displayed on a map](https://minecraft.wiki/w/Map#Map_icons) |
| FLUID | Fluid | [Fluid types](https://minecraft.wiki/w/Fluid)

Brigadier itself also specifies many argument types. For more information on them, see <Javadoc name={"io.papermc.paper.command.brigadier.argument.ArgumentTypes"}>ArgumentTypes</Javadoc>
Hinterhaeltiger marked this conversation as resolved.
Show resolved Hide resolved

### Custom types

Custom arguments can be created by implementing the <Javadoc name={"io.papermc.paper.command.brigadier.argument.CustomArgumentType"}>CustomArgumentType</Javadoc>
interface.

Now, let's say that we want to implement a command which lets you order ice cream. For that,
we add an enum that specifies all available values for our custom type.

```java
public enum IceCreamType {
VANILLA,
CHOCOLATE,
STRAWBERRY,
MINT,
COOKIES
}
```
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:

```java
public class IceCreamTypeArgument implements CustomArgumentType.Converted<IceCreamType, String> {

@Override
public @NotNull IceCreamType convert(String nativeType) throws CommandSyntaxException {
try {
return IceCreamType.valueOf(nativeType.toUpperCase());
} catch (Exception e) {
Message message = MessageComponentSerializer.message().serialize(Component.text("Invalid flavor %s!".formatted(nativeType), NamedTextColor.RED));

throw new CommandSyntaxException(new SimpleCommandExceptionType(message), message);
}
}

@Override
public @NotNull ArgumentType<String> getNativeType() {
return StringArgumentType.word();
}

@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
for (IceCreamType flavor : IceCreamType.values()) {
builder.suggest(flavor.name(), MessageComponentSerializer.message().serialize(Component.text("look at this cool green tooltip!", NamedTextColor.GREEN)));
}

return CompletableFuture.completedFuture(
builder.build()
);
}
}
```

That's a lot of code, so let's start from the top. We implemented the <Javadoc name={"io.papermc.paper.command.brigadier.argument.CustomArgumentType$Converted"}>CustomArgumentType.Converted</Javadoc>
interface. This interface takes two type arguments: our custom enum, T, and a type that is native to
Minecraft, such as String, Integer, etc., called N. The native type exists so that the client can use
the input data, as it doesn't know what our custom `IceCreamType` is.

The first method called `convert()` converts the native type (in this case `String`)
into our own custom type called `IceCreamType`, as the name suggests. This is so we
can keep using our custom type internally. If we wouldn't do that, there would be no point in using a
custom type. If the specified input isn't found in our enum of available flavors, we
output an error.

The second method called `getNativeType()` returns the type of string that our command argument uses.
In our case, we're using a single word, so we return `StringArgumentType.word()`.

In the last method, `listSuggestions()`, we return `CompletableFuture<Suggestions>` so that the client
can suggest all available options. We can even add tooltips to the suggestions to explain them in greater
detail.

As a last step, we need to register the Command:
Hinterhaeltiger marked this conversation as resolved.
Show resolved Hide resolved

```java
public void onEnable() {
LifecycleEventManager manager = this.getLifecycleManager();
manager.registerEventHandler(LifecycleEvents.COMMANDS, event -> {
final Commands commands = event.registrar();
commands.register(Commands.literal("ordericecream")
.then(
Commands.argument("flavor", new IceCreamTypeArgument()).executes((commandContext -> {
IceCreamType argumentResponse = commandContext.getArgument("flavor", IceCreamType.class);
commandContext.getSource().getSender().sendMessage(Component.text("You ordered: " + argumentResponse));
return 1;
}))
).build()
);
});
}
```

Now that we have registered the command, we can execute it ingame:

![command with suggestions](./assets/icecreamargument.gif)
Look, we can even see our tooltip and if we execute the command, we get the message we specified

![executed command](./assets/command-executed.gif)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
slug: /dev/commands
slug: /dev/command-api/commands
description: A guide to Paper's Brigadier command API.
---

# Command API
# Commands

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

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

:::

Expand Down Expand Up @@ -109,21 +109,6 @@ class FunCommand implements BasicCommand {
}
```

## Arguments

### Built-in arguments

Vanilla has lots of built-in arguments that the client also supports. These can provide better
syntax and error-checking before even executing the commands. <Javadoc name={"io.papermc.paper.command.brigadier.argument.ArgumentTypes"}>ArgumentTypes</Javadoc>
has all the argument types available to the API.

For now, you can find specific examples of arguments, among other things, on the [Fabric Wiki](https://fabricmc.net/wiki/tutorial:commands).

### Custom arguments

Custom arguments can be created by implementing the <Javadoc name={"io.papermc.paper.command.brigadier.argument.CustomArgumentType"}>CustomArgumentType</Javadoc>
interface. See the Javadocs for more information on how they work.

## Lifecycle

Commands are not just registered once at the start, but anytime a reload happens. This can be
Expand Down
2 changes: 1 addition & 1 deletion docs/paper/dev/getting-started/paper-plugins.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ See [declaring dependencies](#dependency-declaration) for more information on ho
### Commands
Paper plugins do not use the `commands` field to register commands. This means that you do not need to include all
of your commands in the `paper-plugin.yml` file. Instead, you can register commands using the
[Brigadier Command API](../api/commands.mdx).
[Brigadier Command API](../api/command-api/commands.mdx).

### Cyclic plugin loading

Expand Down