server = player.getPlayer().getCurrentServer();
+ if (server.isEmpty()) {
+ return;
+ }
+ final String serverName = server.get().getServerInfo().getName();
+ final Group group = getGroup(serverName);
+ player.setGroup(group);
+ this.updatePlayer(player, true);
+ player.sendHeaderAndFooter(this);
+ });
+ updateDisplayNames();
}
- /**
- * Get the servers in the same group as the given server, as an optional
- *
- * If the server is not in a group, use the fallback group
- * If the fallback is disabled, return an empty optional
- *
- * @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> getGroupNames(@NotNull 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());
- });
+ public Group getGroup(@NotNull String serverName) {
+ return plugin.getTabGroups().getGroupFromServer(serverName);
}
- /**
- * Get the servers in the same group as the given server, as an optional list of {@link ServerInfo}
- *
- * If the server is not in a group, use the fallback group
- * If the fallback is disabled, return an empty optional
- *
- * @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 List getGroupServers(@NotNull String serverName) {
- return plugin.getServer().getAllServers().stream()
- .filter(server -> plugin.getSettings().getServerGroups().values().stream()
- .filter(servers -> servers.contains(serverName))
- .anyMatch(servers -> servers.contains(server.getServerInfo().getName())))
- .toList();
- }
-
- @Subscribe
- public void proxyReload(@NotNull ProxyReloadEvent event) {
- plugin.loadSettings();
- reloadUpdate();
- plugin.log("Velocitab has been reloaded!");
- }
/**
* Remove an offline player from the list of tracked TAB players
@@ -448,81 +444,4 @@ public class PlayerTabList {
players.remove(player.getUniqueId());
}
- public void vanishPlayer(@NotNull TabPlayer tabPlayer) {
- players.values().forEach(p -> {
- if (p.getPlayer().equals(tabPlayer.getPlayer())) {
- return;
- }
-
- if (!plugin.getVanishManager().canSee(p.getPlayer().getUsername(), tabPlayer.getPlayer().getUsername())) {
- p.getPlayer().getTabList().removeEntry(tabPlayer.getPlayer().getUniqueId());
- }
- });
- }
-
- public void unVanishPlayer(@NotNull TabPlayer tabPlayer) {
- final UUID uuid = tabPlayer.getPlayer().getUniqueId();
-
- tabPlayer.getDisplayName(plugin).thenAccept(c -> players.values().forEach(p -> {
- if (p.getPlayer().equals(tabPlayer.getPlayer())) {
- return;
- }
-
- if (!p.getPlayer().getTabList().containsEntry(uuid)) {
- p.getPlayer().getTabList().addEntry(createEntry(tabPlayer, p.getPlayer().getTabList(), c));
- } else {
- p.getPlayer().getTabList().getEntry(uuid).ifPresent(entry -> entry.setDisplayName(c));
- }
- }));
-
- }
-
- /**
- * Recalculates the visibility of players in the tab list for the given player.
- * If tabPlayer can see the player, the player will be added to the tab list.
- *
- * @param tabPlayer The TabPlayer object representing the player for whom to recalculate the tab list visibility.
- */
- public void recalculateVanishForPlayer(@NotNull TabPlayer tabPlayer) {
- final Player player = tabPlayer.getPlayer();
- final Optional> serversInGroupOptional = getGroupNames(player.getCurrentServer()
- .map(ServerConnection::getServerInfo)
- .map(ServerInfo::getName)
- .orElse("?"));
- final List serversInGroup = serversInGroupOptional.orElseGet(ArrayList::new);
-
- plugin.getServer().getAllPlayers().forEach(p -> {
- if (p.equals(player)) {
- return;
- }
-
- final Optional targetOptional = getTabPlayer(p);
- if (targetOptional.isEmpty()) {
- return;
- }
-
- final TabPlayer target = targetOptional.get();
- final String serverName = target.getServerName();
-
- if (plugin.getSettings().isOnlyListPlayersInSameGroup()
- && !serversInGroup.contains(serverName)) {
- return;
- }
-
- final boolean canSee = !plugin.getVanishManager().isVanished(p.getUsername()) ||
- plugin.getVanishManager().canSee(player.getUsername(), p.getUsername());
-
- if (!canSee) {
- player.getTabList().removeEntry(p.getUniqueId());
- plugin.getScoreboardManager().ifPresent(s -> s.recalculateVanishForPlayer(tabPlayer, target, false));
- } else {
- if (!player.getTabList().containsEntry(p.getUniqueId())) {
- createEntry(target, player.getTabList()).thenAccept(e -> {
- player.getTabList().addEntry(e);
- plugin.getScoreboardManager().ifPresent(s -> s.recalculateVanishForPlayer(tabPlayer, target, true));
- });
- }
- }
- });
- }
}
diff --git a/src/main/java/net/william278/velocitab/tab/TabListListener.java b/src/main/java/net/william278/velocitab/tab/TabListListener.java
new file mode 100644
index 0000000..b619fa4
--- /dev/null
+++ b/src/main/java/net/william278/velocitab/tab/TabListListener.java
@@ -0,0 +1,122 @@
+/*
+ * This file is part of Velocitab, licensed under the Apache License 2.0.
+ *
+ * Copyright (c) William278
+ * Copyright (c) contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.william278.velocitab.tab;
+
+import com.velocitypowered.api.event.PostOrder;
+import com.velocitypowered.api.event.Subscribe;
+import com.velocitypowered.api.event.connection.DisconnectEvent;
+import com.velocitypowered.api.event.player.KickedFromServerEvent;
+import com.velocitypowered.api.event.player.ServerPostConnectEvent;
+import com.velocitypowered.api.event.proxy.ProxyReloadEvent;
+import com.velocitypowered.api.proxy.Player;
+import com.velocitypowered.api.proxy.ServerConnection;
+import com.velocitypowered.api.proxy.server.ServerInfo;
+import net.kyori.adventure.text.Component;
+import net.william278.velocitab.Velocitab;
+import net.william278.velocitab.config.Group;
+import net.william278.velocitab.player.TabPlayer;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * The TabListListener class is responsible for handling events related to the player tab list.
+ */
+@SuppressWarnings("unused")
+public class TabListListener {
+
+ private final Velocitab plugin;
+ private final PlayerTabList tabList;
+
+ public TabListListener(@NotNull Velocitab plugin, @NotNull PlayerTabList tabList) {
+ this.plugin = plugin;
+ this.tabList = tabList;
+ }
+
+ @Subscribe
+ public void onKick(KickedFromServerEvent event) {
+ event.getPlayer().getTabList().clearAll();
+ event.getPlayer().getTabList().clearHeaderAndFooter();
+ }
+
+ @SuppressWarnings("UnstableApiUsage")
+ @Subscribe
+ public void onPlayerJoin(@NotNull ServerPostConnectEvent event) {
+ final Player joined = event.getPlayer();
+ plugin.getScoreboardManager().ifPresent(manager -> manager.resetCache(joined));
+
+ final String serverName = joined.getCurrentServer()
+ .map(ServerConnection::getServerInfo)
+ .map(ServerInfo::getName)
+ .orElse("");
+ final Group group = tabList.getGroup(serverName);
+ final boolean isDefault = !group.servers().contains(serverName);
+
+ // If the server is not in a group, use fallback.
+ // If fallback is disabled, permit the player to switch excluded servers without a header or footer override
+ if (isDefault && !plugin.getSettings().isFallbackEnabled()) {
+ event.getPlayer().sendPlayerListHeaderAndFooter(Component.empty(), Component.empty());
+ tabList.getPlayers().remove(event.getPlayer().getUniqueId());
+ return;
+ }
+
+ tabList.joinPlayer(joined, group);
+ }
+
+ @Subscribe(order = PostOrder.LAST)
+ public void onPlayerQuit(@NotNull DisconnectEvent event) {
+ if (event.getLoginStatus() != DisconnectEvent.LoginStatus.SUCCESSFUL_LOGIN) {
+ return;
+ }
+
+ // Remove the player from the tracking list, Print warning if player was not removed
+ final UUID uuid = event.getPlayer().getUniqueId();
+ final TabPlayer tabPlayer = tabList.getPlayers().get(uuid);
+ if (tabPlayer == null) {
+ plugin.log(String.format("Failed to remove disconnecting player %s (UUID: %s)",
+ event.getPlayer().getUsername(), uuid));
+ }
+
+ // Remove the player from the tab list of all other players
+ plugin.getServer().getAllPlayers().forEach(player -> player.getTabList().removeEntry(uuid));
+
+ // Update the tab list of all players
+ plugin.getServer().getScheduler()
+ .buildTask(plugin, () -> tabList.getPlayers().values().forEach(player -> {
+ player.getPlayer().getTabList().removeEntry(uuid);
+ player.sendHeaderAndFooter(tabList);
+ }))
+ .delay(500, TimeUnit.MILLISECONDS)
+ .schedule();
+ // Delete player team
+ plugin.getScoreboardManager().ifPresent(manager -> manager.resetCache(event.getPlayer()));
+ //remove player from tab list cache
+ tabList.getPlayers().remove(uuid);
+ }
+
+ @Subscribe
+ public void proxyReload(@NotNull ProxyReloadEvent event) {
+ plugin.loadConfigs();
+ tabList.reloadUpdate();
+ plugin.log("Velocitab has been reloaded!");
+ }
+
+}
diff --git a/src/main/java/net/william278/velocitab/tab/VanishTabList.java b/src/main/java/net/william278/velocitab/tab/VanishTabList.java
new file mode 100644
index 0000000..992c134
--- /dev/null
+++ b/src/main/java/net/william278/velocitab/tab/VanishTabList.java
@@ -0,0 +1,119 @@
+/*
+ * This file is part of Velocitab, licensed under the Apache License 2.0.
+ *
+ * Copyright (c) William278
+ * Copyright (c) contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.william278.velocitab.tab;
+
+import com.velocitypowered.api.proxy.Player;
+import net.william278.velocitab.Velocitab;
+import net.william278.velocitab.player.TabPlayer;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+/**
+ * The VanishTabList handles the tab list for vanished players
+ */
+public class VanishTabList {
+
+ private final Velocitab plugin;
+ private final PlayerTabList tabList;
+
+ public VanishTabList(Velocitab plugin, PlayerTabList tabList) {
+ this.plugin = plugin;
+ this.tabList = tabList;
+ }
+
+
+ public void vanishPlayer(@NotNull TabPlayer tabPlayer) {
+ tabList.getPlayers().values().forEach(p -> {
+ if (p.getPlayer().equals(tabPlayer.getPlayer())) {
+ return;
+ }
+
+ if (!plugin.getVanishManager().canSee(p.getPlayer().getUsername(), tabPlayer.getPlayer().getUsername())) {
+ p.getPlayer().getTabList().removeEntry(tabPlayer.getPlayer().getUniqueId());
+ }
+ });
+ }
+
+ public void unVanishPlayer(@NotNull TabPlayer tabPlayer) {
+ final UUID uuid = tabPlayer.getPlayer().getUniqueId();
+
+ tabPlayer.getDisplayName(plugin).thenAccept(c -> tabList.getPlayers().values().forEach(p -> {
+ if (p.getPlayer().equals(tabPlayer.getPlayer())) {
+ return;
+ }
+
+ if (!p.getPlayer().getTabList().containsEntry(uuid)) {
+ p.getPlayer().getTabList().addEntry(tabList.createEntry(tabPlayer, p.getPlayer().getTabList(), c));
+ } else {
+ p.getPlayer().getTabList().getEntry(uuid).ifPresent(entry -> entry.setDisplayName(c));
+ }
+ }));
+
+ }
+
+ /**
+ * Recalculates the visibility of players in the tab list for the given player.
+ * If tabPlayer can see the player, the player will be added to the tab list.
+ *
+ * @param tabPlayer The TabPlayer object representing the player for whom to recalculate the tab list visibility.
+ */
+ public void recalculateVanishForPlayer(@NotNull TabPlayer tabPlayer) {
+ final Player player = tabPlayer.getPlayer();
+ final List serversInGroup = tabPlayer.getGroup().servers();
+
+ plugin.getServer().getAllPlayers().forEach(p -> {
+ if (p.equals(player)) {
+ return;
+ }
+
+ final Optional targetOptional = tabList.getTabPlayer(p);
+ if (targetOptional.isEmpty()) {
+ return;
+ }
+
+ final TabPlayer target = targetOptional.get();
+ final String serverName = target.getServerName();
+
+ if (plugin.getSettings().isOnlyListPlayersInSameGroup()
+ && !serversInGroup.contains(serverName)) {
+ return;
+ }
+
+ final boolean canSee = !plugin.getVanishManager().isVanished(p.getUsername()) ||
+ plugin.getVanishManager().canSee(player.getUsername(), p.getUsername());
+
+ if (!canSee) {
+ player.getTabList().removeEntry(p.getUniqueId());
+ plugin.getScoreboardManager().ifPresent(s -> s.recalculateVanishForPlayer(tabPlayer, target, false));
+ } else {
+ if (!player.getTabList().containsEntry(p.getUniqueId())) {
+ tabList.createEntry(target, player.getTabList()).thenAccept(e -> {
+ player.getTabList().addEntry(e);
+ plugin.getScoreboardManager().ifPresent(s -> s.recalculateVanishForPlayer(tabPlayer, target, true));
+ });
+ }
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/net/william278/velocitab/vanish/VanishManager.java b/src/main/java/net/william278/velocitab/vanish/VanishManager.java
index b566c6f..607b36d 100644
--- a/src/main/java/net/william278/velocitab/vanish/VanishManager.java
+++ b/src/main/java/net/william278/velocitab/vanish/VanishManager.java
@@ -60,8 +60,8 @@ public class VanishManager {
return;
}
- plugin.getTabList().vanishPlayer(tabPlayer.get());
- plugin.getScoreboardManager().ifPresent(scoreboardManager -> scoreboardManager.vanishPlayer(player));
+ plugin.getTabList().getVanishTabList().vanishPlayer(tabPlayer.get());
+ plugin.getScoreboardManager().ifPresent(scoreboardManager -> scoreboardManager.vanishPlayer(tabPlayer.get()));
}
public void unVanishPlayer(@NotNull Player player) {
@@ -71,7 +71,7 @@ public class VanishManager {
return;
}
- plugin.getTabList().unVanishPlayer(tabPlayer.get());
- plugin.getScoreboardManager().ifPresent(scoreboardManager -> scoreboardManager.unVanishPlayer(player));
+ plugin.getTabList().getVanishTabList().unVanishPlayer(tabPlayer.get());
+ plugin.getScoreboardManager().ifPresent(scoreboardManager -> scoreboardManager.unVanishPlayer(tabPlayer.get()));
}
}