From f0c5ebe5a88b67d9bd33996e6998035615bd9fea Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Wed, 8 Mar 2023 13:22:15 +0100 Subject: [PATCH] Server groups, formatting based on server groups (#6) --- .../net/william278/velocitab/Velocitab.java | 5 +- .../william278/velocitab/config/Settings.java | 74 +++++++++++++------ .../velocitab/player/TabPlayer.java | 5 +- .../velocitab/tab/PlayerTabList.java | 58 +++++++++++++-- 4 files changed, 110 insertions(+), 32 deletions(-) diff --git a/src/main/java/net/william278/velocitab/Velocitab.java b/src/main/java/net/william278/velocitab/Velocitab.java index 18b1387..b2a7303 100644 --- a/src/main/java/net/william278/velocitab/Velocitab.java +++ b/src/main/java/net/william278/velocitab/Velocitab.java @@ -78,7 +78,10 @@ public class Velocitab { private void loadSettings() { try { - settings = Annotaml.create(new File(dataDirectory.toFile(), "config.yml"), Settings.class).get(); + settings = Annotaml.create( + new File(dataDirectory.toFile(), "config.yml"), + new Settings(this) + ).get(); } catch (IOException | InvocationTargetException | InstantiationException | IllegalAccessException e) { logger.error("Failed to load config file: " + e.getMessage(), e); } diff --git a/src/main/java/net/william278/velocitab/config/Settings.java b/src/main/java/net/william278/velocitab/config/Settings.java index a2dabcb..c63287d 100644 --- a/src/main/java/net/william278/velocitab/config/Settings.java +++ b/src/main/java/net/william278/velocitab/config/Settings.java @@ -1,13 +1,17 @@ package net.william278.velocitab.config; + +import lombok.Getter; import net.william278.annotaml.YamlComment; import net.william278.annotaml.YamlFile; import net.william278.annotaml.YamlKey; import net.william278.velocitab.BuildConstants; +import net.william278.velocitab.Velocitab; import org.apache.commons.text.StringEscapeUtils; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; +import java.util.List; +import java.util.Map; @YamlFile(header = """ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ @@ -17,40 +21,66 @@ import java.util.ArrayList; ┗╸ Placeholders: %players_online%, %max_players_online%, %local_players_online%, %current_date%, %current_time%, %username%, %server%, %ping%, %prefix%, %suffix%, %role%""") public class Settings { - @YamlKey("header") - private String header = "&rainbow&Running Velocitab v" + BuildConstants.VERSION + " by William278"; - @YamlKey("footer") - private String footer = "[There are currently %players_online%/%max_players_online% players online](gray)"; - @YamlKey("format") - private String format = "&7[%server%] &f%prefix%%username%"; - @YamlComment("Enable the PlaceholderAPI hook (requires PAPIProxyBridge to be installed on proxy & spigot servers)") + + @YamlKey("headers") + private Map headers = Map.of("default", "&rainbow&Running Velocitab v" + BuildConstants.VERSION + " by William278"); + @YamlKey("footers") + private Map footers = Map.of("default", "[There are currently %players_online%/%max_players_online% players online](gray)"); + @YamlKey("formats") + private Map formats = Map.of("default", "&7[%server%] &f%prefix%%username%"); + @Getter + @YamlKey("server_groups") + @YamlComment("The servers in each group of servers") + private Map> serverGroups = Map.of("default", List.of("lobby1", "lobby2", "lobby3")); + @Getter + @YamlKey("fallback_enabled") + @YamlComment("All servers which are not in other groups will be put in the fallback group.\n\"false\" will exclude them from Velocitab.") + private boolean fallbackEnabled = true; + @Getter + @YamlKey("fallback_group") + @YamlComment("The format to use for the fallback group.") + private String fallbackGroup = "default"; @YamlKey("enable_papi_hook") private boolean enablePapiHook = true; - @YamlKey("excluded_servers") - private ArrayList excludedServers = new ArrayList<>(); @YamlKey(("update_rate")) private int updateRate = 0; - private Settings() { + public Settings(@NotNull Velocitab plugin) { + this.serverGroups = Map.of("default", + plugin.getServer().getAllServers().stream().map(server -> server.getServerInfo().getName()).toList() + ); + } + @SuppressWarnings("unused") + public Settings(){} + + @NotNull + public String getHeader(String serverGroup) { + return StringEscapeUtils.unescapeJava( + headers.getOrDefault(serverGroup, "&rainbow&Running Velocitab v" + BuildConstants.VERSION + " by William278")); } @NotNull - public String getHeader() { - return StringEscapeUtils.unescapeJava(header); + public String getFooter(String serverGroup) { + return StringEscapeUtils.unescapeJava( + footers.getOrDefault(serverGroup, "[There are currently %players_online%/%max_players_online% players online](gray)")); } @NotNull - public String getFooter() { - return StringEscapeUtils.unescapeJava(footer); + public String getFormat(String serverGroup) { + return StringEscapeUtils.unescapeJava( + formats.getOrDefault(serverGroup, "&7[%server%] &f%prefix%%username%")); } - @NotNull - public String getFormat() { - return StringEscapeUtils.unescapeJava(format); - } - - public boolean isServerExcluded(@NotNull String serverName) { - return excludedServers.contains(serverName); + /** + * Get the server group that a server is in + * + * @param serverName The name of the server + * @return The server group that the server is in, or "default" if the server is not in a group + */ + public String getServerGroup(String serverName) { + return serverGroups.entrySet().stream() + .filter(entry -> entry.getValue().contains(serverName)).findFirst() + .map(Map.Entry::getKey).orElse(fallbackGroup); } public boolean isPapiHookEnabled() { diff --git a/src/main/java/net/william278/velocitab/player/TabPlayer.java b/src/main/java/net/william278/velocitab/player/TabPlayer.java index 5522183..2a76903 100644 --- a/src/main/java/net/william278/velocitab/player/TabPlayer.java +++ b/src/main/java/net/william278/velocitab/player/TabPlayer.java @@ -40,8 +40,11 @@ public final class TabPlayer implements Comparable { @NotNull public CompletableFuture getDisplayName(@NotNull Velocitab plugin) { - return Placeholder.format(plugin.getSettings().getFormat(), plugin, this) + return Placeholder.format(plugin.getSettings().getFormat( + plugin.getSettings().getServerGroup(getServerName()) + ), plugin, this) .thenApply(formatted -> new MineDown(formatted).toComponent()); + } @NotNull diff --git a/src/main/java/net/william278/velocitab/tab/PlayerTabList.java b/src/main/java/net/william278/velocitab/tab/PlayerTabList.java index bf5ad1b..2712309 100644 --- a/src/main/java/net/william278/velocitab/tab/PlayerTabList.java +++ b/src/main/java/net/william278/velocitab/tab/PlayerTabList.java @@ -16,7 +16,9 @@ import net.william278.velocitab.player.TabPlayer; import org.jetbrains.annotations.NotNull; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.TimeUnit; @@ -24,10 +26,12 @@ import java.util.concurrent.TimeUnit; public class PlayerTabList { private final Velocitab plugin; private final ConcurrentLinkedQueue players; + private final ConcurrentLinkedQueue fallbackServers; public PlayerTabList(@NotNull Velocitab plugin) { this.plugin = plugin; this.players = new ConcurrentLinkedQueue<>(); + this.fallbackServers = new ConcurrentLinkedQueue<>(); // If the update time is set to 0 do not schedule the updater if (plugin.getSettings().getUpdateRate() > 0) { @@ -46,11 +50,16 @@ public class PlayerTabList { players.removeIf(player -> player.getPlayer().getUniqueId().equals(joined.getUniqueId())); } - // Don't set their list if they are on an excluded server - if (plugin.getSettings().isServerExcluded(joined.getCurrentServer() + // Get the servers in the group from the joined server name + // If the server is not in a group, use fallback + Optional> serversInGroup = getSiblings(joined.getCurrentServer() .map(ServerConnection::getServerInfo) .map(ServerInfo::getName) - .orElse("?"))) { + .orElse("?")); + // If the server is not in a group, use fallback. + // If fallback is disabled, permit the player to switch excluded servers without header or footer override + if (serversInGroup.isEmpty() && !this.fallbackServers.contains(event.getPreviousServer().getServerInfo().getName())) { + event.getPlayer().sendPlayerListHeaderAndFooter(Component.empty(), Component.empty()); return; } @@ -63,7 +72,11 @@ public class PlayerTabList { .buildTask(plugin, () -> { final TabList tabList = joined.getTabList(); final Map playerRoles = new HashMap<>(); - players.forEach(player -> { + + for (TabPlayer player : players) { + if (!serversInGroup.get().contains(player.getServerName())) { + continue; // Skip players on other servers + } playerRoles.put(player.getPlayer().getUsername(), player.getTeamName()); tabList.getEntries().stream() .filter(e -> e.getProfile().getId().equals(player.getPlayer().getUniqueId())).findFirst() @@ -73,7 +86,8 @@ public class PlayerTabList { ); addPlayerToTabList(player, tabPlayer); player.sendHeaderAndFooter(this); - }); + } + plugin.getScoreboardManager().setRoles(joined, playerRoles); }) .delay(500, TimeUnit.MILLISECONDS) @@ -142,24 +156,52 @@ public class PlayerTabList { } public CompletableFuture getHeader(@NotNull TabPlayer player) { - return Placeholder.format(plugin.getSettings().getHeader(), plugin, player) + return Placeholder.format(plugin.getSettings().getHeader( + plugin.getSettings().getServerGroup(player.getServerName())), plugin, player) .thenApply(header -> new MineDown(header).toComponent()); } public CompletableFuture getFooter(@NotNull TabPlayer player) { - return Placeholder.format(plugin.getSettings().getFooter(), plugin, player) + return Placeholder.format(plugin.getSettings().getFooter( + plugin.getSettings().getServerGroup(player.getServerName())), plugin, player) .thenApply(header -> new MineDown(header).toComponent()); + } private void updateTimer(int updateRate) { plugin.getServer().getScheduler() .buildTask(plugin, () -> { - if (!players.isEmpty()){ + if (!players.isEmpty()) { players.forEach(this::onUpdate); } }) .repeat(updateRate, TimeUnit.MILLISECONDS) .schedule(); } + + /** + * Get the servers in the same group as the given server + * If the server is not in a group, use fallback + * If fallback is disabled, return empty + * + * @param serverName The server name + * @return The servers in the same group as the given server, empty if the server is not in a group and fallback is disabled + */ + @NotNull + public Optional> getSiblings(String serverName) { + return plugin.getSettings().getServerGroups().values().stream() + .filter(servers -> servers.contains(serverName)) + .findFirst() + .or(() -> { + if (!plugin.getSettings().isFallbackEnabled()) { + return Optional.empty(); + } + + if (!this.fallbackServers.contains(serverName)) { + this.fallbackServers.add(serverName); + } + return Optional.of(this.fallbackServers.stream().toList()); + }); + } }