313 lines
13 KiB
Java
313 lines
13 KiB
Java
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;
|
||
}
|
||
} |