---
title: Command Context
type: docs
weight: 4
---

The `CommandContext` provides access to command execution information, including the sender, parsed arguments, and the original input string.

## Accessing the Context

The context is passed to your `execute()` method:

```java
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
    // Use context here
    return null;
}
```

## Command Sender

Get the entity or console that executed the command:

```java
CommandSender sender = context.sender();

// Send messages (must use Message class)
sender.sendMessage(Message.raw("Hello!"));
sender.sendMessage(Message.translation("my.translation.key"));

// Check permissions
if (sender.hasPermission("myplugin.admin")) {
    // ...
}
```

### Checking Sender Type

```java
if (context.sender() instanceof Player) {
    Player player = (Player) context.sender();
    // Player-specific logic
} else {
    // Console or other sender
    context.sender().sendMessage("This command requires a player!");
}
```

## Getting Arguments

### Required Arguments

```java
private final RequiredArg<PlayerRef> playerArg;
private final RequiredArg<Integer> countArg;

// In execute():
PlayerRef player = context.get(playerArg);  // Never null for required args
int count = context.get(countArg);          // Never null for required args
```

### Optional Arguments

```java
private final OptionalArg<String> reasonArg;

// Get value (may be null if not provided)
String reason = context.get(reasonArg);

// Check if provided before using
if (context.provided(reasonArg)) {
    String reason = context.get(reasonArg);
}
```

### Default Arguments

```java
private final DefaultArg<Integer> countArg;  // Default: 1

// Always returns a value (never null)
int count = context.get(countArg);  // Returns default if not specified
```

### Flag Arguments

```java
private final FlagArg silentFlag;

// Check if flag was provided
boolean isSilent = context.provided(silentFlag);
```

## Input String

Access the original command input:

```java
String input = context.getInputString();
// For "/give player123 sword 5" -> "give player123 sword 5"
```

## The Command

Access the command being executed:

```java
AbstractCommand command = context.getCalledCommand();
String commandName = command.getName();
String fullName = command.getFullyQualifiedName();  // e.g., "admin kick"
```

## Argument Type Fallback Behavior

Some argument types have special processing with fallback behavior. This is handled by the argument type's `processedGet()` method:

### PLAYER_REF Fallback

When using `PLAYER_REF` with optional arguments:
- If argument is not provided and sender is a player, the argument type can return the sender's PlayerRef

```java
// Note: This fallback behavior is in the argument type, not CommandContext
private final OptionalArg<PlayerRef> targetArg;

@Override
protected CompletableFuture<Void> execute(CommandContext context) {
    PlayerRef target = context.get(targetArg);

    // Manual fallback if null
    if (target == null && context.sender() instanceof Player player) {
        target = player.getPlayerRef();
    }
    // ...
}
```

### World Argument Fallback

When using `WORLD` with optional arguments:
- If not specified and sender is player, returns player's world
- If only one world exists, returns that world

```java
private final OptionalArg<World> worldArg;

@Override
protected CompletableFuture<Void> execute(CommandContext context) {
    World world = context.get(worldArg);

    // Manual fallback if null
    if (world == null && context.sender() instanceof Player player) {
        world = player.getWorld();
    }
    // ...
}
```

## Error Handling

Commands can throw exceptions for error cases:

```java
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
    PlayerRef playerRef = context.get(playerArg);

    // Check if player is online via ECS reference
    Ref<EntityStore> ref = playerRef.getReference();
    if (ref == null || !ref.isValid()) {
        throw new GeneralCommandException(
            Message.translation("error.player.offline")
                .param("player", playerRef.getUsername())
        );
    }

    // Continue execution with valid reference
    return null;
}
```

## Asynchronous Commands

Return a `CompletableFuture` for async operations:

```java
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
    if (!(context.sender() instanceof Player player)) {
        return null;
    }

    PlayerRef playerRef = player.getPlayerRef();  // Note: deprecated
    World world = player.getWorld();

    return CompletableFuture.runAsync(() -> {
        // Async operation (e.g., database query)
        // PlayerData data = database.loadData(playerRef.getUuid());

        // Return to world thread for game logic
        world.execute(() -> {
            Ref<EntityStore> ref = playerRef.getReference();
            if (ref != null && ref.isValid()) {
                // applyData(ref, data);
                playerRef.sendMessage(Message.raw("Data loaded!"));
            }
        });
    });
}
```

## Complete Example

```java
public class GiveCommand extends AbstractCommand {

    private final RequiredArg<Item> itemArg;
    private final OptionalArg<PlayerRef> targetArg;
    private final DefaultArg<Integer> countArg;
    private final FlagArg silentFlag;

    public GiveCommand() {
        super("give", "Give items to a player");

        itemArg = withRequiredArg("item", "Item to give", ArgTypes.ITEM_ASSET);
        targetArg = withOptionalArg("target", "Target player", ArgTypes.PLAYER_REF);
        countArg = withDefaultArg("count", "Amount", ArgTypes.INTEGER, 1, "1");
        silentFlag = withFlagArg("silent", "Don't broadcast");
    }

    @Override
    protected CompletableFuture<Void> execute(CommandContext context) {
        // Get arguments
        Item item = context.get(itemArg);
        int count = context.get(countArg);  // Uses default if not specified
        boolean silent = context.provided(silentFlag);

        // Get target with fallback to sender
        PlayerRef targetRef = context.get(targetArg);
        if (targetRef == null && context.sender() instanceof Player senderPlayer) {
            targetRef = senderPlayer.getPlayerRef();  // Note: deprecated
        }

        if (targetRef == null) {
            throw new GeneralCommandException(
                Message.raw("Must specify a target player!")
            );
        }

        // Validate target is online via ECS reference
        Ref<EntityStore> ref = targetRef.getReference();
        if (ref == null || !ref.isValid()) {
            throw new GeneralCommandException(
                Message.raw("Player is not online!")
            );
        }

        // Execute - give item to player via ECS
        // ...

        // Feedback
        if (!silent) {
            context.sendMessage(Message.raw(
                "Gave " + count + "x " + item.getId() + " to " + targetRef.getUsername()
            ));
        }

        return null;
    }
}
```
