@startuml gui-class-diagram title CR-Core — GUI framework (class diagram, réutilisable) skinparam classAttributeIconSize 0 hide empty members package "fr.luc.crcore.util.gui" { abstract class AbstractInventoryGui { - inventory: Inventory - handlers: Map -- # setInventory(Inventory): void + getInventory(): Inventory + {abstract} rebuild(): void + onClose(HumanEntity): void + openTo(HumanEntity): void # setButton(slot, item, handler): void # setDecoration(slot, item): void # clearSlot(slot): void + handleClick(event): void ' appelé par GuiListener + handleClose(event): void } AbstractInventoryGui ..|> "org.bukkit.inventory.InventoryHolder" interface GuiClickHandler <> { + onClick(InventoryClickEvent): void } class GuiListener { + registerOn(JavaPlugin): void -- @ onClick(InventoryClickEvent) @ onClose(InventoryCloseEvent) } GuiListener ..|> "org.bukkit.event.Listener" class GuiItems <> { + {static} named(material, name): Builder + {static} of(material): Builder + {static} filler(): ItemStack + {static} item(builder): ItemStack } class "GuiItems.Builder" as Builder { - stack: ItemStack - meta: ItemMeta + name(text): Builder + lore(lines...): Builder + lore(List): Builder + amount(int): Builder + build(): ItemStack + asItem(): ItemStack } GuiItems +-- Builder GuiListener ..> AbstractInventoryGui : dispatches via getHolder() AbstractInventoryGui --> GuiClickHandler : per-slot } note right of GuiListener Détection par holder : if (e.getInventory().getHolder() instanceof AbstractInventoryGui gui) { e.setCancelled(true); // ← TOUJOURS, même slot vide gui.handleClick(e); } Enregistré une fois dans CRCore.enable(). end note note right of AbstractInventoryGui Pattern : 1. extends AbstractInventoryGui 2. constructeur : Inventory inv = Bukkit.createInventory(this, 27, "&eTitre"); setInventory(inv); 3. override rebuild() pour peindre 4. setButton(slot, GuiItems.named(...).build(), handler) end note @enduml