Skip to main content

Overview

SimpleCommand is the base class for creating commands in Foundation. It provides a clean, intuitive API that replaces Bukkit’s command system with enhanced features like automatic permission handling, cooldowns, argument validation, and built-in messaging utilities.

Class hierarchy

org.bukkit.command.Command
  └── org.mineacademy.fo.command.SimpleCommand

Creating a command

Constructor

SimpleCommand(String label)
constructor
Creates a new simple command with the given label.Separate the label with | to split between label and aliases.Example: remove|r|rm will create a /remove command that can also be run by typing /r and /rm as its aliases.
SimpleCommand(String label, List<String> aliases)
constructor
Creates a new simple command with explicit label and aliases.

Basic example

public class ReloadCommand extends SimpleCommand {
    
    public ReloadCommand() {
        super("reload|rl");
        
        setDescription("Reloads the plugin configuration");
        setUsage("[config|data]");
        setPermission("myplugin.command.reload");
        setMinArguments(0);
    }
    
    @Override
    protected void onCommand() {
        tellSuccess("Plugin reloaded successfully!");
    }
}

Registration

register()

register()
void
Registers this command into Bukkit.Throws an error if the command is already registered.

register(boolean unregisterOldAliases)

register(boolean unregisterOldAliases)
void
Registers this command into Bukkit with options.

unregister()

unregister()
void
Removes the command from Bukkit.Throws an error if the command is not registered.
// Register a command
ReloadCommand reloadCmd = new ReloadCommand();
reloadCmd.register();

// Later unregister it
reloadCmd.unregister();

Core methods

onCommand()

onCommand()
abstract void
Required implementation. Executed when the command is run.You can access sender and args fields directly within this method.
@Override
protected void onCommand() {
    if (args.length == 0) {
        tell("Usage: /mycommand <player>");
        return;
    }
    
    Player target = findPlayer(args[0]);
    tell("Found player: " + target.getName());
}

Convenience checks

These methods throw CommandException internally which is caught and displayed to the player.

checkConsole()

checkConsole()
void
Checks if the sender is console and throws an error if they are.Use this for player-only commands.
@Override
protected void onCommand() {
    checkConsole(); // Only players can run this
    
    Player player = getPlayer();
    // Do something with player...
}

checkPerm(String permission)

checkPerm(String permission)
void
Checks if the sender has the given permission.

checkArgs(int minimumLength, String falseMessage)

checkArgs(int minimumLength, String falseMessage)
void
Checks if the command has the minimum number of arguments.

checkBoolean(boolean value, String falseMessage)

checkBoolean(boolean value, String falseMessage)
void
Checks if the given boolean is true, throws error with message if false.
checkBoolean(player.getHealth() > 0, "You must be alive to use this!");

checkNotNull(Object value, String messageIfNull)

checkNotNull(Object value, String messageIfNull)
void
Checks if the given object is not null.

Finding entities and values

findPlayer(String name)

findPlayer(String name)
Player
Finds a non-vanished online player by name.Returns an error message to sender if player not found.

findPlayerOrSelf(int argsIndex)

findPlayerOrSelf(int argsIndex)
Player
Returns the player at the given args index, or the sender if they are a player and args are too short.
Player target = findPlayerOrSelf(0); // /heal or /heal <player>
tellSuccess("Healed " + target.getName());

findOfflinePlayer(String name, Consumer<OfflinePlayer> callback)

findOfflinePlayer(String name, Consumer<OfflinePlayer> callback)
void
Finds an offline player by name or UUID asynchronously.The lookup is done async, callback is executed synchronously.
findOfflinePlayer(args[0], offlinePlayer -> {
    tell("Player last played: " + offlinePlayer.getLastPlayed());
});

findWorld(String name)

findWorld(String name)
World
Finds a world by name. Use ~ to get the sender’s current world (if sender is a player).

findMaterial(String name, String falseMessage)

findMaterial(String name, String falseMessage)
CompMaterial
Finds a material by name, works for both modern and legacy names.

findEnum(Class<T> enumType, String value, String falseMessage)

findEnum(Class<T> enumType, String value, String falseMessage)
T extends Enum<T>
Finds an enumeration value by name.
GameMode mode = findEnum(GameMode.class, args[0], 
    "Invalid game mode {enum}! Available: {available}");

findNumber(int index, String falseMessage)

findNumber(int index, String falseMessage)
int
Parses an integer from the args at the given index.

findNumber(int index, int min, int max, String falseMessage)

findNumber(int index, int min, int max, String falseMessage)
int
Parses an integer within bounds from the args at the given index.
int amount = findNumber(0, 1, 64, "Amount must be between {min} and {max}!");

findBoolean(int index, String invalidMessage)

findBoolean(int index, String invalidMessage)
boolean
Parses a boolean from the args at the given index.

findTime(String raw)

findTime(String raw)
SimpleTime
Converts a time string (e.g., “1 hour”, “30 minutes”) into a SimpleTime object.

Messaging

tell(String… messages)

tell(String... messages)
void
Sends messages to the command sender.Automatically avoids prefix if 3 or more lines.

tellNoPrefix(String… messages)

tellNoPrefix(String... messages)
void
Sends messages without any prefix.

tellSuccess(String message)

tellSuccess(String message)
void
Sends a success message (typically green).

tellInfo(String message)

tellInfo(String message)
void
Sends an info message (typically blue).

tellWarn(String message)

tellWarn(String message)
void
Sends a warning message (typically yellow).

tellError(String message)

tellError(String message)
void
Sends an error message (typically red).

returnTell(String… messages)

returnTell(String... messages)
void
Sends messages and stops command execution by throwing CommandException.
if (!player.hasPermission("special.feature")) {
    returnTell("You need special permission!");
    // Code here never executes
}

Configuration

setMinArguments(int minArguments)

setMinArguments(int minArguments)
void
Sets the minimum number of arguments required to run this command.

setCooldown(int cooldown, TimeUnit unit)

setCooldown(int cooldown, TimeUnit unit)
void
Sets the cooldown time before the same player can execute this command again.
public MyCommand() {
    super("mycommand");
    setCooldown(30, TimeUnit.SECONDS);
}

setCooldownBypassPermission(String permission)

setCooldownBypassPermission(String permission)
void
Sets a permission that allows players to bypass the cooldown.

setCooldownMessage(String message)

setCooldownMessage(String message)
void
Sets a custom cooldown message. Use {duration} to display remaining time.

setPermission(String permission)

setPermission(String permission)
void
Sets the permission required to run this command.Set to null to allow everyone (unsafe).

setTellPrefix(String prefix)

setTellPrefix(String prefix)
void
Sets a custom prefix for messages sent by this command.

Tab completion

tabComplete()

tabComplete()
List<String>
Override this method to provide tab completion suggestions.Return null to complete player names automatically.
@Override
protected List<String> tabComplete() {
    if (args.length == 1)
        return completeLastWord("create", "delete", "list");
    
    if (args.length == 2 && args[0].equals("delete"))
        return completeLastWord(getArenaNames());
    
    return NO_COMPLETE; // Disable tab completion
}

completeLastWord(T… suggestions)

completeLastWord(T... suggestions)
List<String>
Automatically completes the last argument with the given suggestions.Only returns suggestions that start with what the player typed.

completeLastWordPlayerNames()

completeLastWordPlayerNames()
List<String>
Completes with all visible, non-vanished player names.

completeLastWordWorldNames()

completeLastWordWorldNames()
List<String>
Completes with all world names.

Utility methods

getPlayer()

getPlayer()
Player
Gets the sender as a Player, or null if sender is not a player.

isPlayer()

isPlayer()
boolean
Returns whether the sender is a living player.

hasPerm(String permission)

hasPerm(String permission)
boolean
Checks if the sender has the given permission.

getLastArg()

getLastArg()
String
Returns the last argument in the args array.

joinArgs(int from)

joinArgs(int from)
String
Joins arguments from the given index to the end with spaces.
String message = joinArgs(1); // Join all args after first one
tell("Message: " + message);

joinArgs(int from, int to)

joinArgs(int from, int to)
String
Joins arguments from the given range with spaces.

Protected fields

sender
CommandSender
The command sender. Updated dynamically when the command is executed.
args
String[]
The command arguments. Updated dynamically when the command is executed.
NO_COMPLETE
List<String>
default:"static final"
An empty list used to disable tab completion.

Complete example

public class TeleportCommand extends SimpleCommand {
    
    public TeleportCommand() {
        super("teleport|tp");
        
        setDescription("Teleport to a player or location");
        setUsage("<player> or <x> <y> <z>");
        setPermission("myplugin.command.teleport");
        setMinArguments(1);
        setCooldown(5, TimeUnit.SECONDS);
        setCooldownBypassPermission("myplugin.cooldown.bypass");
    }
    
    @Override
    protected void onCommand() {
        checkConsole(); // Players only
        
        Player player = getPlayer();
        
        // Teleport to player
        if (args.length == 1) {
            Player target = findPlayer(args[0]);
            
            player.teleport(target.getLocation());
            tellSuccess("Teleported to " + target.getName());
            return;
        }
        
        // Teleport to coordinates
        if (args.length == 3) {
            double x = findNumber(Double.class, 0, "Invalid X coordinate!");
            double y = findNumber(Double.class, 1, "Invalid Y coordinate!");
            double z = findNumber(Double.class, 2, "Invalid Z coordinate!");
            
            Location loc = new Location(player.getWorld(), x, y, z);
            player.teleport(loc);
            
            tellSuccess("Teleported to " + x + ", " + y + ", " + z);
            return;
        }
        
        returnInvalidArgs();
    }
    
    @Override
    protected List<String> tabComplete() {
        if (args.length == 1)
            return completeLastWordPlayerNames();
        
        return NO_COMPLETE;
    }
}

See also

Build docs developers (and LLMs) love