Skip to content

Command Builder

darksoldier1404 edited this page Jan 28, 2026 · 1 revision

For a full list of wiki pages, see the Home page.

Command Builder

DPP-Core's CommandBuilder provides a powerful, fluent API for creating complex command structures with minimal boilerplate. It simplifies handling sub-commands, argument parsing, type validation, and tab completion.

Getting Started

To create a command, you first instantiate a CommandBuilder and then use its methods to define the command's behavior. Finally, you register it with a command defined in your plugin.yml.

plugin.yml:

commands:
  mycmd:
    description: My awesome command.
    usage: /<command>

In your onEnable method:

import com.darksoldier1404.dppc.builder.command.CommandBuilder;

// ... inside onEnable
CommandBuilder builder = new CommandBuilder(this);
// ... define sub-commands and arguments (see below)
builder.build("mycmd"); // This registers the executor and tab completer

Defining Sub-Commands

The CommandBuilder is designed around the concept of sub-commands. You can define what happens when a sub-command is executed.

Fluent Sub-Command Builder (Recommended)

The recommended way to define a sub-command is by using the beginSubCommand method, which returns a SubCommandBuilder instance.

builder.beginSubCommand("set", "/mycmd set <player> <value>")
    .withPermission("mycmd.set") // Optional: set a permission
    .playerOnly() // Optional: restrict to players only
    .withArgument(ArgumentIndex.ARG_0, ArgumentType.PLAYER) // Define the first argument
    .withArgument(ArgumentIndex.ARG_1, ArgumentType.INTEGER) // Define the second argument
    .executesPlayer((player, args) -> { // Define the executor logic
        Player target = args.getPlayer(ArgumentIndex.ARG_0);
        int value = args.getInteger(ArgumentIndex.ARG_1);

        if (target == null) {
            player.sendMessage("Target player not found.");
            return false; // Return false to show usage message
        }

        // Your logic here...
        player.sendMessage("You set " + target.getName() + "'s value to " + value);
        return true; // Return true on success
    });

Argument Handling

Arguments are defined using the withArgument and withOptionalArgument methods.

  • withArgument(ArgumentIndex index, ArgumentType type): Defines a required argument.
  • withOptionalArgument(...): Defines an optional argument.

ArgumentIndex

This enum represents the position of the argument after the sub-command. ARG_0 is the first argument, ARG_1 is the second, and so on.

ArgumentType

This enum tells the builder how to parse and tab-complete the argument. The builder handles all the validation and conversion for you.

Available Types: PLAYER, OFFLINE_PLAYER, BYTE, SHORT, INTEGER, FLOAT, DOUBLE, BOOLEAN, CHAR, STRING, STRING_ARRAY, WORLD, MATERIAL, ENTITY_TYPE

Accessing Arguments

Inside your executor, you receive a CommandArguments object. You can retrieve the parsed and type-safe argument values using its getter methods, such as getPlayer(ArgumentIndex.ARG_0) or getString(ArgumentIndex.ARG_1).

Tab Completion

CommandBuilder provides automatic tab completion for most ArgumentTypes (e.g., player names, material names, world names).

You can also provide your own suggestions.

Static Suggestions

Provide a collection of strings for simple static suggestions.

.withArgument(ArgumentIndex.ARG_0, ArgumentType.STRING, Arrays.asList("easy", "medium", "hard"))

Dynamic Suggestions

Provide a function for dynamic suggestions based on the player or current arguments.

.withArgument(ArgumentIndex.ARG_1, ArgumentType.STRING, (player, args) -> {
    // args here is the raw String[] of the command input
    if (player.hasPermission("mycmd.admin")) {
        return Arrays.asList("admin_option1", "admin_option2");
    }
    return Arrays.asList("user_option1", "user_option2");
})

Full Example

This example demonstrates a /dps command with multiple sub-commands, permissions, and argument types.

// In your DPlugin class
public void registerCommands() {
    CommandBuilder builder = new CommandBuilder(this);

    // /dps help
    builder.beginSubCommand("help", "/dps help")
        .executes((sender, args) -> {
            sender.sendMessage("--- DPS Help ---");
            sender.sendMessage("/dps reload - Reloads the plugin.");
            sender.sendMessage("/dps set <player> <stat> <value> - Sets a player's stat.");
            return true;
        });

    // /dps reload
    builder.beginSubCommand("reload", "/dps reload")
        .withPermission("dps.admin")
        .executes((sender, args) -> {
            // your reload logic
            sender.sendMessage(getPrefix() + "Plugin reloaded.");
            return true;
        });

    // /dps set <player> <stat> <value>
    builder.beginSubCommand("set", "/dps set <player> <stat> <value>")
        .withPermission("dps.admin")
        .playerOnly()
        .withArgument(ArgumentIndex.ARG_0, ArgumentType.PLAYER)
        .withArgument(ArgumentIndex.ARG_1, ArgumentType.STRING, Arrays.asList("strength", "agility", "intellect"))
        .withArgument(ArgumentIndex.ARG_2, ArgumentType.INTEGER)
        .executesPlayer((player, args) -> {
            Player target = args.getPlayer(ArgumentIndex.ARG_0);
            String stat = args.getString(ArgumentIndex.ARG_1);
            Integer value = args.getInteger(ArgumentIndex.ARG_2);

            if (target == null || stat == null || value == null) {
                return false; // Show usage message
            }

            // Logic to set the player's stat
            player.sendMessage(getPrefix() + "Set " + target.getName() + "'s " + stat + " to " + value + ".");
            return true;
        });

    builder.build("dps");
}

Clone this wiki locally