> ## Documentation Index
> Fetch the complete documentation index at: https://wiki.refineryteam.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Command Framework

> Annotation-driven commands, subcommands, permissions, cooldowns, and tab-completion.

RefineryCore's command framework (`xyz.refineryteam.refinerycore.api.command`) lets you define a command as a single class with annotated methods, instead of hand-writing a `CommandExecutor` and `TabCompleter` and manually parsing `args[0]`.

## Defining a command

Annotate a class extending `RefineryCommand` with `@Command`, then annotate methods with `@DefaultHandler` (runs with no subcommand) or `@Subcommand` (runs for a named subcommand):

```java RefineryCoreCommand.java icon="java" theme={"system"}
@Command(
        name = "refinery",
        aliases = { "refinerycore" },
        description = "The main command for the RefineryCore plugin",
        permission = "refinerycore.admin"
)
public class RefineryDefaultCommand extends RefineryCommand {

    private final RefineryCorePlugin plugin;

    public RefineryDefaultCommand(RefineryCorePlugin plugin) {
        this.plugin = plugin;
    }

    @DefaultHandler
    public void onDefault(@NonNull CommandContext ctx) {
        ctx.replyRefineryPrefix("<green>You are running RefineryCore version " + plugin.getPluginMeta().getVersion());
    }

    @Subcommand(
            value = "reload",
            description = "Reloads the configurations of the core plugin",
            permission = "refinerycore.commands.reload"
    )
    public void onReload(@NonNull CommandContext context) {
        context.executiveContext(plugin::reload)
                .onSuccess(() -> context.replyRefineryPrefix("<green>Reloaded successfully."))
                .onFailure(e -> context.replyRefineryPrefix("<red>Something went wrong."));
    }
}
```

### `@Command`

Applied to the class. Fields:

| Field         | Description                                                                                        |
| ------------- | -------------------------------------------------------------------------------------------------- |
| `name`        | The command's primary label (e.g. `/refinery`)                                                     |
| `description` | Shown in `/help` and command metadata                                                              |
| `aliases`     | Additional labels that route to the same command                                                   |
| `permission`  | If set, checked against the **root** command — applies to every subcommand and the default handler |

### `@Subcommand`

Applied to a method. Matched against `args[0]` (case-insensitive).

| Field         | Description                                                                             |
| ------------- | --------------------------------------------------------------------------------------- |
| `value`       | The subcommand's literal name, e.g. `"reload"` for `/refinery reload`                   |
| `description` | Shown in the auto-generated help menu                                                   |
| `permission`  | Checked in addition to the root command's permission                                    |
| `completions` | Tab-completion specs for each argument position (see [Tab completion](#tab-completion)) |

### `@DefaultHandler`

Applied to a method that runs when no argument matches a registered subcommand (including zero arguments). A command can have at most one.

### `@PlayerOnly`

Applied to a `@Subcommand` or `@DefaultHandler` method to reject non-player senders. Calls `onPlayerOnly(context)` (overridable) instead of running the method.

### `@Cooldown`

Applied to a `@Subcommand` or `@DefaultHandler` method to rate-limit it per player:

```java KitCommand.java icon="java" theme={"system"}
@Cooldown(value = 10, unit = TimeUnit.SECONDS, bypassPermission = "myplugin.bypass.cooldown")
@Subcommand(value = "kit", description = "Claim your daily kit")
public void onKit(@NonNull CommandContext ctx) {
    // ...
}
```

* Console senders and non-player senders always bypass the cooldown.
* `bypassPermission` (optional) lets specific senders skip the cooldown entirely.
* `message` (optional) customizes the rejection message; the `%time%` placeholder is replaced with the remaining seconds. Default: `<red>Wait <white>%time%s</white> before using this again.`

Cooldowns are tracked per (class, method, player) via a shared `CooldownManager` instance internal to the command bridge — you don't need to manage this yourself.

## Registering a command

Register your command instance through `getCommandRegistry()` (available via `RefineryPluginImplementation`), typically in `onEnable()`:

```java Plugin.java icon="java" theme={"system"}
@Override
public void onEnable() {
    getCommandRegistry().register(new RefineryDefaultCommand(this));
}
```

`CommandRegistry` reflectively registers the command directly into the server's `CommandMap` — you do **not** need to declare the command in `plugin.yml` or `paper-plugin.yml`.

## `CommandContext`

Every handler method receives a `CommandContext` (or takes no arguments, if you don't need it) with helpers for reading arguments and replying:

```java GiveCommand.java icon="java" theme={"system"}
public void onGive(@NonNull CommandContext ctx) {
    Optional<Player> target = ctx.argPlayer(0);
    Optional<Integer> amount = ctx.argInt(1);

    if (target.isEmpty() || amount.isEmpty()) {
        ctx.reply("<red>Usage: /give <player> <amount>");
        return;
    }

    // ...
}
```

Key methods:

| Method                                                                      | Description                                                                                                              |
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `sender()` / `player()`                                                     | The raw `CommandSender`, or the sender cast to `Player` (throws if not a player)                                         |
| `isPlayer()`                                                                | Whether the sender is a player                                                                                           |
| `args()` / `argCount()`                                                     | Raw argument array / count                                                                                               |
| `arg(int)`                                                                  | Raw string argument as `Optional<String>`                                                                                |
| `argInt` / `argDouble` / `argLong` / `argBoolean` / `argEnum` / `argPlayer` | Typed argument parsing, each returning an empty `Optional` on parse failure                                              |
| `joinArgs(int)`                                                             | Joins all arguments from an index onward with spaces (useful for reason/message arguments)                               |
| `reply(String)`                                                             | Sends a MiniMessage-formatted message                                                                                    |
| `replyRefineryPrefix(String)`                                               | Same, but prefixed with the Refinery gradient prefix                                                                     |
| `permission(String)`                                                        | Shorthand for `sender().hasPermission(...)`                                                                              |
| `executiveContext(ExecutiveContext)`                                        | Runs a block of code, catching exceptions, and returns an `ExecutiveResult` for `.onSuccess()` / `.onFailure()` chaining |

## Overridable behavior

`RefineryCommand` provides default implementations you can override:

```java MyCommand.java icon="java" theme={"system"}
@Override
public void onNoMatch(@NonNull CommandContext context) {
    context.reply("<red>Unknown subcommand — try /mycommand help");
}

@Override
public void onPermissionDenied(@NonNull CommandContext context) {
    context.reply("<red>You don't have permission to do that.");
}

@Override
public void onPlayerOnly(@NonNull CommandContext context) {
    context.reply("<red>This command can only be used by players.");
}
```

## Help menu

Calling `instance.onHelp(context)` — triggered automatically when a sender runs `<command> help` — renders a formatted, hoverable/clickable help menu built from every `@Subcommand` method's metadata, via `HelpMenu`. Customize the header/footer text with `@HelpInfo` on the command class:

```java KitsCommand.java icon="java" theme={"system"}
@Command(name = "kits")
@HelpInfo(header = "Kit Commands", footer = "Need help? Ask in #support.")
public class KitsCommand extends RefineryCommand { /* ... */ }
```

Each entry shows the subcommand's usage, description, and permission node on hover, and clicking suggests the command in chat.

## Tab completion

Provide `completions` on `@Subcommand` — one spec string per argument position, matched by index:

```java GiveCommand.java icon="java" theme={"system"}
@Subcommand(
        value = "give",
        completions = { "<player>", "<number>" }
)
public void onGive(@NonNull CommandContext ctx) { /* ... */ }
```

Supported completion specs:

| Spec                               | Resolves to                                            |
| ---------------------------------- | ------------------------------------------------------ |
| `<player>`                         | Online player names                                    |
| `<boolean>`                        | `true` / `false`                                       |
| `<number>`                         | No suggestions (numbers aren't enumerable)             |
| `<enum:fully.qualified.ClassName>` | Lowercased enum constant names of the given enum class |
| `a\|b\|c`                          | Literal pipe-separated options                         |

Subcommand names themselves are also tab-completed automatically (filtered by the sender's permission for each subcommand).
