-
-
Notifications
You must be signed in to change notification settings - Fork 94
Add simple commands docs #363
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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
MagnusHJensen
wants to merge
4
commits into
neoforged:main
Choose a base branch
from
MagnusHJensen:initial-command-docs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| { | ||
| "label": "Advanced Topics", | ||
| "position": 13 | ||
| "label": "Advanced Topics", | ||
| "position": 14 | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "label": "Commands", | ||
| "position": 13 | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| # Commands | ||
|
|
||
| Commands are text-based actions triggered from chat by prefixing a message with a slash (`/`), from the server console, from command blocks, or from [functions]. A command performs some effect in the game, such as modifying the world, querying state, or exposing debug utilities. A mod can define its own commands to run dynamic actions when invoked. | ||
|
|
||
| Command definitions are hierarchical. Minecraft builds commands on Mojang's [Brigadier] library, which models each command as a tree of nodes rooted at a dispatcher. A **literal** node matches a fixed keyword, such as `mymod` or `reload` in `/mymod reload`; an **argument** node matches a typed, named input, such as a number or an entity selector. Nodes are joined through `#then` and made executable through `#executes`, and a node may hold execution logic, child nodes, or both. This nesting produces the tree of subcommands. | ||
|
|
||
| An argument is used in two places. It is **declared** while building the tree, by supplying a name and an `ArgumentType`, and its parsed value is **accessed** inside the execution logic from the `CommandContext`, using that same name. The name is the contract between the two. The sections below cover each half in turn. | ||
|
|
||
| ## Registering Commands | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if there should be a minor note here for registering a command that's only available on the client. The process is exactly the same via |
||
|
|
||
| A command tree is passed to `CommandDispatcher#register` during the [`RegisterCommandsEvent`][event] like so: | ||
|
|
||
| ```java | ||
| @SubscribeEvent // on the game event bus | ||
| public static void registerCommands(RegisterCommandsEvent event) { | ||
| event.getDispatcher().register( | ||
| Commands.literal("mymod") | ||
| .then(Commands.literal("reload") | ||
| .executes(context -> { | ||
| // Perform the command logic here | ||
| return Command.SINGLE_SUCCESS; | ||
| }) | ||
| .then(Commands.literal("force") | ||
| .executes(context -> { | ||
| // Perform the command logic here | ||
| return Command.SINGLE_SUCCESS; | ||
| }) | ||
| ) | ||
| ) | ||
| ); | ||
| } | ||
| ``` | ||
|
|
||
| `Commands#literal` starts a literal builder, `#then` attaches a child node, and `#executes` supplies a `Command` callback whose returned `int` is the result count reported back to the caller. The example above registers `/mymod reload` and `/mymod reload force`. | ||
|
|
||
| :::note | ||
| For more advanced command trees that require registry access, `RegisterCommandsEvent#getBuildContext` provides a `CommandBuildContext` that can be passed to argument types that require it. | ||
| ::: | ||
|
|
||
| ## Arguments | ||
|
|
||
| An argument node is added with `Commands#argument`, supplying the argument name and an `ArgumentType`. The parsed value is read back inside `#executes` through the static getter that pairs with the chosen type, keyed by the same name. | ||
|
|
||
| ```java | ||
| Commands.literal("give") | ||
| .then(Commands.argument("count", IntegerArgumentType.integer(1)) | ||
| .executes(context -> { | ||
| // Access the value declared above as "count" | ||
| int count = IntegerArgumentType.getInteger(context, "count"); | ||
| // Use count | ||
| return count; | ||
| })) | ||
| ``` | ||
|
|
||
| Every `ArgumentType` provides a builder used when declaring the argument and most often a static getter used when accessing the parsed value. The getter throws if the supplied name does not match a declared argument on the current path, which is why the declaration name and the access name must agree. | ||
|
|
||
| If an `ArgumentType` does not provide a static getter, the parsed value can be accessed through `CommandContext#getArgument` with the argument name and the expected class. | ||
|
|
||
| :::note | ||
| An argument is not made optional through a flag. Instead, `#executes` is attached at more than one depth of the tree: once on the parent node for the case where the argument is absent, and again on the argument node for the case where it is provided. | ||
| ::: | ||
|
|
||
| ## Argument Types | ||
|
|
||
| The following tables list common argument types. Each row pairs the builder used to declare the argument with the static getter used to access the parsed value. | ||
|
|
||
| ### Brigadier | ||
|
|
||
| Brigadier provides the primitive types, found in `com.mojang.brigadier.arguments`. These types are synchronized to the client automatically. | ||
|
|
||
| | Argument Type | Declares (builder) | Accesses (getter) | Description | | ||
| | --------------------- | -------------------------------------- | ----------------- | -------------------------------------------------------- | | ||
| | `BoolArgumentType` | `#bool` | `#getBool` | A boolean. | | ||
| | `IntegerArgumentType` | `#integer` (optional min and max) | `#getInteger` | A 32-bit integer. | | ||
| | `LongArgumentType` | `#longArg` (optional min and max) | `#getLong` | A 64-bit integer. | | ||
| | `FloatArgumentType` | `#floatArg` (optional min and max) | `#getFloat` | A single-precision decimal. | | ||
| | `DoubleArgumentType` | `#doubleArg` (optional min and max) | `#getDouble` | A double-precision decimal. | | ||
| | `StringArgumentType` | `#word`, `#string`, or `#greedyString` | `#getString` | A single word, a quotable string, or the remaining text. | | ||
|
MagnusHJensen marked this conversation as resolved.
Outdated
|
||
|
|
||
| ### Built-in Minecraft | ||
|
|
||
| Minecraft adds game-specific argument types, found in `net.minecraft.commands.arguments`. This is not an exhaustive list. | ||
|
|
||
| | Argument Type | Declares (builder) | Accesses (getter) | Description | | ||
| | --------------------- | --------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | | ||
| | `EntityArgument` | `#entity`, `#entities`, `#player`, `#players` | `#getEntity`, `#getEntities`, `#getOptionalEntities`, `#getPlayer`, `#getPlayers`, `#getOptionalPlayers` | A single entity, player, or multiple entities, and players via a selector. | | ||
|
MagnusHJensen marked this conversation as resolved.
Outdated
|
||
| | `BlockPosArgument` | `#blockPos` | `#getLoadedBlockPos`, `#getBlockPos` | A block position. | | ||
| | `Vec3Argument` | `#vec3` | `#getVec3` | A position in the world. | | ||
| | `ItemArgument` | `#item` | `#getItem` | An item stack, including data components. | | ||
| | `BlockStateArgument` | `#block` | `#getBlock` | A block state, including block entity data. | | ||
| | `ResourceArgument` | `#resource` | `#getResource` | A namespaced identifier for a given registry. | | ||
| | `ResourceKeyArgument` | `#key` | `#getRegistryKey` | A resource key for a given registry. | | ||
|
MagnusHJensen marked this conversation as resolved.
Outdated
|
||
|
|
||
| ### NeoForge | ||
|
|
||
| NeoForge adds additional argument types in `net.neoforged.neoforge.server.command`. These are synchronized to the client automatically. | ||
|
MagnusHJensen marked this conversation as resolved.
Outdated
|
||
|
|
||
| | Argument Type | Declares (builder) | Accesses (getter) | Description | | ||
| | --------------- | ------------------ | ------------------------------------------------------------------- | -------------- | | ||
| | `EnumArgument` | `#enumArgument` | `CommandContext#getArgument` with the keyed name and the enum class | An enum value. | | ||
| | `ModIdArgument` | `#modIdArgument` | `CommandContext#getArgument` with the keyed name and `String.class` | A mod ID. | | ||
|
|
||
| [Brigadier]: https://github.com/Mojang/brigadier | ||
| [event]: ../concepts/events.md | ||
| [functions]: https://minecraft.wiki/w/Function_(Java_Edition) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| { | ||
| "label": "Miscellaneous", | ||
| "position": 14 | ||
| "label": "Miscellaneous", | ||
| "position": 15 | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see why this needs to be it's own section instead of something under misc.