Update from Git Manager GUI
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package de.ticketsystem.commands;
|
||||
|
||||
import de.ticketsystem.TicketPlugin;
|
||||
import de.ticketsystem.model.FaqEntry;
|
||||
import de.ticketsystem.model.Ticket;
|
||||
|
||||
import de.ticketsystem.manager.CategoryManager;
|
||||
@@ -35,27 +36,152 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
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 "top" -> handleTop(player);
|
||||
case "archive" -> handleArchive(player);
|
||||
case "comment" -> handleComment(player, args);
|
||||
case "blacklist" -> handleBlacklist(player, args);
|
||||
case "rate" -> handleRate(player, args);
|
||||
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 "top" -> handleTop(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);
|
||||
case "faq" -> handleFaq(player, args);
|
||||
default -> plugin.getTicketManager().sendHelpMessage(player);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ─────────────────────────── /ticket faq ───────────────────────────────
|
||||
|
||||
/**
|
||||
* /ticket faq – öffnet die FAQ-GUI (alle Spieler)
|
||||
* /ticket faq add <Frage> | <Antwort> – fügt ein FAQ hinzu (ticket.admin)
|
||||
* /ticket faq edit <ID> <Frage> | <Antwort> – bearbeitet ein FAQ (ticket.admin)
|
||||
* /ticket faq delete <ID> – löscht ein FAQ (ticket.admin)
|
||||
* /ticket faq reload – lädt FAQs neu (ticket.admin)
|
||||
*/
|
||||
private void handleFaq(Player player, String[] args) {
|
||||
// Kein Subbefehl → GUI öffnen
|
||||
if (args.length == 1) {
|
||||
plugin.getFaqGUI().openFaqGUI(player);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args[1].toLowerCase()) {
|
||||
|
||||
// ── /ticket faq add <Frage> | <Antwort> ────────────────────────
|
||||
case "add" -> {
|
||||
if (!player.hasPermission("ticket.admin")) {
|
||||
player.sendMessage(plugin.formatMessage("messages.no-permission")); return;
|
||||
}
|
||||
if (args.length < 3) {
|
||||
player.sendMessage(plugin.color("&cBenutzung: /ticket faq add <Frage> | <Antwort>"));
|
||||
player.sendMessage(plugin.color("&7Beispiel: &e/ticket faq add Wie erstelle ich ein Ticket? | Nutze /ticket create."));
|
||||
return;
|
||||
}
|
||||
String full = String.join(" ", Arrays.copyOfRange(args, 2, args.length));
|
||||
String[] parts = full.split("\\s*\\|\\s*", 2);
|
||||
if (parts.length < 2 || parts[0].isBlank() || parts[1].isBlank()) {
|
||||
player.sendMessage(plugin.color("&cTrenne Frage und Antwort mit &e|&c, z.B.:"));
|
||||
player.sendMessage(plugin.color("&e/ticket faq add Wie erstelle ich ein Ticket? | Nutze /ticket create."));
|
||||
return;
|
||||
}
|
||||
FaqEntry created = plugin.getFaqManager().add(parts[0].trim(), parts[1].trim());
|
||||
player.sendMessage(plugin.color("&aFAQ &e#" + created.getId() + " &awurde erfolgreich erstellt!"));
|
||||
player.sendMessage(plugin.color("&7Frage: &e" + created.getQuestion()));
|
||||
player.sendMessage(plugin.color("&7Antwort: &f" + created.getAnswer()));
|
||||
}
|
||||
|
||||
// ── /ticket faq edit <ID> <Frage> | <Antwort> ──────────────────
|
||||
case "edit" -> {
|
||||
if (!player.hasPermission("ticket.admin")) {
|
||||
player.sendMessage(plugin.formatMessage("messages.no-permission")); return;
|
||||
}
|
||||
if (args.length < 4) {
|
||||
player.sendMessage(plugin.color("&cBenutzung: /ticket faq edit <ID> <Frage> | <Antwort>"));
|
||||
return;
|
||||
}
|
||||
int id;
|
||||
try { id = Integer.parseInt(args[2]); }
|
||||
catch (NumberFormatException e) {
|
||||
player.sendMessage(plugin.color("&cUngültige FAQ-ID: &e" + args[2])); return;
|
||||
}
|
||||
String full = String.join(" ", Arrays.copyOfRange(args, 3, args.length));
|
||||
String[] parts = full.split("\\s*\\|\\s*", 2);
|
||||
if (parts.length < 2 || parts[0].isBlank() || parts[1].isBlank()) {
|
||||
player.sendMessage(plugin.color("&cTrenne Frage und Antwort mit &e|&c."));
|
||||
return;
|
||||
}
|
||||
boolean ok = plugin.getFaqManager().edit(id, parts[0].trim(), parts[1].trim());
|
||||
if (ok) player.sendMessage(plugin.color("&aFAQ &e#" + id + " &awurde erfolgreich aktualisiert!"));
|
||||
else player.sendMessage(plugin.color("&cFAQ &e#" + id + " &cwurde nicht gefunden."));
|
||||
}
|
||||
|
||||
// ── /ticket faq delete <ID> ─────────────────────────────────────
|
||||
case "delete", "remove" -> {
|
||||
if (!player.hasPermission("ticket.admin")) {
|
||||
player.sendMessage(plugin.formatMessage("messages.no-permission")); return;
|
||||
}
|
||||
if (args.length < 3) {
|
||||
player.sendMessage(plugin.color("&cBenutzung: /ticket faq delete <ID>")); return;
|
||||
}
|
||||
int id;
|
||||
try { id = Integer.parseInt(args[2]); }
|
||||
catch (NumberFormatException e) {
|
||||
player.sendMessage(plugin.color("&cUngültige FAQ-ID: &e" + args[2])); return;
|
||||
}
|
||||
boolean ok = plugin.getFaqManager().delete(id);
|
||||
if (ok) player.sendMessage(plugin.color("&aFAQ &e#" + id + " &awurde gelöscht."));
|
||||
else player.sendMessage(plugin.color("&cFAQ &e#" + id + " &cwurde nicht gefunden."));
|
||||
}
|
||||
|
||||
// ── /ticket faq reload ──────────────────────────────────────────
|
||||
case "reload" -> {
|
||||
if (!player.hasPermission("ticket.admin")) {
|
||||
player.sendMessage(plugin.formatMessage("messages.no-permission")); return;
|
||||
}
|
||||
plugin.getFaqManager().reload();
|
||||
player.sendMessage(plugin.color("&aFAQs wurden neu geladen. ("
|
||||
+ plugin.getFaqManager().getAll().size() + " Einträge)"));
|
||||
}
|
||||
|
||||
// ── /ticket faq list ────────────────────────────────────────────
|
||||
case "list" -> {
|
||||
List<FaqEntry> all = plugin.getFaqManager().getAll();
|
||||
player.sendMessage(plugin.color("&8&m "));
|
||||
player.sendMessage(plugin.color("&6Häufige Fragen (FAQ) &7— " + all.size() + " Einträge"));
|
||||
player.sendMessage(plugin.color("&8&m "));
|
||||
if (all.isEmpty()) {
|
||||
player.sendMessage(plugin.color("&7Noch keine FAQs vorhanden."));
|
||||
} else {
|
||||
for (FaqEntry e : all) {
|
||||
player.sendMessage(plugin.color("&e#" + e.getId() + " &f" + e.getQuestion()));
|
||||
player.sendMessage(plugin.color(" &7→ &f" + e.getAnswer()));
|
||||
}
|
||||
}
|
||||
player.sendMessage(plugin.color("&8&m "));
|
||||
if (player.hasPermission("ticket.admin")) {
|
||||
player.sendMessage(plugin.color("&7Befehle: &e/ticket faq add &8| &e/ticket faq edit <ID> &8| &e/ticket faq delete <ID>"));
|
||||
}
|
||||
}
|
||||
|
||||
default -> {
|
||||
player.sendMessage(plugin.color("&cUnbekannter FAQ-Befehl."));
|
||||
player.sendMessage(plugin.color("&7Benutze &e/ticket faq &7zum Öffnen der GUI."));
|
||||
if (player.hasPermission("ticket.admin")) {
|
||||
player.sendMessage(plugin.color("&7Admin-Befehle: &e/ticket faq add | edit | delete | reload | list"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────── /ticket create ────────────────────────────
|
||||
|
||||
private void handleCreate(Player player, String[] args) {
|
||||
@@ -63,7 +189,6 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
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;
|
||||
@@ -91,7 +216,6 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
return;
|
||||
}
|
||||
|
||||
// Kategorie und Priorität optional parsen
|
||||
CategoryManager cm = plugin.getCategoryManager();
|
||||
ConfigCategory category = cm.getDefault();
|
||||
TicketPriority priority = TicketPriority.NORMAL;
|
||||
@@ -147,13 +271,14 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
Ticket ticket = new Ticket(player.getUniqueId(), player.getName(), message, player.getLocation());
|
||||
ticket.setCategoryKey(finalCategory.getKey());
|
||||
ticket.setPriority(finalPriority);
|
||||
// BungeeCord: Server-Name des erstellenden Servers speichern
|
||||
ticket.setServerName(plugin.getServerName());
|
||||
|
||||
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);
|
||||
// Cache befüllen
|
||||
plugin.getTicketCache().put(ticket);
|
||||
plugin.getTicketManager().setCooldown(player.getUniqueId());
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
String catInfo = plugin.getConfig().getBoolean("categories-enabled", true)
|
||||
@@ -194,14 +319,14 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
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);
|
||||
Ticket ticket = getCachedOrFetch(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);
|
||||
// Teleport beim Annehmen entfernt – Teleport nur noch über das GUI-Item möglich.
|
||||
plugin.getTicketCache().invalidate(ticketId); // Stale cache löschen
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -224,10 +349,9 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
boolean success = plugin.getDatabaseManager().closeTicket(ticketId, comment);
|
||||
if (success) {
|
||||
Ticket ticket = plugin.getDatabaseManager().getTicketById(ticketId);
|
||||
// Ticket in persistente Stats-Tabelle eintragen (bleibt auch nach Löschung erhalten).
|
||||
// player.getName() = der Admin der /ticket close ausgeführt hat – nicht zwingend der Claimer.
|
||||
Ticket ticket = getCachedOrFetch(ticketId);
|
||||
if (ticket != null) plugin.getDatabaseManager().recordClosedTicket(ticket, player.getName());
|
||||
plugin.getTicketCache().invalidate(ticketId);
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
player.sendMessage(plugin.formatMessage("messages.ticket-closed").replace("{id}", String.valueOf(ticketId)));
|
||||
if (ticket != null) {
|
||||
@@ -252,29 +376,26 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
try { id = Integer.parseInt(args[1]); }
|
||||
catch (NumberFormatException e) { player.sendMessage(plugin.color("&cUngültige ID!")); return; }
|
||||
|
||||
// BungeeCord: Ziel-Spieler lokal suchen
|
||||
Player localTarget = Bukkit.getPlayer(args[2]);
|
||||
|
||||
if (localTarget == null) {
|
||||
if (plugin.isBungeeCordEnabled()) {
|
||||
player.sendMessage(plugin.color("&7[BungeeCord] Spieler &e" + args[2]
|
||||
+ " &7ist auf diesem Server nicht online."));
|
||||
player.sendMessage(plugin.color("&7Tipp: Forwarden geht nur zu Spielern auf &bdemselben Server&7."));
|
||||
player.sendMessage(plugin.color("&7[BungeeCord] Spieler &e" + args[2] + " &7ist auf diesem Server nicht online."));
|
||||
} else {
|
||||
player.sendMessage(plugin.color("&cSpieler nicht gefunden!"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final int ticketId = id;
|
||||
final String fromName = player.getName();
|
||||
final Player t = localTarget;
|
||||
final int ticketId = id;
|
||||
final String fromName = player.getName();
|
||||
final Player t = localTarget;
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
boolean success = plugin.getDatabaseManager().forwardTicket(ticketId, t.getUniqueId(), t.getName());
|
||||
plugin.getTicketCache().invalidate(ticketId);
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
if (!success) { player.sendMessage(plugin.formatMessage("messages.ticket-not-found")); return; }
|
||||
Ticket ticket = plugin.getDatabaseManager().getTicketById(ticketId);
|
||||
Ticket ticket = getCachedOrFetch(ticketId);
|
||||
if (ticket == null) return;
|
||||
player.sendMessage(plugin.color("&aTicket &e#" + ticketId + " &awurde an &e" + t.getName() + " &aweitergeleitet."));
|
||||
plugin.getTicketManager().notifyForwardedTo(ticket, fromName);
|
||||
@@ -297,17 +418,17 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
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;
|
||||
final int ticketId = id;
|
||||
final String message = msg;
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
Ticket ticket = plugin.getDatabaseManager().getTicketById(ticketId);
|
||||
Ticket ticket = getCachedOrFetch(ticketId);
|
||||
if (ticket == null) {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> player.sendMessage(plugin.formatMessage("messages.ticket-not-found")));
|
||||
return;
|
||||
}
|
||||
boolean isOwner = ticket.getCreatorUUID().equals(player.getUniqueId());
|
||||
boolean isStaff = player.hasPermission("ticket.support") || player.hasPermission("ticket.admin");
|
||||
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;
|
||||
@@ -327,59 +448,27 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Benachrichtigt alle relevanten Empfänger über einen neuen Kommentar.
|
||||
*
|
||||
* ── BUG FIX #2 ──────────────────────────────────────────────────────────
|
||||
* Vorher: broadcastTeamNotification() wurde am Ende ZUSÄTZLICH aufgerufen –
|
||||
* obwohl alle lokalen Supporter bereits einzeln per Schleife
|
||||
* benachrichtigt wurden. Das führte zu:
|
||||
* a) Doppelter Nachricht für lokale Supporter
|
||||
* b) broadcastTeamNotification() sendet intern ebenfalls lokal →
|
||||
* lokale Supporter sahen die Nachricht dreifach
|
||||
* c) Das Forward-Paket an andere Server war korrekt, aber die
|
||||
* Empfänger auf anderen Servern sahen auch Duplikate da
|
||||
* broadcastTeamNotification() wiederum lokal sendet
|
||||
*
|
||||
* Fix: broadcastTeamNotification() ERSETZT die lokale Supporter-Schleife
|
||||
* komplett. Die Methode sendet bereits lokal direkt und forwardet
|
||||
* gleichzeitig an alle anderen BungeeCord-Server.
|
||||
* Im Standalone-Modus bleibt die lokale Schleife erhalten.
|
||||
* ────────────────────────────────────────────────────────────────────────
|
||||
*/
|
||||
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;
|
||||
|
||||
// ── 1. 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 if (plugin.isBungeeCordEnabled()) {
|
||||
// BungeeCord: Zustellung via Plugin-Messaging, kein Pending-Eintrag
|
||||
// (PlayerJoinListener übernimmt Offline-Fallback via close_notified-Logik)
|
||||
plugin.getBungeeMessenger().sendMessageToPlayer(
|
||||
ticket.getCreatorUUID(), ticket.getCreatorName(), onlineMsg);
|
||||
plugin.getBungeeMessenger().sendMessageToPlayer(ticket.getCreatorUUID(), ticket.getCreatorName(), onlineMsg);
|
||||
} else {
|
||||
// Standalone: Offline → für nächsten Login speichern
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () ->
|
||||
plugin.getDatabaseManager().addPendingNotification(ticket.getCreatorUUID(), offlineMsg));
|
||||
}
|
||||
}
|
||||
|
||||
// ── 2. Supporter/Admin benachrichtigen (wenn Kommentar vom Spieler kommt) ──
|
||||
if (!author.hasPermission("ticket.support") && !author.hasPermission("ticket.admin")) {
|
||||
|
||||
if (plugin.isBungeeCordEnabled()) {
|
||||
// BungeeCord-Modus: broadcastTeamNotification() übernimmt ALLES –
|
||||
// lokal direkt + Forward an alle anderen Server in einem Paket.
|
||||
// KEINE zusätzliche lokale Schleife, da das zu Duplikaten führt.
|
||||
plugin.getBungeeMessenger().broadcastTeamNotification(onlineMsg);
|
||||
|
||||
} else {
|
||||
// Standalone-Modus: Claimer gezielt benachrichtigen
|
||||
UUID claimerUUID = ticket.getClaimerUUID();
|
||||
var claimerUUID = ticket.getClaimerUUID();
|
||||
if (claimerUUID != null && !claimerUUID.equals(author.getUniqueId())) {
|
||||
Player claimer = Bukkit.getPlayer(claimerUUID);
|
||||
if (claimer != null && claimer.isOnline()) {
|
||||
@@ -391,8 +480,6 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
plugin.getDatabaseManager().addPendingNotification(claimerUUID, claimerOffline));
|
||||
}
|
||||
}
|
||||
|
||||
// Alle anderen Online-Supporter auf diesem Server informieren
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
if (p.getUniqueId().equals(author.getUniqueId())) continue;
|
||||
if (claimerUUID != null && p.getUniqueId().equals(claimerUUID)) continue;
|
||||
@@ -426,11 +513,11 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
return;
|
||||
}
|
||||
|
||||
final int ticketId = id;
|
||||
final int ticketId = id;
|
||||
final String finalRating = rating;
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
Ticket ticket = plugin.getDatabaseManager().getTicketById(ticketId);
|
||||
Ticket ticket = getCachedOrFetch(ticketId);
|
||||
if (ticket == null) {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> player.sendMessage(plugin.formatMessage("messages.ticket-not-found")));
|
||||
return;
|
||||
@@ -445,6 +532,7 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
}
|
||||
|
||||
boolean success = plugin.getDatabaseManager().rateTicket(ticketId, finalRating);
|
||||
plugin.getTicketCache().invalidate(ticketId);
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
if (success) {
|
||||
String emoji = "THUMBS_UP".equals(finalRating) ? "§a👍 Positiv" : "§c👎 Negativ";
|
||||
@@ -478,27 +566,22 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
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());
|
||||
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."));
|
||||
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 <Spieler>")); return; }
|
||||
String targetName = args[2];
|
||||
@SuppressWarnings("deprecation")
|
||||
OfflinePlayer target = Bukkit.getOfflinePlayer(targetName);
|
||||
|
||||
OfflinePlayer target = Bukkit.getOfflinePlayer(args[2]);
|
||||
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."));
|
||||
if (success) player.sendMessage(plugin.color("&a" + args[2] + " &awurde von der Blacklist entfernt."));
|
||||
else player.sendMessage(plugin.color("&cSpieler war nicht auf der Blacklist."));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -527,16 +610,9 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
|
||||
// ─────────────────────────── /ticket top ──────────────────────────────
|
||||
|
||||
/**
|
||||
* Zeigt das Leaderboard der Top-5 Ticket-Ersteller.
|
||||
* Basiert auf der ticket_creator_stats-Tabelle, die Werte auch nach
|
||||
* dem Löschen oder Archivieren von Tickets beibehält.
|
||||
* Berechtigung: ticket.create (alle Spieler)
|
||||
*/
|
||||
private void handleTop(Player player) {
|
||||
if (!player.hasPermission("ticket.create") && !player.hasPermission("ticket.admin")) {
|
||||
player.sendMessage(plugin.formatMessage("messages.no-permission"));
|
||||
return;
|
||||
player.sendMessage(plugin.formatMessage("messages.no-permission")); return;
|
||||
}
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
List<String[]> top = plugin.getDatabaseManager().getTopCreators(5);
|
||||
@@ -553,8 +629,7 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
String medal = rankIdx < medals.length ? medals[rankIdx] : "&7#" + entry[0];
|
||||
String name = entry[1];
|
||||
String count = entry[2];
|
||||
player.sendMessage(plugin.color(
|
||||
medal + " &f" + String.format("%-16s", name)
|
||||
player.sendMessage(plugin.color(medal + " &f" + String.format("%-16s", name)
|
||||
+ " &e" + count + " &7Ticket" + (Integer.parseInt(count) == 1 ? "" : "s")));
|
||||
}
|
||||
}
|
||||
@@ -570,7 +645,9 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
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)"));
|
||||
plugin.getFaqManager().reload();
|
||||
plugin.getTicketCache().clear();
|
||||
player.sendMessage(plugin.color("&aKonfiguration wurde neu geladen. &7(Kategorien, FAQs, Cache geleert)"));
|
||||
if (plugin.isBungeeCordEnabled()) {
|
||||
player.sendMessage(plugin.color("&8[BungeeCord] &7Server: &b" + plugin.getServerName()));
|
||||
}
|
||||
@@ -584,7 +661,7 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
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"));
|
||||
else player.sendMessage(plugin.formatMessage("messages.archive-fail"));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -596,7 +673,6 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
var stats = plugin.getDatabaseManager().getTicketStats();
|
||||
var staffRatings = plugin.getDatabaseManager().getStaffRatings();
|
||||
// Persistente Ersteller-Statistik – überlebt Löschen/Archivieren
|
||||
var topCreators = plugin.getDatabaseManager().getTopCreators(5);
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
player.sendMessage(plugin.color("&8&m "));
|
||||
@@ -617,26 +693,21 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
int percent = (int) Math.round(stats.thumbsUp * 100.0 / totalRated);
|
||||
player.sendMessage(plugin.color("&7Zufriedenheit: &e" + percent + "%"));
|
||||
}
|
||||
|
||||
// Bewertungen pro Support-Mitarbeiter
|
||||
if (!staffRatings.isEmpty()) {
|
||||
player.sendMessage(plugin.color("&8&m "));
|
||||
player.sendMessage(plugin.color("&6Bewertungen nach Support-Mitarbeiter:"));
|
||||
player.sendMessage(plugin.color("&7 Name 👍 👎 Tickets Zufrieden"));
|
||||
for (String[] row : staffRatings) {
|
||||
// row: [name, up, down, totalClosed, percent]
|
||||
String name = String.format("%-16s", row[0]);
|
||||
String up = String.format("%-5s", row[1]);
|
||||
String down = String.format("%-5s", row[2]);
|
||||
String total = String.format("%-8s", row[3]);
|
||||
String percent = row[4];
|
||||
player.sendMessage(plugin.color(
|
||||
"&e " + name + " &a" + up + " &c" + down + " &7" + total + " &e" + percent));
|
||||
player.sendMessage(plugin.color("&e " + name + " &a" + up + " &c" + down + " &7" + total + " &e" + percent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BungeeCord: Tickets pro Server anzeigen
|
||||
if (plugin.isBungeeCordEnabled() && !stats.byServer.isEmpty()) {
|
||||
player.sendMessage(plugin.color("&8&m "));
|
||||
player.sendMessage(plugin.color("&6Tickets nach Server:"));
|
||||
@@ -662,6 +733,10 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
}
|
||||
}
|
||||
player.sendMessage(plugin.color("&8&m "));
|
||||
|
||||
// Cache-Status anzeigen
|
||||
player.sendMessage(plugin.color("&8&m "));
|
||||
player.sendMessage(plugin.color("&7Cache: &e" + plugin.getTicketCache().size() + " &7gecachte Ticket(s)"));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -680,7 +755,7 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
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"));
|
||||
else player.sendMessage(plugin.formatMessage("messages.migration-fail"));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -696,7 +771,7 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
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"));
|
||||
else player.sendMessage(plugin.formatMessage("messages.export-fail"));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -713,7 +788,7 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
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"));
|
||||
else player.sendMessage(plugin.formatMessage("messages.import-fail"));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -739,20 +814,31 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
if (priority == null) {
|
||||
player.sendMessage(plugin.color("&cUngültige Priorität! Gültig: &alow&7, &enormal&7, &6high&7, &curgent")); return;
|
||||
}
|
||||
final int finalId = ticketId;
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
boolean success = plugin.getDatabaseManager().setTicketPriority(ticketId, priority);
|
||||
boolean success = plugin.getDatabaseManager().setTicketPriority(finalId, priority);
|
||||
plugin.getTicketCache().invalidate(finalId);
|
||||
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."));
|
||||
}
|
||||
if (success) player.sendMessage(plugin.color("&aPriorität von Ticket &e#" + finalId + " &awurde auf " + priority.getColored() + " &agesetzt."));
|
||||
else player.sendMessage(plugin.color("&cTicket &e#" + finalId + " &cwurde nicht gefunden."));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** Parst Benutzer-Eingaben zu TicketPriority. Gibt null zurück wenn keine Übereinstimmung. */
|
||||
// ─────────────────────────── Hilfsmethoden ─────────────────────────────
|
||||
|
||||
/**
|
||||
* Gibt ein Ticket aus dem Cache zurück, oder lädt es aus der Datenbank
|
||||
* und legt es anschließend in den Cache. Gibt null zurück wenn nicht gefunden.
|
||||
*/
|
||||
private Ticket getCachedOrFetch(int ticketId) {
|
||||
Ticket cached = plugin.getTicketCache().get(ticketId);
|
||||
if (cached != null) return cached;
|
||||
Ticket fresh = plugin.getDatabaseManager().getTicketById(ticketId);
|
||||
if (fresh != null) plugin.getTicketCache().put(fresh);
|
||||
return fresh;
|
||||
}
|
||||
|
||||
private TicketPriority parsePriority(String input) {
|
||||
if (input == null) return null;
|
||||
return switch (input.toLowerCase()) {
|
||||
@@ -772,7 +858,7 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
if (!(sender instanceof Player player)) return completions;
|
||||
|
||||
if (args.length == 1) {
|
||||
List<String> subs = new ArrayList<>(List.of("create", "list", "comment", "top"));
|
||||
List<String> subs = new ArrayList<>(List.of("create", "list", "comment", "top", "faq"));
|
||||
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");
|
||||
@@ -783,6 +869,17 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
subs.add("setpriority");
|
||||
for (String s : subs) if (s.startsWith(args[0].toLowerCase())) completions.add(s);
|
||||
|
||||
} else if (args.length == 2 && args[0].equalsIgnoreCase("faq")) {
|
||||
List<String> faqSubs = new ArrayList<>(List.of("list"));
|
||||
if (player.hasPermission("ticket.admin")) faqSubs.addAll(List.of("add", "edit", "delete", "reload"));
|
||||
for (String s : faqSubs) if (s.startsWith(args[1].toLowerCase())) completions.add(s);
|
||||
|
||||
} else if (args.length == 3 && args[0].equalsIgnoreCase("faq")
|
||||
&& (args[1].equalsIgnoreCase("edit") || args[1].equalsIgnoreCase("delete"))
|
||||
&& player.hasPermission("ticket.admin")) {
|
||||
for (FaqEntry e : plugin.getFaqManager().getAll())
|
||||
completions.add(String.valueOf(e.getId()));
|
||||
|
||||
} else if (args.length == 2 && args[0].equalsIgnoreCase("create")
|
||||
&& plugin.getConfig().getBoolean("categories-enabled", true)) {
|
||||
for (ConfigCategory c : plugin.getCategoryManager().getAll())
|
||||
@@ -801,7 +898,6 @@ public class TicketCommand implements CommandExecutor, TabCompleter {
|
||||
if (p.startsWith(args[2].toLowerCase())) completions.add(p);
|
||||
|
||||
} else if (args.length == 3 && args[0].equalsIgnoreCase("forward")) {
|
||||
// BungeeCord: Nur lokal online Spieler als Tab-Completion
|
||||
for (Player p : Bukkit.getOnlinePlayers())
|
||||
if (p.getName().toLowerCase().startsWith(args[2].toLowerCase())) completions.add(p.getName());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user