Skip to main content
Version: 26.1

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

A command tree is passed to CommandDispatcher#register during the RegisterCommandsEvent like so:

@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.

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.

note

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.

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.

Argument TypeDeclares (builder)Accesses (getter)Description
BoolArgumentType#bool#getBoolA boolean.
IntegerArgumentType#integer (optional min and max)#getIntegerA 32-bit integer.
LongArgumentType#longArg (optional min and max)#getLongA 64-bit integer.
FloatArgumentType#floatArg (optional min and max)#getFloatA single-precision decimal.
DoubleArgumentType#doubleArg (optional min and max)#getDoubleA double-precision decimal.
StringArgumentType#word, #string, or #greedyString#getStringA piece of text, see the note below.
note

The three StringArgumentType builders differ in how much text they consume. #word reads a single unquoted word, ending at the first space. #string reads a single word as well, unless the input is wrapped in double quotes ("hello world"), in which case the whole quoted text is read. #greedyString reads everything after the argument, spaces included, and therefore cannot be followed by further nodes.

Built-in Minecraft

Minecraft adds game-specific argument types, found in net.minecraft.commands.arguments. This is not an exhaustive list.

Argument TypeDeclares (builder)Accesses (getter)Description
EntityArgument#entity, #entities, #player, #players#getEntity, #getEntities, #getOptionalEntities, #getPlayer, #getPlayers, #getOptionalPlayersOne or multiple entities or players, selected by name, UUID, or a selector such as @p or @e.
BlockPosArgument#blockPos#getLoadedBlockPos, #getBlockPosA block position.
Vec3Argument#vec3#getVec3A position in the world.
ItemArgument#item#getItemAn item stack, including data components.
BlockStateArgument#block#getBlockA block state, including block entity data.
ResourceArgument#resource#getResourceAn Identifier pointing to an entry of a given registry.
ResourceKeyArgument#key#getRegistryKeyA ResourceKey for a given registry.

NeoForge

NeoForge adds additional argument types in net.neoforged.neoforge.server.command.

Argument TypeDeclares (builder)Accesses (getter)Description
EnumArgument#enumArgumentCommandContext#getArgument with the keyed name and the enum classAn enum value.
ModIdArgument#modIdArgumentCommandContext#getArgument with the keyed name and String.classA mod ID.

Custom Argument Types

A value that none of the existing types can parse is handled by implementing a custom argument type via. ArgumentType<T>, which reads the raw command text from a StringReader and returns a value of type T.

public class SpellArgument implements ArgumentType<Spell> {
private static final DynamicCommandExceptionType ERROR_UNKNOWN_SPELL = new DynamicCommandExceptionType(
name -> Component.translatableEscape("commands.examplemod.spell.unknown", name)
);

// Follows the naming scheme of the vanilla argument types, used when declaring the argument
public static SpellArgument spell() {
return new SpellArgument();
}

// Consumes as much of the input as the argument needs
@Override
public Spell parse(StringReader reader) throws CommandSyntaxException {
String name = reader.readUnquotedString();
// Look up the spell, throwing ERROR_UNKNOWN_SPELL#createWithContext if there is none
}

// Optional, defaults to no suggestions: the completions offered while typing the argument
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
// Suggest the names of the available spells or none
return Suggestions.empty();
}

// Optional, defaults to an empty list: example inputs used by Brigadier to detect
// ambiguities between sibling nodes
@Override
public Collection<String> getExamples() {
return List.of("fireball", "heal");
}
}

As no static getter exists for a new type, one is usually added next to the builder, so that the value can be accessed like that of a built-in type:

public static Spell getSpell(CommandContext<CommandSourceStack> context, String name) {
return context.getArgument(name, Spell.class);
}
tip

If an existing argument type already parses the desired value and only the suggestions should differ, #suggests on the argument node replaces them without a custom type. Suggestions added this way are requested from the server as the player types.

Synchronization

The server sends its command tree to every client, allowing commands to be parsed and completed locally while being typed. Each argument node is described by an ArgumentTypeInfo, looked up from the COMMAND_ARGUMENT_TYPE registry by the class of the ArgumentType. The types listed in the argument types tables above already have one. A custom type without one cannot be sent to the client.

ArgumentTypeInfos#registerByClass associates the ArgumentType class with its info and returns the info, so it can be registered in the same statement:

public static final DeferredRegister<ArgumentTypeInfo<?, ?>> COMMAND_ARGUMENT_TYPES =
DeferredRegister.create(Registries.COMMAND_ARGUMENT_TYPE, ExampleMod.MOD_ID);

public static final DeferredHolder<ArgumentTypeInfo<?, ?>, SingletonArgumentInfo<SpellArgument>> SPELL = COMMAND_ARGUMENT_TYPES.register(
// The registry name of the argument type.
"spell",
() -> ArgumentTypeInfos.registerByClass(
// The class of the argument type.
SpellArgument.class,
// The info describing it. 'contextFree' is used for argument types
// constructed without parameters, 'contextAware' for those requiring
// a CommandBuildContext.
SingletonArgumentInfo.contextFree(SpellArgument::spell)
)
);

An argument type that holds parameters of its own, such as the bounds of IntegerArgumentType, needs those parameters on the client as well and therefore cannot use SingletonArgumentInfo. Instead, ArgumentTypeInfo is implemented directly, along with an ArgumentTypeInfo.Template holding the parameters: #serializeToNetwork and #deserializeFromNetwork transfer the template, #serializeToJson writes it into the JSON representation of the command tree, #unpack creates a template from an argument type, and Template#instantiate creates an argument type from a template. EnumArgument.Info is a small example of such an implementation.