Comandi Custom
Introduzione ai Comandi
I comandi permettono ai giocatori e agli admin di interagire con il tuo plugin. Spigot/Paper offre un sistema flessibile per creare comandi con argomenti, tab completion e permessi.
Creare un Comando Base
1. Dichiarare il Comando in plugin.yml
```yaml
commands:
heal:
description: Cura il giocatore
usage: /
2. Creare il Command Executor
```java public class HealCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
// Controlla se il sender è un giocatore
if (!(sender instanceof Player)) {
sender.sendMessage("§cQuesto comando può essere usato solo da un giocatore!");
return true;
}
Player player = (Player) sender;
// Cura il giocatore
player.setHealth(20.0);
player.setFoodLevel(20);
player.sendMessage("§aSei stato curato!");
return true;
}
} ```
3. Registrare il Comando
Nella classe principale:
```java public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
// Registra il comando
getCommand("heal").setExecutor(new HealCommand());
}
} ```
Gestire Argomenti
```java public class TeleportCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage("§cSolo giocatori!");
return true;
}
Player player = (Player) sender;
// /tp <x> <y> <z>
if (args.length != 3) {
player.sendMessage("§cUso: /tp <x> <y> <z>");
return true;
}
try {
double x = Double.parseDouble(args[0]);
double y = Double.parseDouble(args[1]);
double z = Double.parseDouble(args[2]);
Location location = new Location(player.getWorld(), x, y, z);
player.teleport(location);
player.sendMessage("§aTeletrasportato a " + x + ", " + y + ", " + z);
} catch (NumberFormatException e) {
player.sendMessage("§cCoordinate non valide!");
}
return true;
}
} ```
Comandi con Target
Curare altri giocatori:
```java public class HealCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
// /heal (cura se stesso)
if (args.length == 0) {
if (!(sender instanceof Player)) {
sender.sendMessage("§cSpecifica un giocatore!");
return true;
}
Player player = (Player) sender;
healPlayer(player);
player.sendMessage("§aSei stato curato!");
return true;
}
// /heal <player> (cura un altro giocatore)
if (args.length == 1) {
if (!sender.hasPermission("myplugin.heal.others")) {
sender.sendMessage("§cNon hai il permesso!");
return true;
}
Player target = Bukkit.getPlayer(args[0]);
if (target == null) {
sender.sendMessage("§cGiocatore non trovato!");
return true;
}
healPlayer(target);
sender.sendMessage("§aHai curato " + target.getName());
target.sendMessage("§aSei stato curato da " + sender.getName());
return true;
}
sender.sendMessage("§cUso: /heal [player]");
return true;
}
private void healPlayer(Player player) {
player.setHealth(20.0);
player.setFoodLevel(20);
player.setSaturation(20);
}
} ```
Tab Completion
Suggerimenti quando il giocatore preme TAB:
```java public class HealCommand implements CommandExecutor, TabCompleter {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
// ... codice comando ...
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
List<String> completions = new ArrayList<>();
// /heal <TAB> -> suggerisci nomi giocatori
if (args.length == 1) {
String partial = args[0].toLowerCase();
for (Player player : Bukkit.getOnlinePlayers()) {
if (player.getName().toLowerCase().startsWith(partial)) {
completions.add(player.getName());
}
}
}
return completions;
}
} ```
Registrare Tab Completer
```java @Override public void onEnable() { PluginCommand command = getCommand(“heal”); HealCommand executor = new HealCommand();
command.setExecutor(executor);
command.setTabCompleter(executor); // Registra tab completer
} ```
Comandi con Subcomandi
```java public class KitCommand implements CommandExecutor, TabCompleter {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage("§cSolo giocatori!");
return true;
}
Player player = (Player) sender;
if (args.length == 0) {
player.sendMessage("§cUso: /kit <starter|pvp|builder>");
return true;
}
String subcommand = args[0].toLowerCase();
switch (subcommand) {
case "starter":
giveStarterKit(player);
break;
case "pvp":
if (!player.hasPermission("myplugin.kit.pvp")) {
player.sendMessage("§cNon hai il permesso!");
return true;
}
givePvPKit(player);
break;
case "builder":
giveBuilderKit(player);
break;
default:
player.sendMessage("§cKit non valido!");
return true;
}
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length == 1) {
return Arrays.asList("starter", "pvp", "builder");
}
return null;
}
private void giveStarterKit(Player player) {
player.getInventory().addItem(
new ItemStack(Material.WOODEN_SWORD),
new ItemStack(Material.BREAD, 16)
);
player.sendMessage("§aKit starter ricevuto!");
}
private void givePvPKit(Player player) {
player.getInventory().addItem(
new ItemStack(Material.DIAMOND_SWORD),
new ItemStack(Material.DIAMOND_CHESTPLATE),
new ItemStack(Material.GOLDEN_APPLE, 5)
);
player.sendMessage("§aKit PvP ricevuto!");
}
private void giveBuilderKit(Player player) {
player.getInventory().addItem(
new ItemStack(Material.STONE, 64),
new ItemStack(Material.OAK_PLANKS, 64),
new ItemStack(Material.GLASS, 32)
);
player.sendMessage("§aKit builder ricevuto!");
}
} ```
Comandi dalla Console
Permettere l’esecuzione dalla console:
```java @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { // Funziona sia per giocatori che console if (args.length == 0) { sender.sendMessage(“§cSpecifica un giocatore!”); return true; }
Player target = Bukkit.getPlayer(args[0]);
if (target == null) {
sender.sendMessage("§cGiocatore non trovato!");
return true;
}
target.setHealth(20.0);
sender.sendMessage("§a" + target.getName() + " è stato curato!");
return true;
} ```
Permessi nei Comandi
```java @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { // Controlla permesso if (!sender.hasPermission(“myplugin.admin”)) { sender.sendMessage(“§cNon hai il permesso!”); return true; }
// Codice del comando...
return true;
} ```
Best Practices
- Ritorna sempre true: Se gestisci l’errore, ritorna
trueper evitare che venga mostrato l’usage - Valida gli input: Controlla sempre che gli argomenti siano validi
- Messaggi chiari: Usa colori e messaggi descrittivi
- Tab completion: Migliora l’UX suggerendo opzioni valide
- Permessi granulari: Crea permessi separati per ogni funzionalità
Comandi Avanzati: Brigadier (Paper)
Paper supporta Brigadier per comandi più avanzati:
```java public class BrigadierExample implements CommandExecutor {
public void registerBrigadier() {
LiteralCommandNode<CommandSourceStack> node = Commands.literal("example")
.then(Commands.argument("player", ArgumentTypes.player())
.executes(context -> {
Player player = context.getArgument("player", Player.class);
player.sendMessage("Hello!");
return 1;
})
)
.build();
// Registra con Brigadier
}
} ```
Errori Comuni
Comando non registrato
// SBAGLIATO: dimenticato di registrare
new HealCommand(); // Non fa nulla!
// CORRETTO
getCommand("heal").setExecutor(new HealCommand());
Nome comando non corrisponde
// plugin.yml
commands:
heal: ...
// SBAGLIATO
getCommand("cure").setExecutor(...); // Nome diverso!
// CORRETTO
getCommand("heal").setExecutor(...);
Non controllare null
// SBAGLIATO
Player target = Bukkit.getPlayer(args[0]);
target.sendMessage("Hi!"); // NullPointerException se offline!
// CORRETTO
Player target = Bukkit.getPlayer(args[0]);
if (target == null) {
sender.sendMessage("Giocatore non trovato!");
return true;
}
target.sendMessage("Hi!");
Conclusione
I comandi sono l’interfaccia principale tra i giocatori e il tuo plugin. Un sistema di comandi ben progettato, con tab completion e messaggi chiari, rende il plugin intuitivo e piacevole da usare.