359 lines
14 KiB
Markdown
359 lines
14 KiB
Markdown
# 🖼️ betterMcGuis
|
||
|
||
[](https://www.oracle.com/java/)
|
||
[](https://papermc.io/)
|
||
[](https://docs.advntr.dev/)
|
||
[](#)
|
||
|
||
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`)](#-guides-détaillés-dossier-docs)
|
||
- [🌟 Fonctionnalités](#-fonctionnalités)
|
||
- [🏗️ Architecture & Flux d'Interactions](#️-architecture--flux-dinteractions)
|
||
- [📦 Installation & Configuration](#-installation--configuration)
|
||
- [🚀 Guide de Démarrage Rapide](#-guide-de-démarrage-rapide)
|
||
- [💡 Exemples de Menus](#-exemples-de-menus)
|
||
- [1. Menu Principal Standard (`GuiBuilder`)](#1-menu-principal-standard-guibuilder)
|
||
- [2. Menu Paginé Dynamique (`PaginatedGui`)](#2-menu-paginé-dynamique-paginatedgui)
|
||
- [3. Motifs ASCII & Grilles de Disposition (`GuiPattern`)](#3-motifs-ascii--grilles-de-disposition-guipattern)
|
||
- [4. Menus à Onglets sans Réouverture (`TabbedGui`)](#4-menus-à-onglets-sans-réouverture-tabbedgui)
|
||
- [5. Zones de Dépôt / Poubelle (`StorageGui`)](#5-zones-de-dépôt--poubelle-storagegui)
|
||
- [💎 Construction d'Items (`ItemBuilder`)](#-construction-ditems-itembuilder)
|
||
- [🎯 Système d'Événements & Écouteurs Annotés](#-système-dévénements--écouteurs-annotés)
|
||
- [📂 Organisation des Packages](#-organisation-des-packages)
|
||
|
||
---
|
||
|
||
## 📚 Guides Détaillés (Dossier `/docs`)
|
||
|
||
Pour une exploration approfondie de chaque composant, consultez la documentation modulaire :
|
||
* 📘 [**01. Guide de Démarrage Rapide**](docs/01_GETTING_STARTED.md) : Installation Gradle/Maven, initialisation dans `JavaPlugin` et cycle de vie.
|
||
* 🏗️ [**02. Fluent GUI Builder DSL**](docs/02_GUI_BUILDER_DSL.md) : Méthodes de placement de slots, dimensions, bordures, remplissages et propriétés dynamiques.
|
||
* 💎 [**03. ItemBuilder & GuiItem**](docs/03_ITEM_BUILDER_AND_ITEMS.md) : Formatage MiniMessage, têtes personnalisées, armures teintées, sons, cooldowns et `GuiClickContext`.
|
||
* 🎨 [**04. Motifs & Masques ASCII**](docs/04_PATTERNS_AND_MASKS.md) : Conception visuelle de grilles par matrices textuelles (`GuiPattern`, `GuiMask`).
|
||
* 📚 [**05. Menus Paginés, Onglets & Animations**](docs/05_PAGINATED_AND_ADVANCED_GUIS.md) : Pagination automatique, onglets commutables sans réouverture et frames animées.
|
||
* 🎯 [**06. Cycle de Vie & Événements**](docs/06_LIFECYCLE_AND_EVENTS.md) : Hooks locaux (`.onClick()`, `.onClose()`) et écouteurs globaux annotés `@GuiEventHandler`.
|
||
* 📦 [**07. Zones de Stockage & Slots Éditables**](docs/07_STORAGE_AND_EDITABLE_SLOTS.md) : Menus de dépôts, restitution d'items et sécurités anti-glitch.
|
||
|
||
---
|
||
|
||
## 🌟 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
|
||
|
||
```mermaid
|
||
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)
|
||
|
||
```kotlin
|
||
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`
|
||
|
||
```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() {
|
||
// 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`)
|
||
|
||
```java
|
||
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`)
|
||
|
||
```java
|
||
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`)
|
||
|
||
```java
|
||
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`)
|
||
|
||
```java
|
||
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`)
|
||
|
||
```java
|
||
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`)
|
||
|
||
```java
|
||
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
|
||
|
||
```java
|
||
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](LICENSE). |