Create a subcommand

Since version 3.0 it is possible to create your own subcommands using the plugin API.

Summary

Admin subcommand

To add your own admin subcommand, you need to create a class that extends AdminCommandBase. This class requires three methods to be overide: getName(), getPermission() and execute(CommandSender sender, String[] args). Here is an example of implementation:

public class MyAdminCommand extends AdminCommandBase {

    @Override
    public String getName() {
        return "hello";
    }

    @Override
    public String getPermission() {
        return "odailyquests.admin.hello";
    }

    @Override
    public void execute(CommandSender sender, String[] args) {
        if (args.length == 2 && args[1] != null) {
            final Player target = getTargetPlayer(sender, args[1]);
            if (target == null) return;

            sendHelloMessage(sender, target);
        } else {
            help(sender);
        }
    }

    private void sendHelloMessage(CommandSender sender, Player target) {
        target.sendMessage("Hello from " + sender.getName() + "!");
        sender.sendMessage("You greeted " + target.getName() + ".");
    }
}

In this case, the command will be /dqa hello <target>. It will require the odailyquests.admin.hello permission. You don't need to check that the user has permission, ODailyQuests takes care of that for you! It will use the value returned by the getPermission() method.

The AdminCommandBase class itself inherits from a AdminMessages class, which contains utility methods to avoid duplication of code, which you can also use. They all return messages present in the messages.yml file.

The AdminCommandBase class also provides two methods for retrieving a player and parse a quest identifier, getTargetPlayer(...) and parseQuestIndex(...).

    /**
     * Retrieves a player instance by their exact name.
     * 
     * If the player is not found (offline or name mismatch), sends an "invalid player" message
     * to the sender and returns null.
     *
     * @param sender     the command sender (used to send feedback in case of an invalid player)
     * @param playerName the exact name of the target player
     * @return the target Player if found, or null otherwise
     */
    protected Player getTargetPlayer(CommandSender sender, String playerName)
    
    /**
     * Parses an integer value from a string argument.
     * 
     * If the argument is not a valid number, sends an "invalid quest index" message
     * to the sender and returns -1 as a fallback.
     *
     * @param sender the command sender (used to send feedback in case of invalid input)
     * @param arg    the string to parse as an integer
     * @return the parsed integer value, or -1 if the input was invalid
     */
    protected int parseQuestIndex(CommandSender sender, String arg);

Player subcommand

To add your own player subcommand, you need to create a class that extends PlayerCommandBase. This class requires three methods to be overide: getName(), getPermission() and execute(Player player, String[] args). Here is an example of implementation:

public class MyPlayerCommand extends PlayerCommandBase {
    
    @Override
    public String getName() {
        return "hello";
    }

    @Override
    public String getPermission() {
        return "odailyquests.hello";
    }

    @Override
    public void execute(CommandSender sender, String[] args) {
        if (!(sender instanceof Player player)) {
            playerOnly(sender);
            return;
        }

        sender.sendMessage("Hello from my custom command!");
    }
}

In this case, the command will be /dq hello. It will require the odailyquests.hello permission. You don't need to check that the user has permission, ODailyQuests takes care of that for you! It will use the value returned by the getPermission() method.

The PlayerCommandBase class itself inherits from a PlayerMessages class, which contains utility methods to avoid duplication of code, which you can also use. They all return messages present in the messages.yml file.

Method
Associated message

Register your command

You can register your command in the onEnable() method of your main class, by retrieving the AdminCommandRegistry or PlayerCommandRegistry, dependeing of the type of command.

@Override
public void onEnable() {
    AdminCommandRegistry adminRegistry = API.getAdminCommandRegistry();
    adminRegistry.registerCommand(new MyAdminCommand());
        
    PlayerCommandRegistry playerRegistry = API.getPlayerCommandRegistry();
    playerRegistry.registerCommand(new MyPlayerCommand());
}

Tab completion

Depending on how you use it, you'll probably want to add auto completion to your commands. You can do this by overriding the onTabComplete(CommandSender sender, String[] args) method, which is included in both AdminCommandBase and PlayerCommandBase. By default, this method returns an empty list.

Note that if you want to return the players' nicknames, you'll have to return null instead of an empty list. This is a specific Bukkit behaviour.

Here is an example of tab completion for our MyAdminCommand class.

@Override
public List<String> onTabComplete(@NotNull CommandSender sender, String[] args) {
    // Suggest "hello" if it's the first argument after the command
    if (args.length == 2) {
        return List.of("hello");
    }

    // Suggest player names if the second argument is "hello"
    if (args.length == 3 && args[1].equalsIgnoreCase("hello")) {
        // Returning null makes Bukkit auto-complete with online player names
        return null;
    }

    return Collections.emptyList();
}

Last updated