Initialisation complète de la bibliothèque betterMcCommands (DSL, arguments typés, cycle de vie des événements, injection dynamique CommandMap)
This commit is contained in:
@@ -0,0 +1,321 @@
|
||||
package fr.luc.bettermccommands.api;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Contexte complet d'exécution d'une commande.
|
||||
* Contient l'émetteur, les arguments analysés et typés, les métadonnées et des utilitaires de réponse.
|
||||
*/
|
||||
public class CommandContext {
|
||||
|
||||
private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
|
||||
|
||||
private final CommandSender sender;
|
||||
private final String label;
|
||||
private final String[] rawArgs;
|
||||
private final Map<String, Object> arguments;
|
||||
private final Map<String, Object> metadata;
|
||||
|
||||
/**
|
||||
* Construit un nouveau contexte de commande.
|
||||
*
|
||||
* @param sender L'émetteur de la commande.
|
||||
* @param label Le nom ou alias utilisé pour invoquer la commande.
|
||||
* @param rawArgs Les arguments bruts sous forme de tableau de chaînes.
|
||||
* @param arguments La table des arguments résolus et typés.
|
||||
*/
|
||||
public CommandContext(CommandSender sender, String label, String[] rawArgs, Map<String, Object> arguments) {
|
||||
this.sender = Objects.requireNonNull(sender, "sender cannot be null");
|
||||
this.label = label != null ? label : "";
|
||||
this.rawArgs = rawArgs != null ? rawArgs : new String[0];
|
||||
this.arguments = arguments != null ? new HashMap<>(arguments) : new HashMap<>();
|
||||
this.metadata = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return L'émetteur de la commande (Player, ConsoleCommandSender, etc.).
|
||||
*/
|
||||
public CommandSender getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true si l'émetteur est un {@link Player}, sinon false.
|
||||
*/
|
||||
public boolean isPlayer() {
|
||||
return sender instanceof Player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true si l'émetteur est la console du serveur.
|
||||
*/
|
||||
public boolean isConsole() {
|
||||
return sender instanceof ConsoleCommandSender;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le joueur émetteur de la commande.
|
||||
*
|
||||
* @return L'instance de {@link Player}.
|
||||
* @throws IllegalStateException si l'émetteur n'est pas un joueur.
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
if (!isPlayer()) {
|
||||
throw new IllegalStateException("CommandSender is not a Player: " + sender.getClass().getSimpleName());
|
||||
}
|
||||
return (Player) sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère la console émettrice de la commande.
|
||||
*
|
||||
* @return L'instance de {@link ConsoleCommandSender}.
|
||||
* @throws IllegalStateException si l'émetteur n'est pas la console.
|
||||
*/
|
||||
public ConsoleCommandSender getConsole() {
|
||||
if (!isConsole()) {
|
||||
throw new IllegalStateException("CommandSender is not a ConsoleCommandSender: " + sender.getClass().getSimpleName());
|
||||
}
|
||||
return (ConsoleCommandSender) sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Le label ou alias utilisé lors de l'exécution.
|
||||
*/
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Le tableau des arguments bruts passés lors de l'appel.
|
||||
*/
|
||||
public String[] getRawArgs() {
|
||||
return rawArgs.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Une vue non modifiable des arguments analysés.
|
||||
*/
|
||||
public Map<String, Object> getArguments() {
|
||||
return Collections.unmodifiableMap(arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un argument du nom donné a été renseigné et analysé.
|
||||
*
|
||||
* @param name Le nom de l'argument.
|
||||
* @return true si l'argument est présent, sinon false.
|
||||
*/
|
||||
public boolean hasArgument(String name) {
|
||||
return arguments.containsKey(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un argument typé par son nom.
|
||||
*
|
||||
* @param name Le nom de l'argument.
|
||||
* @param type La classe attendue pour l'argument.
|
||||
* @param <T> Le type générique.
|
||||
* @return L'instance de l'argument analysé.
|
||||
* @throws IllegalArgumentException si l'argument est manquant ou n'est pas du type attendu.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(String name, Class<T> type) {
|
||||
Object val = arguments.get(name);
|
||||
if (val == null) {
|
||||
throw new IllegalArgumentException("Argument '" + name + "' is missing from context.");
|
||||
}
|
||||
if (!type.isInstance(val)) {
|
||||
throw new IllegalArgumentException("Argument '" + name + "' is of type " +
|
||||
val.getClass().getSimpleName() + ", expected " + type.getSimpleName());
|
||||
}
|
||||
return (T) val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un argument de manière optionnelle.
|
||||
*
|
||||
* @param name Le nom de l'argument.
|
||||
* @param type La classe attendue pour l'argument.
|
||||
* @param <T> Le type générique.
|
||||
* @return Un {@link Optional} contenant la valeur si présente.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Optional<T> getOptional(String name, Class<T> type) {
|
||||
Object val = arguments.get(name);
|
||||
if (val != null && type.isInstance(val)) {
|
||||
return Optional.of((T) val);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un argument sous forme de chaîne de caractères.
|
||||
*
|
||||
* @param name Le nom de l'argument.
|
||||
* @return La chaîne analysée.
|
||||
*/
|
||||
public String getString(String name) {
|
||||
return get(name, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un argument entier.
|
||||
*
|
||||
* @param name Le nom de l'argument.
|
||||
* @return L'entier analysé.
|
||||
*/
|
||||
public int getInt(String name) {
|
||||
return get(name, Integer.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un argument double.
|
||||
*
|
||||
* @param name Le nom de l'argument.
|
||||
* @return Le double analysé.
|
||||
*/
|
||||
public double getDouble(String name) {
|
||||
return get(name, Double.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un argument booléen.
|
||||
*
|
||||
* @param name Le nom de l'argument.
|
||||
* @return Le booléen analysé.
|
||||
*/
|
||||
public boolean getBoolean(String name) {
|
||||
return get(name, Boolean.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un joueur cible ciblé par l'argument.
|
||||
*
|
||||
* @param name Le nom de l'argument.
|
||||
* @return Le joueur cible.
|
||||
*/
|
||||
public Player getTargetPlayer(String name) {
|
||||
return get(name, Player.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un monde ciblé par l'argument.
|
||||
*
|
||||
* @param name Le nom de l'argument.
|
||||
* @return Le monde cible.
|
||||
*/
|
||||
public World getWorld(String name) {
|
||||
return get(name, World.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère une durée ciblée par l'argument.
|
||||
*
|
||||
* @param name Le nom de l'argument.
|
||||
* @return La durée analysée.
|
||||
*/
|
||||
public Duration getDuration(String name) {
|
||||
return get(name, Duration.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit une métadonnée personnalisée dans le contexte d'exécution.
|
||||
*
|
||||
* @param key La clé de la métadonnée.
|
||||
* @param value La valeur associée.
|
||||
*/
|
||||
public void setMetadata(String key, Object value) {
|
||||
this.metadata.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère une métadonnée du contexte.
|
||||
*
|
||||
* @param key La clé.
|
||||
* @param type Le type attendu.
|
||||
* @param <T> Le type générique.
|
||||
* @return Un {@link Optional} contenant la métadonnée si présente.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Optional<T> getMetadata(String key, Class<T> type) {
|
||||
Object val = metadata.get(key);
|
||||
if (val != null && type.isInstance(val)) {
|
||||
return Optional.of((T) val);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie un message formaté avec MiniMessage à l'émetteur de la commande.
|
||||
*
|
||||
* @param miniMessageText Le texte formaté avec tags MiniMessage (ex: "<green>Succès !</green>").
|
||||
*/
|
||||
public void reply(String miniMessageText) {
|
||||
if (miniMessageText == null || miniMessageText.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (sender instanceof Audience) {
|
||||
((Audience) sender).sendMessage(MINI_MESSAGE.deserialize(miniMessageText));
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', miniMessageText));
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
sender.sendMessage(miniMessageText);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie un composant Kyori Adventure directement à l'émetteur.
|
||||
*
|
||||
* @param component Le composant texte Adventure.
|
||||
*/
|
||||
public void reply(Component component) {
|
||||
if (component == null) {
|
||||
return;
|
||||
}
|
||||
if (sender instanceof Audience) {
|
||||
((Audience) sender).sendMessage(component);
|
||||
} else {
|
||||
sender.sendMessage(component.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie un message de succès (préfixé en vert).
|
||||
*
|
||||
* @param message Le message de succès.
|
||||
*/
|
||||
public void replySuccess(String message) {
|
||||
reply("<dark_gray>[<green>✔</green>]</dark_gray> <green>" + message + "</green>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie un message d'erreur (préfixé en rouge).
|
||||
*
|
||||
* @param message Le message d'erreur.
|
||||
*/
|
||||
public void replyError(String message) {
|
||||
reply("<dark_gray>[<red>✖</red>]</dark_gray> <red>" + message + "</red>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie un message informatif (préfixé en bleu/aqua).
|
||||
*
|
||||
* @param message Le message d'information.
|
||||
*/
|
||||
public void replyInfo(String message) {
|
||||
reply("<dark_gray>[<aqua>ℹ</aqua>]</dark_gray> <gray>" + message + "</gray>");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user