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:
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user