diff --git a/src/main/java/de/ticketsystem/commands/TicketCommand.java b/src/main/java/de/ticketsystem/commands/TicketCommand.java index 4f02151..586df5f 100644 --- a/src/main/java/de/ticketsystem/commands/TicketCommand.java +++ b/src/main/java/de/ticketsystem/commands/TicketCommand.java @@ -446,7 +446,7 @@ public class TicketCommand implements CommandExecutor, TabCompleter { // ── /ticket forward ─────────────────────────────────────────────────── private void handleForward(Player player, String[] args) { - if (!player.hasPermission("ticket.admin")) { + if (!player.hasPermission("ticket.support") && !player.hasPermission("ticket.admin")) { plugin.lang().send(player, "general.no-permission"); return; } if (args.length < 3) { player.sendMessage(plugin.lang().get("forward.usage")); return; } @@ -454,27 +454,50 @@ public class TicketCommand implements CommandExecutor, TabCompleter { try { id = Integer.parseInt(args[1]); } catch (NumberFormatException e) { plugin.lang().send(player, "general.invalid-id"); return; } - Player target = Bukkit.getPlayer(args[2]); - if (target == null) { + String targetName = args[2]; + + // Selbst-Weiterleitung verhindern + if (targetName.equalsIgnoreCase(player.getName())) { + plugin.lang().send(player, "forward.cannot-self"); return; + } + + // Ziel-Spieler auflösen: zuerst online prüfen, dann OfflinePlayer + Player onlineTarget = Bukkit.getPlayer(targetName); + + // Wenn online: Permission-Prüfung direkt möglich + if (onlineTarget != null) { + if (!onlineTarget.hasPermission("ticket.support") && !onlineTarget.hasPermission("ticket.admin")) { + plugin.lang().send(player, "forward.not-a-supporter"); return; + } + } + + @SuppressWarnings("deprecation") + OfflinePlayer offlineTarget = onlineTarget != null + ? onlineTarget + : Bukkit.getOfflinePlayer(targetName); + + // Spieler komplett unbekannt (hasPlayedBefore = false, nicht online) + if (!offlineTarget.hasPlayedBefore() && !offlineTarget.isOnline()) { player.sendMessage(plugin.isBungeeCordEnabled() - ? plugin.lang().format("forward.bungee-offline", "{player}", args[2]) + ? plugin.lang().format("forward.bungee-offline", "{player}", targetName) : plugin.lang().get("forward.local-not-found")); return; } - final int ticketId = id; - final String fromName = player.getName(); - final Player t = target; + final int ticketId = id; + final String fromName = player.getName(); + final UUID targetUUID = offlineTarget.getUniqueId(); + final String resolvedName = offlineTarget.getName() != null ? offlineTarget.getName() : targetName; Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { - boolean ok = plugin.getDatabaseManager().forwardTicket(ticketId, t.getUniqueId(), t.getName()); + boolean ok = plugin.getDatabaseManager().forwardTicket(ticketId, targetUUID, resolvedName); plugin.getTicketCache().invalidate(ticketId); Bukkit.getScheduler().runTask(plugin, () -> { if (!ok) { plugin.lang().send(player, "general.ticket-not-found"); return; } Ticket ticket = getCachedOrFetch(ticketId); if (ticket == null) return; player.sendMessage(plugin.lang().format("ticket.forwarded", - "{id}", String.valueOf(ticketId), "{player}", t.getName())); + "{id}", String.valueOf(ticketId), "{player}", resolvedName)); plugin.getTicketManager().notifyForwardedTo(ticket, fromName); plugin.getTicketManager().notifyCreatorForwarded(ticket); }); @@ -1357,8 +1380,11 @@ public class TicketCommand implements CommandExecutor, TabCompleter { completions.addAll(getPriorityInputsForTab(args[2])); } else if (args.length == 3 && normalize(args[0]).equals("forward")) { - for (Player p : Bukkit.getOnlinePlayers()) + for (Player p : Bukkit.getOnlinePlayers()) { + if (p.equals(player)) continue; // Selbst-Forward ausblenden + if (!p.hasPermission("ticket.support") && !p.hasPermission("ticket.admin")) continue; if (p.getName().toLowerCase().startsWith(args[2].toLowerCase())) completions.add(p.getName()); + } } else if (args.length == 2 && normalize(args[0]).equals("blacklist")) { if (useEn) completions.addAll(List.of("add", "remove", "list")); diff --git a/src/main/java/de/ticketsystem/manager/TicketManager.java b/src/main/java/de/ticketsystem/manager/TicketManager.java index e776b76..cb98eb8 100644 --- a/src/main/java/de/ticketsystem/manager/TicketManager.java +++ b/src/main/java/de/ticketsystem/manager/TicketManager.java @@ -274,9 +274,9 @@ public class TicketManager { if (player.hasPermission("ticket.support") || player.hasPermission("ticket.admin")) { plugin.lang().send(player, "help.claim"); plugin.lang().send(player, "help.close"); + plugin.lang().send(player, "help.forward"); } if (player.hasPermission("ticket.admin")) { - plugin.lang().send(player, "help.forward"); plugin.lang().send(player, "help.blacklist"); plugin.lang().send(player, "help.reload"); plugin.lang().send(player, "help.stats"); diff --git a/src/main/resources/lang_de.yml b/src/main/resources/lang_de.yml index d5e0d3d..81b948f 100644 --- a/src/main/resources/lang_de.yml +++ b/src/main/resources/lang_de.yml @@ -111,6 +111,8 @@ forward: usage: "&cBenutzung: {cmd_forward} " bungee-offline: "&7[BungeeCord] Spieler &e{player} &7ist auf diesem Server nicht online." local-not-found: "&cSpieler nicht gefunden!" + not-a-supporter: "&cDieser Spieler hat keine Supporter-Berechtigung!" + cannot-self: "&cDu kannst ein Ticket nicht an dich selbst weiterleiten!" # ============================================================ # KOMMENTARE diff --git a/src/main/resources/lang_en.yml b/src/main/resources/lang_en.yml index 6fe1d46..577cfef 100644 --- a/src/main/resources/lang_en.yml +++ b/src/main/resources/lang_en.yml @@ -111,6 +111,8 @@ forward: usage: "&cUsage: {cmd_forward} " bungee-offline: "&7[BungeeCord] Player &e{player} &7is not online on this server." local-not-found: "&cPlayer not found!" + not-a-supporter: "&cThis player does not have supporter permission!" + cannot-self: "&cYou cannot forward a ticket to yourself!" # ============================================================ # COMMENTS diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 1bf24c2..d578282 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: TicketSystem -version: 1.1.6 +version: 1.1.7 main: de.ticketsystem.TicketPlugin api-version: 1.20 author: M_Viper @@ -39,7 +39,7 @@ permissions: # ── Supporter-Permissions ───────────────────────────────────────────────── ticket.support: - description: Supporter kann Tickets einsehen, claimen und schließen + description: Supporter kann Tickets einsehen, claimen, schließen und weiterleiten default: false ticket.archive: