package de.ticketsystem.commands; import de.ticketsystem.TicketPlugin; import de.ticketsystem.model.Ticket; import de.ticketsystem.manager.CategoryManager; import de.ticketsystem.model.ConfigCategory; import de.ticketsystem.model.TicketComment; import de.ticketsystem.model.TicketPriority; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; public class TicketCommand implements CommandExecutor, TabCompleter { private final TicketPlugin plugin; public TicketCommand(TicketPlugin plugin) { this.plugin = plugin; } @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (!(sender instanceof Player player)) { sender.sendMessage("Dieser Befehl kann nur von Spielern ausgeführt werden."); return true; } if (args.length == 0) { plugin.getTicketManager().sendHelpMessage(player); return true; } switch (args[0].toLowerCase()) { case "create" -> handleCreate(player, args); case "list" -> handleList(player); case "claim" -> handleClaim(player, args); case "close" -> handleClose(player, args); case "forward" -> handleForward(player, args); case "reload" -> handleReload(player); case "migrate" -> handleMigrate(player, args); case "export" -> handleExport(player, args); case "import" -> handleImport(player, args); case "stats" -> handleStats(player); case "archive" -> handleArchive(player); case "comment" -> handleComment(player, args); case "blacklist" -> handleBlacklist(player, args); case "rate" -> handleRate(player, args); case "setpriority" -> handleSetPriority(player, args); default -> plugin.getTicketManager().sendHelpMessage(player); } return true; } // ─────────────────────────── /ticket create ──────────────────────────── private void handleCreate(Player player, String[] args) { if (!player.hasPermission("ticket.create")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } // Blacklist-Check if (plugin.getDatabaseManager().isBlacklisted(player.getUniqueId())) { player.sendMessage(plugin.color("&cDu wurdest vom Ticket-System gesperrt und kannst keine Tickets erstellen.")); return; } if (args.length < 2) { player.sendMessage(plugin.color("&cBenutzung: /ticket create [Kategorie] [Priorität] ")); if (plugin.getConfig().getBoolean("categories-enabled", true)) { player.sendMessage(plugin.color("&7Kategorien: &ebug&7, &efrage&7, &ebeschwerde&7, &esonstiges&7, &eallgemein")); } if (plugin.getConfig().getBoolean("priorities-enabled", true)) { player.sendMessage(plugin.color("&7Prioritäten: &alow&7, &enormal&7, &6high&7, &curgent")); } return; } if (plugin.getTicketManager().hasCooldown(player.getUniqueId())) { long remaining = plugin.getTicketManager().getRemainingCooldown(player.getUniqueId()); player.sendMessage(plugin.formatMessage("messages.cooldown").replace("{seconds}", String.valueOf(remaining))); return; } if (plugin.getTicketManager().hasReachedTicketLimit(player.getUniqueId())) { int max = plugin.getConfig().getInt("max-open-tickets-per-player", 2); player.sendMessage(plugin.color("&cDu hast bereits &e" + max + " &coffene Ticket(s). Bitte warte, bis dein Ticket bearbeitet wurde.")); return; } // Kategorie und Priorität optional parsen CategoryManager cm = plugin.getCategoryManager(); ConfigCategory category = cm.getDefault(); TicketPriority priority = TicketPriority.NORMAL; int messageStartIndex = 1; boolean categoriesOn = plugin.getConfig().getBoolean("categories-enabled", true); boolean prioritiesOn = plugin.getConfig().getBoolean("priorities-enabled", true); if (args.length >= 3) { // args[1]: erst als Kategorie prüfen, dann als Priorität if (categoriesOn) { ConfigCategory parsedCat = cm.resolve(args[1]); if (parsedCat != null) { category = parsedCat; messageStartIndex = 2; // args[2]: Priorität prüfen (nur wenn danach noch Text kommt) if (prioritiesOn && args.length >= 4) { TicketPriority parsedPrio = parsePriority(args[2]); if (parsedPrio != null) { priority = parsedPrio; messageStartIndex = 3; } } } else { // Keine Kategorie erkannt → args[1] als Priorität prüfen if (prioritiesOn) { TicketPriority parsedPrio = parsePriority(args[1]); if (parsedPrio != null) { priority = parsedPrio; messageStartIndex = 2; } } } } else if (prioritiesOn) { // Kategorien aus → args[1] direkt als Priorität prüfen TicketPriority parsedPrio = parsePriority(args[1]); if (parsedPrio != null) { priority = parsedPrio; messageStartIndex = 2; } } } else if (args.length == 2) { // Nur ein Argument: könnte Kategorie oder Priorität sein, aber kein Text danach // → einfach als Beschreibung behandeln, nichts parsen } String message = String.join(" ", Arrays.copyOfRange(args, messageStartIndex, args.length)); int maxLen = plugin.getConfig().getInt("max-description-length", 100); if (message.isEmpty()) { player.sendMessage(plugin.color("&cBitte gib eine Beschreibung für dein Ticket an.")); return; } if (message.length() > maxLen) { player.sendMessage(plugin.color("&cDeine Beschreibung ist zu lang! Maximal " + maxLen + " Zeichen.")); return; } final ConfigCategory finalCategory = category; final TicketPriority finalPriority = priority; Ticket ticket = new Ticket(player.getUniqueId(), player.getName(), message, player.getLocation()); ticket.setCategoryKey(finalCategory.getKey()); ticket.setPriority(finalPriority); Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { int id = plugin.getDatabaseManager().createTicket(ticket); if (id == -1) { player.sendMessage(plugin.color("&cFehler beim Erstellen des Tickets!")); return; } ticket.setId(id); plugin.getTicketManager().setCooldown(player.getUniqueId()); Bukkit.getScheduler().runTask(plugin, () -> { String catInfo = plugin.getConfig().getBoolean("categories-enabled", true) ? " §7[" + finalCategory.getColored() + "§7]" : ""; String prioInfo = plugin.getConfig().getBoolean("priorities-enabled", true) ? " §7[" + finalPriority.getColored() + "§7]" : ""; player.sendMessage(plugin.formatMessage("messages.ticket-created").replace("{id}", String.valueOf(id)) + catInfo + prioInfo); plugin.getTicketManager().notifyTeam(ticket); }); }); } // ─────────────────────────── /ticket list ────────────────────────────── private void handleList(Player player) { if (player.hasPermission("ticket.support") || player.hasPermission("ticket.admin")) { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> Bukkit.getScheduler().runTask(plugin, () -> plugin.getTicketGUI().openGUI(player))); } else { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> Bukkit.getScheduler().runTask(plugin, () -> plugin.getTicketGUI().openPlayerGUI(player))); } } // ─────────────────────────── /ticket claim ───────────────────────────── private void handleClaim(Player player, String[] args) { if (!player.hasPermission("ticket.support") && !player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } if (args.length < 2) { player.sendMessage(plugin.color("&cBenutzung: /ticket claim ")); return; } int id; try { id = Integer.parseInt(args[1]); } catch (NumberFormatException e) { player.sendMessage(plugin.color("&cUngültige ID!")); return; } final int ticketId = id; Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { boolean success = plugin.getDatabaseManager().claimTicket(ticketId, player.getUniqueId(), player.getName()); Bukkit.getScheduler().runTask(plugin, () -> { if (!success) { player.sendMessage(plugin.formatMessage("messages.already-claimed")); return; } Ticket ticket = plugin.getDatabaseManager().getTicketById(ticketId); if (ticket == null) return; player.sendMessage(plugin.formatMessage("messages.ticket-claimed") .replace("{id}", String.valueOf(ticketId)) .replace("{player}", ticket.getCreatorName())); plugin.getTicketManager().notifyCreatorClaimed(ticket); if (ticket.getLocation() != null) player.teleport(ticket.getLocation()); }); }); } // ─────────────────────────── /ticket close ───────────────────────────── private void handleClose(Player player, String[] args) { if (!player.hasPermission("ticket.support") && !player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } if (args.length < 2) { player.sendMessage(plugin.color("&cBenutzung: /ticket close [Kommentar]")); return; } int id; try { id = Integer.parseInt(args[1]); } catch (NumberFormatException e) { player.sendMessage(plugin.color("&cUngültige ID!")); return; } String closeComment = args.length > 2 ? String.join(" ", Arrays.copyOfRange(args, 2, args.length)) : ""; final int ticketId = id; final String comment = closeComment; Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { boolean success = plugin.getDatabaseManager().closeTicket(ticketId, comment); if (success) { Ticket ticket = plugin.getDatabaseManager().getTicketById(ticketId); Bukkit.getScheduler().runTask(plugin, () -> { player.sendMessage(plugin.formatMessage("messages.ticket-closed").replace("{id}", String.valueOf(ticketId))); if (ticket != null) { ticket.setCloseComment(comment); plugin.getTicketManager().notifyCreatorClosed(ticket, player.getName()); } }); } else { Bukkit.getScheduler().runTask(plugin, () -> player.sendMessage(plugin.formatMessage("messages.ticket-not-found"))); } }); } // ─────────────────────────── /ticket forward ─────────────────────────── private void handleForward(Player player, String[] args) { if (!player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } if (args.length < 3) { player.sendMessage(plugin.color("&cBenutzung: /ticket forward ")); return; } int id; try { id = Integer.parseInt(args[1]); } catch (NumberFormatException e) { player.sendMessage(plugin.color("&cUngültige ID!")); return; } Player target = Bukkit.getPlayer(args[2]); if (target == null) { player.sendMessage(plugin.color("&cSpieler nicht gefunden!")); return; } final int ticketId = id; final String fromName = player.getName(); final Player t = target; Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { boolean success = plugin.getDatabaseManager().forwardTicket(ticketId, t.getUniqueId(), t.getName()); Bukkit.getScheduler().runTask(plugin, () -> { if (!success) { player.sendMessage(plugin.formatMessage("messages.ticket-not-found")); return; } Ticket ticket = plugin.getDatabaseManager().getTicketById(ticketId); if (ticket == null) return; player.sendMessage(plugin.color("&aTicket &e#" + ticketId + " &awurde an &e" + t.getName() + " &aweitergeleitet.")); plugin.getTicketManager().notifyForwardedTo(ticket, fromName); plugin.getTicketManager().notifyCreatorForwarded(ticket); }); }); } // ─────────────────────────── /ticket comment ─────────────────────────── private void handleComment(Player player, String[] args) { if (!player.hasPermission("ticket.create") && !player.hasPermission("ticket.support") && !player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } if (args.length < 3) { player.sendMessage(plugin.color("&cBenutzung: /ticket comment ")); return; } int id; try { id = Integer.parseInt(args[1]); } catch (NumberFormatException e) { player.sendMessage(plugin.color("&cUngültige ID!")); return; } String msg = String.join(" ", Arrays.copyOfRange(args, 2, args.length)); if (msg.length() > 500) { player.sendMessage(plugin.color("&cNachricht zu lang! Maximal 500 Zeichen.")); return; } final int ticketId = id; final String message = msg; Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { Ticket ticket = plugin.getDatabaseManager().getTicketById(ticketId); if (ticket == null) { Bukkit.getScheduler().runTask(plugin, () -> player.sendMessage(plugin.formatMessage("messages.ticket-not-found"))); return; } // Spieler darf nur auf eigene Tickets kommentieren (Supporter/Admin: alle) boolean isOwner = ticket.getCreatorUUID().equals(player.getUniqueId()); boolean isStaff = player.hasPermission("ticket.support") || player.hasPermission("ticket.admin"); if (!isOwner && !isStaff) { Bukkit.getScheduler().runTask(plugin, () -> player.sendMessage(plugin.color("&cDu kannst nur deine eigenen Tickets kommentieren."))); return; } TicketComment comment = new TicketComment(ticketId, player.getUniqueId(), player.getName(), message); boolean success = plugin.getDatabaseManager().addComment(comment); Bukkit.getScheduler().runTask(plugin, () -> { if (success) { player.sendMessage(plugin.color("&aDein Kommentar zu Ticket &e#" + ticketId + " &awurde gespeichert.")); // Supporter/Admin und Ticket-Ersteller benachrichtigen notifyCommentReceivers(player, ticket, message); } else { player.sendMessage(plugin.color("&cFehler beim Speichern des Kommentars.")); } }); }); } private void notifyCommentReceivers(Player author, Ticket ticket, String message) { String onlineMsg = plugin.color("&e[Ticket #" + ticket.getId() + "] &f" + author.getName() + " &7hat kommentiert: &f" + message); String offlineMsg = "&e[Ticket #" + ticket.getId() + "] &f" + author.getName() + " &7hat kommentiert (während du offline warst): &f" + message; // Ticket-Ersteller benachrichtigen (wenn nicht der Autor selbst) if (!ticket.getCreatorUUID().equals(author.getUniqueId())) { Player creator = Bukkit.getPlayer(ticket.getCreatorUUID()); if (creator != null && creator.isOnline()) { creator.sendMessage(onlineMsg); } else { // Offline → für nächsten Login speichern Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> plugin.getDatabaseManager().addPendingNotification(ticket.getCreatorUUID(), offlineMsg)); } } // Supporter/Admin benachrichtigen (wenn Autor kein Supporter ist) if (!author.hasPermission("ticket.support") && !author.hasPermission("ticket.admin")) { // Claimer des Tickets bevorzugt benachrichtigen UUID claimerUUID = ticket.getClaimerUUID(); if (claimerUUID != null && !claimerUUID.equals(author.getUniqueId())) { Player claimer = Bukkit.getPlayer(claimerUUID); if (claimer != null && claimer.isOnline()) { claimer.sendMessage(onlineMsg); } else { String claimerOffline = "&e[Ticket #" + ticket.getId() + "] &f" + author.getName() + " &7hat auf dein bearbeitetes Ticket kommentiert (offline): &f" + message; Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> plugin.getDatabaseManager().addPendingNotification(claimerUUID, claimerOffline)); } } // Alle anderen Online-Supporter zusätzlich informieren for (Player p : Bukkit.getOnlinePlayers()) { if (p.getUniqueId().equals(author.getUniqueId())) continue; if (claimerUUID != null && p.getUniqueId().equals(claimerUUID)) continue; // schon oben if (p.hasPermission("ticket.support") || p.hasPermission("ticket.admin")) { p.sendMessage(onlineMsg); } } } } // ─────────────────────────── /ticket rate ────────────────────────────── private void handleRate(Player player, String[] args) { if (!plugin.getConfig().getBoolean("rating-enabled", true)) { player.sendMessage(plugin.color("&cBewertungen sind deaktiviert.")); return; } if (args.length < 3) { player.sendMessage(plugin.color("&cBenutzung: /ticket rate ")); return; } int id; try { id = Integer.parseInt(args[1]); } catch (NumberFormatException e) { player.sendMessage(plugin.color("&cUngültige ID!")); return; } String ratingArg = args[2].toLowerCase(); String rating; if (ratingArg.equals("good") || ratingArg.equals("gut") || ratingArg.equals("thumbsup")) { rating = "THUMBS_UP"; } else if (ratingArg.equals("bad") || ratingArg.equals("schlecht") || ratingArg.equals("thumbsdown")) { rating = "THUMBS_DOWN"; } else { player.sendMessage(plugin.color("&cUngültige Bewertung! Benutze &egood &coder &ebad&c.")); return; } final int ticketId = id; final String finalRating = rating; Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { Ticket ticket = plugin.getDatabaseManager().getTicketById(ticketId); if (ticket == null) { Bukkit.getScheduler().runTask(plugin, () -> player.sendMessage(plugin.formatMessage("messages.ticket-not-found"))); return; } if (!ticket.getCreatorUUID().equals(player.getUniqueId())) { Bukkit.getScheduler().runTask(plugin, () -> player.sendMessage(plugin.color("&cDu kannst nur deine eigenen Tickets bewerten."))); return; } if (ticket.hasRating()) { Bukkit.getScheduler().runTask(plugin, () -> player.sendMessage(plugin.color("&cDu hast dieses Ticket bereits bewertet."))); return; } boolean success = plugin.getDatabaseManager().rateTicket(ticketId, finalRating); Bukkit.getScheduler().runTask(plugin, () -> { if (success) { String emoji = "THUMBS_UP".equals(finalRating) ? "§a👍 Positiv" : "§c👎 Negativ"; player.sendMessage(plugin.color("&aDanke für deine Bewertung! (" + emoji + "§a)")); } else { player.sendMessage(plugin.color("&cBewertung konnte nicht gespeichert werden. Ticket geschlossen?")); } }); }); } // ─────────────────────────── /ticket blacklist ───────────────────────── private void handleBlacklist(Player player, String[] args) { if (!player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } if (args.length < 2) { player.sendMessage(plugin.color("&cBenutzung: /ticket blacklist [Spieler] [Grund]")); return; } switch (args[1].toLowerCase()) { case "add" -> { if (args.length < 3) { player.sendMessage(plugin.color("&cBenutzung: /ticket blacklist add [Grund]")); return; } String targetName = args[2]; String reason = args.length > 3 ? String.join(" ", Arrays.copyOfRange(args, 3, args.length)) : "Missbrauch"; @SuppressWarnings("deprecation") OfflinePlayer target = Bukkit.getOfflinePlayer(targetName); if (target.getUniqueId() == null) { player.sendMessage(plugin.color("&cSpieler nicht gefunden.")); return; } Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { boolean success = plugin.getDatabaseManager().addBlacklist( target.getUniqueId(), targetName, reason, player.getName()); Bukkit.getScheduler().runTask(plugin, () -> { if (success) player.sendMessage(plugin.color("&a" + targetName + " &awurde zur Ticket-Blacklist hinzugefügt. &7Grund: &e" + reason)); else player.sendMessage(plugin.color("&cSpieler ist bereits auf der Blacklist.")); }); }); } case "remove" -> { if (args.length < 3) { player.sendMessage(plugin.color("&cBenutzung: /ticket blacklist remove ")); return; } String targetName = args[2]; @SuppressWarnings("deprecation") OfflinePlayer target = Bukkit.getOfflinePlayer(targetName); Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { boolean success = plugin.getDatabaseManager().removeBlacklist(target.getUniqueId()); Bukkit.getScheduler().runTask(plugin, () -> { if (success) player.sendMessage(plugin.color("&a" + targetName + " &awurde von der Blacklist entfernt.")); else player.sendMessage(plugin.color("&cSpieler war nicht auf der Blacklist.")); }); }); } case "list" -> { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { var list = plugin.getDatabaseManager().getBlacklist(); Bukkit.getScheduler().runTask(plugin, () -> { player.sendMessage(plugin.color("&8&m ")); player.sendMessage(plugin.color("&6Ticket-Blacklist &7(" + list.size() + " Einträge)")); player.sendMessage(plugin.color("&8&m ")); if (list.isEmpty()) { player.sendMessage(plugin.color("&7Keine gesperrten Spieler.")); } else { for (String[] entry : list) { // {uuid, name, reason, bannedBy, bannedAt} player.sendMessage(plugin.color("&e" + entry[1] + " &7– &f" + entry[2] + " &7(gesperrt von &e" + entry[3] + "&7)")); } } player.sendMessage(plugin.color("&8&m ")); }); }); } default -> player.sendMessage(plugin.color("&cBenutzung: /ticket blacklist [Spieler] [Grund]")); } } // ─────────────────────────── /ticket reload ──────────────────────────── private void handleReload(Player player) { if (!player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } plugin.reloadConfig(); plugin.getCategoryManager().reload(); player.sendMessage(plugin.color("&aKonfiguration wurde neu geladen. &7(inkl. Kategorien)")); } // ─────────────────────────── /ticket archive ─────────────────────────── private void handleArchive(Player player) { if (!player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { int count = plugin.getDatabaseManager().archiveClosedTickets(); Bukkit.getScheduler().runTask(plugin, () -> { if (count > 0) player.sendMessage(plugin.formatMessage("messages.archive-success").replace("{count}", String.valueOf(count))); else player.sendMessage(plugin.formatMessage("messages.archive-fail")); }); }); } // ─────────────────────────── /ticket stats ───────────────────────────── private void handleStats(Player player) { if (!player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { var stats = plugin.getDatabaseManager().getTicketStats(); Bukkit.getScheduler().runTask(plugin, () -> { player.sendMessage(plugin.color("&8&m ")); player.sendMessage(plugin.color("&6Ticket Statistik")); player.sendMessage(plugin.color("&8&m ")); player.sendMessage(plugin.color("&eGesamt: &a" + stats.total)); player.sendMessage(plugin.color("&eOffen: &a" + stats.open)); player.sendMessage(plugin.color("&eGeschlossen: &a" + stats.closed)); player.sendMessage(plugin.color("&eWeitergeleitet: &a" + stats.forwarded)); if (plugin.getConfig().getBoolean("rating-enabled", true)) { player.sendMessage(plugin.color("&8&m ")); player.sendMessage(plugin.color("&6Support-Bewertungen")); player.sendMessage(plugin.color("&a👍 Positiv: &f" + stats.thumbsUp + " &c👎 Negativ: &f" + stats.thumbsDown)); int total = stats.thumbsUp + stats.thumbsDown; if (total > 0) { int percent = (int) Math.round(stats.thumbsUp * 100.0 / total); player.sendMessage(plugin.color("&7Zufriedenheit: &e" + percent + "%")); } } player.sendMessage(plugin.color("&8&m ")); player.sendMessage(plugin.color("&6Top Ersteller:")); stats.byPlayer.entrySet().stream() .sorted((a, b) -> b.getValue() - a.getValue()) .limit(5) .forEach(e -> player.sendMessage(plugin.color("&e " + e.getKey() + ": &a" + e.getValue()))); player.sendMessage(plugin.color("&8&m ")); }); }); } // ─────────────────────────── /ticket migrate ─────────────────────────── private void handleMigrate(Player player, String[] args) { if (!player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } if (args.length < 2) { player.sendMessage(plugin.color("&cBenutzung: /ticket migrate ")); return; } Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { int migrated = 0; String mode = args[1].toLowerCase(); if (mode.equals("tomysql")) migrated = plugin.getDatabaseManager().migrateToMySQL(); else if (mode.equals("tofile")) migrated = plugin.getDatabaseManager().migrateToFile(); else { player.sendMessage(plugin.formatMessage("messages.unknown-mode")); return; } int f = migrated; Bukkit.getScheduler().runTask(plugin, () -> { if (f > 0) player.sendMessage(plugin.formatMessage("messages.migration-success").replace("{count}", String.valueOf(f))); else player.sendMessage(plugin.formatMessage("messages.migration-fail")); }); }); } // ─────────────────────────── /ticket export ──────────────────────────── private void handleExport(Player player, String[] args) { if (!player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } if (args.length < 2) { player.sendMessage(plugin.color("&cBenutzung: /ticket export ")); return; } String filename = args[1]; File exportFile = new File(plugin.getDataFolder(), filename); Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { int count = plugin.getDatabaseManager().exportTickets(exportFile); Bukkit.getScheduler().runTask(plugin, () -> { if (count > 0) player.sendMessage(plugin.formatMessage("messages.export-success").replace("{count}", String.valueOf(count)).replace("{file}", filename)); else player.sendMessage(plugin.formatMessage("messages.export-fail")); }); }); } // ─────────────────────────── /ticket import ──────────────────────────── private void handleImport(Player player, String[] args) { if (!player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } if (args.length < 2) { player.sendMessage(plugin.color("&cBenutzung: /ticket import ")); return; } String filename = args[1]; File importFile = new File(plugin.getDataFolder(), filename); if (!importFile.exists()) { player.sendMessage(plugin.formatMessage("messages.file-not-found").replace("{file}", filename)); return; } Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { int count = plugin.getDatabaseManager().importTickets(importFile); Bukkit.getScheduler().runTask(plugin, () -> { if (count > 0) player.sendMessage(plugin.formatMessage("messages.import-success").replace("{count}", String.valueOf(count))); else player.sendMessage(plugin.formatMessage("messages.import-fail")); }); }); } // ─────────────────────────── /ticket setpriority ────────────────────── private void handleSetPriority(Player player, String[] args) { if (!player.hasPermission("ticket.support") && !player.hasPermission("ticket.admin")) { player.sendMessage(plugin.formatMessage("messages.no-permission")); return; } if (!plugin.getConfig().getBoolean("priorities-enabled", true)) { player.sendMessage(plugin.color("&cDas Prioritäten-System ist deaktiviert.")); return; } if (args.length < 3) { player.sendMessage(plugin.color("&cBenutzung: /ticket setpriority ")); return; } int ticketId; try { ticketId = Integer.parseInt(args[1]); } catch (NumberFormatException e) { player.sendMessage(plugin.color("&cUngültige Ticket-ID: &e" + args[1])); return; } TicketPriority priority = parsePriority(args[2]); if (priority == null) { player.sendMessage(plugin.color("&cUngültige Priorität! Gültig: &alow&7, &enormal&7, &6high&7, &curgent")); return; } Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { boolean success = plugin.getDatabaseManager().setTicketPriority(ticketId, priority); Bukkit.getScheduler().runTask(plugin, () -> { if (success) { player.sendMessage(plugin.color("&aPriorität von Ticket &e#" + ticketId + " &awurde auf " + priority.getColored() + " &agesetzt.")); } else { player.sendMessage(plugin.color("&cTicket &e#" + ticketId + " &cwurde nicht gefunden.")); } }); }); } /** Parst Benutzer-Eingaben wie "high", "hoch", "urgent", "dringend" etc. zu TicketPriority. * Gibt null zurück wenn keine Übereinstimmung. */ private TicketPriority parsePriority(String input) { if (input == null) return null; return switch (input.toLowerCase()) { case "low", "niedrig" -> TicketPriority.LOW; case "normal" -> TicketPriority.NORMAL; case "high", "hoch" -> TicketPriority.HIGH; case "urgent", "dringend" -> TicketPriority.URGENT; default -> null; }; } // ─────────────────────────── Tab-Completion ──────────────────────────── @Override public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { List completions = new ArrayList<>(); if (!(sender instanceof Player player)) return completions; if (args.length == 1) { List subs = new ArrayList<>(List.of("create", "list", "comment")); if (player.hasPermission("ticket.support") || player.hasPermission("ticket.admin")) subs.addAll(List.of("claim", "close")); if (plugin.getConfig().getBoolean("rating-enabled", true)) subs.add("rate"); if (player.hasPermission("ticket.admin")) subs.addAll(List.of("forward", "reload", "stats", "archive", "migrate", "export", "import", "blacklist")); if ((player.hasPermission("ticket.support") || player.hasPermission("ticket.admin")) && plugin.getConfig().getBoolean("priorities-enabled", true)) subs.add("setpriority"); for (String s : subs) if (s.startsWith(args[0].toLowerCase())) completions.add(s); } else if (args.length == 2 && args[0].equalsIgnoreCase("create") && plugin.getConfig().getBoolean("categories-enabled", true)) { for (ConfigCategory c : plugin.getCategoryManager().getAll()) if (c.getKey().startsWith(args[1].toLowerCase())) completions.add(c.getKey()); // auch Priorität direkt ohne Kategorie anbieten if (plugin.getConfig().getBoolean("priorities-enabled", true)) for (String p : List.of("low", "normal", "high", "urgent")) if (p.startsWith(args[1].toLowerCase())) completions.add(p); } else if (args.length == 3 && args[0].equalsIgnoreCase("create") && plugin.getConfig().getBoolean("priorities-enabled", true)) { // Priorität nach Kategorie for (String p : List.of("low", "normal", "high", "urgent")) if (p.startsWith(args[2].toLowerCase())) completions.add(p); } else if (args.length == 3 && args[0].equalsIgnoreCase("setpriority")) { for (String p : List.of("low", "normal", "high", "urgent")) if (p.startsWith(args[2].toLowerCase())) completions.add(p); } else if (args.length == 3 && args[0].equalsIgnoreCase("forward")) { for (Player p : Bukkit.getOnlinePlayers()) if (p.getName().toLowerCase().startsWith(args[2].toLowerCase())) completions.add(p.getName()); } else if (args.length == 2 && args[0].equalsIgnoreCase("blacklist")) { completions.addAll(List.of("add", "remove", "list")); } else if (args.length == 3 && args[0].equalsIgnoreCase("blacklist") && (args[1].equalsIgnoreCase("add") || args[1].equalsIgnoreCase("remove"))) { for (Player p : Bukkit.getOnlinePlayers()) if (p.getName().toLowerCase().startsWith(args[2].toLowerCase())) completions.add(p.getName()); } else if (args.length == 3 && args[0].equalsIgnoreCase("rate")) { completions.addAll(List.of("good", "bad")); } return completions; } }