forked from Upstream/Velocitab
feat: add show_all_players_from_all_groups
config option (#183)
Code refactor Improved system that handles latency
This commit is contained in:
parent
5b5e40e7f8
commit
b7c353a0ec
@ -26,6 +26,8 @@ formatter: MINEDOWN
|
||||
fallback_enabled: true
|
||||
# The formats to use for the fallback group.
|
||||
fallback_group: default
|
||||
# Whether to show all players from all groups in the TAB list.
|
||||
show_all_players_from_all_groups: false
|
||||
# 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.
|
||||
server_display_names:
|
||||
|
@ -27,6 +27,7 @@ import net.william278.velocitab.player.TabPlayer;
|
||||
import net.william278.velocitab.tab.Nametag;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.event.Level;
|
||||
|
||||
import java.util.List;
|
||||
@ -65,7 +66,13 @@ public record Group(
|
||||
|
||||
@NotNull
|
||||
public Set<RegisteredServer> registeredServers(@NotNull Velocitab plugin) {
|
||||
if (isDefault(plugin) && plugin.getSettings().isFallbackEnabled()) {
|
||||
return registeredServers(plugin, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<RegisteredServer> registeredServers(@NotNull Velocitab plugin, boolean includeAllPlayers) {
|
||||
if ((includeAllPlayers && plugin.getSettings().isShowAllPlayersFromAllGroups()) ||
|
||||
(isDefault(plugin) && plugin.getSettings().isFallbackEnabled())) {
|
||||
return Sets.newHashSet(plugin.getServer().getAllServers());
|
||||
}
|
||||
return getRegexServers(plugin);
|
||||
@ -103,6 +110,9 @@ public record Group(
|
||||
|
||||
@NotNull
|
||||
public Set<Player> getPlayers(@NotNull Velocitab plugin, @NotNull TabPlayer tabPlayer) {
|
||||
if (plugin.getSettings().isShowAllPlayersFromAllGroups()) {
|
||||
return Sets.newHashSet(plugin.getServer().getAllPlayers());
|
||||
}
|
||||
if (onlyListPlayersInSameServer) {
|
||||
return tabPlayer.getPlayer().getCurrentServer()
|
||||
.map(s -> Sets.newHashSet(s.getServer().getPlayersConnected()))
|
||||
@ -111,8 +121,18 @@ public record Group(
|
||||
return getPlayers(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the set of TabPlayers associated with the given Velocitab plugin instance.
|
||||
* If the plugin is configured to show all players from all groups, all players will be returned.
|
||||
*
|
||||
* @param plugin The Velocitab plugin instance.
|
||||
* @return A set of TabPlayers.
|
||||
*/
|
||||
@NotNull
|
||||
public Set<TabPlayer> getTabPlayers(@NotNull Velocitab plugin) {
|
||||
if (plugin.getSettings().isShowAllPlayersFromAllGroups()) {
|
||||
return Sets.newHashSet(plugin.getTabList().getPlayers().values());
|
||||
}
|
||||
return plugin.getTabList().getPlayers()
|
||||
.values()
|
||||
.stream()
|
||||
@ -122,6 +142,9 @@ public record Group(
|
||||
|
||||
@NotNull
|
||||
public Set<TabPlayer> getTabPlayers(@NotNull Velocitab plugin, @NotNull TabPlayer tabPlayer) {
|
||||
if (plugin.getSettings().isShowAllPlayersFromAllGroups()) {
|
||||
return Sets.newHashSet(plugin.getTabList().getPlayers().values());
|
||||
}
|
||||
if (onlyListPlayersInSameServer) {
|
||||
return plugin.getTabList().getPlayers()
|
||||
.values()
|
||||
@ -133,7 +156,7 @@ public record Group(
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (!(obj instanceof Group group)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -63,6 +63,9 @@ public class Settings implements ConfigValidator {
|
||||
@Comment("The formats to use for the fallback group.")
|
||||
private String fallbackGroup = "default";
|
||||
|
||||
@Comment("Whether to show all players from all groups in the TAB list.")
|
||||
private boolean showAllPlayersFromAllGroups = false;
|
||||
|
||||
@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.")
|
||||
private Map<String, String> serverDisplayNames = Map.of("very-long-server-name", "VLSN");
|
||||
|
@ -89,7 +89,7 @@ public class TabGroups implements ConfigValidator {
|
||||
throw new IllegalStateException("No default group found");
|
||||
}
|
||||
for (Group group : groups) {
|
||||
if (group.registeredServers(plugin)
|
||||
if (group.registeredServers(plugin, false)
|
||||
.stream()
|
||||
.anyMatch(s -> s.getServerInfo().getName().equalsIgnoreCase(server))) {
|
||||
return group;
|
||||
|
@ -24,17 +24,18 @@ import net.william278.velocitab.Velocitab;
|
||||
import net.william278.velocitab.config.Placeholder;
|
||||
import net.william278.velocitab.player.TabPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.event.Level;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SortingManager {
|
||||
|
||||
private final Velocitab plugin;
|
||||
private static final String DELIMITER = ":::";
|
||||
private static final Pattern NUMBER_PATTERN = Pattern.compile("^-?[0-9]\\d*(\\.\\d+)?$");
|
||||
|
||||
public SortingManager(@NotNull Velocitab plugin) {
|
||||
this.plugin = plugin;
|
||||
@ -71,7 +72,7 @@ public class SortingManager {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (value.matches("^-?[0-9]\\d*(\\.\\d+)?$")) {
|
||||
if (NUMBER_PATTERN.matcher(value).matches()) {
|
||||
double parsed = Double.parseDouble(value);
|
||||
parsed = Math.max(0, parsed);
|
||||
return compressNumber(Integer.MAX_VALUE / 4d - parsed);
|
||||
|
39
src/main/java/net/william278/velocitab/tab/GroupTasks.java
Normal file
39
src/main/java/net/william278/velocitab/tab/GroupTasks.java
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of Velocitab, licensed under the Apache License 2.0.
|
||||
*
|
||||
* Copyright (c) William278 <will27528@gmail.com>
|
||||
* 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.scheduler.ScheduledTask;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public record GroupTasks(@Nullable ScheduledTask updateTask, @Nullable ScheduledTask headerFooterTask, @Nullable ScheduledTask latencyTask) {
|
||||
|
||||
public void cancel() {
|
||||
if (updateTask != null) {
|
||||
updateTask.cancel();
|
||||
}
|
||||
if (headerFooterTask != null) {
|
||||
headerFooterTask.cancel();
|
||||
}
|
||||
if (latencyTask != null) {
|
||||
latencyTask.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -25,7 +25,6 @@ import com.velocitypowered.api.proxy.ServerConnection;
|
||||
import com.velocitypowered.api.proxy.player.TabList;
|
||||
import com.velocitypowered.api.proxy.player.TabListEntry;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.scheduler.ScheduledTask;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
@ -36,7 +35,6 @@ import net.william278.velocitab.config.Group;
|
||||
import net.william278.velocitab.config.Placeholder;
|
||||
import net.william278.velocitab.player.Role;
|
||||
import net.william278.velocitab.player.TabPlayer;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.event.Level;
|
||||
@ -54,15 +52,13 @@ public class PlayerTabList {
|
||||
private final VanishTabList vanishTabList;
|
||||
@Getter(value = AccessLevel.PUBLIC)
|
||||
private final Map<UUID, TabPlayer> players;
|
||||
private final Map<Group, ScheduledTask> placeholderTasks;
|
||||
private final Map<Group, ScheduledTask> headerFooterTasks;
|
||||
private final Map<Group, GroupTasks> groupTasks;
|
||||
|
||||
public PlayerTabList(@NotNull Velocitab plugin) {
|
||||
this.plugin = plugin;
|
||||
this.vanishTabList = new VanishTabList(plugin, this);
|
||||
this.players = Maps.newConcurrentMap();
|
||||
this.placeholderTasks = Maps.newConcurrentMap();
|
||||
this.headerFooterTasks = Maps.newConcurrentMap();
|
||||
this.groupTasks = Maps.newConcurrentMap();
|
||||
this.reloadUpdate();
|
||||
this.registerListener();
|
||||
}
|
||||
@ -104,7 +100,9 @@ public class PlayerTabList {
|
||||
|
||||
final String serverName = server.get().getServerInfo().getName();
|
||||
final Group group = getGroup(serverName);
|
||||
final boolean isDefault = group.registeredServers(plugin).stream().noneMatch(s -> s.getServerInfo().getName().equals(serverName));
|
||||
final boolean isDefault = group.registeredServers(plugin)
|
||||
.stream()
|
||||
.noneMatch(s -> s.getServerInfo().getName().equals(serverName));
|
||||
|
||||
if (isDefault && !plugin.getSettings().isFallbackEnabled()) {
|
||||
return;
|
||||
@ -119,10 +117,7 @@ public class PlayerTabList {
|
||||
* Removes the player's entry from the tab list of all other players on the same group servers.
|
||||
*/
|
||||
public void close() {
|
||||
placeholderTasks.values().forEach(ScheduledTask::cancel);
|
||||
placeholderTasks.clear();
|
||||
headerFooterTasks.values().forEach(ScheduledTask::cancel);
|
||||
headerFooterTasks.clear();
|
||||
groupTasks.values().forEach(GroupTasks::cancel);
|
||||
plugin.getServer().getAllPlayers().forEach(p -> {
|
||||
final Optional<ServerConnection> server = p.getCurrentServer();
|
||||
if (server.isEmpty()) return;
|
||||
@ -345,10 +340,7 @@ public class PlayerTabList {
|
||||
|
||||
player.getPlayer().getTabList().getEntries().stream()
|
||||
.filter(e -> e.getProfile().getId().equals(tabPlayer.getPlayer().getUniqueId())).findFirst()
|
||||
.ifPresent(entry -> {
|
||||
entry.setDisplayName(displayName);
|
||||
entry.setLatency(Math.max((int) tabPlayer.getPlayer().getPing(), 0));
|
||||
});
|
||||
.ifPresent(entry -> entry.setDisplayName(displayName));
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -375,26 +367,54 @@ public class PlayerTabList {
|
||||
}
|
||||
|
||||
// Update the tab list periodically
|
||||
private void updatePeriodically(Group group) {
|
||||
private void updatePeriodically(@NotNull Group group) {
|
||||
cancelTasks(group);
|
||||
|
||||
ScheduledTask headerFooterTask = null;
|
||||
ScheduledTask updateTask = null;
|
||||
ScheduledTask latencyTask;
|
||||
|
||||
if (group.headerFooterUpdateRate() > 0) {
|
||||
final ScheduledTask headerFooterTask = plugin.getServer().getScheduler()
|
||||
headerFooterTask = plugin.getServer().getScheduler()
|
||||
.buildTask(plugin, () -> updateGroupPlayers(group, false, true))
|
||||
.delay(1, TimeUnit.SECONDS)
|
||||
.repeat(Math.max(200, group.headerFooterUpdateRate()), TimeUnit.MILLISECONDS)
|
||||
.schedule();
|
||||
headerFooterTasks.put(group, headerFooterTask);
|
||||
}
|
||||
|
||||
if (group.placeholderUpdateRate() > 0) {
|
||||
final ScheduledTask updateTask = plugin.getServer().getScheduler()
|
||||
updateTask = plugin.getServer().getScheduler()
|
||||
.buildTask(plugin, () -> updateGroupPlayers(group, true, false))
|
||||
.delay(1, TimeUnit.SECONDS)
|
||||
.repeat(Math.max(200, group.placeholderUpdateRate()), TimeUnit.MILLISECONDS)
|
||||
.schedule();
|
||||
placeholderTasks.put(group, updateTask);
|
||||
}
|
||||
|
||||
latencyTask = plugin.getServer().getScheduler()
|
||||
.buildTask(plugin, () -> updateLatency(group))
|
||||
.delay(1, TimeUnit.SECONDS)
|
||||
.repeat(3, TimeUnit.SECONDS)
|
||||
.schedule();
|
||||
|
||||
groupTasks.put(group, new GroupTasks(headerFooterTask, updateTask, latencyTask));
|
||||
}
|
||||
|
||||
private void updateLatency(@NotNull Group group) {
|
||||
final Set<TabPlayer> groupPlayers = group.getTabPlayers(plugin);
|
||||
if (groupPlayers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
groupPlayers.stream()
|
||||
.filter(player -> player.getPlayer().isActive())
|
||||
.forEach(player -> {
|
||||
final int latency = (int) player.getPlayer().getPing();
|
||||
final Set<TabPlayer> players = group.getTabPlayers(plugin, player);
|
||||
players.forEach(p -> {
|
||||
p.getPlayer().getTabList().getEntries().stream()
|
||||
.filter(e -> e.getProfile().getId().equals(player.getPlayer().getUniqueId())).findFirst()
|
||||
.ifPresent(entry -> entry.setLatency(Math.max(latency, 0)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -425,25 +445,11 @@ public class PlayerTabList {
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelTasks(Group group) {
|
||||
ScheduledTask task = placeholderTasks.entrySet().stream()
|
||||
.filter(entry -> entry.getKey().equals(group))
|
||||
.map(Map.Entry::getValue)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
placeholderTasks.remove(group);
|
||||
}
|
||||
|
||||
task = headerFooterTasks.entrySet().stream()
|
||||
.filter(entry -> entry.getKey().equals(group))
|
||||
.map(Map.Entry::getValue)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
headerFooterTasks.remove(group);
|
||||
private void cancelTasks(@NotNull Group group) {
|
||||
final GroupTasks tasks = groupTasks.get(group);
|
||||
if (tasks != null) {
|
||||
tasks.cancel();
|
||||
groupTasks.remove(group);
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,8 +457,6 @@ public class PlayerTabList {
|
||||
* Update the TAB list for all players when a plugin or proxy reload is performed
|
||||
*/
|
||||
public void reloadUpdate() {
|
||||
placeholderTasks.values().forEach(ScheduledTask::cancel);
|
||||
placeholderTasks.clear();
|
||||
plugin.getTabGroups().getGroups().forEach(this::updatePeriodically);
|
||||
|
||||
if (players.isEmpty()) {
|
||||
|
Loading…
Reference in New Issue
Block a user