Update from Git Manager GUI

This commit is contained in:
2026-03-24 08:54:30 +01:00
parent 6edf8f9157
commit e4b2ac32ca
18 changed files with 2748 additions and 265 deletions

View File

@@ -0,0 +1,313 @@
package me.viper.teamplugin.gui;
import me.viper.teamplugin.manager.LangManager;
import me.viper.teamplugin.manager.MailboxManager;
import me.viper.teamplugin.manager.MessageManager;
import me.viper.teamplugin.util.Utils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.*;
/**
* MailboxGUI two-view postfach for TeamPlugin.
*
* LIST VIEW (54 slots)
* ┌─────────────────────────┐
* │ Header row (glass) │ slot 4 = mailbox info item
* │ Message items 9-44 │ WRITTEN_BOOK=unread, BOOK=read
* │ Footer nav 45/49/53 │ ← page | close | page →
* └─────────────────────────┘
*
* READ VIEW (54 slots)
* ┌─────────────────────────┐
* │ Background filler │
* │ Full message at 22 │
* │ Delete:20 Reply:24 │
* │ Back:49 │
* └─────────────────────────┘
*/
public class MailboxGUI {
private static final int ITEMS_PER_PAGE = 36; // rows 1-4, slots 9-44
/** UUID → current list-view page number */
private static final Map<UUID, Integer> CURRENT_PAGE = new HashMap<>();
/** UUID → whose mailbox is open (player name) */
private static final Map<UUID, String> OPEN_FOR_PLAYER = new HashMap<>();
/** UUID → msgId of message currently being read */
private static final Map<UUID, String> READING_ID = new HashMap<>();
// ── Open: list view ───────────────────────────────────────────────
/** Opens the caller's own mailbox at page 0. */
public static void openMailbox(Player viewer) {
openMailbox(viewer, viewer.getName(), 0);
}
/** Opens a specific player's mailbox at a given page (admins can inspect others). */
public static void openMailbox(Player viewer, String targetPlayer, int page) {
List<String[]> messages = MailboxManager.getParsedMessages(targetPlayer);
int totalPages = Math.max(1, (int) Math.ceil((double) messages.size() / ITEMS_PER_PAGE));
page = Math.max(0, Math.min(page, totalPages - 1));
OPEN_FOR_PLAYER.put(viewer.getUniqueId(), targetPlayer);
CURRENT_PAGE.put(viewer.getUniqueId(), page);
Inventory inv = Bukkit.createInventory(null, 54, Utils.color(getListTitle()));
// Header row
ItemStack headerGlass = filler(Material.CYAN_STAINED_GLASS_PANE);
for (int i = 0; i < 9; i++) inv.setItem(i, headerGlass);
// Footer row
ItemStack footerGlass = filler(Material.BLACK_STAINED_GLASS_PANE);
for (int i = 45; i < 54; i++) inv.setItem(i, footerGlass);
// Info item (slot 4)
int unread = MailboxManager.getUnreadCount(targetPlayer);
inv.setItem(4, buildInfoItem(targetPlayer, unread, page + 1, totalPages));
// Message items (slots 9-44)
int start = page * ITEMS_PER_PAGE;
for (int i = 0; i < ITEMS_PER_PAGE; i++) {
int idx = start + i;
if (idx >= messages.size()) break;
inv.setItem(9 + i, buildMessageListItem(messages.get(idx)));
}
// Navigation
if (page > 0) inv.setItem(45, navItem(Material.ARROW,
Utils.color(LangManager.get("mailbox_prev_page")),
List.of(Utils.color("&7Vorherige Seite"))));
inv.setItem(49, navItem(Material.BARRIER,
Utils.color(LangManager.get("mailbox_close")),
List.of(Utils.color("&7Postfach schließen"))));
if (page + 1 < totalPages) inv.setItem(53, navItem(Material.ARROW,
Utils.color(LangManager.get("mailbox_next_page")),
List.of(Utils.color("&7Nächste Seite"))));
viewer.openInventory(inv);
}
// ── Open: read view ───────────────────────────────────────────────
private static void openMessage(Player viewer, String[] parts) {
// parts: [id, from, isoTimestamp, read, text]
String msgId = parts[0];
String from = parts[1];
String date = Utils.prettifyIso(parts[2]);
String text = parts[4];
READING_ID.put(viewer.getUniqueId(), msgId);
String targetPlayer = OPEN_FOR_PLAYER.getOrDefault(viewer.getUniqueId(), viewer.getName());
MailboxManager.markRead(targetPlayer, msgId);
Inventory inv = Bukkit.createInventory(null, 54, Utils.color(getReadTitle()));
// Background
ItemStack bg = filler(Material.GRAY_STAINED_GLASS_PANE);
for (int i = 0; i < 54; i++) inv.setItem(i, bg);
// Message paper at slot 22
inv.setItem(22, buildFullMessageItem(from, date, text));
// Delete (slot 20)
inv.setItem(20, navItem(Material.RED_CONCRETE,
Utils.color(LangManager.get("mailbox_delete_btn")),
List.of(Utils.color("&7Nachricht endgültig löschen"))));
// Reply (slot 24)
inv.setItem(24, navItem(Material.WRITABLE_BOOK,
Utils.color(Utils.replace(LangManager.get("mailbox_reply_btn"), "%player%", from)),
List.of(Utils.color("&7An &b" + from + " &7antworten"))));
// Back (slot 49)
inv.setItem(49, navItem(Material.ARROW,
Utils.color(LangManager.get("mailbox_back_btn")),
List.of(Utils.color("&7Zurück zur Liste"))));
viewer.openInventory(inv);
}
// ── Click handlers ────────────────────────────────────────────────
public static void handleListClick(Player player, InventoryClickEvent e) {
e.setCancelled(true);
int slot = e.getRawSlot();
ItemStack clicked = e.getCurrentItem();
if (clicked == null || clicked.getType().isAir()) return;
String target = OPEN_FOR_PLAYER.getOrDefault(player.getUniqueId(), player.getName());
int page = CURRENT_PAGE.getOrDefault(player.getUniqueId(), 0);
switch (slot) {
case 45 -> openMailbox(player, target, page - 1);
case 49 -> {
cleanup(player.getUniqueId());
player.closeInventory();
}
case 53 -> openMailbox(player, target, page + 1);
default -> {
if (slot >= 9 && slot <= 44) {
List<String[]> messages = MailboxManager.getParsedMessages(target);
int idx = page * ITEMS_PER_PAGE + (slot - 9);
if (idx < messages.size()) openMessage(player, messages.get(idx));
}
}
}
}
public static void handleReadClick(Player player, InventoryClickEvent e) {
e.setCancelled(true);
int slot = e.getRawSlot();
ItemStack clicked = e.getCurrentItem();
if (clicked == null || clicked.getType().isAir()) return;
String target = OPEN_FOR_PLAYER.getOrDefault(player.getUniqueId(), player.getName());
String msgId = READING_ID.get(player.getUniqueId());
int page = CURRENT_PAGE.getOrDefault(player.getUniqueId(), 0);
switch (slot) {
case 20 -> { // delete
if (msgId != null) MailboxManager.delete(target, msgId);
READING_ID.remove(player.getUniqueId());
player.sendMessage(Utils.color(LangManager.get("mail_deleted")));
openMailbox(player, target, page);
}
case 24 -> { // reply
if (msgId != null) {
MailboxManager.getParsedMessages(target).stream()
.filter(a -> a[0].equals(msgId))
.findFirst()
.ifPresent(parts -> {
cleanup(player.getUniqueId());
player.closeInventory();
MessageManager.startReply(player, parts[1]);
});
}
}
case 49 -> { // back
READING_ID.remove(player.getUniqueId());
openMailbox(player, target, page);
}
}
}
// ── Title helpers ─────────────────────────────────────────────────
public static String getListTitle() {
return LangManager.get("mailbox_title");
}
public static String getReadTitle() {
return LangManager.get("mailbox_read_title");
}
public static boolean isListTitle(String colored) {
return colored.equals(Utils.color(getListTitle()));
}
public static boolean isReadTitle(String colored) {
return colored.equals(Utils.color(getReadTitle()));
}
// ── State cleanup ─────────────────────────────────────────────────
public static void cleanup(UUID uuid) {
CURRENT_PAGE.remove(uuid);
OPEN_FOR_PLAYER.remove(uuid);
READING_ID.remove(uuid);
}
// ── Item builders ─────────────────────────────────────────────────
private static ItemStack buildInfoItem(String owner, int unread, int page, int total) {
ItemStack item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta m = item.getItemMeta();
if (m != null) {
m.setDisplayName(Utils.color("&b&lPostfach &8 &7" + owner));
m.setLore(List.of(
Utils.color("&7Ungelesen&8: &e" + unread),
Utils.color("&7Seite &e" + page + " &7/ &e" + total)
));
item.setItemMeta(m);
}
return item;
}
private static ItemStack buildMessageListItem(String[] parts) {
// parts: [id, from, iso, read, text]
boolean read = "true".equals(parts[3]);
ItemStack item = new ItemStack(read ? Material.BOOK : Material.WRITTEN_BOOK);
ItemMeta m = item.getItemMeta();
if (m != null) {
m.setDisplayName(Utils.color((read ? "&7" : "&e&l") + "Von: " + parts[1]));
String preview = parts[4].length() > 38 ? parts[4].substring(0, 38) + "" : parts[4];
m.setLore(List.of(
Utils.color("&7" + Utils.prettifyIso(parts[2])),
Utils.color("&f" + preview),
"",
Utils.color(read ? "&8Gelesen" : "&eUngelesen Klicken zum Lesen")
));
item.setItemMeta(m);
}
return item;
}
private static ItemStack buildFullMessageItem(String from, String date, String text) {
ItemStack item = new ItemStack(Material.PAPER);
ItemMeta m = item.getItemMeta();
if (m != null) {
m.setDisplayName(Utils.color("&bVon: &e" + from + " &8| &7" + date));
List<String> lore = new ArrayList<>();
lore.add("");
for (String line : wrapText(text, 40)) lore.add(Utils.color("&f" + line));
m.setLore(lore);
item.setItemMeta(m);
}
return item;
}
// ── Generic helpers ───────────────────────────────────────────────
private static ItemStack filler(Material mat) {
ItemStack item = new ItemStack(mat);
ItemMeta m = item.getItemMeta();
if (m != null) { m.setDisplayName(" "); item.setItemMeta(m); }
return item;
}
private static ItemStack navItem(Material mat, String name, List<String> lore) {
ItemStack item = new ItemStack(mat);
ItemMeta m = item.getItemMeta();
if (m != null) { m.setDisplayName(name); m.setLore(lore); item.setItemMeta(m); }
return item;
}
/** Word-wraps {@code text} at {@code maxChars} characters per line. */
private static List<String> wrapText(String text, int maxChars) {
List<String> lines = new ArrayList<>();
String[] words = text.split(" ");
StringBuilder cur = new StringBuilder();
for (String w : words) {
if (cur.length() > 0 && cur.length() + 1 + w.length() > maxChars) {
lines.add(cur.toString());
cur = new StringBuilder(w);
} else {
if (cur.length() > 0) cur.append(' ');
cur.append(w);
}
}
if (cur.length() > 0) lines.add(cur.toString());
return lines.isEmpty() ? List.of(text) : lines;
}
}