feat: initialisation complète de la bibliothèque betterMcGuis (Fluent DSL, ItemBuilder, PaginatedGui, TabbedGui, AnimatedGui, Patterns ASCII, Moteur d'événements, Sécurité anti-glitch et documentation)

This commit is contained in:
2026-08-23 18:10:49 +02:00
parent b88eaad155
commit 806d1789a1
63 changed files with 6233 additions and 2 deletions
+89
View File
@@ -0,0 +1,89 @@
# 🚀 Guide de Démarrage Rapide - betterMcGuis
Ce guide vous accompagne dans l'installation, la configuration et la création de vos premières interfaces graphiques interactives (GUIs) avec la bibliothèque **betterMcGuis**.
---
## 📦 1. Installation
### Gradle (Kotlin DSL)
Ajoutez les dépôts et la dépendance dans votre fichier `build.gradle.kts` :
```kotlin
repositories {
mavenCentral()
maven("https://repo.papermc.io/repository/maven-public/")
}
dependencies {
// Intégration de betterMcGuis
implementation("fr.luc:betterMcGuis:1.0.0-SNAPSHOT")
}
```
---
## ⚙️ 2. Initialisation dans votre Plugin Bukkit/Paper
Créez une instance de `BetterMcGuis` dans la méthode `onEnable()` de votre plugin et nettoyez-la proprement dans `onDisable()` :
```java
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() {
// 1. Initialisation du gestionnaire et enregistrement automatique des écouteurs Bukkit
this.guiManager = BetterMcGuis.create(this);
// 2. Enregistrement d'écouteurs d'événements globaux (optionnel)
this.guiManager.registerListeners(new MonEcouteurDeGui());
getLogger().info("betterMcGuis est prêt !");
}
@Override
public void onDisable() {
// 3. Nettoyage des écouteurs et suppression des ressources
if (guiManager != null) {
guiManager.unregisterAll();
}
}
}
```
---
## 💡 3. Votre Premier Menu en 5 Lignes
```java
public void ouvrirMenuBienvenue(Player player) {
BetterMcGuis.builder()
.title("<gradient:#00c6ff:#0072ff><bold>Menu de Bienvenue</bold></gradient>")
.rows(3)
.fillBorder(Material.BLACK_STAINED_GLASS_PANE)
.item(13, BetterMcGuis.item(Material.DIAMOND)
.name("<gold><bold>Réclamer le Cadeau</bold></gold>")
.lore("<gray>Cliquez pour recevoir 1 Diamant gratuit !</gray>")
.glowing(true)
.asGuiItem(ctx -> {
ctx.getPlayer().getInventory().addItem(new ItemStack(Material.DIAMOND));
ctx.replySuccess("Diamant reçu avec succès !");
ctx.close();
})
)
.build()
.open(player);
}
```
---
> 📖 **Étape suivante** : Découvrez la syntaxe complète du constructeur dans [02_GUI_BUILDER_DSL.md](02_GUI_BUILDER_DSL.md).
+94
View File
@@ -0,0 +1,94 @@
# 🏗️ Fluent GUI Builder DSL - betterMcGuis
La création de menus repose sur un pattern **Builder chainable, fluide et modulaire**.
---
## 📑 Sommaire
- [1. Configuration des Dimensions et Types d'Inventaires](#1-configuration-des-dimensions-et-types-dinventaires)
- [2. Placement des Items](#2-placement-des-items)
- [3. Remplissage et Bordures](#3-remplissage-et-bordures)
- [4. Propriétés Dynamiques](#4-propriétés-dynamiques)
- [5. Contrôle du Cycle de Vie et Ouvertures](#5-contrôle-du-cycle-de-vie-et-ouvertures)
---
## 1. Configuration des Dimensions et Types d'Inventaires
Vous pouvez configurer des coffres standards de 1 à 6 lignes, ou des types d'inventaires Bukkit spécifiques :
```java
// Coffre 3 lignes (27 slots)
BetterMcGuis.builder("Titre", 3);
// Types spécifiques via GuiType
BetterMcGuis.builder()
.title("<yellow>Distributeur</yellow>")
.type(GuiType.DISPENSER); // DISPENSER, DROPPER, HOPPER, ANVIL, WORKBENCH, BREWING
```
---
## 2. Placement des Items
Vous pouvez positionner des items selon trois méthodes d'adressage :
```java
var builder = BetterMcGuis.builder("Exemple", 4);
// Par slot absolu (0-indexé, 0 à 35)
builder.item(13, monItem);
// Par coordonnées ligne/colonne (0-indexé, ligne 1, col 4)
builder.item(1, 4, monItem);
// Par SlotPos
builder.item(SlotPos.of(1, 4), monItem);
```
---
## 3. Remplissage et Bordures
Des méthodes utilitaires permettent de remplir instantanément l'inventaire ou ses contours :
```java
// Remplit toutes les bordures extérieures avec du vitrage teinté
builder.fillBorder(Material.GRAY_STAINED_GLASS_PANE);
// Remplit une plage continue de slots
builder.fillRange(SlotRange.of(10, 16), monItem);
// Remplit tout l'inventaire
builder.fill(monItem);
```
---
## 4. Propriétés Dynamiques
Vous pouvez attacher des données arbitraires à l'instance de GUI pour les partager entre callbacks :
```java
Gui gui = BetterMcGuis.builder("Profil", 3)
.property("targetPlayerUuid", target.getUniqueId())
.property("openedAt", System.currentTimeMillis())
.build();
// Récupération typée dans un callback
UUID uuid = gui.getProperty("targetPlayerUuid", UUID.class);
```
---
## 5. Contrôle du Cycle de Vie et Ouvertures
* `gui.open(Player)` : Ouvre l'inventaire pour le joueur.
* `gui.close(Player)` : Ferme l'inventaire.
* `gui.refresh(Player)` : Met à jour visuellement les items sans réouverture.
* `gui.refreshAll()` : Rafraîchit l'affichage pour tous les spectateurs actifs.
* `gui.setTitle("<green>Nouveau Titre</green>")` : Modifie le titre du menu.
---
> 📖 **Étape suivante** : Découvrez la création d'items avec [03_ITEM_BUILDER_AND_ITEMS.md](03_ITEM_BUILDER_AND_ITEMS.md).
+111
View File
@@ -0,0 +1,111 @@
# 💎 ItemBuilder & GuiItem - betterMcGuis
La création et l'interaction avec les items Minecraft sont grandement simplifiées grâce à `ItemBuilder` et `GuiItem`.
---
## 📑 Sommaire
- [1. Création d'ItemStacks avec `ItemBuilder`](#1-création-ditemstacks-avec-itembuilder)
- [2. Prise en Charge de MiniMessage et Kyori Adventure](#2-prise-en-charge-de-minimessage-et-kyori-adventure)
- [3. Têtes Personnalisées, Couleurs et Flags](#3-têtes-personnalisées-couleurs-et-flags)
- [4. L'Objet Interactif `GuiItem`](#4-lobjet-interactif-guiitem)
- [5. Le Contexte de Clic (`GuiClickContext`)](#5-le-contexte-de-clic-guiclickcontext)
---
## 1. Création d'ItemStacks avec `ItemBuilder`
```java
ItemStack epee = ItemBuilder.of(Material.DIAMOND_SWORD)
.name("<gradient:#ff0844:#ffb199><bold>Lame des Enfers</bold></gradient>")
.lore(
"<gray>Une épée forgée dans les profondeurs du Nether.</gray>",
"",
"<yellow>Dégâts : <red>+15</red></yellow>",
"<green>Effet : <gold>Enflamme les cibles</gold></green>"
)
.amount(1)
.enchant(Enchantment.DAMAGE_ALL, 5)
.enchant(Enchantment.FIRE_ASPECT, 2)
.unbreakable(true)
.flags(ItemFlag.HIDE_UNBREAKABLE)
.customModelData(1001)
.build();
```
---
## 2. Prise en Charge de MiniMessage et Kyori Adventure
Tous les noms et lores utilisent nativement les balises MiniMessage :
* `<gradient:#color1:#color2>Texte</gradient>` : Dégradés de couleurs HEX.
* `<bold>`, `<italic>`, `<underlined>`, `<strikethrough>` : Mises en forme.
* `<rainbow>Texte Arc-en-ciel</rainbow>` : Animation multicolore.
* `<green>`, `<red>`, `<gold>`, `<aqua>`, `<gray>`, etc.
---
## 3. Têtes Personnalisées, Couleurs et Flags
```java
// Tête de joueur par pseudo ou UUID
GuiItem tete = ItemBuilder.skull()
.skullOwner("Luc")
.name("<yellow>Profil de Luc</yellow>")
.asGuiItem();
// Armure en cuir teintée
ItemStack armure = ItemBuilder.of(Material.LEATHER_CHESTPLATE)
.color(Color.fromRGB(41, 128, 185))
.build();
// Item brillant sans texte d'enchantement
GuiItem etoile = ItemBuilder.of(Material.NETHER_STAR)
.glowing(true)
.asGuiItem();
```
---
## 4. L'Objet Interactif `GuiItem`
Un `GuiItem` encapsule un `ItemStack` avec des comportements avancés :
```java
GuiItem bouton = ItemBuilder.of(Material.EMERALD)
.name("<green>Confirmer l'achat</green>")
.asGuiItem(ctx -> {
ctx.replySuccess("Achat confirmé !");
})
// Condition de visibilité : seuls les joueurs avec la permission voient cet item
.visibleIf(player -> player.hasPermission("monplugin.vip"))
// Cooldown de 2 secondes entre les clics
.cooldown(Duration.ofSeconds(2))
// Joue un son au joueur
.sound(Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.2f)
// Ferme l'inventaire après le clic
.closeOnClick();
```
---
## 5. Le Contexte de Clic (`GuiClickContext`)
| Méthode | Description |
|---|---|
| `ctx.getPlayer()` | Récupère le joueur ayant cliqué. |
| `ctx.getSlot()` | Récupère l'index du slot absolu cliqué. |
| `ctx.getSlotPos()` | Récupère la position (ligne, colonne). |
| `ctx.getClickType()` | Récupère le type de clic (`LEFT`, `RIGHT`, `SHIFT_LEFT`, etc.). |
| `ctx.isLeftClick()` / `isRightClick()` | Raccourcis booléens pour tester le type de clic. |
| `ctx.isShiftClick()` | Teste si la touche Shift était enfoncée. |
| `ctx.close()` | Ferme l'inventaire actuel. |
| `ctx.refresh()` | Rafraîchit les items du menu. |
| `ctx.playSound(sound, vol, pitch)` | Joue un son de confirmation ou d'erreur. |
| `ctx.reply("<yellow>Message</yellow>")`| Envoie un message formaté en MiniMessage. |
| `ctx.replySuccess(msg)` | Envoie un message de succès préfixé en vert. |
| `ctx.replyError(msg)` | Envoie un message d'erreur préfixé en rouge. |
---
> 📖 **Étape suivante** : Apprenez à concevoir des grilles avec [04_PATTERNS_AND_MASKS.md](04_PATTERNS_AND_MASKS.md).
+82
View File
@@ -0,0 +1,82 @@
# 🎨 Motifs & Masques ASCII - betterMcGuis
La création de mises en page complexes est grandement facilitée par le système de **Motifs (Patterns)** et **Masques (Masks)** textuels.
---
## 📑 Sommaire
- [1. Qu'est-ce qu'un Motif ASCII (`GuiPattern`) ?](#1-quest-ce-quun-motif-ascii-guipattern-)
- [2. Déclaration et Utilisation](#2-déclaration-et-utilisation)
- [3. Masques de Sélection de Slots (`GuiMask`)](#3-masques-de-sélection-de-slots-guimask)
---
## 1. Qu'est-ce qu'un Motif ASCII (`GuiPattern`) ?
Un `GuiPattern` vous permet de dessiner littéralement la disposition visuelle de votre inventaire sous forme de lignes de texte, où chaque caractère représente un type d'item.
---
## 2. Déclaration et Utilisation
```java
GuiPattern pattern = BetterMcGuis.pattern(
"#########",
"# S K Q #",
"# #",
"# C #",
"#########"
)
.bindFiller('#', Material.BLACK_STAINED_GLASS_PANE)
.bind('S', ItemBuilder.of(Material.EMERALD).name("<green>Boutique</green>").asGuiItem(this::ouvrirShop))
.bind('K', ItemBuilder.of(Material.CHEST).name("<gold>Kits</gold>").asGuiItem(this::ouvrirKits))
.bind('Q', ItemBuilder.of(Material.BOOK).name("<aqua>Quêtes</aqua>").asGuiItem(this::ouvrirQuetes))
.bind('C', ItemBuilder.of(Material.BARRIER).name("<red>Fermer</red>").asGuiItem(GuiClickContext::close))
.build();
// Application directe sur le GUI
BetterMcGuis.builder("Menu Principal", 5)
.pattern(pattern)
.build()
.open(player);
```
Vous pouvez aussi définir le motif directement dans le builder de manière fluide :
```java
BetterMcGuis.builder("Menu Compact", 3)
.pattern(p -> p
.lines(
"111111111",
"1 D 1",
"111111111"
)
.bindFiller('1', Material.GRAY_STAINED_GLASS_PANE)
.bind('D', ItemBuilder.of(Material.DIAMOND).name("<aqua>Trésor</aqua>").asGuiItem())
)
.build();
```
---
## 3. Masques de Sélection de Slots (`GuiMask`)
Un `GuiMask` permet de sélectionner des ensembles de slots spécifiques via une matrice binaire (`0` et `1`) pour définir par exemple des zones d'items paginés ou des slots éditables :
```java
GuiMask masqueZone = new GuiMask(
"000000000",
"011111110",
"011111110",
"000000000"
);
// Utilisation pour définir les slots d'un menu paginé
BetterMcGuis.paginated("Boutique", 4)
.itemSlots(masqueZone)
.build();
```
---
> 📖 **Étape suivante** : Découvrez les menus avancés dans [05_PAGINATED_AND_ADVANCED_GUIS.md](05_PAGINATED_AND_ADVANCED_GUIS.md).
+89
View File
@@ -0,0 +1,89 @@
# 📚 Menus Paginés, Onglets & Animations - betterMcGuis
Ce guide explore les types d'inventaires avancés : **PaginatedGui**, **TabbedGui** et **AnimatedGui**.
---
## 📑 Sommaire
- [1. Menus Paginés (`PaginatedGui`)](#1-menus-paginés-paginatedgui)
- [2. Menus à Onglets (`TabbedGui`)](#2-menus-à-onglets-tabbedgui)
- [3. Menus Animés (`AnimatedGui`)](#3-menus-animés-animatedgui)
---
## 1. Menus Paginés (`PaginatedGui`)
Le `PaginatedGui` prend en charge le calcul automatique des pages, la disposition des boutons de navigation et les indicateurs dynamiques.
```java
var shop = BetterMcGuis.paginated("Boutique", 5)
.fillBorder(Material.BLACK_STAINED_GLASS_PANE)
// Personnalisation des boutons de navigation
.previousButton(38, ItemBuilder.of(Material.ARROW).name("<yellow>◀ Page Précédente</yellow>").asGuiItem())
.nextButton(42, ItemBuilder.of(Material.ARROW).name("<yellow>Page Suivante ▶</yellow>").asGuiItem())
// Indicateur de page personnalisée
.pageIndicator(40, (page, total) -> ItemBuilder.of(Material.PAPER)
.name("<gold><bold>Page " + page + " / " + total + "</bold></gold>")
.asGuiItem()
);
// Ajout de 100 items au catalogue
for (int i = 1; i <= 100; i++) {
shop.addPageItem(ItemBuilder.of(Material.GOLD_INGOT)
.name("<yellow>Lingot #" + i + "</yellow>")
.asGuiItem(ctx -> ctx.replySuccess("Achat réussi !"))
);
}
shop.build().open(player);
```
---
## 2. Menus à Onglets (`TabbedGui`)
Permet de basculer instantanément entre plusieurs catégories d'items **sans fermer ni rouvrir l'inventaire** :
```java
BetterMcGuis.tabbed("Menu Multi-Catégories", 4)
// Onglet 1 : Guerrier
.tab("warrior", 11, ItemBuilder.of(Material.IRON_SWORD).name("<red>Guerrier</red>").asGuiItem(), tabGui -> {
tabGui.setTabItem("warrior", 20, ItemBuilder.of(Material.DIAMOND_SWORD).name("<red>Épée Lourde</red>").asGuiItem());
tabGui.setTabItem("warrior", 24, ItemBuilder.of(Material.SHIELD).name("<gray>Bouclier</gray>").asGuiItem());
})
// Onglet 2 : Archer
.tab("archer", 15, ItemBuilder.of(Material.BOW).name("<green>Archer</green>").asGuiItem(), tabGui -> {
tabGui.setTabItem("archer", 22, ItemBuilder.of(Material.CROSSBOW).name("<green>Arbalète Précise</green>").asGuiItem());
})
.build()
.open(player);
```
---
## 3. Menus Animés (`AnimatedGui`)
Permet d'animer des frames d'inventaires cadencées par tick ou secondes :
```java
AnimatedGui animated = BetterMcGuis.animated()
.title("<gold>Ouverture de Coffre Mystère...</gold>")
.rows(3)
// Frame 1
.frame(f -> f.item(13, ItemBuilder.of(Material.CHEST).name("<yellow>Chargement.</yellow>").asGuiItem()))
// Frame 2
.frame(f -> f.item(13, ItemBuilder.of(Material.ENDER_CHEST).name("<gold>Chargement..</gold>").asGuiItem()))
// Frame 3 : Révélation du lot !
.frame(f -> f.item(13, ItemBuilder.of(Material.NETHER_STAR).name("<gradient:#00f2fe:#4facfe>Bravo ! Trésor Obtenu !</gradient>").asGuiItem()))
.loop(false)
.build();
animated.open(player);
animated.startAnimation(monPlugin, Duration.ofMillis(600));
```
---
> 📖 **Étape suivante** : Découvrez le cycle de vie et les événements dans [06_LIFECYCLE_AND_EVENTS.md](06_LIFECYCLE_AND_EVENTS.md).
+91
View File
@@ -0,0 +1,91 @@
# 🎯 Cycle de Vie & Système d'Événements - betterMcGuis
La bibliothèque intègre un moteur d'événements à deux niveaux : **Hooks Locaux** (sur l'instance du menu) et **Bus d'Événements Global** (avec annotations `@GuiEventHandler`).
---
## 📑 Sommaire
- [1. Hooks Locaux sur l'Instance de Menu](#1-hooks-locaux-sur-linstance-de-menu)
- [2. Bus d'Événements Global & Annotations `@GuiEventHandler`](#2-bus-dévénements-global--annotations-guieventhandler)
- [3. Référence Exhaustive des Événements](#3-référence-exhaustive-des-événements)
---
## 1. Hooks Locaux sur l'Instance de Menu
```java
BetterMcGuis.builder("Banque", 3)
.onOpen(ctx -> {
ctx.getPlayer().sendMessage("§aBienvenue dans votre coffre sécurisé.");
})
.onClose(ctx -> {
sauvegarderDonnees(ctx.getPlayer());
})
.onOutsideClick(ctx -> {
// Ferme si le joueur clique en dehors du menu
ctx.close();
})
.onBottomClick(ctx -> {
// Clic dans son propre inventaire
ctx.getPlayer().sendMessage("§7Action détectée dans votre inventaire.");
})
.build();
```
---
## 2. Bus d'Événements Global & Annotations `@GuiEventHandler`
Vous pouvez créer des classes dédiées pour auditer, logger ou sécuriser l'ensemble des GUIs de votre serveur :
```java
package fr.luc.monplugin.listener;
import fr.luc.bettermcguis.event.*;
import fr.luc.bettermcguis.event.annotation.GuiEventHandler;
public class MonEcouteurGlobalGui {
// Écoute TOUS les clics de GUIs avec priorité élevée
@GuiEventHandler(priority = 100)
public void onGlobalClick(GuiClickEvent event) {
var ctx = event.getContext();
System.out.println("[Audit GUI] Joueur : " + ctx.getPlayer().getName() +
" | Slot : #" + ctx.getSlot() +
" | Clic : " + ctx.getClickType());
}
// Écoute UNIQUEMENT les ouvertures de la boutique
@GuiEventHandler(guiTitle = "<gradient:#00c6ff:#0072ff><bold>Boutique Paginée</bold></gradient>")
public void onShopOpen(GuiOpenEvent event) {
event.getPlayer().sendMessage("§eProfitez des promotions du week-end !");
}
// Écoute les fermetures de menus
@GuiEventHandler
public void onClose(GuiCloseEvent event) {
// Traitement global
}
}
```
Pour enregistrer l'écouteur :
```java
guiManager.registerListeners(new MonEcouteurGlobalGui());
```
---
## 3. Référence Exhaustive des Événements
| Classe d'Événement | Description | Annulable ? |
|---|---|:---:|
| `GuiOpenEvent` | Déclenché avant l'ouverture du menu pour un joueur. | ✅ **Oui** |
| `GuiCloseEvent` | Déclenché lorsque le joueur ferme le menu. | ❌ Non |
| `GuiClickEvent` | Déclenché lors de chaque clic (item, slot vide ou extérieur). | ✅ **Oui** |
| `GuiPageChangeEvent` | Déclenché lors d'un changement de page dans un `PaginatedGui`. | ❌ Non |
| `GuiRefreshEvent` | Déclenché lors du rafraîchissement d'un inventaire. | ❌ Non |
---
> 📖 **Étape suivante** : Découvrez les zones de stockage dans [07_STORAGE_AND_EDITABLE_SLOTS.md](07_STORAGE_AND_EDITABLE_SLOTS.md).
+59
View File
@@ -0,0 +1,59 @@
# 📦 Zones de Stockage & Slots Éditables - betterMcGuis
Par défaut, tous les menus créés avec `betterMcGuis` interdisent le vol, le déplacement et le shift-clic d'items pour garantir une sécurité totale contre les duplications de bugs d'inventaires.
Cependant, pour les fonctionnalités nécessitant que les joueurs déposent ou retirent des objets (comme une poubelle, un coffre de recyclage, une enclume ou un hôtel des ventes), `betterMcGuis` propose **les slots éditables** et le **`StorageGui`**.
---
## 📑 Sommaire
- [1. Slots Éditables dans un GUI Standard](#1-slots-éditables-dans-un-gui-standard)
- [2. Menu de Stockage Dédié (`StorageGui`)](#2-menu-de-stockage-dédié-storagegui)
- [3. Sécurité contre les Duplications et Glitches](#3-sécurité-contre-les-duplications-et-glitches)
---
## 1. Slots Éditables dans un GUI Standard
Vous pouvez autoriser les interactions de placement et retrait d'items sur des slots ciblés avec `.editable(...)` :
```java
BetterMcGuis.builder("Boîte de Dépôt", 3)
.fillBorder(Material.BLACK_STAINED_GLASS_PANE)
// Rend le slot 13 (centre) modifiable librement par le joueur
.editable(13)
.build()
.open(player);
```
---
## 2. Menu de Stockage Dédié (`StorageGui`)
`StorageGui` simplifie la gestion d'une zone centrale de dépôt avec restitution automatique des items laissés à la fermeture :
```java
StorageGui trash = new StorageGui("<red>Poubelle</red>", GuiType.CHEST_4_ROWS);
// Remplissage des bordures avec du vitrage
trash.fillBorder(ItemBuilder.filler(Material.RED_STAINED_GLASS_PANE).asGuiItem());
// Définit les slots intérieurs comme zone de dépôt
trash.setStorageSlots(SlotRange.interior(4, 9));
// true = restitue les items au joueur à la fermeture
// false = détruit définitivement les items à la fermeture (idéal poubelle)
trash.returnItemsOnClose(false);
trash.open(player);
```
---
## 3. Sécurité contre les Duplications et Glitches
Le gestionnaire `BukkitGuiEventListener` applique des sécurités strictes :
* **Shift-Clic Protection** : Empêche un joueur de shift-cliquer un item depuis son inventaire vers un slot protégé du menu.
* **Number Key Protection** : Empêche l'échange d'items via les touches numériques (1 à 9 de la hotbar) vers des slots non éditables.
* **Drag-and-Drop Protection** : Bloque le glisser-déposer de curseur sur tous les slots non autorisés.
* **Nettoyage automatique** : En cas de déconnexion ou de fermeture inopinée, les items des zones avec `returnItemsOnClose(true)` sont automatiquement réinsérés dans l'inventaire du joueur ou déposés au sol s'il est plein.