Files
betterMcCommands/src/main/java/fr/luc/bettermccommands/api/CommandContext.java
T

322 lines
9.6 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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>");
}
}