303 lines
15 KiB
Java
303 lines
15 KiB
Java
package de.ticketsystem;
|
||
|
||
import de.ticketsystem.bungee.BungeeMessenger;
|
||
import de.ticketsystem.cache.TicketCache;
|
||
import de.ticketsystem.commands.TicketCommand;
|
||
import de.ticketsystem.database.DatabaseManager;
|
||
import de.ticketsystem.discord.DiscordWebhook;
|
||
import de.ticketsystem.gui.FaqGUI;
|
||
import de.ticketsystem.gui.TicketGUI;
|
||
import de.ticketsystem.listeners.PlayerJoinListener;
|
||
import de.ticketsystem.manager.CategoryManager;
|
||
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 de.ticketsystem.web.SessionManager;
|
||
import de.ticketsystem.web.WebServer;
|
||
import org.bukkit.ChatColor;
|
||
import org.bukkit.plugin.java.JavaPlugin;
|
||
|
||
import java.util.Objects;
|
||
|
||
public class TicketPlugin extends JavaPlugin {
|
||
|
||
private static TicketPlugin instance;
|
||
|
||
private boolean debug;
|
||
|
||
/**
|
||
* Name dieses Servers im BungeeCord-Netzwerk.
|
||
* Konfigurierbar in config.yml → server-name
|
||
*/
|
||
private String serverName;
|
||
|
||
private LanguageManager languageManager;
|
||
private DatabaseManager databaseManager;
|
||
private TicketManager ticketManager;
|
||
private CategoryManager categoryManager;
|
||
private FaqManager faqManager;
|
||
private TicketGUI ticketGUI;
|
||
private FaqGUI faqGUI;
|
||
private DiscordWebhook discordWebhook;
|
||
private BungeeMessenger bungeeMessenger;
|
||
private TicketCache ticketCache;
|
||
private SessionManager sessionManager;
|
||
private WebServer webServer;
|
||
|
||
@Override
|
||
public void onEnable() {
|
||
instance = this;
|
||
|
||
saveDefaultConfig();
|
||
|
||
// Ticket-Klasse für YAML-Serialisierung registrieren
|
||
Ticket.register();
|
||
|
||
// ── 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);
|
||
getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeMessenger.CUSTOM_CHANNEL);
|
||
|
||
bungeeMessenger = new BungeeMessenger(this);
|
||
getServer().getMessenger().registerIncomingPluginChannel(this, BungeeMessenger.CUSTOM_CHANNEL, bungeeMessenger);
|
||
|
||
// Server-Name aus Config lesen
|
||
serverName = getConfig().getString("server-name", "unknown");
|
||
if ("unknown".equals(serverName)) {
|
||
getLogger().warning("[BungeeCord] Kein 'server-name' in der config.yml definiert!");
|
||
}
|
||
|
||
// 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.");
|
||
}
|
||
|
||
// Update-Checker
|
||
int resourceId = 132757;
|
||
new UpdateChecker(this, resourceId).getVersion(version -> {
|
||
String current = getDescription().getVersion();
|
||
if (!current.equals(version)) {
|
||
String msg = lang().format("update.available-line1", "{version}", version);
|
||
getLogger().warning(lang().format("update.available-console",
|
||
"{new}", version, "{current}", current));
|
||
getServer().getScheduler().runTaskLater(this, () ->
|
||
getServer().getOnlinePlayers().stream()
|
||
.filter(p -> p.hasPermission("ticket.admin"))
|
||
.forEach(p -> p.sendMessage(msg)), 20L);
|
||
}
|
||
});
|
||
|
||
// Versionsprüfung der config.yml
|
||
String configVersion = getConfig().getString("version", "");
|
||
String expectedVersion = "2.5";
|
||
if (!expectedVersion.equals(configVersion)) {
|
||
getLogger().warning("[WARNUNG] config.yml-Version (" + configVersion
|
||
+ ") stimmt nicht mit der erwarteten Version (" + expectedVersion + ") überein!");
|
||
}
|
||
|
||
debug = getConfig().getBoolean("debug", false);
|
||
|
||
// ── Performance: Ticket-Cache ──────────────────────────────────────
|
||
long cacheTtl = getConfig().getLong("cache-ttl-seconds", 60) * 1000L;
|
||
ticketCache = new TicketCache(cacheTtl);
|
||
|
||
// Regelmäßige Cache-Bereinigung alle 5 Minuten
|
||
getServer().getScheduler().runTaskTimerAsynchronously(this,
|
||
() -> ticketCache.evictExpired(), 6000L, 6000L);
|
||
|
||
// Datenbankverbindung
|
||
databaseManager = new DatabaseManager(this);
|
||
if (!databaseManager.connect()) {
|
||
getLogger().severe("Konnte keine Datenbankverbindung herstellen! Plugin läuft im Datei-Modus weiter.");
|
||
}
|
||
|
||
// Manager, GUI, FAQ & Discord-Webhook initialisieren
|
||
categoryManager = new CategoryManager(this);
|
||
ticketManager = new TicketManager(this);
|
||
faqManager = new FaqManager(this);
|
||
ticketGUI = new TicketGUI(this);
|
||
faqGUI = new FaqGUI(this);
|
||
discordWebhook = new DiscordWebhook(this);
|
||
|
||
if (getConfig().getBoolean("discord.enabled", false)) {
|
||
String url = getConfig().getString("discord.webhook-url", "");
|
||
if (url.isEmpty()) {
|
||
getLogger().warning("[DiscordWebhook] Aktiviert, aber keine Webhook-URL in config.yml eingetragen!");
|
||
}
|
||
}
|
||
|
||
// Commands & Events
|
||
TicketCommand ticketCommand = new TicketCommand(this);
|
||
Objects.requireNonNull(getCommand("ticket")).setExecutor(ticketCommand);
|
||
Objects.requireNonNull(getCommand("ticket")).setTabCompleter(ticketCommand);
|
||
|
||
getServer().getPluginManager().registerEvents(new PlayerJoinListener(this), this);
|
||
getServer().getPluginManager().registerEvents(ticketGUI, this);
|
||
getServer().getPluginManager().registerEvents(faqGUI, this);
|
||
|
||
// Automatische Archivierung
|
||
int archiveIntervalH = getConfig().getInt("auto-archive-interval-hours", 24);
|
||
if (archiveIntervalH > 0) {
|
||
long ticks = archiveIntervalH * 60L * 60L * 20L;
|
||
getServer().getScheduler().runTaskTimer(this, () -> {
|
||
int archived = databaseManager.archiveClosedTickets();
|
||
if (archived > 0) {
|
||
getLogger().info("Automatische Archivierung: " + archived + " Tickets archiviert.");
|
||
}
|
||
}, ticks, ticks);
|
||
}
|
||
|
||
// Web-Panel starten
|
||
if (getConfig().getBoolean("web-panel.enabled", false)) {
|
||
sessionManager = new SessionManager(this);
|
||
webServer = new WebServer(this, sessionManager);
|
||
webServer.start();
|
||
}
|
||
|
||
getLogger().info("TicketSystem v" + getDescription().getVersion() + " erfolgreich gestartet!");
|
||
}
|
||
|
||
@Override
|
||
public void onDisable() {
|
||
getServer().getMessenger().unregisterOutgoingPluginChannel(this);
|
||
getServer().getMessenger().unregisterIncomingPluginChannel(this);
|
||
|
||
if (webServer != null) webServer.stop();
|
||
if (ticketCache != null) ticketCache.clear();
|
||
if (databaseManager != null) databaseManager.disconnect();
|
||
getLogger().info("TicketSystem wurde deaktiviert.");
|
||
}
|
||
|
||
// ─────────────────────────── Hilfsmethoden ─────────────────────────────
|
||
|
||
/**
|
||
* Gibt den LanguageManager zurück – bevorzugte Methode für alle Texte.
|
||
*
|
||
* Verwendung:
|
||
* plugin.lang().get("ticket.created")
|
||
* plugin.lang().format("ticket.created", "{id}", String.valueOf(id))
|
||
* plugin.lang().send(player, "ticket.created", "{id}", String.valueOf(id))
|
||
*/
|
||
public LanguageManager lang() {
|
||
return languageManager;
|
||
}
|
||
|
||
/**
|
||
* Kompatibilitätsmethode für bestehenden Code.
|
||
* Liest Pfade der Form "messages.xxx" aus lang.yml (ohne "messages."-Prefix).
|
||
*
|
||
* Beispiel: formatMessage("messages.ticket-created") → lang "ticket.created"
|
||
*
|
||
* @deprecated Direkt {@link #lang()} verwenden.
|
||
*/
|
||
@Deprecated
|
||
public String formatMessage(String path) {
|
||
// "messages.ticket-created" → "ticket.created" (legacy-Mapping)
|
||
String langKey = mapLegacyPath(path);
|
||
if (langKey != null) {
|
||
return lang().formatWithPrefix(langKey);
|
||
}
|
||
// Fallback: Direkt in lang.yml nachschlagen
|
||
String value = lang().getRaw(path);
|
||
return lang().getPrefix() + lang().color(value);
|
||
}
|
||
|
||
/**
|
||
* Übersetzt &-Farbcodes in §-Farbcodes.
|
||
* Kompatibilitätsmethode – bevorzugt lang().color() verwenden.
|
||
*/
|
||
public String color(String text) {
|
||
return ChatColor.translateAlternateColorCodes('&', text);
|
||
}
|
||
|
||
/**
|
||
* Mappt alte "messages.xxx"-Pfade auf neue lang.yml-Pfade.
|
||
* Muss ergänzt werden wenn neue Schlüssel im alten Stil genutzt wurden.
|
||
*/
|
||
private String mapLegacyPath(String path) {
|
||
if (path == null) return null;
|
||
return switch (path) {
|
||
case "messages.export-success" -> "system.export-success";
|
||
case "messages.export-fail" -> "system.export-fail";
|
||
case "messages.import-success" -> "system.import-success";
|
||
case "messages.import-fail" -> "system.import-fail";
|
||
case "messages.migration-success" -> "system.migration-success";
|
||
case "messages.migration-fail" -> "system.migration-fail";
|
||
case "messages.archive-success" -> "system.archive-success";
|
||
case "messages.archive-fail" -> "system.archive-fail";
|
||
case "messages.file-not-found" -> "system.file-not-found";
|
||
case "messages.unknown-mode" -> "system.unknown-mode";
|
||
case "messages.validation-warning" -> "system.validation-warning";
|
||
case "messages.ticket-created" -> "ticket.created";
|
||
case "messages.ticket-created-category" -> "ticket.created-category";
|
||
case "messages.ticket-claimed" -> "ticket.claimed";
|
||
case "messages.ticket-claimed-notify" -> "ticket.claimed-notify";
|
||
case "messages.ticket-closed" -> "ticket.closed";
|
||
case "messages.ticket-closed-notify" -> "ticket.closed-notify";
|
||
case "messages.ticket-forwarded" -> "ticket.forwarded";
|
||
case "messages.ticket-forwarded-notify" -> "ticket.forwarded-notify";
|
||
case "messages.ticket-forwarded-creator-notify" -> "ticket.forwarded-creator";
|
||
case "messages.new-ticket-notify" -> "ticket.new-notify";
|
||
case "messages.comment-saved" -> "comment.saved";
|
||
case "messages.comment-notify" -> "comment.notify-online";
|
||
case "messages.comment-no-permission" -> "comment.no-permission";
|
||
case "messages.rating-saved-good" -> "rating.saved-good";
|
||
case "messages.rating-saved-bad" -> "rating.saved-bad";
|
||
case "messages.rating-already-rated" -> "rating.already-rated";
|
||
case "messages.rating-not-yours" -> "rating.not-yours";
|
||
case "messages.rating-disabled" -> "rating.disabled";
|
||
case "messages.rating-prompt" -> "rating.prompt-title";
|
||
case "messages.blacklist-added" -> "blacklist.added";
|
||
case "messages.blacklist-removed" -> "blacklist.removed";
|
||
case "messages.blacklist-already" -> "blacklist.already";
|
||
case "messages.blacklist-not-found" -> "blacklist.not-found";
|
||
case "messages.blacklist-blocked" -> "create.blacklist-blocked";
|
||
case "messages.no-permission" -> "general.no-permission";
|
||
case "messages.no-open-tickets" -> "general.no-open-tickets";
|
||
case "messages.join-open-tickets" -> "join.open-tickets";
|
||
case "messages.already-claimed" -> "general.already-claimed";
|
||
case "messages.ticket-not-found" -> "general.ticket-not-found";
|
||
case "messages.cooldown" -> "general.cooldown";
|
||
case "messages.category-invalid" -> "create.category-invalid";
|
||
default -> null;
|
||
};
|
||
}
|
||
|
||
// ─────────────────────────── Getter ────────────────────────────────────
|
||
|
||
/**
|
||
* Aktualisiert serverName und debug-Flag aus der (bereits neu geladenen) Config.
|
||
* Muss nach plugin.reloadConfig() aufgerufen werden.
|
||
*/
|
||
public void reloadSettings() {
|
||
serverName = getConfig().getString("server-name", "unknown");
|
||
if ("unknown".equals(serverName)) {
|
||
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; }
|
||
public LanguageManager getLanguageManager() { return languageManager; }
|
||
public DatabaseManager getDatabaseManager() { return databaseManager; }
|
||
public TicketManager getTicketManager() { return ticketManager; }
|
||
public CategoryManager getCategoryManager() { return categoryManager; }
|
||
public FaqManager getFaqManager() { return faqManager; }
|
||
public TicketGUI getTicketGUI() { return ticketGUI; }
|
||
public FaqGUI getFaqGUI() { return faqGUI; }
|
||
public DiscordWebhook getDiscordWebhook() { return discordWebhook; }
|
||
public BungeeMessenger getBungeeMessenger() { return bungeeMessenger; }
|
||
public TicketCache getTicketCache() { return ticketCache; }
|
||
public boolean isDebug() { return debug; }
|
||
public String getServerName() { return serverName; }
|
||
public boolean isBungeeCordEnabled() { return getConfig().getBoolean("bungeecord", false); }
|
||
public SessionManager getSessionManager() { return sessionManager; }
|
||
public WebServer getWebServer() { return webServer; }
|
||
} |