From a625527a1e5eef87d24deb30c86e49f93cffa0b9 Mon Sep 17 00:00:00 2001 From: M_Viper Date: Mon, 25 Aug 2025 01:11:39 +0000 Subject: [PATCH] src/main/java/de/viper/survivalplus/Manager/TablistManager.java aktualisiert --- .../survivalplus/Manager/TablistManager.java | 236 ++++++++++++++++-- 1 file changed, 216 insertions(+), 20 deletions(-) diff --git a/src/main/java/de/viper/survivalplus/Manager/TablistManager.java b/src/main/java/de/viper/survivalplus/Manager/TablistManager.java index acdbc20..b20e371 100644 --- a/src/main/java/de/viper/survivalplus/Manager/TablistManager.java +++ b/src/main/java/de/viper/survivalplus/Manager/TablistManager.java @@ -3,20 +3,30 @@ package de.viper.survivalplus.Manager; import de.viper.survivalplus.SurvivalPlus; import org.bukkit.Bukkit; import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.ScoreboardManager; +import org.bukkit.scoreboard.Team; import me.clip.placeholderapi.PlaceholderAPI; import net.luckperms.api.LuckPerms; import net.luckperms.api.LuckPermsProvider; import net.luckperms.api.model.user.User; +import java.io.File; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; -public class TablistManager { +public class TablistManager implements Listener { private final SurvivalPlus plugin; private final List headerAnim = new ArrayList<>(); @@ -34,9 +44,17 @@ public class TablistManager { private String separatorLine; private LuckPerms luckPerms; private boolean hasPlaceholderAPI; + private final Scoreboard scoreboard; + private final Map prefixTeams; + private FileConfiguration nicknameConfig; public TablistManager(SurvivalPlus plugin) { this.plugin = plugin; + this.prefixTeams = new HashMap<>(); + + // Scoreboard initialisieren + ScoreboardManager scoreboardManager = Bukkit.getScoreboardManager(); + this.scoreboard = scoreboardManager != null ? scoreboardManager.getMainScoreboard() : null; // Resource sicherstellen, Config laden try { @@ -47,6 +65,17 @@ public class TablistManager { } catch (Exception ignored) {} FileConfiguration config = plugin.getTablistConfig(); + // Nicknames.yml laden + try { + File nicknameFile = new File(plugin.getDataFolder(), "nicknames.yml"); + if (!nicknameFile.exists()) { + plugin.saveResource("nicknames.yml", false); + } + this.nicknameConfig = YamlConfiguration.loadConfiguration(nicknameFile); + } catch (Exception ignored) { + this.nicknameConfig = null; // Keine Konsolenausgabe + } + // Konfigurationswerte laden this.enabled = config.getBoolean("enabled", true); this.serverName = config.getString("server-name", "SurvivalPlus"); @@ -61,13 +90,18 @@ public class TablistManager { // LuckPerms API initialisieren try { this.luckPerms = LuckPermsProvider.get(); - } catch (Throwable e) { // Fängt NoClassDefFoundError und andere Fehler + } catch (Throwable e) { luckPerms = null; // Keine Konsolenausgabe } // Prüfen, ob PlaceholderAPI verfügbar ist this.hasPlaceholderAPI = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); + // Chat-Listener registrieren + if (enabled) { + Bukkit.getPluginManager().registerEvents(this, plugin); + } + if (!enabled) { plugin.getLogger().info("Tablist ist deaktiviert (tablist.yml -> enabled: false)"); return; @@ -114,24 +148,29 @@ public class TablistManager { for (Player player : Bukkit.getOnlinePlayers()) { try { + // Nickname oder Spielername verwenden + String displayName = getNickname(player); + if (displayName == null || displayName.trim().isEmpty()) { + displayName = player.getName(); + } + // Spielername für die Tablist setzen String playerListName; + String prefix = getPlayerPrefix(player); if (luckPerms == null && !hasPlaceholderAPI) { - // Fallback: Nur Spielername, ohne Prefix oder Ping - playerListName = player.getName(); + playerListName = displayName; + updateNametag(player, "", displayName); } else { - // Spieler-Prefix abrufen (LuckPerms primär, PlaceholderAPI als Fallback) - String prefix = getPlayerPrefix(player); int ping = getPlayerPing(player); - // Korrigierte Formatierung: Gesamten String durch color-Methode leiten - playerListName = color(prefix + player.getName() + "&8 | &e" + ping + "ms"); + playerListName = color(prefix + displayName + (ping >= 0 ? "&8 | &e" + ping + "ms" : "")); + updateNametag(player, prefix, displayName); } player.setPlayerListName(playerListName); - // Header mit Spielername und Statistiken + // Header mit Spielername/Nickname und Statistiken String headerRaw = headerAnim.get(headerIndex) .replace("{server}", serverName) - .replace("{player}", player.getName()) + .replace("{player}", displayName) .replace("{online}", String.valueOf(onlinePlayers)) .replace("{staff}", String.valueOf(onlineStaff)); String footerRaw = footerAnim.get(footerIndex); @@ -182,33 +221,171 @@ public class TablistManager { }.runTaskTimer(plugin, 0L, interval); } + /** + * Nickname aus nicknames.yml abrufen + */ + private String getNickname(Player player) { + if (nicknameConfig == null) return null; + try { + String uuid = player.getUniqueId().toString(); + String nickname = nicknameConfig.getString(uuid); + if (nickname != null && !nickname.trim().isEmpty()) { + try { + File debugFile = new File(plugin.getDataFolder(), "debug.yml"); + FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile); + debugConfig.set(player.getUniqueId().toString() + ".nickname", nickname); + debugConfig.save(debugFile); + } catch (Exception ignored) {} + return nickname; + } + } catch (Exception ignored) { + // Keine Konsolenausgabe + } + return null; + } + + /** + * Nametag über dem Kopf aktualisieren + */ + private void updateNametag(Player player, String prefix, String displayName) { + if (scoreboard == null) return; + + try { + String teamName = generateTeamName(player, prefix); + Team team = scoreboard.getTeam(teamName); + + // Team erstellen oder aktualisieren + if (team == null) { + team = scoreboard.registerNewTeam(teamName); + } + + // Prefix zwingend setzen, wenn LuckPerms installiert ist + String coloredPrefix = color(prefix != null && !prefix.trim().isEmpty() ? prefix : (luckPerms != null ? "&7[Spieler] " : "")); + team.setPrefix(coloredPrefix); + + // Spieler dem Team hinzufügen + String entry = displayName != null && !displayName.trim().isEmpty() ? displayName : player.getName(); + if (!team.hasEntry(entry)) { + // Spieler aus anderen Teams entfernen, um Konflikte zu vermeiden + for (Team existingTeam : scoreboard.getTeams()) { + if (!existingTeam.getName().equals(teamName)) { + existingTeam.removeEntry(entry); + existingTeam.removeEntry(player.getName()); + } + } + team.addEntry(entry); + } + + // Team für alle Spieler sichtbar machen + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { + if (onlinePlayer.getScoreboard() != scoreboard) { + onlinePlayer.setScoreboard(scoreboard); + } + } + + // Debug-Ausgabe für Nametag + try { + File debugFile = new File(plugin.getDataFolder(), "debug.yml"); + FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile); + debugConfig.set(player.getUniqueId().toString() + ".nametag_prefix", coloredPrefix); + debugConfig.set(player.getUniqueId().toString() + ".nametag_entry", entry); + debugConfig.save(debugFile); + } catch (Exception ignored) {} + } catch (Exception ignored) { + // Keine Konsolenausgabe + } + } + + /** + * Eindeutigen Teamnamen generieren + */ + private String generateTeamName(Player player, String prefix) { + // Verwende UUID für eindeutige Teamnamen, falls kein Prefix vorhanden + if (prefix == null || prefix.trim().isEmpty()) { + return "nametag_" + player.getUniqueId().toString().substring(0, 8); + } + // Verwende Prefix für Teamnamen, max 16 Zeichen (Bukkit-Beschränkung) + String sanitizedPrefix = prefix.replaceAll("[^a-zA-Z0-9]", "").toLowerCase(); + return "prefix_" + sanitizedPrefix.substring(0, Math.min(sanitizedPrefix.length(), 12)); + } + /** * Spieler-Prefix abrufen (LuckPerms primär, PlaceholderAPI als Fallback) */ private String getPlayerPrefix(Player player) { - // Versuche LuckPerms-API zuerst + // Wenn LuckPerms installiert ist, Prefix zwingend abrufen if (luckPerms != null) { + // Versuche LuckPerms-API zuerst try { User user = luckPerms.getPlayerAdapter(Player.class).getUser(player); String prefix = user.getCachedData().getMetaData().getPrefix(); - return (prefix == null || prefix.isEmpty()) ? "&7[Spieler] " : prefix + " "; + if (prefix != null && !prefix.trim().isEmpty()) { + try { + File debugFile = new File(plugin.getDataFolder(), "debug.yml"); + FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile); + debugConfig.set(player.getUniqueId().toString() + ".prefix", prefix); + debugConfig.save(debugFile); + } catch (Exception ignored) {} + return prefix + " "; + } } catch (Exception ignored) { - // Keine Konsolenausgabe für LuckPerms-Fehler + // Keine Konsolenausgabe } + + // Fallback auf PlaceholderAPI, wenn LuckPerms installiert ist + if (hasPlaceholderAPI) { + try { + String prefix = PlaceholderAPI.setPlaceholders(player, "%luckperms_prefix%"); + if (prefix != null && !prefix.trim().isEmpty()) { + try { + File debugFile = new File(plugin.getDataFolder(), "debug.yml"); + FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile); + debugConfig.set(player.getUniqueId().toString() + ".prefix", prefix); + debugConfig.save(debugFile); + } catch (Exception ignored) {} + return prefix + " "; + } + } catch (Exception ignored) { + // Keine Konsolenausgabe + } + } + + // Standard-Prefix, wenn LuckPerms installiert ist, aber kein Prefix definiert + try { + File debugFile = new File(plugin.getDataFolder(), "debug.yml"); + FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile); + debugConfig.set(player.getUniqueId().toString() + ".prefix", "&7[Spieler]"); + debugConfig.save(debugFile); + } catch (Exception ignored) {} + return "&7[Spieler] "; } - // Fallback auf PlaceholderAPI + // Wenn LuckPerms nicht installiert ist, aber PlaceholderAPI vorhanden ist if (hasPlaceholderAPI) { try { String prefix = PlaceholderAPI.setPlaceholders(player, "%luckperms_prefix%"); - return (prefix == null || prefix.isEmpty()) ? "&7[Spieler] " : prefix + " "; + if (prefix != null && !prefix.trim().isEmpty()) { + try { + File debugFile = new File(plugin.getDataFolder(), "debug.yml"); + FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile); + debugConfig.set(player.getUniqueId().toString() + ".prefix", prefix); + debugConfig.save(debugFile); + } catch (Exception ignored) {} + return prefix + " "; + } } catch (Exception ignored) { - // Keine Konsolenausgabe für PlaceholderAPI-Fehler + // Keine Konsolenausgabe } } - // Letzter Fallback: Kein Prefix, da nur Spielername gewünscht - return ""; + // Standard-Prefix, wenn weder LuckPerms noch PlaceholderAPI einen Prefix liefern + try { + File debugFile = new File(plugin.getDataFolder(), "debug.yml"); + FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile); + debugConfig.set(player.getUniqueId().toString() + ".prefix", "&7[Spieler]"); + debugConfig.save(debugFile); + } catch (Exception ignored) {} + return "&7[Spieler] "; } /** @@ -220,8 +397,27 @@ public class TablistManager { Object entityPlayer = getHandle.invoke(player); return entityPlayer.getClass().getField("ping").getInt(entityPlayer); } catch (Exception ignored) { - // Keine Konsolenausgabe für Ping-Fehler - return -1; + return -1; // Keine Konsolenausgabe + } + } + + /** + * Chat-Format modifizieren + */ + @EventHandler + public void onPlayerChat(AsyncPlayerChatEvent event) { + try { + Player player = event.getPlayer(); + String displayName = getNickname(player); + if (displayName == null || displayName.trim().isEmpty()) { + displayName = player.getName(); + } + + String prefix = getPlayerPrefix(player); + String format = color(prefix + displayName + "&7: &f") + "%2$s"; + event.setFormat(format); + } catch (Exception ignored) { + // Keine Konsolenausgabe } }