Upload via GUI (85 Dateien)

This commit is contained in:
2026-11-11 00:38:32 +00:00
parent 7cc38d7c0f
commit 68dee989ee
4 changed files with 92 additions and 46 deletions
@@ -107,60 +107,80 @@ public class ScoreboardModule implements Module, Listener {
player.setScoreboard(board); player.setScoreboard(board);
} }
// Altes Objective entfernen // Falls ein anderes Plugin dem Spieler ein fremdes Board gesetzt hat: zurückholen
Objective oldObj = board.getObjective("lobby"); if (player.getScoreboard() != board) {
if (oldObj != null) oldObj.unregister(); player.setScoreboard(board);
// 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();
} }
// Paper 1.21: Objective mit Component-Titel registrieren // ---------------------------------------------------------
String translatedTitle = translate(player, title); // FLACKER-FIX: Nichts mehr löschen und neu aufbauen.
Objective obj = board.registerNewObjective( // Objective und Teams bleiben bestehen, es wird nur geändert,
"lobby", // was sich wirklich geändert hat. So werden keine unnötigen
Criteria.DUMMY, // Pakete gesendet und das Scoreboard flackert nicht.
// ---------------------------------------------------------
net.kyori.adventure.text.Component titleComponent =
net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
.legacySection() .legacySection()
.deserialize(translatedTitle) .deserialize(translate(player, title));
);
obj.setDisplaySlot(DisplaySlot.SIDEBAR);
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) // Zahlen global für dieses Objective ausblenden (Paper 1.20.4+ API)
obj.numberFormat(NumberFormat.blank()); 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++) { for (int i = 0; i < lines.size(); i++) {
String lineText = translate(player, lines.get(i)); String lineText = translate(player, lines.get(i));
// Eindeutiger unsichtbarer Entry pro Zeile via Farb-Code // Eindeutiger unsichtbarer Entry pro Zeile via Farb-Code
String entry = ChatColor.values()[i % ChatColor.values().length].toString() String entry = lineEntry(i);
+ ChatColor.RESET;
// getTeam statt registerNewTeam — verhindert "already in use" Fehler
Team team = board.getTeam("line_" + i); Team team = board.getTeam("line_" + i);
if (team == null) team = board.registerNewTeam("line_" + i); if (team == null) team = board.registerNewTeam("line_" + i);
if (!team.hasEntry(entry)) {
team.getEntries().forEach(team::removeEntry); team.getEntries().forEach(team::removeEntry);
team.addEntry(entry); team.addEntry(entry);
}
// Text aufteilen falls länger als 64 Zeichen // Text aufteilen falls länger als 64 Zeichen
String prefix;
String suffix;
if (lineText.length() > 64) { if (lineText.length() > 64) {
team.setPrefix(lineText.substring(0, 64)); prefix = lineText.substring(0, 64);
team.setSuffix(lineText.substring(64, Math.min(lineText.length(), 128))); suffix = lineText.substring(64, Math.min(lineText.length(), 128));
} else { } else {
team.setPrefix(lineText); prefix = lineText;
team.setSuffix(""); suffix = "";
} }
if (!prefix.equals(team.getPrefix())) team.setPrefix(prefix);
if (!suffix.equals(team.getSuffix())) team.setSuffix(suffix);
// Score setzen + Zahl pro Eintrag zusätzlich ausblenden // Score nur setzen, wenn er sich geändert hat oder neu ist
org.bukkit.scoreboard.Score score = obj.getScore(entry); org.bukkit.scoreboard.Score score = obj.getScore(entry);
score.setScore(lines.size() - i); int wanted = lines.size() - i;
if (!score.isScoreSet() || score.getScore() != wanted) {
score.setScore(wanted);
score.numberFormat(NumberFormat.blank()); score.numberFormat(NumberFormat.blank());
} }
}
// Kein player.setScoreboard(board) nötig, da wir das Objekt 'board' // Zeilen entfernen, die nicht mehr gebraucht werden (z. B. Wechsel Default <-> Owner)
// direkt verändert haben, das der Spieler bereits hat. 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 --- // --- Methoden für den /nexus sb Befehl ---
@@ -39,7 +39,7 @@ public class SecurityModule implements Module, Listener {
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onAsyncLogin(AsyncPlayerPreLoginEvent event) { public void onAsyncLogin(AsyncPlayerPreLoginEvent event) {
FileConfiguration config = plugin.getConfig(); FileConfiguration config = getSecurityConfig();
UUID uuid = event.getUniqueId(); UUID uuid = event.getUniqueId();
String ip = event.getAddress().getHostAddress(); String ip = event.getAddress().getHostAddress();
@@ -48,8 +48,9 @@ public class SecurityModule implements Module, Listener {
return; // Teammitglieder dürfen immer drauf return; // Teammitglieder dürfen immer drauf
} }
boolean vpnEnabled = config.getBoolean("security.vpn-blocker.enabled", true); // Standard: aus, wenn nichts konfiguriert ist (kein ungewolltes Kicken)
boolean countryEnabled = config.getBoolean("security.country-blocker.enabled", true); boolean vpnEnabled = config.getBoolean("security.vpn-blocker.enabled", false);
boolean countryEnabled = config.getBoolean("security.country-blocker.enabled", false);
if (!vpnEnabled && !countryEnabled) return; if (!vpnEnabled && !countryEnabled) return;
@@ -69,11 +70,12 @@ public class SecurityModule implements Module, Listener {
// 2. VPN / Proxy Check // 2. VPN / Proxy Check
if (vpnEnabled) { if (vpnEnabled) {
boolean isProxy = (boolean) json.get("proxy"); boolean isProxy = Boolean.TRUE.equals(json.get("proxy"));
boolean isHosting = (boolean) json.get("hosting"); boolean isHosting = Boolean.TRUE.equals(json.get("hosting"));
if (isProxy || isHosting) { if (isProxy || isHosting) {
event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER,
colorize(config.getString("security.vpn-blocker.kick-message"))); colorize(config.getString("security.vpn-blocker.kick-message",
"&cVPN und Proxies sind auf diesem Server nicht erlaubt!")));
return; return;
} }
} }
@@ -110,6 +112,21 @@ public class SecurityModule implements Module, Listener {
return user != null && user.getCachedData().getPermissionData().checkPermission("nexuslobby.security.bypass").asBoolean(); 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) { private String colorize(String s) {
return s == null ? "" : s.replace("&", "§"); return s == null ? "" : s.replace("&", "§");
} }
@@ -9,7 +9,9 @@ import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
@@ -71,7 +73,10 @@ public class ServerSwitcherListener implements Listener, CommandExecutor {
return true; 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) { public void onCompassClick(PlayerInteractEvent e) {
Player p = e.getPlayer(); 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 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; || 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); e.setCancelled(true);
openServerGUI(p);
} }
private void openServerGUI(Player p) { private void openServerGUI(Player p) {
+1 -1
View File
@@ -1,6 +1,6 @@
name: NexusLobby name: NexusLobby
main: de.nexuslobby.NexusLobby main: de.nexuslobby.NexusLobby
version: "2.0" version: "2.1"
api-version: "1.21" api-version: "1.21"
author: M_Viper author: M_Viper
description: Modular Lobby Plugin with an invisible Particle-Parkour system. description: Modular Lobby Plugin with an invisible Particle-Parkour system.