Skip to content

Commit

Permalink
Added regex system and fixed ghost players bug (#176)
Browse files Browse the repository at this point in the history
* Added regex system for TabGroup's servers.
Fixed ghost player after kick/disconnect.

* Fixed config docs with missing entries

* Bumped version
  • Loading branch information
alexdev03 authored Mar 11, 2024
1 parent c0abf48 commit 4e2749a
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 37 deletions.
9 changes: 8 additions & 1 deletion docs/Config-File.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ The config file is located in `/plugins/velocitab/config.yml` and the tab groups
check_for_updates: true
# Whether to remove nametag from players' heads if the nametag associated with their server group is empty.
remove_nametags: true
# Whether to disable header and footer if they are empty and let backend servers handle them.
disable_header_footer_if_empty: true
# Which text formatter to use (MINEDOWN, MINIMESSAGE, or LEGACY)
formatter: MINEDOWN
# All servers which are not in other groups will be put in the fallback group.
Expand All @@ -33,16 +35,21 @@ server_display_names:
# Whether to enable the PAPIProxyBridge hook for PAPI support
enable_papi_hook: true
# How long in seconds to cache PAPI placeholders for, in milliseconds. (0 to disable)
papi_cache_time: 200
papi_cache_time: 30000
# If you are using MINIMESSAGE formatting, enable this to support MiniPlaceholders in formatting.
enable_mini_placeholders_hook: true
# Whether to send scoreboard teams packets. Required for player list sorting and nametag formatting.
# Turn this off if you're using scoreboard teams on backend servers.
send_scoreboard_packets: true
# If built-in placeholders return a blank string, fallback to Placeholder API equivalents.
# For example, if %prefix% returns a blank string, use %luckperms_prefix%. Requires PAPIProxyBridge.
fallback_to_papi_if_placeholder_blank: false
# Whether to sort players in the TAB list.
sort_players: true
# Remove gamemode spectator effect for other players in the TAB list.
remove_spectator_effect: false
# Whether to enable the Plugin Message API (allows backend plugins to perform certain operations)
enable_plugin_message_api: true
```
</details>
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ javaVersion=17
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
org.gradle.daemon=true

plugin_version=1.6.3
plugin_version=1.6.4
plugin_archive=velocitab
plugin_description=A beautiful and versatile TAB list plugin for Velocity proxies

Expand Down
54 changes: 39 additions & 15 deletions src/main/java/net/william278/velocitab/config/Group.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package net.william278.velocitab.config;

import com.google.common.collect.Sets;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import net.william278.velocitab.Velocitab;
Expand All @@ -27,9 +28,12 @@
import org.apache.commons.text.StringEscapeUtils;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;

@SuppressWarnings("unused")
public record Group(
Expand All @@ -38,8 +42,8 @@ public record Group(
List<String> footers,
String format,
Nametag nametag,
List<String> servers,
List<String> sortingPlaceholders,
Set<String> servers,
Set<String> sortingPlaceholders,
boolean collisions,
int headerFooterUpdateRate,
int placeholderUpdateRate
Expand All @@ -58,37 +62,57 @@ public String getFooter(int index) {
}

@NotNull
public List<RegisteredServer> registeredServers(Velocitab plugin) {
public Set<RegisteredServer> registeredServers(@NotNull Velocitab plugin) {
if (isDefault() && plugin.getSettings().isFallbackEnabled()) {
return new ArrayList<>(plugin.getServer().getAllServers());
return Sets.newHashSet(plugin.getServer().getAllServers());
}
return servers.stream()
.map(plugin.getServer()::getServer)
.filter(Optional::isPresent)
.map(Optional::get)
.toList();
return getRegexServers(plugin);
}

@NotNull
private Set<RegisteredServer> getRegexServers(@NotNull Velocitab plugin) {
final Set<RegisteredServer> totalServers = Sets.newHashSet();
for (String server : servers) {
if (!server.contains("*") && !server.contains(".")) {
plugin.getServer().getServer(server).ifPresent(totalServers::add);
continue;
}

try {
final Matcher matcher = Pattern.compile(server
.replace(".", "\\.")
.replace("*", ".*"))
.matcher("");
plugin.getServer().getAllServers().stream()
.filter(registeredServer -> matcher.reset(registeredServer.getServerInfo().getName()).matches())
.forEach(totalServers::add);
} catch (PatternSyntaxException ignored) {
plugin.getServer().getServer(server).ifPresent(totalServers::add);
}
}
return totalServers;
}

public boolean isDefault() {
return name.equals("default");
}

@NotNull
public List<Player> getPlayers(Velocitab plugin) {
List<Player> players = new ArrayList<>();
public Set<Player> getPlayers(@NotNull Velocitab plugin) {
Set<Player> players = Sets.newHashSet();
for (RegisteredServer server : registeredServers(plugin)) {
players.addAll(server.getPlayersConnected());
}
return players;
}

@NotNull
public List<TabPlayer> getTabPlayers(Velocitab plugin) {
public Set<TabPlayer> getTabPlayers(@NotNull Velocitab plugin) {
return plugin.getTabList().getPlayers()
.values()
.stream()
.filter(tabPlayer -> tabPlayer.getGroup().equals(this))
.toList();
.collect(Collectors.toSet());
}

@Override
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/net/william278/velocitab/config/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public class Settings implements ConfigValidator {
@Comment("Whether to remove nametag from players' heads if the nametag associated with their server group is empty.")
private boolean removeNametags = false;

@Comment("Whether to disable header and footer if they are empty and let backend servers handle them.")
private boolean disableHeaderFooterIfEmpty = true;

@Comment("Which text formatter to use (MINEDOWN, MINIMESSAGE, or LEGACY)")
private Formatter formatter = Formatter.MINEDOWN;

Expand Down
12 changes: 5 additions & 7 deletions src/main/java/net/william278/velocitab/config/TabGroups.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package net.william278.velocitab.config;

import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import de.exlll.configlib.Configuration;
Expand All @@ -29,10 +30,7 @@
import net.william278.velocitab.tab.Nametag;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.*;

@SuppressWarnings("FieldMayBeFinal")
@Getter
Expand All @@ -54,8 +52,8 @@ public class TabGroups implements ConfigValidator {
List.of("[There are currently %players_online%/%max_players_online% players online](gray)"),
"&7[%server%] &f%prefix%%username%",
new Nametag("&f%prefix%", "&f%suffix%"),
List.of("lobby", "survival", "creative", "minigames", "skyblock", "prison", "hub"),
List.of("%role_weight%", "%username_lower%"),
Set.of("lobby", "survival", "creative", "minigames", "skyblock", "prison", "hub"),
Set.of("%role_weight%", "%username_lower%"),
false,
1000,
1000
Expand Down Expand Up @@ -113,7 +111,7 @@ public void validateConfig(@NotNull Velocitab plugin) {

@NotNull
private Multimap<Group, String> getMissingKeys() {
final Multimap<Group, String> missingKeys = Multimaps.newSetMultimap(new HashMap<>(), HashSet::new);
final Multimap<Group, String> missingKeys = Multimaps.newSetMultimap(Maps.newHashMap(), HashSet::new);

for (Group group : groups) {
if (group.format() == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ private void handleVanish(@NotNull TabPlayer tabPlayer, boolean vanish) {
if (teamName == null) {
return;
}
final List<RegisteredServer> siblings = tabPlayer.getGroup().registeredServers(plugin);
final Set<RegisteredServer> siblings = tabPlayer.getGroup().registeredServers(plugin);

final Optional<Nametag> cachedTag = Optional.ofNullable(nametags.getOrDefault(teamName, null));
cachedTag.ifPresent(nametag -> {
Expand Down Expand Up @@ -175,7 +175,7 @@ public void resendAllTeams(@NotNull TabPlayer tabPlayer) {
}

final Player player = tabPlayer.getPlayer();
final List<RegisteredServer> siblings = tabPlayer.getGroup().registeredServers(plugin);
final Set<RegisteredServer> siblings = tabPlayer.getGroup().registeredServers(plugin);
final List<Player> players = siblings.stream()
.map(RegisteredServer::getPlayersConnected)
.flatMap(Collection::stream)
Expand Down Expand Up @@ -253,7 +253,7 @@ private void dispatchGroupPacket(@NotNull UpdateTeamsPacket packet, @NotNull Tab
return;
}

final List<RegisteredServer> siblings = tabPlayer.getGroup().registeredServers(plugin);
final Set<RegisteredServer> siblings = tabPlayer.getGroup().registeredServers(plugin);
siblings.forEach(server -> server.getPlayersConnected().forEach(connected -> {
try {
final boolean canSee = plugin.getVanishManager().canSee(connected.getUsername(), player.getUsername());
Expand Down
24 changes: 19 additions & 5 deletions src/main/java/net/william278/velocitab/player/TabPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
@ToString
public final class TabPlayer implements Comparable<TabPlayer> {

private final Velocitab plugin;
private final Player player;
@Setter
private Role role;
Expand All @@ -65,7 +66,9 @@ public final class TabPlayer implements Comparable<TabPlayer> {
@Setter
private boolean loaded;

public TabPlayer(@NotNull Player player, @NotNull Role role, @NotNull Group group) {
public TabPlayer(@NotNull Velocitab plugin, @NotNull Player player,
@NotNull Role role, @NotNull Group group) {
this.plugin = plugin;
this.player = player;
this.role = role;
this.group = group;
Expand Down Expand Up @@ -134,12 +137,23 @@ public Optional<String> getLastTeamName() {
}

public CompletableFuture<Void> sendHeaderAndFooter(@NotNull PlayerTabList tabList) {
return tabList.getHeader(this).thenCompose(header -> tabList.getFooter(this)
.thenAccept(footer -> {
return tabList.getHeader(this).thenCompose(header -> tabList.getFooter(this).thenAccept(footer -> {
final boolean disabled = plugin.getSettings().isDisableHeaderFooterIfEmpty();
if (disabled) {
if (!Component.empty().equals(header)) {
lastHeader = header;
player.sendPlayerListHeader(header);
}
if (!Component.empty().equals(footer)) {
lastFooter = footer;
player.sendPlayerListHeaderAndFooter(header, footer);
}));
player.sendPlayerListFooter(footer);
}
} else {
lastHeader = header;
lastFooter = footer;
player.sendPlayerListHeaderAndFooter(header, footer);
}
}));
}

public void incrementIndexes() {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/net/william278/velocitab/tab/PlayerTabList.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public void close() {
return;
}

final List<RegisteredServer> serversInGroup = Lists.newArrayList(tabPlayer.getGroup().registeredServers(plugin));
final Set<RegisteredServer> serversInGroup = tabPlayer.getGroup().registeredServers(plugin);
if (serversInGroup.isEmpty()) {
return;
}
Expand Down Expand Up @@ -283,7 +283,7 @@ private void addPlayerToTabList(@NotNull TabPlayer player, @NotNull TabPlayer ne

@NotNull
public TabPlayer createTabPlayer(@NotNull Player player, @NotNull Group group) {
return new TabPlayer(player,
return new TabPlayer(plugin, player,
plugin.getLuckPermsHook().map(hook -> hook.getPlayerRole(player)).orElse(Role.DEFAULT_ROLE),
group
);
Expand Down Expand Up @@ -379,7 +379,7 @@ private void updatePeriodically(Group group) {
* @param incrementIndexes Whether to increment the header and footer indexes.
*/
private void updateGroupPlayers(@NotNull Group group, boolean all, boolean incrementIndexes) {
List<TabPlayer> groupPlayers = group.getTabPlayers(plugin);
Set<TabPlayer> groupPlayers = group.getTabPlayers(plugin);
if (groupPlayers.isEmpty()) {
return;
}
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/net/william278/velocitab/tab/TabListListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ public void onPlayerJoin(@NotNull ServerPostConnectEvent event) {
@Subscribe(order = PostOrder.LAST)
public void onPlayerQuit(@NotNull DisconnectEvent event) {
if (event.getLoginStatus() != DisconnectEvent.LoginStatus.SUCCESSFUL_LOGIN) {
checkDelayedDisconnect(event);
return;
}

Expand All @@ -124,6 +125,21 @@ public void onPlayerQuit(@NotNull DisconnectEvent event) {
tabList.removePlayer(event.getPlayer());
}

private void checkDelayedDisconnect(@NotNull DisconnectEvent event) {
final Player player = event.getPlayer();
plugin.getServer().getScheduler().buildTask(plugin, () -> {
final Optional<Player> actualPlayer = plugin.getServer().getPlayer(player.getUniqueId());
if (actualPlayer.isPresent() && !actualPlayer.get().equals(player)) {
return;
}
if (player.getCurrentServer().isPresent()) {
return;
}
tabList.removePlayer(player);
plugin.log("Player " + player.getUsername() + " was not removed from the tab list, removing now.");
}).delay(500, TimeUnit.MILLISECONDS).schedule();
}

@Subscribe
public void proxyReload(@NotNull ProxyReloadEvent event) {
plugin.loadConfigs();
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/net/william278/velocitab/tab/VanishTabList.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
import net.william278.velocitab.player.TabPlayer;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;

/**
Expand Down Expand Up @@ -79,7 +79,7 @@ public void unVanishPlayer(@NotNull TabPlayer tabPlayer) {
*/
public void recalculateVanishForPlayer(@NotNull TabPlayer tabPlayer) {
final Player player = tabPlayer.getPlayer();
final List<String> serversInGroup = tabPlayer.getGroup().servers();
final Set<String> serversInGroup = tabPlayer.getGroup().servers();

plugin.getServer().getAllPlayers().forEach(p -> {
if (p.equals(player)) {
Expand Down

0 comments on commit 4e2749a

Please sign in to comment.