🖼️ betterMcGuis

Java Paper Kyori Adventure License

Une bibliothèque Java moderne, fluide et événementielle permettant de créer, animer et gérer des interfaces graphiques (GUIs / Menus interactifs / Inventaires) sur serveurs Minecraft Paper et Spigot (1.20.4+).


📑 Sommaire


📚 Guides Détaillés (Dossier /docs)

Pour une exploration approfondie de chaque composant, consultez la documentation modulaire :


🌟 Fonctionnalités

  • DSL Fluide & Déclaratif : Construction rapide et lisible (BetterMcGuis.builder("Titre", 3)).
  • Formatage Moderne MiniMessage & Adventure : Prise en charge native des gradients HEX, balises de style et composants texte.
  • Grilles & Motifs ASCII (GuiPattern) : Dessinez vos interfaces directement en texte sous forme de matrice avec associations de caractères.
  • Pagination Intelligente (PaginatedGui) : Calcul automatique des pages, boutons de navigation dynamiques et indicateurs de progression.
  • Onglets Commutables (TabbedGui) : Basculez entre plusieurs vues de menu instantanément sans fermer la fenêtre du joueur.
  • Animations Cadencées (AnimatedGui) : Lecture de séquences de frames temporelles (titres animés, coffres mystères, carrousels).
  • Protection Anti-Duplication & Sécurité : Blocage natif et sécurisé des vols d'items, glisser-déposer illégaux, shift-clics et raccourcis de hotbar.
  • Moteur d'Événements Riches : Bus d'événements global avec priorités et annotations @GuiEventHandler.

🏗️ Architecture & Flux d'Interactions

flowchart TD
    Player["Joueur en Jeu"] -->|Effectue un Clic / Drag / Fermeture| BukkitEvt["BukkitGuiEventListener (Sécurité & Interception)"]
    
    BukkitEvt --> HolderCheck{"Inventaire lié à BetterGuiHolder ?"}
    HolderCheck -- Non --> Ignore["Ignore l'interaction"]
    
    HolderCheck -- Oui --> SlotTypeCheck{"Localisation du Clic"}
    
    SlotTypeCheck -- Extérieur (-999) --> OutsideHook["gui.handleOutsideClick() & GuiClickEvent"]
    SlotTypeCheck -- Inventaire Joueur --> BottomCheck{"Shift-Clic ou Hotbar Swap vers slot protégé ?"}
    BottomCheck -- Oui --> BlockShift["event.setCancelled(true) & Blocage"]
    BottomCheck -- Non --> BottomHook["gui.handleBottomClick()"]
    
    SlotTypeCheck -- Inventaire Supérieur (GUI) --> EditCheck{"Le Slot est-il Editable ?"}
    EditCheck -- Non (Défaut) --> CancelDef["event.setCancelled(true) (Empêche le vol)"]
    EditCheck -- Oui --> AllowEdit["event.setCancelled(false) (Autorise le dépôt)"]
    
    CancelDef --> CoolCheck{"Cooldown Actif sur l'Item ?"}
    AllowEdit --> CoolCheck
    
    CoolCheck -- Oui --> CoolBlock["Interruption silencieuse"]
    CoolCheck -- Non --> SoundTrigger["Déclenchement du Son configuré"]
    
    SoundTrigger --> ItemAction["Exécution de l'Action Métier (item.handleClick)"]
    ItemAction --> GuiHook["Exécution du Hook Local (gui.handleClick)"]
    GuiHook --> EventBus["Diffusion sur le Bus Global (GuiClickEvent)"]

📦 Installation & Configuration

Gradle (Kotlin DSL)

repositories {
    mavenCentral()
    maven("https://repo.papermc.io/repository/maven-public/")
}

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

🚀 Guide de Démarrage Rapide

1. Initialisation dans votre JavaPlugin

package fr.luc.monplugin;

import fr.luc.bettermcguis.BetterMcGuis;
import org.bukkit.plugin.java.JavaPlugin;

public class MonPlugin extends JavaPlugin {

    private BetterMcGuis guiManager;

    @Override
    public void onEnable() {
        // Initialisation de betterMcGuis (enregistre automatiquement les écouteurs Bukkit)
        this.guiManager = BetterMcGuis.create(this);

        // Enregistrement d'écouteurs annotés globaux (optionnel)
        this.guiManager.registerListeners(new MonEcouteurDeGui());
    }

    @Override
    public void onDisable() {
        // Nettoyage complet
        if (guiManager != null) {
            guiManager.unregisterAll();
        }
    }
}

💡 Exemples de Menus

1. Menu Principal Standard (GuiBuilder)

BetterMcGuis.builder()
    .title("<gradient:#ff5e62:#ff9966><bold>Menu Principal</bold></gradient>")
    .rows(3)
    .fillBorder(Material.BLACK_STAINED_GLASS_PANE)

    // Bouton central interactif
    .item(13, BetterMcGuis.item(Material.NETHER_STAR)
        .name("<gold><bold>Récompense Quotidienne</bold></gold>")
        .lore(
            "<gray>Récupérez votre bonus de connexion !</gray>",
            "",
            "<yellow>▶ Cliquez pour réclamer</yellow>"
        )
        .glowing(true)
        .asGuiItem(ctx -> {
            ctx.playSound(Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.2f);
            ctx.replySuccess("Bonus réclamé avec succès !");
            ctx.close();
        })
    )
    .build()
    .open(player);

2. Menu Paginé Dynamique (PaginatedGui)

var shop = BetterMcGuis.paginated()
    .title("<gradient:#00c6ff:#0072ff><bold>Boutique du Serveur</bold></gradient>")
    .rows(5)
    .fillBorder(Material.GRAY_STAINED_GLASS_PANE);

// Ajout de 50 articles dans le catalogue paginé
for (int i = 1; i <= 50; i++) {
    int id = i;
    shop.addPageItem(BetterMcGuis.item(Material.DIAMOND)
        .name("<aqua>Article #" + id + "</aqua>")
        .lore("<gray>Prix : <gold>100 $</gold></gray>")
        .asGuiItem(ctx -> {
            ctx.replySuccess("Achat de l'article #" + id + " validé !");
        })
    );
}

shop.build().open(player);

3. Motifs ASCII & Grilles de Disposition (GuiPattern)

BetterMcGuis.builder("Menu Quêtes", 5)
    .pattern(p -> p
        .lines(
            "#########",
            "# 1 2 3 #",
            "#       #",
            "#   C   #",
            "#########"
        )
        .bindFiller('#', Material.BLACK_STAINED_GLASS_PANE)
        .bind('1', BetterMcGuis.item(Material.BOOK).name("<green>Quête Facile</green>").asGuiItem())
        .bind('2', BetterMcGuis.item(Material.WRITABLE_BOOK).name("<yellow>Quête Moyenne</yellow>").asGuiItem())
        .bind('3', BetterMcGuis.item(Material.ENCHANTED_BOOK).name("<red>Quête Difficile</red>").asGuiItem())
        .bind('C', BetterMcGuis.item(Material.BARRIER).name("<red>Fermer</red>").asGuiItem(GuiClickContext::close))
    )
    .build()
    .open(player);

4. Menus à Onglets sans Réouverture (TabbedGui)

BetterMcGuis.tabbed("Menu Profil", 4)
    // Onglet 1 : Statistiques
    .tab("stats", 11, BetterMcGuis.item(Material.PAPER).name("<yellow>Statistiques</yellow>").asGuiItem(), tab -> {
        tab.setTabItem("stats", 22, BetterMcGuis.item(Material.EXPERIENCE_BOTTLE).name("<green>Niveau 42</green>").asGuiItem());
    })
    // Onglet 2 : Récompenses
    .tab("rewards", 15, BetterMcGuis.item(Material.CHEST).name("<gold>Récompenses</gold>").asGuiItem(), tab -> {
        tab.setTabItem("rewards", 22, BetterMcGuis.item(Material.GOLD_INGOT).name("<gold>Bonus Débloqué</gold>").asGuiItem());
    })
    .build()
    .open(player);

5. Zones de Dépôt / Poubelle (StorageGui)

StorageGui trash = new StorageGui("<red><bold>Poubelle Publique</bold></red>", GuiType.CHEST_4_ROWS);
trash.fillBorder(Material.RED_STAINED_GLASS_PANE);
trash.setStorageSlots(SlotRange.interior(4, 9));
trash.returnItemsOnClose(false); // Détruit définitivement les objets déposés
trash.open(player);

💎 Construction d'Items (ItemBuilder)

ItemStack item = BetterMcGuis.item(Material.DIAMOND_HELMET)
    .name("<gradient:#4facfe:#00f2fe><bold>Casque de Diamant Divin</bold></gradient>")
    .lore(
        "<gray>Forgé par les anciens dieux.</gray>",
        "",
        "<yellow>Protection : <aqua>IV</aqua></yellow>"
    )
    .enchant(Enchantment.PROTECTION_ENVIRONMENTAL, 4)
    .unbreakable(true)
    .customModelData(2005)
    .glowing(true)
    .build();

🎯 Système d'Événements & Écouteurs Annotés

package fr.luc.monplugin.listener;

import fr.luc.bettermcguis.event.*;
import fr.luc.bettermcguis.event.annotation.GuiEventHandler;

public class MonEcouteurGlobalGui {

    @GuiEventHandler(priority = 10)
    public void onGuiClick(GuiClickEvent event) {
        var ctx = event.getContext();
        System.out.println("[GUI] Clic de " + ctx.getPlayer().getName() + " sur le slot #" + ctx.getSlot());
    }

    @GuiEventHandler
    public void onGuiClose(GuiCloseEvent event) {
        System.out.println("[GUI] Fermeture du menu : " + event.getGui().getTitle());
    }
}

📂 Organisation des Packages

fr.luc.bettermcguis/
 ├── BetterMcGuis.java                    (Façade principale & Enregistrement)
 ├── api/                                 (Contrats et modèles publics)
 │    ├── Gui.java                        (Interface de base de tout GUI)
 │    ├── GuiType.java                    (Types de coffres 1-6 et types Bukkit)
 │    ├── GuiItem.java                    (Items interactifs, cooldowns, sons, visibilité)
 │    ├── GuiClickAction.java             (Callback fonctionnel de clic)
 │    ├── GuiClickContext.java            (Contexte complet de clic)
 │    ├── GuiOpenContext.java             (Contexte d'ouverture)
 │    ├── GuiCloseContext.java            (Contexte de fermeture)
 │    └── slot/
 │         ├── SlotPos.java               (Position ligne, colonne)
 │         └── SlotRange.java             (Bordures, intérieurs, plages)
 ├── builder/                             (Constructeurs fluides)
 │    ├── ItemBuilder.java                (Création d'ItemStacks riches avec Adventure)
 │    ├── GuiBuilder.java                 (Constructeur de menus standards)
 │    ├── PaginatedGuiBuilder.java        (Constructeur de menus paginés)
 │    ├── TabbedGuiBuilder.java           (Constructeur de menus à onglets)
 │    ├── AnimatedGuiBuilder.java         (Constructeur de menus animés)
 │    └── PatternBuilder.java             (Constructeur de motifs ASCII)
 ├── pattern/                             (Moteur de disposition par grilles ASCII)
 │    ├── GuiPattern.java
 │    └── GuiMask.java
 ├── type/                                (Implémentations de GUIs)
 │    ├── SimpleGui.java
 │    ├── PaginatedGui.java
 │    ├── TabbedGui.java
 │    ├── AnimatedGui.java
 │    └── StorageGui.java
 ├── animation/                           (Moteur d'animation)
 │    └── Frame.java
 ├── event/                               (Bus d'événements & Lifecycle)
 │    ├── GuiEvent.java
 │    ├── CancellableGuiEvent.java
 │    ├── GuiOpenEvent.java
 │    ├── GuiCloseEvent.java
 │    ├── GuiClickEvent.java
 │    ├── GuiPageChangeEvent.java
 │    ├── GuiRefreshEvent.java
 │    ├── GuiEventManager.java
 │    ├── GuiEventListener.java
 │    └── annotation/
 │         └── GuiEventHandler.java
 ├── holder/                              (Liaison avec InventoryHolder de Bukkit)
 │    └── BetterGuiHolder.java
 ├── listener/                            (Interception Bukkit & Sécurités anti-glitch)
 │    └── BukkitGuiEventListener.java
 └── demo/                                (Démonstrations et plugin de test)
      ├── DemoGuiPlugin.java
      ├── guis/
      │    ├── DemoMainMenuGui.java
      │    ├── DemoPaginatedShopGui.java
      │    └── DemoStorageTrashGui.java
      └── listeners/
           └── DemoGuiListener.java

📄 Licence

Ce projet est sous licence MIT.

S
Description
Bibliotheque Java moderne, fluide et evenementielle pour la creation dynamique de GUIs et menus interactifs Minecraft Paper/Spigot.
Readme MIT 140 KiB
Languages
Java 100%