Files
betterMcCommands/README.md
T

7.5 KiB

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 (<gradient>, <green>, etc.).

📦 Installation & Configuration Gradle

Ajoutez la dépendance dans votre build.gradle.kts :

dependencies {
    implementation("fr.luc:betterMcCommands:1.0.0-SNAPSHOT")
}

🚀 Guide de Démarrage Rapide

1. Initialisation dans votre Plugin

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

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("<red>Impossible d'exécuter cette commande en combat !</red>");
        }
    })

    // Exécution de la commande racine : /commande-demo
    .executes(context -> {
        context.reply("<gradient:#00d2ff:#3a7bd5><bold>=== Démo betterMcCommands ===</bold></gradient>");
        context.reply("<gray>Utilisez <yellow>/demo give</yellow> pour donner des ressources.</gray>");
    })

    // Sous-commande : /demo give <cible> [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 <gold>" + quantite + "</gold> items à <aqua>" + target.getName() + "</aqua> !");
        })
    )

    // Sous-commande avec argument gourmand (greedy) : /demo broadcast <message...>
    .subcommand(BetterMcCommands.subBuilder("broadcast")
        .description("Diffuse une annonce")
        .argument(Arguments.greedyString("message"))
        .executes(context -> {
            String msg = context.getString("message");
            context.replySuccess("Diffusion : <yellow>" + msg + "</yellow>");
        })
    )

    // 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 :

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("<dark_red>Accès refusé ! Permission requise : " + event.getRequiredPermission() + "</dark_red>");
    }

    @CommandEventHandler
    public void onCooldown(CommandCooldownEvent event) {
        event.setCustomMessage("<red>⏳ Patientez <gold>" + event.getRemainingCooldown().toSeconds() + "s</gold> avant de réutiliser cette commande.</red>");
    }
}

📂 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)