Init
This commit is contained in:
272
content/core-concepts/commands/command-context.en.md
Normal file
272
content/core-concepts/commands/command-context.en.md
Normal file
@@ -0,0 +1,272 @@
|
||||
---
|
||||
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;
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user