2 Commits
1.0.9 ... main

Author SHA1 Message Date
6fe5e59964 Update from Git Manager GUI 2026-03-24 08:55:02 +01:00
957b5a4d9e Upload file pom.xml via GUI 2026-03-24 08:54:59 +01:00
11 changed files with 174 additions and 53 deletions

View File

@@ -6,7 +6,7 @@
<groupId>de.ticketsystem</groupId>
<artifactId>TicketSystem</artifactId>
<version>1.0.8</version>
<version>1.0.9</version>
<packaging>jar</packaging>
<name>TicketSystem</name>

View File

@@ -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; }

View File

@@ -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<String> getPriorityInputsForTab(String input) {
List<String> 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<String> 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<String> 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<String> 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);
} 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);
// 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")) {
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())

View File

@@ -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();

View File

@@ -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<String> getDisplayNamesForTabComplete(String input) {
String lowerInput = input == null ? "" : input.toLowerCase();
Set<String> 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().

View File

@@ -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 ─────────────────────────────────────────────────────────

View File

@@ -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);
}
}
}
}

View File

@@ -108,6 +108,11 @@ categories-enabled: true
# Admins/Supporter können die Priorität nachträglich ändern: /ticket setpriority <id> <low|normal|high|urgent>
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 <id> 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:

View File

@@ -82,8 +82,8 @@ notify:
# ============================================================
create:
usage: "&cBenutzung: {cmd_create} [Kategorie] [Priorität] <Beschreibung>"
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} <ID> <low|normal|high|urgent>"
usage: "&cBenutzung: {cmd_setpriority} <ID> <niedrig|normal|hoch|dringend>"
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

View File

@@ -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

View File

@@ -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