# ⚡ betterMcCommands Une bibliothèque Java moderne, fluide et événementielle pour créer et gérer des commandes Minecraft de façon hautement dynamique sans aucune configuration dans `plugin.yml`. --- ## 🌟 Fonctionnalités Clés - **DSL Fluide & Déclaratif** : Création chainable de commandes racines et sous-commandes imbriquées avec `BetterMcCommands.builder("ma-commande")`. - **Zéro `plugin.yml`** : Injection et dé-enregistrement à chaud à l'exécution dans la `CommandMap` du serveur. - **Arguments Typés & Auto-complétion** : - Types primitifs : `string`, `word`, `greedyString`, `integer`, `decimal`, `bool`, `enumOf`. - Types Minecraft : `player`, `offlinePlayer`, `world`, `location`, `duration`. - Arguments optionnels, valeurs par défaut et suggestions (Tab-Complete) dynamiques. - **Moteur d'Événements & Lifecycle** : - Hooks par commande (`.onPreExecute()`, `.onPostExecute()`, `.onPermissionDenied()`, `.onSyntaxError()`, `.onCooldown()`, `.onTabComplete()`). - Bus d'événements global supportant les lambdas ou les classes d'écoute avec `@CommandEventHandler`. - Événements annulables (`PreExecuteEvent`) pour vérifier des conditions de jeu (cooldowns, état de combat, économie). - **Temps de recharge (Cooldowns) natifs** : Configuration directe avec permission de bypass optionnelle. - **Formatage Moderne** : Support direct des composants Kyori Adventure et des balises MiniMessage (``, ``, etc.). --- ## 📦 Installation & Configuration Gradle Ajoutez la dépendance dans votre `build.gradle.kts` : ```kotlin dependencies { implementation("fr.luc:betterMcCommands:1.0.0-SNAPSHOT") } ``` --- ## 🚀 Guide de Démarrage Rapide ### 1. Initialisation dans votre Plugin ```java public class MyPlugin extends JavaPlugin { private BetterMcCommands commandsManager; @Override public void onEnable() { // Initialisation du gestionnaire pour ce plugin this.commandsManager = BetterMcCommands.create(this); // Enregistrement de vos classes d'écouteurs d'événements this.commandsManager.registerListeners(new MyCommandEventsListener()); // Enregistrement d'une commande DemoBaseCommand.create().register(); } @Override public void onDisable() { // Désenregistrement à chaud et nettoyage propre if (commandsManager != null) { commandsManager.unregisterAll(); } } } ``` --- ## 💡 Exemples de Commandes ### Déclaration d'une commande racine avec sous-commandes et arguments typés ```java BetterMcCommands.builder("commande-demo") .description("Commande de démonstration") .aliases("demo", "cdemo") .permission("bettermc.demo") // Événement exécuté avant la commande (annulable) .onPreExecute(event -> { if (event.isPlayer() && isInCombat(event.getPlayer())) { event.setCancelled(true); event.reply("Impossible d'exécuter cette commande en combat !"); } }) // Exécution de la commande racine : /commande-demo .executes(context -> { context.reply("=== Démo betterMcCommands ==="); context.reply("Utilisez /demo give pour donner des ressources."); }) // Sous-commande : /demo give [quantite] .subcommand(BetterMcCommands.subBuilder("give") .description("Donne des ressources à un joueur") .permission("bettermc.demo.give") .argument(Arguments.player("cible").description("Joueur recevant les items")) .argument(Arguments.integer("quantite", 1, 64).defaultValue(1)) .executes(context -> { Player target = context.getTargetPlayer("cible"); int quantite = context.getInt("quantite"); context.replySuccess("Attribution de " + quantite + " items à " + target.getName() + " !"); }) ) // Sous-commande avec argument gourmand (greedy) : /demo broadcast .subcommand(BetterMcCommands.subBuilder("broadcast") .description("Diffuse une annonce") .argument(Arguments.greedyString("message")) .executes(context -> { String msg = context.getString("message"); context.replySuccess("Diffusion : " + msg + ""); }) ) // Sous-commande avec Cooldown : /demo kit (recharge de 60 secondes) .subcommand(BetterMcCommands.subBuilder("kit") .cooldown(Duration.ofSeconds(60)) .cooldownBypass("bettermc.bypass.kit") .playerOnly() .executes(context -> { context.replySuccess("Kit reçu !"); }) ) .register(); ``` --- ## 🎯 Système d'Événements & Lifecycle Vous pouvez intercepter les événements du cycle de vie des commandes soit directement sur le builder (`.onPreExecute(...)`, `.onPostExecute(...)`), soit dans une classe dédiée avec `@CommandEventHandler` : ```java public class MyCommandEventsListener { @CommandEventHandler(priority = 10) public void onPreExecute(CommandPreExecuteEvent event) { System.out.println("Commande demandée : /" + event.getNode().getFullName() + " par " + event.getSender().getName()); } @CommandEventHandler(command = "commande-demo") public void onDemoPostExecute(CommandPostExecuteEvent event) { System.out.println("Commande exécutée en " + event.getExecutionDuration().toMillis() + "ms."); } @CommandEventHandler public void onPermissionDenied(CommandPermissionDeniedEvent event) { event.setCustomErrorMessage("Accès refusé ! Permission requise : " + event.getRequiredPermission() + ""); } @CommandEventHandler public void onCooldown(CommandCooldownEvent event) { event.setCustomMessage("⏳ Patientez " + event.getRemainingCooldown().toSeconds() + "s avant de réutiliser cette commande."); } } ``` --- ## 📂 Architecture des Packages ``` fr.luc.bettermccommands/ ├── BetterMcCommands.java (Manager principal & Façade) ├── api/ (Interfaces et modèles publics) │ ├── Command.java │ ├── CommandNode.java │ ├── CommandContext.java │ ├── CommandExecutor.java │ ├── CommandSenderType.java │ ├── CommandResult.java │ └── suggestion/ ├── builder/ (Fluent DSL Builder) │ ├── AbstractCommandBuilder.java │ ├── CommandBuilder.java │ └── SubCommandBuilder.java ├── argument/ (Arguments typés & Auto-complétion) │ ├── CommandArgument.java │ ├── ArgumentType.java │ ├── Arguments.java │ └── type/ ├── event/ (Bus d'événements & Lifecycle) │ ├── CommandEvent.java │ ├── CancellableCommandEvent.java │ ├── CommandPreExecuteEvent.java │ ├── CommandPostExecuteEvent.java │ ├── CommandPermissionDeniedEvent.java │ ├── CommandSyntaxErrorEvent.java │ ├── CommandCooldownEvent.java │ ├── CommandTabCompleteEvent.java │ └── annotation/ ├── cooldown/ (Gestion des cooldowns par joueur) ├── platform/ (Injection runtime CommandMap Paper/Spigot) └── demo/ (Plugin de démonstration et exemples) ```