From 68dee989eec82b65e8b2412b6e083111e5cdee41 Mon Sep 17 00:00:00 2001 From: M_Viper Date: Wed, 11 Nov 2026 00:38:32 +0000 Subject: [PATCH] Upload via GUI (85 Dateien) --- .../nexuslobby/modules/ScoreboardModule.java | 92 +++++++++++-------- .../modules/security/SecurityModule.java | 31 +++++-- .../servers/ServerSwitcherListener.java | 13 ++- src/main/resources/plugin.yml | 2 +- 4 files changed, 92 insertions(+), 46 deletions(-) diff --git a/src/main/java/de/nexuslobby/modules/ScoreboardModule.java b/src/main/java/de/nexuslobby/modules/ScoreboardModule.java index 3757fb4..f5b10e2 100644 --- a/src/main/java/de/nexuslobby/modules/ScoreboardModule.java +++ b/src/main/java/de/nexuslobby/modules/ScoreboardModule.java @@ -107,60 +107,80 @@ public class ScoreboardModule implements Module, Listener { player.setScoreboard(board); } - // Altes Objective entfernen - Objective oldObj = board.getObjective("lobby"); - if (oldObj != null) oldObj.unregister(); - - // Alle alten Zeilen-Teams sicher entfernen (großzügige Obergrenze) - for (int i = 0; i < Math.max(lines.size() + 5, 32); i++) { - Team old = board.getTeam("line_" + i); - if (old != null) old.unregister(); + // Falls ein anderes Plugin dem Spieler ein fremdes Board gesetzt hat: zurückholen + if (player.getScoreboard() != board) { + player.setScoreboard(board); } - // Paper 1.21: Objective mit Component-Titel registrieren - String translatedTitle = translate(player, title); - Objective obj = board.registerNewObjective( - "lobby", - Criteria.DUMMY, + // --------------------------------------------------------- + // FLACKER-FIX: Nichts mehr löschen und neu aufbauen. + // Objective und Teams bleiben bestehen, es wird nur geändert, + // was sich wirklich geändert hat. So werden keine unnötigen + // Pakete gesendet und das Scoreboard flackert nicht. + // --------------------------------------------------------- + net.kyori.adventure.text.Component titleComponent = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer .legacySection() - .deserialize(translatedTitle) - ); - obj.setDisplaySlot(DisplaySlot.SIDEBAR); + .deserialize(translate(player, title)); - // Zahlen global für dieses Objective ausblenden (Paper 1.20.4+ API) - obj.numberFormat(NumberFormat.blank()); + Objective obj = board.getObjective("lobby"); + if (obj == null) { + obj = board.registerNewObjective("lobby", Criteria.DUMMY, titleComponent); + // Zahlen global für dieses Objective ausblenden (Paper 1.20.4+ API) + obj.numberFormat(NumberFormat.blank()); + } else if (!titleComponent.equals(obj.displayName())) { + obj.displayName(titleComponent); + } + if (obj.getDisplaySlot() != DisplaySlot.SIDEBAR) { + obj.setDisplaySlot(DisplaySlot.SIDEBAR); + } for (int i = 0; i < lines.size(); i++) { String lineText = translate(player, lines.get(i)); // Eindeutiger unsichtbarer Entry pro Zeile via Farb-Code - String entry = ChatColor.values()[i % ChatColor.values().length].toString() - + ChatColor.RESET; + String entry = lineEntry(i); - // getTeam statt registerNewTeam — verhindert "already in use" Fehler Team team = board.getTeam("line_" + i); if (team == null) team = board.registerNewTeam("line_" + i); - team.getEntries().forEach(team::removeEntry); - team.addEntry(entry); - - // Text aufteilen falls länger als 64 Zeichen - if (lineText.length() > 64) { - team.setPrefix(lineText.substring(0, 64)); - team.setSuffix(lineText.substring(64, Math.min(lineText.length(), 128))); - } else { - team.setPrefix(lineText); - team.setSuffix(""); + if (!team.hasEntry(entry)) { + team.getEntries().forEach(team::removeEntry); + team.addEntry(entry); } - // Score setzen + Zahl pro Eintrag zusätzlich ausblenden + // Text aufteilen falls länger als 64 Zeichen + String prefix; + String suffix; + if (lineText.length() > 64) { + prefix = lineText.substring(0, 64); + suffix = lineText.substring(64, Math.min(lineText.length(), 128)); + } else { + prefix = lineText; + suffix = ""; + } + if (!prefix.equals(team.getPrefix())) team.setPrefix(prefix); + if (!suffix.equals(team.getSuffix())) team.setSuffix(suffix); + + // Score nur setzen, wenn er sich geändert hat oder neu ist org.bukkit.scoreboard.Score score = obj.getScore(entry); - score.setScore(lines.size() - i); - score.numberFormat(NumberFormat.blank()); + int wanted = lines.size() - i; + if (!score.isScoreSet() || score.getScore() != wanted) { + score.setScore(wanted); + score.numberFormat(NumberFormat.blank()); + } } - // Kein player.setScoreboard(board) nötig, da wir das Objekt 'board' - // direkt verändert haben, das der Spieler bereits hat. + // Zeilen entfernen, die nicht mehr gebraucht werden (z. B. Wechsel Default <-> Owner) + for (int i = lines.size(); i < 32; i++) { + Team old = board.getTeam("line_" + i); + if (old == null) continue; + board.resetScores(lineEntry(i)); + old.unregister(); + } + } + + private String lineEntry(int i) { + return ChatColor.values()[i % ChatColor.values().length].toString() + ChatColor.RESET; } // --- Methoden für den /nexus sb Befehl --- diff --git a/src/main/java/de/nexuslobby/modules/security/SecurityModule.java b/src/main/java/de/nexuslobby/modules/security/SecurityModule.java index ec12a9a..b9f1255 100644 --- a/src/main/java/de/nexuslobby/modules/security/SecurityModule.java +++ b/src/main/java/de/nexuslobby/modules/security/SecurityModule.java @@ -39,7 +39,7 @@ public class SecurityModule implements Module, Listener { @EventHandler(priority = EventPriority.HIGHEST) public void onAsyncLogin(AsyncPlayerPreLoginEvent event) { - FileConfiguration config = plugin.getConfig(); + FileConfiguration config = getSecurityConfig(); UUID uuid = event.getUniqueId(); String ip = event.getAddress().getHostAddress(); @@ -48,8 +48,9 @@ public class SecurityModule implements Module, Listener { return; // Teammitglieder dürfen immer drauf } - boolean vpnEnabled = config.getBoolean("security.vpn-blocker.enabled", true); - boolean countryEnabled = config.getBoolean("security.country-blocker.enabled", true); + // Standard: aus, wenn nichts konfiguriert ist (kein ungewolltes Kicken) + boolean vpnEnabled = config.getBoolean("security.vpn-blocker.enabled", false); + boolean countryEnabled = config.getBoolean("security.country-blocker.enabled", false); if (!vpnEnabled && !countryEnabled) return; @@ -69,11 +70,12 @@ public class SecurityModule implements Module, Listener { // 2. VPN / Proxy Check if (vpnEnabled) { - boolean isProxy = (boolean) json.get("proxy"); - boolean isHosting = (boolean) json.get("hosting"); + boolean isProxy = Boolean.TRUE.equals(json.get("proxy")); + boolean isHosting = Boolean.TRUE.equals(json.get("hosting")); if (isProxy || isHosting) { - event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, - colorize(config.getString("security.vpn-blocker.kick-message"))); + event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, + colorize(config.getString("security.vpn-blocker.kick-message", + "&cVPN und Proxies sind auf diesem Server nicht erlaubt!"))); return; } } @@ -110,6 +112,21 @@ public class SecurityModule implements Module, Listener { return user != null && user.getCachedData().getPermissionData().checkPermission("nexuslobby.security.bypass").asBoolean(); } + /** + * Die Security-Einstellungen stehen in der settings.yml (nicht in der config.yml). + * Fallback auf die config.yml, falls das Settings-Modul noch nicht bereit ist. + */ + private FileConfiguration getSecurityConfig() { + try { + var module = plugin.getLobbySettingsModule(); + if (module != null && module.getSettingsConfig() != null) { + return module.getSettingsConfig(); + } + } catch (Exception ignored) { + } + return plugin.getConfig(); + } + private String colorize(String s) { return s == null ? "" : s.replace("&", "§"); } diff --git a/src/main/java/de/nexuslobby/modules/servers/ServerSwitcherListener.java b/src/main/java/de/nexuslobby/modules/servers/ServerSwitcherListener.java index 04261b8..04090a4 100644 --- a/src/main/java/de/nexuslobby/modules/servers/ServerSwitcherListener.java +++ b/src/main/java/de/nexuslobby/modules/servers/ServerSwitcherListener.java @@ -9,7 +9,9 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.bukkit.event.Event; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.inventory.InventoryClickEvent; @@ -71,7 +73,10 @@ public class ServerSwitcherListener implements Listener, CommandExecutor { return true; } - @EventHandler + // LOWEST: Wir reagieren als Erste. So können andere Plugins (z. B. der Navigations-Stab + // von WorldEdit, der standardmäßig ein Kompass ist und beim Klick teleportiert) + // den Klick nicht mehr verarbeiten. + @EventHandler(priority = EventPriority.LOWEST) public void onCompassClick(PlayerInteractEvent e) { Player p = e.getPlayer(); @@ -79,8 +84,12 @@ public class ServerSwitcherListener implements Listener, CommandExecutor { if (!(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK || e.getAction() == Action.LEFT_CLICK_AIR || e.getAction() == Action.LEFT_CLICK_BLOCK)) return; - openServerGUI(p); + // Klick komplett sperren, bevor andere Plugins ihn sehen + e.setUseItemInHand(Event.Result.DENY); + e.setUseInteractedBlock(Event.Result.DENY); e.setCancelled(true); + + openServerGUI(p); } private void openServerGUI(Player p) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index da2f024..8e67a79 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: NexusLobby main: de.nexuslobby.NexusLobby -version: "2.0" +version: "2.1" api-version: "1.21" author: M_Viper description: Modular Lobby Plugin with an invisible Particle-Parkour system.