fix: inconsistencies when players kicked/redirected on servers (#180)

Added onlyListPlayersInSameServer inside groups
Removed onlyListPlayersInSameGroup from config
Fixed problems with regex for servers
Fixed other problems
This commit is contained in:
AlexDev_ 2024-03-14 23:08:02 +01:00 committed by GitHub
parent 4e2749ac9e
commit 48b3b2af48
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 154 additions and 87 deletions

View File

@ -26,8 +26,6 @@ formatter: MINEDOWN
fallback_enabled: true fallback_enabled: true
# The formats to use for the fallback group. # The formats to use for the fallback group.
fallback_group: default fallback_group: default
# Only show other players on a server that is part of the same server group as the player.
only_list_players_in_same_group: true
# Define custom names to be shown in the TAB list for specific server names. # Define custom names to be shown in the TAB list for specific server names.
# If no custom display name is provided for a server, its original name will be used. # If no custom display name is provided for a server, its original name will be used.
server_display_names: server_display_names:
@ -79,18 +77,19 @@ groups:
prefix: '&f%prefix%' prefix: '&f%prefix%'
suffix: '&f%suffix%' suffix: '&f%suffix%'
servers: servers:
- lobby - ^lobby[^ ]*
- survival - survival
- creative - creative
- minigames - minigames
- skyblock - skyblock
- prison - prison
- hub
sorting_placeholders: sorting_placeholders:
- '%role_weight%' - '%role_weight%'
- '%username_lower%' - '%username_lower%'
collisions: false
header_footer_update_rate: 1000 header_footer_update_rate: 1000
placeholder_update_rate: 1000 placeholder_update_rate: 1000
only_list_players_in_same_server: false
``` ```
</details> </details>

View File

@ -27,6 +27,7 @@ import net.william278.velocitab.player.TabPlayer;
import net.william278.velocitab.tab.Nametag; import net.william278.velocitab.tab.Nametag;
import org.apache.commons.text.StringEscapeUtils; import org.apache.commons.text.StringEscapeUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.slf4j.event.Level;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -43,10 +44,11 @@ public record Group(
String format, String format,
Nametag nametag, Nametag nametag,
Set<String> servers, Set<String> servers,
Set<String> sortingPlaceholders, List<String> sortingPlaceholders,
boolean collisions, boolean collisions,
int headerFooterUpdateRate, int headerFooterUpdateRate,
int placeholderUpdateRate int placeholderUpdateRate,
boolean onlyListPlayersInSameServer
) { ) {
@NotNull @NotNull
@ -63,7 +65,7 @@ public record Group(
@NotNull @NotNull
public Set<RegisteredServer> registeredServers(@NotNull Velocitab plugin) { public Set<RegisteredServer> registeredServers(@NotNull Velocitab plugin) {
if (isDefault() && plugin.getSettings().isFallbackEnabled()) { if (isDefault(plugin) && plugin.getSettings().isFallbackEnabled()) {
return Sets.newHashSet(plugin.getServer().getAllServers()); return Sets.newHashSet(plugin.getServer().getAllServers());
} }
return getRegexServers(plugin); return getRegexServers(plugin);
@ -73,28 +75,21 @@ public record Group(
private Set<RegisteredServer> getRegexServers(@NotNull Velocitab plugin) { private Set<RegisteredServer> getRegexServers(@NotNull Velocitab plugin) {
final Set<RegisteredServer> totalServers = Sets.newHashSet(); final Set<RegisteredServer> totalServers = Sets.newHashSet();
for (String server : servers) { for (String server : servers) {
if (!server.contains("*") && !server.contains(".")) {
plugin.getServer().getServer(server).ifPresent(totalServers::add);
continue;
}
try { try {
final Matcher matcher = Pattern.compile(server final Matcher matcher = Pattern.compile(server, Pattern.CASE_INSENSITIVE).matcher("");
.replace(".", "\\.")
.replace("*", ".*"))
.matcher("");
plugin.getServer().getAllServers().stream() plugin.getServer().getAllServers().stream()
.filter(registeredServer -> matcher.reset(registeredServer.getServerInfo().getName()).matches()) .filter(registeredServer -> matcher.reset(registeredServer.getServerInfo().getName()).matches())
.forEach(totalServers::add); .forEach(totalServers::add);
} catch (PatternSyntaxException ignored) { } catch (PatternSyntaxException exception) {
plugin.log(Level.WARN, "Invalid regex pattern " + server + " in group " + name, exception);
plugin.getServer().getServer(server).ifPresent(totalServers::add); plugin.getServer().getServer(server).ifPresent(totalServers::add);
} }
} }
return totalServers; return totalServers;
} }
public boolean isDefault() { public boolean isDefault(@NotNull Velocitab plugin) {
return name.equals("default"); return name.equals(plugin.getSettings().getFallbackGroup());
} }
@NotNull @NotNull
@ -106,6 +101,16 @@ public record Group(
return players; return players;
} }
@NotNull
public Set<Player> getPlayers(@NotNull Velocitab plugin, @NotNull TabPlayer tabPlayer) {
if (onlyListPlayersInSameServer) {
return tabPlayer.getPlayer().getCurrentServer()
.map(s -> Sets.newHashSet(s.getServer().getPlayersConnected()))
.orElseGet(Sets::newHashSet);
}
return getPlayers(plugin);
}
@NotNull @NotNull
public Set<TabPlayer> getTabPlayers(@NotNull Velocitab plugin) { public Set<TabPlayer> getTabPlayers(@NotNull Velocitab plugin) {
return plugin.getTabList().getPlayers() return plugin.getTabList().getPlayers()
@ -115,6 +120,18 @@ public record Group(
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
@NotNull
public Set<TabPlayer> getTabPlayers(@NotNull Velocitab plugin, @NotNull TabPlayer tabPlayer) {
if (onlyListPlayersInSameServer) {
return plugin.getTabList().getPlayers()
.values()
.stream()
.filter(player -> player.getGroup().equals(this) && player.getServerName().equals(tabPlayer.getServerName()))
.collect(Collectors.toSet());
}
return getTabPlayers(plugin);
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof Group group)) { if (!(obj instanceof Group group)) {

View File

@ -63,9 +63,6 @@ public class Settings implements ConfigValidator {
@Comment("The formats to use for the fallback group.") @Comment("The formats to use for the fallback group.")
private String fallbackGroup = "default"; private String fallbackGroup = "default";
@Comment("Only show other players on a server that is part of the same server group as the player.")
private boolean onlyListPlayersInSameGroup = true;
@Comment("Define custom names to be shown in the TAB list for specific server names." @Comment("Define custom names to be shown in the TAB list for specific server names."
+ "\nIf no custom display name is provided for a server, its original name will be used.") + "\nIf no custom display name is provided for a server, its original name will be used.")
private Map<String, String> serverDisplayNames = Map.of("very-long-server-name", "VLSN"); private Map<String, String> serverDisplayNames = Map.of("very-long-server-name", "VLSN");

View File

@ -53,10 +53,11 @@ public class TabGroups implements ConfigValidator {
"&7[%server%] &f%prefix%%username%", "&7[%server%] &f%prefix%%username%",
new Nametag("&f%prefix%", "&f%suffix%"), new Nametag("&f%prefix%", "&f%suffix%"),
Set.of("lobby", "survival", "creative", "minigames", "skyblock", "prison", "hub"), Set.of("lobby", "survival", "creative", "minigames", "skyblock", "prison", "hub"),
Set.of("%role_weight%", "%username_lower%"), List.of("%role_weight%", "%username_lower%"),
false, false,
1000, 1000,
1000 1000,
false
); );
public List<Group> groups = List.of(DEFAULT_GROUP); public List<Group> groups = List.of(DEFAULT_GROUP);
@ -77,9 +78,20 @@ public class TabGroups implements ConfigValidator {
} }
@NotNull @NotNull
public Group getGroupFromServer(@NotNull String server) { public Group getGroupFromServer(@NotNull String server, @NotNull Velocitab plugin) {
final List<Group> groups = new ArrayList<>(this.groups);
final Optional<Group> defaultGroup = getGroup("default");
// Ensure the default group is always checked last
if (defaultGroup.isPresent()) {
groups.remove(defaultGroup.get());
groups.add(defaultGroup.get());
} else {
throw new IllegalStateException("No default group found");
}
for (Group group : groups) { for (Group group : groups) {
if (group.servers().contains(server)) { if (group.registeredServers(plugin)
.stream()
.anyMatch(s -> s.getServerInfo().getName().equalsIgnoreCase(server))) {
return group; return group;
} }
} }
@ -101,7 +113,6 @@ public class TabGroups implements ConfigValidator {
} }
final Multimap<Group, String> missingKeys = getMissingKeys(); final Multimap<Group, String> missingKeys = getMissingKeys();
if (missingKeys.isEmpty()) { if (missingKeys.isEmpty()) {
return; return;
} }
@ -148,7 +159,8 @@ public class TabGroups implements ConfigValidator {
group.sortingPlaceholders() == null ? DEFAULT_GROUP.sortingPlaceholders() : group.sortingPlaceholders(), group.sortingPlaceholders() == null ? DEFAULT_GROUP.sortingPlaceholders() : group.sortingPlaceholders(),
group.collisions(), group.collisions(),
group.headerFooterUpdateRate(), group.headerFooterUpdateRate(),
group.placeholderUpdateRate() group.placeholderUpdateRate(),
group.onlyListPlayersInSameServer()
); );
groups.add(group); groups.add(group);

View File

@ -175,13 +175,9 @@ public class ScoreboardManager {
} }
final Player player = tabPlayer.getPlayer(); final Player player = tabPlayer.getPlayer();
final Set<RegisteredServer> siblings = tabPlayer.getGroup().registeredServers(plugin); final Set<Player> players = tabPlayer.getGroup().getPlayers(plugin, tabPlayer);
final List<Player> players = siblings.stream()
.map(RegisteredServer::getPlayersConnected)
.flatMap(Collection::stream)
.toList();
final List<String> roles = new ArrayList<>(); final Set<String> roles = Sets.newHashSet();
players.forEach(p -> { players.forEach(p -> {
if (p == player || !p.isActive()) { if (p == player || !p.isActive()) {
return; return;
@ -253,8 +249,8 @@ public class ScoreboardManager {
return; return;
} }
final Set<RegisteredServer> siblings = tabPlayer.getGroup().registeredServers(plugin); final Set<Player> players = tabPlayer.getGroup().getPlayers(plugin);
siblings.forEach(server -> server.getPlayersConnected().forEach(connected -> { players.forEach(connected -> {
try { try {
final boolean canSee = plugin.getVanishManager().canSee(connected.getUsername(), player.getUsername()); final boolean canSee = plugin.getVanishManager().canSee(connected.getUsername(), player.getUsername());
if (!canSee) { if (!canSee) {
@ -266,7 +262,7 @@ public class ScoreboardManager {
} catch (Throwable e) { } catch (Throwable e) {
plugin.log(Level.ERROR, "Failed to dispatch packet (unsupported client or server version)", e); plugin.log(Level.ERROR, "Failed to dispatch packet (unsupported client or server version)", e);
} }
})); });
} }
public void registerPacket() { public void registerPacket() {

View File

@ -19,7 +19,6 @@
package net.william278.velocitab.tab; package net.william278.velocitab.tab;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.ServerConnection;
@ -37,7 +36,9 @@ import net.william278.velocitab.config.Group;
import net.william278.velocitab.config.Placeholder; import net.william278.velocitab.config.Placeholder;
import net.william278.velocitab.player.Role; import net.william278.velocitab.player.Role;
import net.william278.velocitab.player.TabPlayer; import net.william278.velocitab.player.TabPlayer;
import org.apache.commons.lang3.ObjectUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.event.Level; import org.slf4j.event.Level;
import java.util.*; import java.util.*;
@ -97,11 +98,13 @@ public class PlayerTabList {
public void load() { public void load() {
plugin.getServer().getAllPlayers().forEach(p -> { plugin.getServer().getAllPlayers().forEach(p -> {
final Optional<ServerConnection> server = p.getCurrentServer(); final Optional<ServerConnection> server = p.getCurrentServer();
if (server.isEmpty()) return; if (server.isEmpty()) {
return;
}
final String serverName = server.get().getServerInfo().getName(); final String serverName = server.get().getServerInfo().getName();
final Group group = getGroup(serverName); final Group group = getGroup(serverName);
final boolean isDefault = !group.servers().contains(serverName); final boolean isDefault = group.registeredServers(plugin).stream().noneMatch(s -> s.getServerInfo().getName().equals(serverName));
if (isDefault && !plugin.getSettings().isFallbackEnabled()) { if (isDefault && !plugin.getSettings().isFallbackEnabled()) {
return; return;
@ -146,12 +149,12 @@ public class PlayerTabList {
tabPlayer.setGroup(group); tabPlayer.setGroup(group);
players.putIfAbsent(joined.getUniqueId(), tabPlayer); players.putIfAbsent(joined.getUniqueId(), tabPlayer);
final String serverName = getServerName(joined);
//store last server, so it's possible to have the last server on disconnect //store last server, so it's possible to have the last server on disconnect
tabPlayer.setLastServer(joined.getCurrentServer().map(ServerConnection::getServerInfo).map(ServerInfo::getName).orElse("")); tabPlayer.setLastServer(serverName);
final boolean isVanished = plugin.getVanishManager().isVanished(joined.getUsername()); final boolean isVanished = plugin.getVanishManager().isVanished(joined.getUsername());
final boolean isDefault = group.isDefault();
final boolean isFallback = isDefault && plugin.getSettings().isFallbackEnabled();
tabPlayer.getDisplayName(plugin).thenAccept(d -> { tabPlayer.getDisplayName(plugin).thenAccept(d -> {
@ -167,16 +170,20 @@ public class PlayerTabList {
return null; return null;
}); });
final Set<String> serversInGroup = group.registeredServers(plugin).stream()
.map(server -> server.getServerInfo().getName())
.collect(HashSet::new, HashSet::add, HashSet::addAll);
serversInGroup.remove(serverName);
// Update lists // Update lists
plugin.getServer().getScheduler() plugin.getServer().getScheduler()
.buildTask(plugin, () -> { .buildTask(plugin, () -> {
final TabList tabList = joined.getTabList(); final TabList tabList = joined.getTabList();
for (final TabPlayer player : players.values()) { final Set<TabPlayer> tabPlayers = group.getTabPlayers(plugin);
for (final TabPlayer player : tabPlayers) {
// Skip players on other servers if the setting is enabled // Skip players on other servers if the setting is enabled
if (plugin.getSettings().isOnlyListPlayersInSameGroup() if (group.onlyListPlayersInSameServer() && !serverName.equals(getServerName(player.getPlayer()))) {
&& !isFallback &&
!group.servers().contains(player.getServerName())
) {
continue; continue;
} }
// check if current player can see the joined player // check if current player can see the joined player
@ -187,7 +194,8 @@ public class PlayerTabList {
} }
// check if joined player can see current player // check if joined player can see current player
if ((plugin.getVanishManager().isVanished(player.getPlayer().getUsername()) && if ((plugin.getVanishManager().isVanished(player.getPlayer().getUsername()) &&
!plugin.getVanishManager().canSee(joined.getUsername(), player.getPlayer().getUsername())) && player.getPlayer() != joined) { !plugin.getVanishManager().canSee(joined.getUsername(), player.getPlayer().getUsername())) &&
player.getPlayer() != joined) {
tabList.removeEntry(player.getPlayer().getUniqueId()); tabList.removeEntry(player.getPlayer().getUniqueId());
} else { } else {
tabList.getEntry(player.getPlayer().getUniqueId()).ifPresentOrElse( tabList.getEntry(player.getPlayer().getUniqueId()).ifPresentOrElse(
@ -221,16 +229,35 @@ public class PlayerTabList {
}); });
} }
@NotNull
private String getServerName(@NotNull Player player) {
return player.getCurrentServer()
.map(serverConnection -> serverConnection.getServerInfo().getName())
.orElse("");
}
protected void removePlayer(@NotNull Player target) { protected void removePlayer(@NotNull Player target) {
removePlayer(target, null);
}
protected void removePlayer(@NotNull Player target, @Nullable RegisteredServer server) {
final UUID uuid = target.getUniqueId(); final UUID uuid = target.getUniqueId();
plugin.getServer().getAllPlayers().forEach(player -> player.getTabList().removeEntry(uuid)); plugin.getServer().getAllPlayers().forEach(player -> player.getTabList().removeEntry(uuid));
final Set<Player> currentServerPlayers = Optional.ofNullable(server)
.map(RegisteredServer::getPlayersConnected)
.map(HashSet::new)
.orElseGet(HashSet::new);
currentServerPlayers.add(target);
// Update the tab list of all players // Update the tab list of all players
plugin.getServer().getScheduler() plugin.getServer().getScheduler()
.buildTask(plugin, () -> getPlayers().values().forEach(player -> { .buildTask(plugin, () -> getPlayers().values().stream()
player.getPlayer().getTabList().removeEntry(uuid); .filter(p -> currentServerPlayers.isEmpty() || !currentServerPlayers.contains(p.getPlayer()))
player.sendHeaderAndFooter(this); .forEach(player -> {
})) player.getPlayer().getTabList().removeEntry(uuid);
player.sendHeaderAndFooter(this);
}))
.delay(500, TimeUnit.MILLISECONDS) .delay(500, TimeUnit.MILLISECONDS)
.schedule(); .schedule();
// Delete player team // Delete player team
@ -240,20 +267,15 @@ public class PlayerTabList {
} }
@NotNull @NotNull
CompletableFuture<TabListEntry> createEntry(@NotNull TabPlayer player, @NotNull TabList tabList) { protected CompletableFuture<TabListEntry> createEntry(@NotNull TabPlayer player, @NotNull TabList tabList) {
return player.getDisplayName(plugin).thenApply(name -> TabListEntry.builder() return player.getDisplayName(plugin).thenApply(name -> createEntry(player, tabList, name));
.profile(player.getPlayer().getGameProfile())
.displayName(name)
.latency(0)
.tabList(tabList)
.build());
} }
protected TabListEntry createEntry(@NotNull TabPlayer player, @NotNull TabList tabList, @NotNull Component displayName) { protected TabListEntry createEntry(@NotNull TabPlayer player, @NotNull TabList tabList, @NotNull Component displayName) {
return TabListEntry.builder() return TabListEntry.builder()
.profile(player.getPlayer().getGameProfile()) .profile(player.getPlayer().getGameProfile())
.displayName(displayName) .displayName(displayName)
.latency(0) .latency(Math.max((int) player.getPlayer().getPing(), 0))
.tabList(tabList) .tabList(tabList)
.build(); .build();
} }
@ -314,15 +336,19 @@ public class PlayerTabList {
} }
final boolean isVanished = plugin.getVanishManager().isVanished(tabPlayer.getPlayer().getUsername()); final boolean isVanished = plugin.getVanishManager().isVanished(tabPlayer.getPlayer().getUsername());
final Set<TabPlayer> players = tabPlayer.getGroup().getTabPlayers(plugin, tabPlayer);
players.values().forEach(player -> { players.forEach(player -> {
if (isVanished && !plugin.getVanishManager().canSee(player.getPlayer().getUsername(), tabPlayer.getPlayer().getUsername())) { if (isVanished && !plugin.getVanishManager().canSee(player.getPlayer().getUsername(), tabPlayer.getPlayer().getUsername())) {
return; return;
} }
player.getPlayer().getTabList().getEntries().stream() player.getPlayer().getTabList().getEntries().stream()
.filter(e -> e.getProfile().getId().equals(tabPlayer.getPlayer().getUniqueId())).findFirst() .filter(e -> e.getProfile().getId().equals(tabPlayer.getPlayer().getUniqueId())).findFirst()
.ifPresent(entry -> entry.setDisplayName(displayName)); .ifPresent(entry -> {
entry.setDisplayName(displayName);
entry.setLatency(Math.max((int) tabPlayer.getPlayer().getPing(), 0));
});
}); });
}); });
} }
@ -379,7 +405,7 @@ public class PlayerTabList {
* @param incrementIndexes Whether to increment the header and footer indexes. * @param incrementIndexes Whether to increment the header and footer indexes.
*/ */
private void updateGroupPlayers(@NotNull Group group, boolean all, boolean incrementIndexes) { private void updateGroupPlayers(@NotNull Group group, boolean all, boolean incrementIndexes) {
Set<TabPlayer> groupPlayers = group.getTabPlayers(plugin); final Set<TabPlayer> groupPlayers = group.getTabPlayers(plugin);
if (groupPlayers.isEmpty()) { if (groupPlayers.isEmpty()) {
return; return;
} }
@ -449,7 +475,7 @@ public class PlayerTabList {
@NotNull @NotNull
public Group getGroup(@NotNull String serverName) { public Group getGroup(@NotNull String serverName) {
return plugin.getTabGroups().getGroupFromServer(serverName); return plugin.getTabGroups().getGroupFromServer(serverName, plugin);
} }

View File

@ -19,6 +19,7 @@
package net.william278.velocitab.tab; package net.william278.velocitab.tab;
import com.google.common.collect.Sets;
import com.velocitypowered.api.event.PostOrder; import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.DisconnectEvent; import com.velocitypowered.api.event.connection.DisconnectEvent;
@ -35,6 +36,7 @@ import net.william278.velocitab.player.TabPlayer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -46,20 +48,34 @@ public class TabListListener {
private final Velocitab plugin; private final Velocitab plugin;
private final PlayerTabList tabList; private final PlayerTabList tabList;
// In 1.8 there is a packet delay problem
private final Set<UUID> justQuit;
public TabListListener(@NotNull Velocitab plugin, @NotNull PlayerTabList tabList) { public TabListListener(@NotNull Velocitab plugin, @NotNull PlayerTabList tabList) {
this.plugin = plugin; this.plugin = plugin;
this.tabList = tabList; this.tabList = tabList;
this.justQuit = Sets.newConcurrentHashSet();
} }
@Subscribe @Subscribe
public void onKick(@NotNull KickedFromServerEvent event) { public void onKick(@NotNull KickedFromServerEvent event) {
event.getPlayer().getTabList().clearAll(); event.getPlayer().getTabList().getEntries().stream()
.filter(entry -> entry.getProfile() != null && !entry.getProfile().getId().equals(event.getPlayer().getUniqueId()))
.forEach(entry -> event.getPlayer().getTabList().removeEntry(entry.getProfile().getId()));
event.getPlayer().getTabList().clearHeaderAndFooter(); event.getPlayer().getTabList().clearHeaderAndFooter();
if (event.getResult() instanceof KickedFromServerEvent.DisconnectPlayer || event.getResult() instanceof KickedFromServerEvent.RedirectPlayer) { if (event.getResult() instanceof KickedFromServerEvent.DisconnectPlayer) {
tabList.removePlayer(event.getPlayer()); tabList.removePlayer(event.getPlayer());
} else if (event.getResult() instanceof KickedFromServerEvent.RedirectPlayer redirectPlayer) {
tabList.removePlayer(event.getPlayer(), redirectPlayer.getServer());
} }
justQuit.add(event.getPlayer().getUniqueId());
plugin.getServer().getScheduler().buildTask(plugin,
() -> justQuit.remove(event.getPlayer().getUniqueId()))
.delay(300, TimeUnit.MILLISECONDS)
.schedule();
} }
@SuppressWarnings("UnstableApiUsage") @SuppressWarnings("UnstableApiUsage")
@ -73,7 +89,8 @@ public class TabListListener {
.orElse(""); .orElse("");
final Group group = tabList.getGroup(serverName); final Group group = tabList.getGroup(serverName);
plugin.getScoreboardManager().ifPresent(manager -> manager.resetCache(joined, group)); plugin.getScoreboardManager().ifPresent(manager -> manager.resetCache(joined, group));
final boolean isDefault = !group.servers().contains(serverName); final boolean isDefault = group.registeredServers(plugin).stream()
.noneMatch(server -> server.getServerInfo().getName().equalsIgnoreCase(serverName));
// If the server is not in a group, use fallback. // 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 fallback is disabled, permit the player to switch excluded servers without a header or footer override
@ -92,15 +109,15 @@ public class TabListListener {
final Component displayName = tabPlayer.get().getLastDisplayName(); final Component displayName = tabPlayer.get().getLastDisplayName();
plugin.getServer().getScheduler().buildTask(plugin, () -> { plugin.getServer().getScheduler().buildTask(plugin, () -> {
if (header.equals(event.getPlayer().getPlayerListHeader()) && footer.equals(event.getPlayer().getPlayerListFooter())) { final Component currentHeader = joined.getPlayerListHeader();
event.getPlayer().sendPlayerListHeaderAndFooter(header, footer); final Component currentFooter = joined.getPlayerListFooter();
event.getPlayer().getCurrentServer().ifPresent(serverConnection -> if ((header.equals(currentHeader) && footer.equals(currentFooter)) ||
serverConnection.getServer().getPlayersConnected().forEach(player -> (currentHeader.equals(Component.empty()) && currentFooter.equals(Component.empty()))
player.getTabList().getEntry(joined.getUniqueId()).ifPresent(entry -> { ) {
if (entry.getDisplayNameComponent().isPresent() && entry.getDisplayNameComponent().get().equals(displayName)) { joined.sendPlayerListHeaderAndFooter(Component.empty(), Component.empty());
entry.setDisplayName(Component.text(joined.getUsername())); joined.getCurrentServer().ifPresent(serverConnection -> serverConnection.getServer().getPlayersConnected().forEach(player ->
} player.getTabList().getEntry(joined.getUniqueId())
}))); .ifPresent(entry -> entry.setDisplayName(Component.text(joined.getUsername())))));
} }
}).delay(500, TimeUnit.MILLISECONDS).schedule(); }).delay(500, TimeUnit.MILLISECONDS).schedule();
@ -108,6 +125,14 @@ public class TabListListener {
return; return;
} }
if (justQuit.contains(joined.getUniqueId())) {
plugin.getServer().getScheduler().buildTask(plugin,
() -> tabList.joinPlayer(joined, group))
.delay(250, TimeUnit.MILLISECONDS)
.schedule();
return;
}
tabList.joinPlayer(joined, group); tabList.joinPlayer(joined, group);
} }
@ -118,9 +143,6 @@ public class TabListListener {
return; return;
} }
// Remove the player from the tracking list, Print warning if player was not removed
final UUID uuid = event.getPlayer().getUniqueId();
// Remove the player from the tab list of all other players // Remove the player from the tab list of all other players
tabList.removePlayer(event.getPlayer()); tabList.removePlayer(event.getPlayer());
} }

View File

@ -27,15 +27,16 @@ import org.jetbrains.annotations.NotNull;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
/** /**
* The VanishTabList handles the tab list for vanished players * The VanishTabList handles the tab list for vanished players
*/ */
public class VanishTabList { public class VanishTabList {
private final Velocitab plugin; private final Velocitab plugin;
private final PlayerTabList tabList; private final PlayerTabList tabList;
public VanishTabList(Velocitab plugin, PlayerTabList tabList) { public VanishTabList(Velocitab plugin, PlayerTabList tabList) {
this.plugin = plugin; this.plugin = plugin;
this.tabList = tabList; this.tabList = tabList;
@ -79,8 +80,6 @@ public class VanishTabList {
*/ */
public void recalculateVanishForPlayer(@NotNull TabPlayer tabPlayer) { public void recalculateVanishForPlayer(@NotNull TabPlayer tabPlayer) {
final Player player = tabPlayer.getPlayer(); final Player player = tabPlayer.getPlayer();
final Set<String> serversInGroup = tabPlayer.getGroup().servers();
plugin.getServer().getAllPlayers().forEach(p -> { plugin.getServer().getAllPlayers().forEach(p -> {
if (p.equals(player)) { if (p.equals(player)) {
return; return;
@ -94,8 +93,8 @@ public class VanishTabList {
final TabPlayer target = targetOptional.get(); final TabPlayer target = targetOptional.get();
final String serverName = target.getServerName(); final String serverName = target.getServerName();
if (plugin.getSettings().isOnlyListPlayersInSameGroup() if (tabPlayer.getGroup().onlyListPlayersInSameServer()
&& !serversInGroup.contains(serverName)) { && !tabPlayer.getServerName().equals(serverName)) {
return; return;
} }
@ -115,5 +114,4 @@ public class VanishTabList {
} }
}); });
} }
} }