Entity and Player Arguments
The arguments described in this section relate to arguments which you can use to retrieve entities. Their main usage is the selection of command targets.
All of these have entity selectors (@a
, @e
, @n
, etc.) as valid inputs, though they require the minecraft.command.selector
permission in order to
be able to be used. The specific arguments may allow or disallow certain selectors.
Entity Argument
This argument, after resolving its returning EntitySelectorArgumentResolver
, returns a list of exactly one, no more and no less, entity. It is safe
to call List#getFirst()
to retrieve that entity.
Example usage
public static LiteralCommandNode<CommandSourceStack> entity() {
return Commands.literal("entityarg")
.requires(ctx -> ctx.getSender().isOp())
.then(Commands.argument("arg", ArgumentTypes.entity())
.executes(ctx -> {
final EntitySelectorArgumentResolver entitySelectorArgumentResolver = ctx.getArgument("arg", EntitySelectorArgumentResolver.class);
final List<Entity> entities = entitySelectorArgumentResolver.resolve(ctx.getSource());
ctx.getSource().getSender().sendRichMessage("Found a <entitytype>",
Placeholder.unparsed("entitytype", entities.getFirst().getType().name())
);
return Command.SINGLE_SUCCESS;
}))
.build();
}
In-game preview
If the executing player is not opped:
If the executing player is opped:
Entities Argument
In contrast to the single entity argument, this multi entity argument accepts any amount of entities, with the minimum amount of entities being 1.
They can, once again, be resolved using EntitySelectorArgumentResolver#resolve(CommandSourceStack)
, which returns a List<Entity>
.
Example usage
public static LiteralCommandNode<CommandSourceStack> entities() {
return Commands.literal("entitiesarg")
.requires(ctx -> ctx.getSender().isOp())
.then(Commands.argument("arg", ArgumentTypes.entities())
.executes(ctx -> {
final EntitySelectorArgumentResolver entitySelectorArgumentResolver = ctx.getArgument("arg", EntitySelectorArgumentResolver.class);
final List<Entity> entities = entitySelectorArgumentResolver.resolve(ctx.getSource());
ctx.getSource().getSender().sendRichMessage("Found the following entities: <entitytypes>",
Placeholder.unparsed("entitytypes", String.join(", ", entities.stream().map(Entity::getType).map(EntityType::name).toList()))
);
return Command.SINGLE_SUCCESS;
}))
.build();
}
In-game preview
Player Argument
The player argument allows you to be given some player input. Running ctx.getArgument
return a PlayerSelectorArgumentResolver
for player arguments.
For the "one player" argument (this one), you can safely get the target player by running PlayerSelectorArgumentResolver.resolve(ctx.getSource()).getFirst()
,
which returns a Bukkit Player
object.
Example usage
This command yeets the targeted player into the air!
public static LiteralCommandNode<CommandSourceStack> playerArgument() {
return Commands.literal("player")
.then(Commands.argument("target", ArgumentTypes.player())
.executes(ctx -> {
final PlayerSelectorArgumentResolver targetResolver = ctx.getArgument("target", PlayerSelectorArgumentResolver.class);
final Player target = targetResolver.resolve(ctx.getSource()).getFirst();
target.setVelocity(new Vector(0, 100, 0));
target.sendRichMessage("<rainbow>Yeeeeeeeeeet");
ctx.getSource().getSender().sendRichMessage("Yeeted <target>!",
Placeholder.component("target", target.name())
);
return Command.SINGLE_SUCCESS;
}))
.build();
}
In-game preview
Players Argument
The "multiple players" argument works similarly to the Player argument, also returning a PlayerSelectorArgumentResolver
. Instead of just resolving to exactly one Player
, this
one can resolve to more than just one player - which you should account for in case of using this argument. PlayerSelectorArgumentResolver.resolve#(ctx.getSource())
returns a
List<Player>
, which you can just iterate through.
Example usage
Extending the "single player" yeet command to support multiple targets
public static LiteralCommandNode<CommandSourceStack> playersArgument() {
return Commands.literal("players")
.then(Commands.argument("targets", ArgumentTypes.players())
.executes(ctx -> {
final PlayerSelectorArgumentResolver targetResolver = ctx.getArgument("targets", PlayerSelectorArgumentResolver.class);
final List<Player> targets = targetResolver.resolve(ctx.getSource());
final CommandSender sender = ctx.getSource().getSender();
for (final Player target : targets) {
target.setVelocity(new Vector(0, 100, 0));
target.sendRichMessage("<rainbow>Yeeeeeeeeeet");
sender.sendRichMessage("Yeeted <target>!",
Placeholder.component("target", target.name())
);
}
return Command.SINGLE_SUCCESS;
}))
.build();
}
In-game preview
Player Profiles Argument
The player profiles argument is a very powerful argument which can retrieve both offline and online players. It returns the result of the argument as a PlayerProfileListResolver
,
which resolves to a Collection<PlayerProfile>
. This collection can be iterated to get the resulting profile(s). Usually, it only returns a single PlayerProfile
if retrieving
a player by name, but it can return multiple if using the entity selectors (like @a
on online players). Thus it always makes sense to run whatever operation you want to run on
all entries in the collection instead of just the first one.
Sometimes, the API call to players, which are currently offline and have no yet logged onto the server, may fail. This is also visible in the in-game preview down below. This
weird behavior also explains why the /whitelist add
command fails, so now you know 🚀.
Example usage - Player lookup command
public static LiteralCommandNode<CommandSourceStack> playerProfilesArgument() {
return Commands.literal("lookup")
.then(Commands.argument("profile", ArgumentTypes.playerProfiles())
.executes(ctx -> {
final PlayerProfileListResolver profilesResolver = ctx.getArgument("profile", PlayerProfileListResolver.class);
final Collection<PlayerProfile> foundProfiles = profilesResolver.resolve(ctx.getSource());
for (final PlayerProfile profile : foundProfiles) {
ctx.getSource().getSender().sendMessage("Found " + profile.getName());
}
return Command.SINGLE_SUCCESS;
}))
.build();
}