Skip to content

Paper-specific

The arguments in this section return objects frequently used in Paper API.

The block state argument can be used for getting a block type and explicit, associated data.

public static LiteralCommandNode<CommandSourceStack> blockStateArgument() {
return Commands.literal("blockstateargument")
.then(Commands.argument("arg", ArgumentTypes.blockState())
.executes(ctx -> {
final BlockState blockState = ctx.getArgument("arg", BlockState.class);
ctx.getSource().getSender().sendPlainMessage("You specified a " + blockState.getType() + "!");
return Command.SINGLE_SUCCESS;
}))
.build();
}

The item stack argument is the way to retrieve an ItemStack following the same argument format as the Vanilla /give <player> <item> [<amount>] command as its second argument. The user may also define components to further customize the ItemStack. If you only require a Material, you should instead check out the registry arguments.

public static LiteralCommandNode<CommandSourceStack> itemStackArgument() {
return Commands.literal("itemstack")
.then(Commands.argument("stack", ArgumentTypes.itemStack())
.executes(ctx -> {
final ItemStack itemStack = ctx.getArgument("stack", ItemStack.class);
if (ctx.getSource().getExecutor() instanceof Player player) {
player.getInventory().addItem(itemStack);
ctx.getSource().getSender().sendRichMessage("<green>Successfully gave <player> a <item>",
Placeholder.component("player", player.name()),
Placeholder.component("item", Component.translatable(itemStack))
);
return Command.SINGLE_SUCCESS;
}
ctx.getSource().getSender().sendRichMessage("<red>This argument requires a player!");
return Command.SINGLE_SUCCESS;
}))
.build();
}

This argument allows the user to provide any artificial (namespaced) key. The return value of this argument is a NamespacedKey, which makes it useful when dealing with Bukkit API.

public static LiteralCommandNode<CommandSourceStack> namespacedKeyArgument() {
return Commands.literal("namespacedkey")
.then(Commands.argument("key", ArgumentTypes.namespacedKey())
.executes(ctx -> {
final NamespacedKey key = ctx.getArgument("key", NamespacedKey.class);
ctx.getSource().getSender().sendRichMessage("You put in <aqua><key></aqua>!",
Placeholder.unparsed("key", key.toString())
);
return Command.SINGLE_SUCCESS;
}))
.build();
}

The time argument allows the user to define a time frame, similar to the Vanilla /time <set|time> <time> time argument. The user has 4 possible ways of inputting time:

  • Just as a number: This resolves to as usual ticks (/timearg 1 —> 1 tick)
  • With a t suffix: This also resolves to ticks (/timearg 1t —> 1 tick)
  • With a s suffix: This resolves to seconds, meaning multiplying the first number by 20. (/timearg 1s —> 20 ticks)
  • With a d suffix. This resolves as in-game days, meaning multiplying the first number by 24000. (/timearg 1d —> 24000 ticks)

If you choose to use this argument, it is advised to explain to the users what these suffixes mean, as real time (s suffix) is mixed with in-game time (t and d suffix).

The ArgumentTypes.time() method has one additional overload: ArgumentTypes.time(int mintime). This allows to set the minimum required amount of ticks this argument has to resolve to. By default this value is set to 0.

public static LiteralCommandNode<CommandSourceStack> timeArgument() {
return Commands.literal("timearg")
.then(Commands.argument("time", ArgumentTypes.time())
.executes(ctx -> {
final int timeInTicks = IntegerArgumentType.getInteger(ctx, "time");
if (ctx.getSource().getExecutor() instanceof Player player) {
player.getWorld().setFullTime(player.getWorld().getFullTime() + timeInTicks);
player.sendRichMessage("Moved time forward by " + timeInTicks + " ticks!");
return Command.SINGLE_SUCCESS;
}
ctx.getSource().getSender().sendPlainMessage("This argument requires a player!");
return Command.SINGLE_SUCCESS;
})
).build();
}

The UUID argument allows the user to input a valid UUID. You can retrieve that value as a UUID object, which is used in various places, like Bukkit.getOfflinePlayer(UUID). This argument is not very user-friendly, which is why it is suggested to only use this as a moderation or debug argument. For user input regarding offline player retrieval, the player profiles argument is preferred, as it allows by-name lookup.

public static LiteralCommandNode<CommandSourceStack> uuidArgument() {
return Commands.literal("uuid-lookup")
.then(Commands.argument("uuid", ArgumentTypes.uuid())
.executes(ctx -> {
final UUID uuid = ctx.getArgument("uuid", UUID.class);
final OfflinePlayer result = Bukkit.getOfflinePlayer(uuid);
ctx.getSource().getSender().sendRichMessage("Has <aqua><uuid></aqua> played before: <result>",
Placeholder.unparsed("uuid", uuid.toString()),
Placeholder.parsed("result", result.hasPlayedBefore() ? "<green>true</green>" : "<red>false</red>")
);
return Command.SINGLE_SUCCESS;
})
).build();
}

You can retrieve the argument value as a Criteria enum value, which can be used with Scoreboard objects.

public static LiteralCommandNode<CommandSourceStack> objectiveCriteriaArgument() {
return Commands.literal("objectivecriteria")
.then(Commands.argument("criteria", ArgumentTypes.objectiveCriteria())
.executes(ctx -> {
final Criteria criteria = ctx.getArgument("criteria", Criteria.class);
ctx.getSource().getSender().sendRichMessage("Default render type for <criteria>: <rendertype>",
Placeholder.unparsed("criteria", criteria.getName()),
Placeholder.unparsed("rendertype", criteria.getDefaultRenderType().name())
);
return Command.SINGLE_SUCCESS;
}))
.build();
}