diff --git a/src/main/java/de/lasertec/protection/ModProtectionManager.java b/src/main/java/de/lasertec/protection/ModProtectionManager.java deleted file mode 100644 index cc7b83a..0000000 --- a/src/main/java/de/lasertec/protection/ModProtectionManager.java +++ /dev/null @@ -1,215 +0,0 @@ -package de.lasertec.protection; - -import de.lasertec.LasertecPlugin; -import de.lasertec.game.Game; -import org.bukkit.*; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.scoreboard.Scoreboard; -import org.bukkit.scoreboard.Team; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -/** - * Mod-Schutz System gegen Minimap-Mods (Xaero, VoxelMap etc.) - * - * WAS MINIMAP-MODS NUTZEN: - * - Spieler-Positionen aus Entity-Tracking Paketen - * - Chunk-Daten für Kartenansicht - * - Tab-Liste für Spielernamen mit Positionen - * - * WAS WIR TUN KÖNNEN (ohne ProtocolLib): - * 1. NAMETAGS verbergen (Scoreboard-Teams mit hidden nametags) - * 2. FOG-OF-WAR simulieren via Blindness-Effekt der zu naher Spieler - * → Macht Karten-Mods wertlos (sie sehen nur was der Client sieht) - * 3. TAB-LISTE leeren für Spieler im Match - * 4. SPIELER-KOLLISION deaktivieren - * - * WAS NICHT MÖGLICH IST (ohne ProtocolLib / NMS): - * - Chunk-Pakete manipulieren - * - Entity-Positionen in Paketen fälschen - * - F3-Koordinaten blockieren - * - * MIT ProtocolLib (optional, erweiterbar): - * - Echte Koordinaten-Verschleierung möglich - * - Spieler-Pakete filtern - */ -public class ModProtectionManager { - - private final LasertecPlugin plugin; - private BukkitTask fogTask; - - // Scoreboard-Team für versteckte Nametags - private org.bukkit.scoreboard.Scoreboard hiddenNametagBoard; - private final Map originalDisplayNames = new HashMap<>(); - - public ModProtectionManager(LasertecPlugin plugin) { - this.plugin = plugin; - } - - /** Wird aufgerufen wenn ein Spieler einem Spiel beitritt. */ - public void applyProtection(Player player, Game game) { - if (!plugin.getConfigManager().isModProtectionEnabled()) return; - - // 1. Nametags verstecken - if (plugin.getConfigManager().isHideNametags()) { - hideNametag(player, game); - } - - // 2. Tab-Liste leeren (nur den eigenen Tab-Name anpassen) - if (plugin.getConfigManager().isHideFromTab()) { - applyTabHide(player, game); - } - - // 3. Fog-of-War: Spieler außerhalb fog-radius unsichtbar machen - if (plugin.getConfigManager().isFogOfWarEnabled()) { - startFogOfWar(game); - } - } - - /** Alle Schutz-Effekte entfernen wenn Spieler das Spiel verlässt. */ - public void removeProtection(Player player) { - // Nametag zurücksetzen - restoreNametag(player); - - // Tab-Liste zurücksetzen - player.setPlayerListName(null); - - // Blindheit entfernen (falls aktiv) - player.removePotionEffect(PotionEffectType.BLINDNESS); - player.removePotionEffect(PotionEffectType.NIGHT_VISION); - } - - /** Alle Schutz-Effekte für alle Spieler entfernen. */ - public void removeAll(Game game) { - if (fogTask != null) { fogTask.cancel(); fogTask = null; } - for (Player p : game.getOnline()) removeProtection(p); - } - - // ─── Nametag verstecken ────────────────────────────────────────────────── - - private void hideNametag(Player player, Game game) { - // Eigenes Scoreboard für jeden Spieler im Spiel - // Wir nutzen das scoreboard das der ScoreboardManager bereits verwaltet — - // dort ein "hidden" Team erstellen - Scoreboard sb = player.getScoreboard(); - if (sb == null) sb = Bukkit.getScoreboardManager().getNewScoreboard(); - - // Team per Spieler-Name (max 16 Zeichen im Team-Namen) - String teamName = "lt_" + player.getName().substring(0, Math.min(player.getName().length(), 13)); - org.bukkit.scoreboard.Team team = sb.getTeam(teamName); - if (team == null) team = sb.registerNewTeam(teamName); - - team.setOption(org.bukkit.scoreboard.Team.Option.NAME_TAG_VISIBILITY, - org.bukkit.scoreboard.Team.OptionStatus.FOR_OTHER_TEAMS); // Eigene Tags nicht verstecken - team.addEntry(player.getName()); - - // Alle anderen Spieler im Spiel aktualisieren - for (Player other : game.getOnline()) { - if (other.equals(player)) continue; - Scoreboard otherSb = other.getScoreboard(); - if (otherSb == null) continue; - String tn = "lt_" + player.getName().substring(0, Math.min(player.getName().length(), 13)); - org.bukkit.scoreboard.Team t = otherSb.getTeam(tn); - if (t == null) t = otherSb.registerNewTeam(tn); - t.setOption(org.bukkit.scoreboard.Team.Option.NAME_TAG_VISIBILITY, - org.bukkit.scoreboard.Team.OptionStatus.NEVER); - t.addEntry(player.getName()); - } - } - - private void restoreNametag(Player player) { - // Nametag-Teams aus Scoreboard entfernen - Scoreboard sb = player.getScoreboard(); - if (sb == null) return; - String teamName = "lt_" + player.getName().substring(0, Math.min(player.getName().length(), 13)); - org.bukkit.scoreboard.Team team = sb.getTeam(teamName); - if (team != null) { - team.removeEntry(player.getName()); - } - } - - // ─── Tab-Liste ──────────────────────────────────────────────────────────── - - private void applyTabHide(Player player, Game game) { - // Spielernamen in der Tab-Liste durch Team-Tag ersetzen - // (versteckt echte Position-Infos, die manche Mods aus der Tab-Liste lesen) - var lp = game.getLP(player.getUniqueId()); - if (lp == null) return; - String teamTag = lp.getTeam().getChatColor() + "[" + lp.getTeam().getDisplayName().substring(0,1) + "] "; - player.setPlayerListName(teamTag + player.getName()); - } - - // ─── Fog-of-War ────────────────────────────────────────────────────────── - - /** - * Fog-of-War: Spieler außerhalb des fog-radius werden für andere - * Spieler unsichtbar gemacht. Das verhindert dass Minimap-Mods - * Gegner-Positionen auf der Karte anzeigen können. - * - * Technisch: Wir nutzen die Spigot hide/show Player API. - * Spieler die außerhalb des Radius sind werden per hidePlayer() ausgeblendet. - */ - private void startFogOfWar(Game game) { - if (fogTask != null) return; // Läuft bereits - int fogRadius = plugin.getConfigManager().getFogRadius(); - long fogRadiusSq = (long) fogRadius * fogRadius; - - fogTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> { - if (!game.isRunning()) { - fogTask.cancel(); fogTask = null; return; - } - for (Player viewer : game.getOnline()) { - for (Player target : game.getOnline()) { - if (viewer.equals(target)) continue; - boolean sameTeam = false; - var vlp = game.getLP(viewer.getUniqueId()); - var tlp = game.getLP(target.getUniqueId()); - if (vlp != null && tlp != null) sameTeam = vlp.getTeam() == tlp.getTeam(); - - long distSq = (long) viewer.getLocation().distanceSquared(target.getLocation()); - - if (distSq <= fogRadiusSq || sameTeam) { - // In Reichweite oder gleiches Team → sichtbar - viewer.showPlayer(plugin, target); - } else { - // Außerhalb → verstecken (Minimap sieht diesen Spieler nicht) - viewer.hidePlayer(plugin, target); - } - } - } - }, 0L, 10L); // Alle 10 Ticks (0.5s) aktualisieren - } - - // ─── Info-Methode ──────────────────────────────────────────────────────── - - /** - * Sendet eine Erklärung der Mod-Schutz-Maßnahmen an den Spieler. - * Nützlich für Admins. - */ - public void sendProtectionInfo(org.bukkit.command.CommandSender sender) { - sender.sendMessage("§8§l═══════════════════════════════════════"); - sender.sendMessage("§b§l MOD-SCHUTZ — STATUS & ERKLÄRUNG"); - sender.sendMessage("§8§l═══════════════════════════════════════"); - sender.sendMessage((plugin.getConfigManager().isModProtectionEnabled() ? "§a✔" : "§c✘") - + " §7Mod-Schutz aktiv"); - sender.sendMessage((plugin.getConfigManager().isHideNametags() ? "§a✔" : "§c✘") - + " §7Nametags versteckt §8(verhindert Spieler-Tracking)"); - sender.sendMessage((plugin.getConfigManager().isHideFromTab() ? "§a✔" : "§c✘") - + " §7Tab-Liste angepasst §8(versteckt Spielernamen)"); - sender.sendMessage((plugin.getConfigManager().isFogOfWarEnabled() ? "§a✔" : "§c✘") - + " §7Fog-of-War aktiv §8(Radius: §b" - + plugin.getConfigManager().getFogRadius() + " Blöcke§8)"); - sender.sendMessage("§8§l───────────────────────────────────────"); - sender.sendMessage("§7§oWas NICHT blockiert werden kann:"); - sender.sendMessage("§c§o - Chunk-basierte Kartendaten (bräuchte ProtocolLib)"); - sender.sendMessage("§c§o - F3-Koordinaten (Clientseitig)"); - sender.sendMessage("§c§o - Vollständige Minimap-Blöcke"); - sender.sendMessage("§7§oFür vollständigen Schutz: ProtocolLib + PacketBlocker"); - sender.sendMessage("§8§l═══════════════════════════════════════"); - } -}