This commit is contained in:
2026-01-20 20:33:59 +01:00
commit b16a40e431
583 changed files with 87339 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
---
title: Commands
type: docs
weight: 1
---
Commands allow players and operators to interact with your plugin through the chat or console. This section covers how to create and register commands.
{{< cards >}}
{{< card link="creating-commands" title="Creating Commands" subtitle="Implement AbstractCommand for custom commands" >}}
{{< card link="argument-types" title="Argument Types" subtitle="All available ArgTypes and how to use them" >}}
{{< card link="subcommands" title="Subcommands" subtitle="Create command hierarchies" >}}
{{< card link="command-context" title="Command Context" subtitle="Access sender, arguments, and more" >}}
{{< /cards >}}

View File

@@ -0,0 +1,14 @@
---
title: Commandes
type: docs
weight: 1
---
Les commandes permettent aux joueurs et opérateurs d'interagir avec votre plugin via le chat ou la console. Cette section explique comment créer et enregistrer des commandes.
{{< cards >}}
{{< card link="creating-commands" title="Créer des Commandes" subtitle="Implémenter AbstractCommand pour des commandes personnalisées" >}}
{{< card link="argument-types" title="Types d'Arguments" subtitle="Tous les ArgTypes disponibles et comment les utiliser" >}}
{{< card link="subcommands" title="Sous-commandes" subtitle="Créer des hiérarchies de commandes" >}}
{{< card link="command-context" title="Contexte de Commande" subtitle="Accéder à l'expéditeur, arguments, et plus" >}}
{{< /cards >}}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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;
}
}
```

View 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;
}
}
```

View File

@@ -0,0 +1,264 @@
---
title: Creating Commands
type: docs
weight: 1
---
Commands in Hytale are created by extending the `AbstractCommand` class. This page covers the basics of creating and registering commands.
## Basic Command Structure
```java
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.server.core.Message;
import java.util.concurrent.CompletableFuture;
public class HelloCommand extends AbstractCommand {
public HelloCommand() {
super("hello", "Sends a greeting message");
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
context.sendMessage(Message.raw("Hello, World!"));
return null;
}
}
```
## Constructors
`AbstractCommand` provides several constructors:
```java
// Name and description
protected AbstractCommand(String name, String description)
// Name, description, and requires confirmation flag
protected AbstractCommand(String name, String description, boolean requiresConfirmation)
// Description only (for variant commands)
protected AbstractCommand(String description)
```
## Registering Commands
Register commands in your plugin's `start()` method:
```java
@Override
public void start() {
getCommandRegistry().registerCommand(new HelloCommand());
}
```
## Adding Aliases
Commands can have multiple names:
```java
public class TeleportCommand extends AbstractCommand {
public TeleportCommand() {
super("teleport", "Teleport to a location");
addAliases("tp", "warp");
}
// ...
}
```
Players can now use `/teleport`, `/tp`, or `/warp`.
## Command with Arguments
Add required arguments using `withRequiredArg`:
```java
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg;
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes;
// For ECS operations: import com.hypixel.hytale.component.Ref;
// For ECS operations: import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.Message;
import java.util.concurrent.CompletableFuture;
public class GiveCommand extends AbstractCommand {
private final RequiredArg<PlayerRef> targetArg;
private final RequiredArg<Item> itemArg;
public GiveCommand() {
super("give", "Give an item to a player");
targetArg = withRequiredArg("player", "Target player", ArgTypes.PLAYER_REF);
itemArg = withRequiredArg("item", "Item to give", ArgTypes.ITEM_ASSET);
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
PlayerRef targetRef = context.get(targetArg);
Item item = context.get(itemArg);
// PlayerRef provides direct access to player info
String username = targetRef.getUsername();
// For ECS operations, use getReference() to access the EntityStore
// Ref<EntityStore> entityRef = targetRef.getReference();
// Give item to player...
context.sendMessage(Message.raw("Gave item to " + username));
return null;
}
}
```
## Optional Arguments
Add optional arguments that don't need to be specified:
```java
private final OptionalArg<Integer> countArg;
public GiveCommand() {
super("give", "Give items to a player");
targetArg = withRequiredArg("player", "Target player", ArgTypes.PLAYER_REF);
itemArg = withRequiredArg("item", "Item to give", ArgTypes.ITEM_ASSET);
countArg = withOptionalArg("count", "Number of items", ArgTypes.INTEGER);
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
PlayerRef targetRef = context.get(targetArg);
Item item = context.get(itemArg);
Integer count = context.get(countArg); // May be null
int amount = count != null ? count : 1;
// Give items to player...
return null;
}
```
Usage: `/give player123 iron_sword` or `/give player123 iron_sword --count 5`
## Default Arguments
Arguments with default values:
```java
private final DefaultArg<Integer> countArg;
public GiveCommand() {
super("give", "Give items to a player");
countArg = withDefaultArg("count", "Number of items",
ArgTypes.INTEGER, 1, "defaults to 1");
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
int count = context.get(countArg); // Never null, uses default
// ...
}
```
## Flag Arguments
Boolean flags that can be toggled:
```java
private final FlagArg silentFlag;
public BroadcastCommand() {
super("broadcast", "Send a message to all players");
silentFlag = withFlagArg("silent", "Don't show sender name");
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
boolean silent = context.provided(silentFlag);
// ...
}
```
Usage: `/broadcast Hello everyone! --silent`
## List Arguments
For arguments that accept multiple values:
```java
private final RequiredArg<List<String>> playersArg;
public KickAllCommand() {
super("kickall", "Kick multiple players");
playersArg = withListRequiredArg("players", "Players to kick", ArgTypes.STRING);
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
List<String> players = context.get(playersArg);
for (String player : players) {
// Kick each player
}
return null;
}
```
Usage: `/kickall player1 player2 player3`
Available list argument methods:
- `withListRequiredArg(name, description, argType)` - Required list
- `withListOptionalArg(name, description, argType)` - Optional list
- `withListDefaultArg(name, description, argType, defaultValue, defaultDesc)` - List with default
## Requiring Confirmation
For dangerous commands, require explicit confirmation:
```java
public class ResetCommand extends AbstractCommand {
public ResetCommand() {
super("reset", "Reset all player data", true); // requiresConfirmation = true
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
// This only runs if --confirm was provided
resetAllData();
return null;
}
}
```
Usage: `/reset --confirm`
## Permissions
Commands automatically generate permissions based on your plugin name:
```
{group}.{plugin}.command.{commandname}
```
For example: `com.example.myplugin.command.give`
You can also set a custom permission:
```java
public GiveCommand() {
super("give", "Give items");
requirePermission("myplugin.admin.give");
}
```

View File

@@ -0,0 +1,264 @@
---
title: Créer des Commandes
type: docs
weight: 1
---
Les commandes dans Hytale sont créées en étendant la classe `AbstractCommand`. Cette page couvre les bases de la création et de l'enregistrement des commandes.
## Structure de Base d'une Commande
```java
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.server.core.Message;
import java.util.concurrent.CompletableFuture;
public class HelloCommand extends AbstractCommand {
public HelloCommand() {
super("hello", "Envoie un message de salutation");
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
context.sendMessage(Message.raw("Bonjour, le monde !"));
return null;
}
}
```
## Constructeurs
`AbstractCommand` fournit plusieurs constructeurs :
```java
// Nom et description
protected AbstractCommand(String name, String description)
// Nom, description, et flag de confirmation requise
protected AbstractCommand(String name, String description, boolean requiresConfirmation)
// Description seule (pour les commandes variantes)
protected AbstractCommand(String description)
```
## Enregistrer des Commandes
Enregistrez les commandes dans la méthode `start()` de votre plugin :
```java
@Override
public void start() {
getCommandRegistry().registerCommand(new HelloCommand());
}
```
## Ajouter des Alias
Les commandes peuvent avoir plusieurs noms :
```java
public class TeleportCommand extends AbstractCommand {
public TeleportCommand() {
super("teleport", "Téléporter vers un emplacement");
addAliases("tp", "warp");
}
// ...
}
```
Les joueurs peuvent maintenant utiliser `/teleport`, `/tp`, ou `/warp`.
## Commande avec Arguments
Ajoutez des arguments requis avec `withRequiredArg` :
```java
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.server.core.command.system.CommandContext;
import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg;
import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes;
// Pour les opérations ECS: import com.hypixel.hytale.component.Ref;
// Pour les opérations ECS: import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.Message;
import java.util.concurrent.CompletableFuture;
public class GiveCommand extends AbstractCommand {
private final RequiredArg<PlayerRef> targetArg;
private final RequiredArg<Item> itemArg;
public GiveCommand() {
super("give", "Donner un item à un joueur");
targetArg = withRequiredArg("player", "Joueur cible", ArgTypes.PLAYER_REF);
itemArg = withRequiredArg("item", "Item à donner", ArgTypes.ITEM_ASSET);
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
PlayerRef targetRef = context.get(targetArg);
Item item = context.get(itemArg);
// PlayerRef fournit un accès direct aux infos du joueur
String username = targetRef.getUsername();
// Pour les opérations ECS, utiliser getReference() pour accéder à l'EntityStore
// Ref<EntityStore> entityRef = targetRef.getReference();
// Donner l'item au joueur...
context.sendMessage(Message.raw("Item donné à " + username));
return null;
}
}
```
## Arguments Optionnels
Ajoutez des arguments optionnels qui n'ont pas besoin d'être spécifiés :
```java
private final OptionalArg<Integer> countArg;
public GiveCommand() {
super("give", "Donner des items à un joueur");
targetArg = withRequiredArg("player", "Joueur cible", ArgTypes.PLAYER_REF);
itemArg = withRequiredArg("item", "Item à donner", ArgTypes.ITEM_ASSET);
countArg = withOptionalArg("count", "Nombre d'items", ArgTypes.INTEGER);
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
PlayerRef targetRef = context.get(targetArg);
Item item = context.get(itemArg);
Integer count = context.get(countArg); // Peut être null
int amount = count != null ? count : 1;
// Donner les items au joueur...
return null;
}
```
Utilisation : `/give player123 iron_sword` ou `/give player123 iron_sword --count 5`
## Arguments par Défaut
Arguments avec valeurs par défaut :
```java
private final DefaultArg<Integer> countArg;
public GiveCommand() {
super("give", "Donner des items à un joueur");
countArg = withDefaultArg("count", "Nombre d'items",
ArgTypes.INTEGER, 1, "par défaut 1");
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
int count = context.get(countArg); // Jamais null, utilise la valeur par défaut
// ...
}
```
## Arguments Flag
Flags booléens qui peuvent être activés :
```java
private final FlagArg silentFlag;
public BroadcastCommand() {
super("broadcast", "Envoyer un message à tous les joueurs");
silentFlag = withFlagArg("silent", "Ne pas afficher le nom de l'expéditeur");
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
boolean silent = context.provided(silentFlag);
// ...
}
```
Utilisation : `/broadcast Bonjour à tous ! --silent`
## Arguments Liste
Pour les arguments qui acceptent plusieurs valeurs :
```java
private final RequiredArg<List<String>> playersArg;
public KickAllCommand() {
super("kickall", "Expulser plusieurs joueurs");
playersArg = withListRequiredArg("players", "Joueurs à expulser", ArgTypes.STRING);
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
List<String> players = context.get(playersArg);
for (String player : players) {
// Expulser chaque joueur
}
return null;
}
```
Utilisation : `/kickall player1 player2 player3`
Méthodes d'arguments liste disponibles :
- `withListRequiredArg(name, description, argType)` - Liste requise
- `withListOptionalArg(name, description, argType)` - Liste optionnelle
- `withListDefaultArg(name, description, argType, defaultValue, defaultDesc)` - Liste avec défaut
## Exiger une Confirmation
Pour les commandes dangereuses, exigez une confirmation explicite :
```java
public class ResetCommand extends AbstractCommand {
public ResetCommand() {
super("reset", "Réinitialiser toutes les données joueur", true); // requiresConfirmation = true
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
// Ceci ne s'exécute que si --confirm a été fourni
resetAllData();
return null;
}
}
```
Utilisation : `/reset --confirm`
## Permissions
Les commandes génèrent automatiquement des permissions basées sur le nom de votre plugin :
```
{group}.{plugin}.command.{commandname}
```
Par exemple : `com.example.myplugin.command.give`
Vous pouvez aussi définir une permission personnalisée :
```java
public GiveCommand() {
super("give", "Donner des items");
requirePermission("myplugin.admin.give");
}
```

View File

@@ -0,0 +1,224 @@
---
title: Subcommands
type: docs
weight: 3
---
Subcommands allow you to create hierarchical command structures, organizing related functionality under a single parent command.
## Creating Subcommands
### Basic Structure
```java
public class AdminCommand extends AbstractCommand {
public AdminCommand() {
super("admin", "Administration commands");
// Add subcommands
addSubCommand(new KickSubCommand());
addSubCommand(new BanSubCommand());
addSubCommand(new MuteSubCommand());
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
// This runs when no subcommand is specified
context.sender().sendMessage(Message.raw("Usage: /admin <kick|ban|mute>"));
return null;
}
}
```
### Subcommand Implementation
```java
public class KickSubCommand extends AbstractCommand {
private final RequiredArg<PlayerRef> playerArg;
private final OptionalArg<String> reasonArg;
public KickSubCommand() {
super("kick", "Kick a player from the server");
playerArg = withRequiredArg("player", "Player to kick", ArgTypes.PLAYER_REF);
reasonArg = withOptionalArg("reason", "Kick reason", ArgTypes.STRING);
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
PlayerRef target = context.get(playerArg);
String reason = context.get(reasonArg);
// Check if player is online via ECS reference
Ref<EntityStore> ref = target.getReference();
if (ref != null && ref.isValid()) {
// Disconnect via PacketHandler
String kickReason = reason != null ? reason : "Kicked by admin";
target.getPacketHandler().disconnect(kickReason);
context.sendMessage(Message.raw("Kicked " + target.getUsername()));
}
return null;
}
}
```
Usage: `/admin kick player123 --reason "Breaking rules"`
## Command Collections
For commands that only contain subcommands (no direct execution), extend `AbstractCommandCollection`:
```java
public class ManageCommand extends AbstractCommandCollection {
public ManageCommand() {
super("manage", "Management commands");
addSubCommand(new ManageUsersCommand());
addSubCommand(new ManageWorldsCommand());
addSubCommand(new ManagePluginsCommand());
}
}
```
With `AbstractCommandCollection`, running `/manage` without a subcommand will show available subcommands automatically.
## Nested Subcommands
Subcommands can have their own subcommands:
```java
public class ManageUsersCommand extends AbstractCommand {
public ManageUsersCommand() {
super("users", "User management");
addSubCommand(new ListUsersCommand()); // /manage users list
addSubCommand(new AddUserCommand()); // /manage users add
addSubCommand(new RemoveUserCommand()); // /manage users remove
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
// Show usage for /manage users
return null;
}
}
```
## Subcommand Aliases
Subcommands can have aliases just like regular commands:
```java
public class TeleportCommand extends AbstractCommand {
public TeleportCommand() {
super("teleport", "Teleport commands");
addAliases("tp");
addSubCommand(new TeleportHereCommand());
addSubCommand(new TeleportAllCommand());
}
}
public class TeleportHereCommand extends AbstractCommand {
public TeleportHereCommand() {
super("here", "Teleport player to you");
addAliases("h", "tome");
}
// ...
}
```
Now players can use:
- `/teleport here player1`
- `/tp here player1`
- `/tp h player1`
- `/tp tome player1`
## Command Variants
Variants allow the same command to accept different argument patterns:
```java
public class TpCommand extends AbstractCommand {
private final RequiredArg<PlayerRef> targetArg;
public TpCommand() {
super("tp", "Teleport command");
// Main variant: /tp <player>
targetArg = withRequiredArg("target", "Player to teleport to", ArgTypes.PLAYER_REF);
// Add variant: /tp <player> <destination>
addUsageVariant(new TpToPlayerVariant());
// Add variant: /tp <x> <y> <z>
addUsageVariant(new TpToPositionVariant());
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
// Teleport sender to target player
PlayerRef target = context.get(targetArg);
// ...
return null;
}
}
```
### Variant Implementation
```java
public class TpToPlayerVariant extends AbstractCommand {
private final RequiredArg<PlayerRef> playerArg;
private final RequiredArg<PlayerRef> destinationArg;
public TpToPlayerVariant() {
// No name for variants - use description only
super("Teleport one player to another");
playerArg = withRequiredArg("player", "Player to teleport", ArgTypes.PLAYER_REF);
destinationArg = withRequiredArg("destination", "Destination player", ArgTypes.PLAYER_REF);
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
PlayerRef player = context.get(playerArg);
PlayerRef destination = context.get(destinationArg);
// Teleport player to destination
return null;
}
}
```
{{< callout type="info" >}}
Variants are distinguished by the number of required parameters. Each variant must have a different number of required arguments.
{{< /callout >}}
## Permission Inheritance
Subcommand permissions are automatically built from the parent:
```
/admin -> myplugin.command.admin
/admin kick -> myplugin.command.admin.kick
/admin ban -> myplugin.command.admin.ban
```
You can also set custom permissions:
```java
public KickSubCommand() {
super("kick", "Kick a player");
requirePermission("myplugin.admin.kick");
}
```

View File

@@ -0,0 +1,224 @@
---
title: Subcommands
type: docs
weight: 3
---
Subcommands allow you to create hierarchical command structures, organizing related functionality under a single parent command.
## Creating Subcommands
### Basic Structure
```java
public class AdminCommand extends AbstractCommand {
public AdminCommand() {
super("admin", "Administration commands");
// Add subcommands
addSubCommand(new KickSubCommand());
addSubCommand(new BanSubCommand());
addSubCommand(new MuteSubCommand());
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
// This runs when no subcommand is specified
context.sender().sendMessage(Message.raw("Usage: /admin <kick|ban|mute>"));
return null;
}
}
```
### Subcommand Implementation
```java
public class KickSubCommand extends AbstractCommand {
private final RequiredArg<PlayerRef> playerArg;
private final OptionalArg<String> reasonArg;
public KickSubCommand() {
super("kick", "Kick a player from the server");
playerArg = withRequiredArg("player", "Player to kick", ArgTypes.PLAYER_REF);
reasonArg = withOptionalArg("reason", "Kick reason", ArgTypes.STRING);
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
PlayerRef target = context.get(playerArg);
String reason = context.get(reasonArg);
// Check if player is online via ECS reference
Ref<EntityStore> ref = target.getReference();
if (ref != null && ref.isValid()) {
// Disconnect via PacketHandler
String kickReason = reason != null ? reason : "Kicked by admin";
target.getPacketHandler().disconnect(kickReason);
context.sendMessage(Message.raw("Kicked " + target.getUsername()));
}
return null;
}
}
```
Usage: `/admin kick player123 --reason "Breaking rules"`
## Command Collections
For commands that only contain subcommands (no direct execution), extend `AbstractCommandCollection`:
```java
public class ManageCommand extends AbstractCommandCollection {
public ManageCommand() {
super("manage", "Management commands");
addSubCommand(new ManageUsersCommand());
addSubCommand(new ManageWorldsCommand());
addSubCommand(new ManagePluginsCommand());
}
}
```
With `AbstractCommandCollection`, running `/manage` without a subcommand will show available subcommands automatically.
## Nested Subcommands
Subcommands can have their own subcommands:
```java
public class ManageUsersCommand extends AbstractCommand {
public ManageUsersCommand() {
super("users", "User management");
addSubCommand(new ListUsersCommand()); // /manage users list
addSubCommand(new AddUserCommand()); // /manage users add
addSubCommand(new RemoveUserCommand()); // /manage users remove
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
// Show usage for /manage users
return null;
}
}
```
## Subcommand Aliases
Subcommands can have aliases just like regular commands:
```java
public class TeleportCommand extends AbstractCommand {
public TeleportCommand() {
super("teleport", "Teleport commands");
addAliases("tp");
addSubCommand(new TeleportHereCommand());
addSubCommand(new TeleportAllCommand());
}
}
public class TeleportHereCommand extends AbstractCommand {
public TeleportHereCommand() {
super("here", "Teleport player to you");
addAliases("h", "tome");
}
// ...
}
```
Now players can use:
- `/teleport here player1`
- `/tp here player1`
- `/tp h player1`
- `/tp tome player1`
## Command Variants
Variants allow the same command to accept different argument patterns:
```java
public class TpCommand extends AbstractCommand {
private final RequiredArg<PlayerRef> targetArg;
public TpCommand() {
super("tp", "Teleport command");
// Main variant: /tp <player>
targetArg = withRequiredArg("target", "Player to teleport to", ArgTypes.PLAYER_REF);
// Add variant: /tp <player> <destination>
addUsageVariant(new TpToPlayerVariant());
// Add variant: /tp <x> <y> <z>
addUsageVariant(new TpToPositionVariant());
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
// Teleport sender to target player
PlayerRef target = context.get(targetArg);
// ...
return null;
}
}
```
### Variant Implementation
```java
public class TpToPlayerVariant extends AbstractCommand {
private final RequiredArg<PlayerRef> playerArg;
private final RequiredArg<PlayerRef> destinationArg;
public TpToPlayerVariant() {
// No name for variants - use description only
super("Teleport one player to another");
playerArg = withRequiredArg("player", "Player to teleport", ArgTypes.PLAYER_REF);
destinationArg = withRequiredArg("destination", "Destination player", ArgTypes.PLAYER_REF);
}
@Override
protected CompletableFuture<Void> execute(CommandContext context) {
PlayerRef player = context.get(playerArg);
PlayerRef destination = context.get(destinationArg);
// Teleport player to destination
return null;
}
}
```
{{< callout type="info" >}}
Variants are distinguished by the number of required parameters. Each variant must have a different number of required arguments.
{{< /callout >}}
## Permission Inheritance
Subcommand permissions are automatically built from the parent:
```
/admin -> myplugin.command.admin
/admin kick -> myplugin.command.admin.kick
/admin ban -> myplugin.command.admin.ban
```
You can also set custom permissions:
```java
public KickSubCommand() {
super("kick", "Kick a player");
requirePermission("myplugin.admin.kick");
}
```