273 lines
6.9 KiB
Markdown
273 lines
6.9 KiB
Markdown
---
|
|
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;
|
|
}
|
|
}
|
|
```
|