diff --git a/src/main/java/de/ticketsystem/TicketPlugin.java b/src/main/java/de/ticketsystem/TicketPlugin.java index 8e6419e..71be4eb 100644 --- a/src/main/java/de/ticketsystem/TicketPlugin.java +++ b/src/main/java/de/ticketsystem/TicketPlugin.java @@ -13,6 +13,7 @@ import de.ticketsystem.manager.FaqManager; import de.ticketsystem.manager.LanguageManager; import de.ticketsystem.manager.TicketManager; import de.ticketsystem.model.Ticket; +import de.ticketsystem.model.TicketPriority; import org.bukkit.ChatColor; import org.bukkit.plugin.java.JavaPlugin; @@ -53,6 +54,7 @@ public class TicketPlugin extends JavaPlugin { // ── Sprachdatei laden (lang.yml) ────────────────────────────────── // Muss VOR allen anderen Managern geschehen, da diese lang() nutzen. languageManager = new LanguageManager(this); + TicketPriority.reloadLocalizedNames(this); // ── BungeeCord Plugin-Messaging-Kanäle registrieren ─────────────── getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeMessenger.BUNGEE_CHANNEL); @@ -67,8 +69,8 @@ public class TicketPlugin extends JavaPlugin { getLogger().warning("[BungeeCord] Kein 'server-name' in der config.yml definiert!"); } - // BungeeCord-Hinweis nur bei deaktiviertem Feature ausgeben - if (!getConfig().getBoolean("bungeecord", false)) { + // BungeeCord-Hinweis nur bei deaktiviertem Feature und aktivem Debug ausgeben + if (getConfig().getBoolean("debug", false) && !getConfig().getBoolean("bungeecord", false)) { getLogger().info("[BungeeCord] Cross-Server-Features deaktiviert. Setze 'bungeecord: true' um sie zu aktivieren."); } @@ -267,6 +269,7 @@ public class TicketPlugin extends JavaPlugin { getLogger().warning("[BungeeCord] Kein 'server-name' in der config.yml definiert!"); } debug = getConfig().getBoolean("debug", false); + TicketPriority.reloadLocalizedNames(this); } public static TicketPlugin getInstance() { return instance; } diff --git a/src/main/java/de/ticketsystem/commands/TicketCommand.java b/src/main/java/de/ticketsystem/commands/TicketCommand.java index 7905bdd..675b853 100644 --- a/src/main/java/de/ticketsystem/commands/TicketCommand.java +++ b/src/main/java/de/ticketsystem/commands/TicketCommand.java @@ -133,6 +133,8 @@ public class TicketCommand implements CommandExecutor, TabCompleter { boolean categoriesOn = plugin.getConfig().getBoolean("categories-enabled", true); boolean prioritiesOn = plugin.getConfig().getBoolean("priorities-enabled", true); + boolean allowPlayersPrio = plugin.getConfig().getBoolean("allow-players-to-set-priority", false); + boolean isTeam = player.hasPermission("ticket.support") || player.hasPermission("ticket.admin"); if (args.length >= 3) { if (categoriesOn) { @@ -140,15 +142,15 @@ public class TicketCommand implements CommandExecutor, TabCompleter { if (parsedCat != null) { category = parsedCat; msgStart = 2; - if (prioritiesOn && args.length >= 4) { + if (prioritiesOn && args.length >= 4 && (allowPlayersPrio || isTeam)) { TicketPriority parsedPrio = parsePriority(args[2]); if (parsedPrio != null) { priority = parsedPrio; msgStart = 3; } } - } else if (prioritiesOn) { + } else if (prioritiesOn && (allowPlayersPrio || isTeam)) { TicketPriority parsedPrio = parsePriority(args[1]); if (parsedPrio != null) { priority = parsedPrio; msgStart = 2; } } - } else if (prioritiesOn) { + } else if (prioritiesOn && (allowPlayersPrio || isTeam)) { TicketPriority parsedPrio = parsePriority(args[1]); if (parsedPrio != null) { priority = parsedPrio; msgStart = 2; } } @@ -856,6 +858,26 @@ public class TicketCommand implements CommandExecutor, TabCompleter { }; } + private List getPriorityInputsForTab(String input) { + List options = new ArrayList<>(); + String lowerInput = input == null ? "" : input.toLowerCase(); + + if (plugin.lang().acceptsGerman()) { + options.addAll(List.of("niedrig", "normal", "hoch", "dringend")); + } + if (plugin.lang().acceptsEnglish()) { + options.addAll(List.of("low", "normal", "high", "urgent")); + } + + List filtered = new ArrayList<>(); + for (String option : options) { + if (option.startsWith(lowerInput) && !filtered.contains(option)) { + filtered.add(option); + } + } + return filtered; + } + // ── Tab-Completion ──────────────────────────────────────────────────── @Override @@ -863,7 +885,7 @@ public class TicketCommand implements CommandExecutor, TabCompleter { List completions = new ArrayList<>(); if (!(sender instanceof Player player)) return completions; - // Immer direkt vom LanguageManager lesen – kein Cache, immer aktuell nach reload + // Nur die in der Config eingestellte Sprache verwenden final boolean useDe = plugin.lang().acceptsGerman(); final boolean useEn = plugin.lang().acceptsEnglish(); @@ -875,24 +897,25 @@ public class TicketCommand implements CommandExecutor, TabCompleter { if (player.hasPermission("ticket.support") || player.hasPermission("ticket.admin")) { if (useEn) subs.addAll(List.of("claim", "close")); if (useDe) subs.addAll(List.of("übernehmen", "schließen")); - } - if (plugin.getConfig().getBoolean("rating-enabled", true)) { - if (useEn) subs.add("rate"); - if (useDe) subs.add("bewerten"); - } - if (player.hasPermission("ticket.admin")) { - if (useEn) subs.addAll(List.of("forward", "reload", "stats", "archive", - "migrate", "export", "import", "blacklist")); - if (useDe) subs.addAll(List.of("weiterleiten", "neuladen", "statistik", - "archivieren", "migrieren", "exportieren", "importieren", "sperrliste")); - } - if ((player.hasPermission("ticket.support") || player.hasPermission("ticket.admin")) - && plugin.getConfig().getBoolean("priorities-enabled", true)) { + + if (useEn) subs.addAll(List.of("forward", "reload", "stats", "archive", "blacklist")); + if (useDe) subs.addAll(List.of("weiterleiten", "neuladen", "statistik", "archiv", "blacklist")); + if (useEn) subs.add("setpriority"); if (useDe) subs.add("priorität"); } + + if (player.hasPermission("ticket.admin")) { + if (useEn) subs.addAll(List.of("faq")); + if (useDe) subs.addAll(List.of("faq")); + } + + if (useEn) subs.add("rate"); + if (useDe) subs.add("bewerten"); + for (String s : subs) - if (s.startsWith(args[0].toLowerCase())) completions.add(s); + if (s.toLowerCase().startsWith(args[0].toLowerCase())) completions.add(s); + return completions; } else if (args.length == 2 && normalize(args[0]).equals("faq")) { List faqSubs = new ArrayList<>(); @@ -912,22 +935,39 @@ public class TicketCommand implements CommandExecutor, TabCompleter { for (FaqEntry e : plugin.getFaqManager().getAll()) completions.add(String.valueOf(e.getId())); - } else if (args.length == 2 && normalize(args[0]).equals("create") - && plugin.getConfig().getBoolean("categories-enabled", true)) { - for (ConfigCategory c : plugin.getCategoryManager().getAll()) - if (c.getKey().startsWith(args[1].toLowerCase())) completions.add(c.getKey()); - 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 == 2 && normalize(args[0]).equals("create")) { + boolean categoriesOn = plugin.getConfig().getBoolean("categories-enabled", true); + boolean prioritiesOn = plugin.getConfig().getBoolean("priorities-enabled", true); + + // Wenn Kategorien aktiviert: zeige nur Kategorien-Anzeigenamen bei args[1] + if (categoriesOn) { + completions.addAll(plugin.getCategoryManager().getDisplayNamesForTabComplete(args[1])); + } else if (prioritiesOn) { + // Wenn nur Prioritäten aktiviert (keine Kategorien): zeige Prioritäten bei args[1] + boolean allowPlayersPrio = plugin.getConfig().getBoolean("allow-players-to-set-priority", false); + boolean isTeam = sender instanceof Player p && + (p.hasPermission("ticket.support") || p.hasPermission("ticket.admin")); + if (allowPlayersPrio || isTeam) { + completions.addAll(getPriorityInputsForTab(args[1])); + } + } - } else if (args.length == 3 && normalize(args[0]).equals("create") - && plugin.getConfig().getBoolean("priorities-enabled", true)) { - for (String p : List.of("low", "normal", "high", "urgent")) - if (p.startsWith(args[2].toLowerCase())) completions.add(p); + } else if (args.length == 3 && normalize(args[0]).equals("create")) { + boolean categoriesOn = plugin.getConfig().getBoolean("categories-enabled", true); + boolean prioritiesOn = plugin.getConfig().getBoolean("priorities-enabled", true); + + // Wenn beide aktiviert: args[2] = Priorität + if (categoriesOn && prioritiesOn) { + boolean allowPlayersPrio = plugin.getConfig().getBoolean("allow-players-to-set-priority", false); + boolean isTeam = sender instanceof Player p && + (p.hasPermission("ticket.support") || p.hasPermission("ticket.admin")); + if (allowPlayersPrio || isTeam) { + completions.addAll(getPriorityInputsForTab(args[2])); + } + } } else if (args.length == 3 && normalize(args[0]).equals("setpriority")) { - for (String p : List.of("low", "normal", "high", "urgent")) - if (p.startsWith(args[2].toLowerCase())) completions.add(p); + completions.addAll(getPriorityInputsForTab(args[2])); } else if (args.length == 3 && normalize(args[0]).equals("forward")) { for (Player p : Bukkit.getOnlinePlayers()) diff --git a/src/main/java/de/ticketsystem/database/DatabaseManager.java b/src/main/java/de/ticketsystem/database/DatabaseManager.java index 06bb9ae..57fdd10 100644 --- a/src/main/java/de/ticketsystem/database/DatabaseManager.java +++ b/src/main/java/de/ticketsystem/database/DatabaseManager.java @@ -125,6 +125,14 @@ public class DatabaseManager { config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSqlLimit","2048"); + // HikariCP-Logs unterdrücken wenn debug: false + if (!plugin.isDebug()) { + java.util.logging.Logger.getLogger("de.ticketsystem.libs.hikari").setLevel(java.util.logging.Level.WARNING); + java.util.logging.Logger.getLogger("de.ticketsystem.libs.hikari.HikariDataSource").setLevel(java.util.logging.Level.WARNING); + java.util.logging.Logger.getLogger("de.ticketsystem.libs.hikari.pool.HikariPool").setLevel(java.util.logging.Level.WARNING); + java.util.logging.Logger.getLogger("de.ticketsystem.libs.hikari.pool.PoolBase").setLevel(java.util.logging.Level.WARNING); + } + dataSource = new HikariDataSource(config); createTables(); ensureColumns(); diff --git a/src/main/java/de/ticketsystem/manager/CategoryManager.java b/src/main/java/de/ticketsystem/manager/CategoryManager.java index 6e40ebc..673f53e 100644 --- a/src/main/java/de/ticketsystem/manager/CategoryManager.java +++ b/src/main/java/de/ticketsystem/manager/CategoryManager.java @@ -7,9 +7,11 @@ import org.bukkit.configuration.ConfigurationSection; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; /** * Loads and manages ticket categories defined in config.yml under the "categories" section. @@ -88,13 +90,18 @@ public class CategoryManager { for (String alias : aliases) { aliasMap.put(alias.toLowerCase(), key.toLowerCase()); } + + // Der Anzeigename soll ebenfalls als Eingabe funktionieren (z.B. "Fehler") + aliasMap.put(name.toLowerCase(), key.toLowerCase()); } if (categories.isEmpty()) { plugin.getLogger().warning("[CategoryManager] Keine gültigen Kategorien in der config.yml gefunden. Lade Standardkategorien."); loadDefaults(); } else { - plugin.getLogger().info("[CategoryManager] " + categories.size() + " Kategorie(n) geladen: " + String.join(", ", categories.keySet())); + if (plugin.isDebug()) { + plugin.getLogger().info("[CategoryManager] " + categories.size() + " Kategorie(n) geladen: " + String.join(", ", categories.keySet())); + } } } @@ -113,6 +120,7 @@ public class CategoryManager { categories.put(key, cat); aliasMap.put(key, key); for (String alias : aliases) aliasMap.put(alias.toLowerCase(), key); + aliasMap.put(name.toLowerCase(), key); } // ─────────────────────────── Public API ──────────────────────────────── @@ -160,6 +168,22 @@ public class CategoryManager { return String.join(", ", categories.keySet()); } + /** + * Gibt für Tab-Completion nur die Kategorie-Anzeigenamen in Config-Reihenfolge zurück. + * Beispiel: "all" -> ["allgemein"] + */ + public List getDisplayNamesForTabComplete(String input) { + String lowerInput = input == null ? "" : input.toLowerCase(); + Set results = new LinkedHashSet<>(); + for (ConfigCategory category : categories.values()) { + String displayName = category.getName().toLowerCase(); + if (displayName.startsWith(lowerInput)) { + results.add(displayName); + } + } + return new ArrayList<>(results); + } + /** * Reloads categories from the (already reloaded) config. * Call this after plugin.reloadConfig(). diff --git a/src/main/java/de/ticketsystem/manager/LanguageManager.java b/src/main/java/de/ticketsystem/manager/LanguageManager.java index a61012b..a5b8e50 100644 --- a/src/main/java/de/ticketsystem/manager/LanguageManager.java +++ b/src/main/java/de/ticketsystem/manager/LanguageManager.java @@ -195,9 +195,11 @@ public class LanguageManager { prefix = color(lang.getString("prefix", "&8[&6Ticket&8] &r")); cmdNames = buildCmdNames(); - plugin.getLogger().info("[LanguageManager] Geladen: " + fileName - + " | language=" + activeLang - + " | Befehle: " + describeMode()); + if (plugin.isDebug()) { + plugin.getLogger().info("[LanguageManager] Geladen: " + fileName + + " | language=" + activeLang + + " | Befehle: " + describeMode()); + } } // ── Befehlsnamen ───────────────────────────────────────────────────────── diff --git a/src/main/java/de/ticketsystem/model/TicketPriority.java b/src/main/java/de/ticketsystem/model/TicketPriority.java index 33e2126..8bae640 100644 --- a/src/main/java/de/ticketsystem/model/TicketPriority.java +++ b/src/main/java/de/ticketsystem/model/TicketPriority.java @@ -1,21 +1,24 @@ package de.ticketsystem.model; +import de.ticketsystem.TicketPlugin; import org.bukkit.Material; public enum TicketPriority { - LOW ("Niedrig", "§a", Material.GREEN_WOOL), - NORMAL ("Normal", "§e", Material.YELLOW_WOOL), - HIGH ("Hoch", "§6", Material.ORANGE_WOOL), - URGENT ("Dringend","§c", Material.RED_WOOL); + LOW ("priorities.low", "§a", Material.GREEN_WOOL), + NORMAL ("priorities.normal", "§e", Material.YELLOW_WOOL), + HIGH ("priorities.high", "§6", Material.ORANGE_WOOL), + URGENT ("priorities.urgent", "§c", Material.RED_WOOL); - private final String displayName; + private final String langKey; private final String color; private final Material guiMaterial; + private String displayName; - TicketPriority(String displayName, String color, Material guiMaterial) { - this.displayName = displayName; - this.color = color; - this.guiMaterial = guiMaterial; + TicketPriority(String langKey, String color, Material guiMaterial) { + this.langKey = langKey; + this.color = color; + this.guiMaterial = guiMaterial; + this.displayName = langKey; } public String getDisplayName() { return displayName; } @@ -28,4 +31,20 @@ public enum TicketPriority { try { return valueOf(s.toUpperCase()); } catch (IllegalArgumentException e) { return NORMAL; } } + + /** + * Lädt die lokalisierten Namen aus der Sprachdatei neu. + * Sollte beim Laden des Plugins / beim Reload aufgerufen werden. + */ + public static void reloadLocalizedNames(TicketPlugin plugin) { + if (plugin == null) return; + + for (TicketPriority prio : values()) { + prio.displayName = plugin.lang().get(prio.langKey); + if (prio.displayName == null || prio.displayName.isEmpty()) { + // Fallback wenn Schlüssel nicht gefunden + prio.displayName = prio.langKey.substring(prio.langKey.indexOf('.') + 1); + } + } + } } \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index b124d88..0fb8acb 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -108,6 +108,11 @@ categories-enabled: true # Admins/Supporter können die Priorität nachträglich ändern: /ticket setpriority priorities-enabled: true +# Dürfen normale Spieler beim Erstellen eine Priorität setzen? +# false = Nur Admins/Supporter können Prioritäten setzen (ticket.support, ticket.admin) +# true = Spieler können beim /ticket create dabei Prioritäten angeben +allow-players-to-set-priority: false + # Bewertungs-System (true = aktiviert) # Spieler können nach dem Schließen den Support bewerten: /ticket rate good|bad # Ergebnisse sind in /ticket stats sichtbar @@ -135,7 +140,7 @@ categories: - "general" - "default" bug: - name: "Bug" + name: "Fehler" color: "&c" material: "REDSTONE" aliases: diff --git a/src/main/resources/lang_de.yml b/src/main/resources/lang_de.yml index fd52787..3d6bf6a 100644 --- a/src/main/resources/lang_de.yml +++ b/src/main/resources/lang_de.yml @@ -82,8 +82,8 @@ notify: # ============================================================ create: usage: "&cBenutzung: {cmd_create} [Kategorie] [Priorität] " - categories-hint: "&7Kategorien: &ebug&7, &efrage&7, &ebeschwerde&7, &esonstiges&7, &eallgemein" - priorities-hint: "&7Prioritäten: &alow&7, &enormal&7, &6high&7, &curgent" + categories-hint: "&7Kategorien: &efehler&7, &efrage&7, &ebeschwerde&7, &esonstiges&7, &eallgemein" + priorities-hint: "&7Prioritäten: &aniedrig&7, &enormal&7, &6hoch&7, &cdringend" max-tickets: "&cDu hast bereits &e{max} &coffene Ticket(s). Bitte warte, bis dein Ticket bearbeitet wurde." no-description: "&cBitte gib eine Beschreibung für dein Ticket an." too-long: "&cDeine Beschreibung ist zu lang! Maximal {max} Zeichen." @@ -139,11 +139,21 @@ rating: # PRIORITÄT SETZEN # ============================================================ setpriority: - usage: "&cBenutzung: {cmd_setpriority} " + usage: "&cBenutzung: {cmd_setpriority} " disabled: "&cDas Prioritäten-System ist deaktiviert." - invalid: "&cUngültige Priorität! Gültig: &alow&7, &enormal&7, &6high&7, &curgent" + invalid: "&cUngültige Priorität! Gültig: &aniedrig&7, &enormal&7, &6hoch&7, &cdringend" success: "&aPriorität von Ticket &e#{id} &awurde auf {priority} &agesetzt." not-found: "&cTicket &e#{id} &cwurde nicht gefunden." + no-player-permission: "&cNur Admins und Supporter dürfen die Priorität setzen." + +# ============================================================ +# PRIORITÄTEN LABELS (Low, Normal, High, Urgent) +# ============================================================ +priorities: + low: "Niedrig" + normal: "Normal" + high: "Hoch" + urgent: "Dringend" # ============================================================ # BLACKLIST diff --git a/src/main/resources/lang_en.yml b/src/main/resources/lang_en.yml index a8b8da7..399fbdf 100644 --- a/src/main/resources/lang_en.yml +++ b/src/main/resources/lang_en.yml @@ -145,6 +145,16 @@ setpriority: invalid: "&cInvalid priority! Valid: &alow&7, &enormal&7, &6high&7, &curgent" success: "&aPriority of ticket &e#{id} &ahas been set to {priority}&a." not-found: "&cTicket &e#{id} &cwas not found." + no-player-permission: "&cOnly admins and supporters are allowed to set priority." + +# ============================================================ +# PRIORITY LABELS (Low, Normal, High, Urgent) +# ============================================================ +priorities: + low: "Low" + normal: "Normal" + high: "High" + urgent: "Urgent" # ============================================================ # BLACKLIST diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 3ad07b4..1d10bd0 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: TicketSystem -version: 1.0.8 +version: 1.0.9 main: de.ticketsystem.TicketPlugin api-version: 1.20 author: M_Viper