Reduce number of packets being sent, adjust logic

This commit is contained in:
William 2023-02-26 19:54:12 +00:00
parent de747bf3eb
commit 0a39899705
No known key found for this signature in database
6 changed files with 125 additions and 99 deletions

View File

@ -48,7 +48,7 @@ public class LuckPermsHook {
public void onLuckPermsGroupUpdate(@NotNull UserDataRecalculateEvent event) {
plugin.getServer().getPlayer(event.getUser().getUniqueId())
.ifPresent(player -> plugin.getTabList().updatePlayer(new TabPlayer(
.ifPresent(player -> plugin.getTabList().onPlayerRoleUpdate(new TabPlayer(
player,
getRoleFromMetadata(event.getData().getMetaData()),
getHighestWeight()
@ -80,5 +80,4 @@ public class LuckPermsHook {
}
}

View File

@ -5,21 +5,54 @@ import dev.simplix.protocolize.api.PacketDirection;
import dev.simplix.protocolize.api.Protocol;
import dev.simplix.protocolize.api.Protocolize;
import net.william278.velocitab.Velocitab;
import net.william278.velocitab.player.TabPlayer;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.*;
import java.util.stream.Collectors;
public class ScoreboardManager {
private final Velocitab plugin;
private final ConcurrentHashMap<UUID, String> fauxTeams;
private final Map<UUID, List<String>> createdTeams;
private final Map<UUID, Map<String, String>> roleMappings;
public ScoreboardManager(@NotNull Velocitab velocitab) {
this.plugin = velocitab;
this.fauxTeams = new ConcurrentHashMap<>();
this.createdTeams = new HashMap<>();
this.roleMappings = new HashMap<>();
}
public void resetCache(@NotNull Player player) {
createdTeams.remove(player.getUniqueId());
roleMappings.remove(player.getUniqueId());
}
public void sendTeamPackets(@NotNull Player player, @NotNull Map<Player, String> playerRoles) {
playerRoles.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(entry -> entry.getKey().getUsername(), Collectors.toList())
))
.forEach((role, players) -> updateRoles(player, role, players.toArray(new String[0])));
}
public void updateRoles(@NotNull Player player, @NotNull String role, @NotNull String... playerNames) {
if (!createdTeams.getOrDefault(player.getUniqueId(), List.of()).contains(role)) {
dispatchPacket(UpdateTeamsPacket.create(role, playerNames), player);
createdTeams.computeIfAbsent(player.getUniqueId(), k -> new ArrayList<>()).add(role);
} else {
roleMappings.getOrDefault(player.getUniqueId(), Map.of())
.entrySet().stream()
.filter((entry) -> List.of(playerNames).contains(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
.forEach((playerName, oldRole) -> dispatchPacket(UpdateTeamsPacket.removeFromTeam(oldRole, playerName), player));
dispatchPacket(UpdateTeamsPacket.addToTeam(role, playerNames), player);
roleMappings.computeIfAbsent(player.getUniqueId(), k -> new HashMap<>()).put(player.getUsername(), role);
}
}
private void dispatchPacket(@NotNull UpdateTeamsPacket packet, @NotNull Player player) {
Protocolize.playerProvider().player(player.getUniqueId()).sendPacket(packet);
}
public void registerPacket() {
@ -35,40 +68,5 @@ public class ScoreboardManager {
}
}
public void setPlayerTeam(@NotNull TabPlayer player) {
removeTeam(player.getPlayer());
createTeam(player.getTeamName(), player.getPlayer());
}
private void createTeam(@NotNull String teamName, @NotNull Player member) {
final UUID uuid = member.getUniqueId();
try {
final UpdateTeamsPacket createTeamPacket = UpdateTeamsPacket.create(teamName, member.getUsername());
fauxTeams.put(uuid, teamName);
plugin.getServer().getAllPlayers().stream()
.map(Player::getUniqueId)
.map(Protocolize.playerProvider()::player)
.forEach(protocolPlayer -> protocolPlayer.sendPacket(createTeamPacket));
} catch (Exception e) {
plugin.log("Skipped setting team for " + member.getUsername());
}
}
public void removeTeam(@NotNull Player member) {
final UUID uuid = member.getUniqueId();
try {
final String teamName = fauxTeams.getOrDefault(uuid, null);
if (teamName != null) {
final UpdateTeamsPacket removeTeamPacket = UpdateTeamsPacket.remove(teamName);
plugin.getServer().getAllPlayers().stream()
.map(Player::getUniqueId)
.map(Protocolize.playerProvider()::player)
.forEach(protocolPlayer -> protocolPlayer.sendPacket(removeTeamPacket));
}
} catch (Exception e) {
plugin.log("Skipped removing team for " + member.getUsername());
}
fauxTeams.remove(uuid);
}
}

View File

@ -45,7 +45,7 @@ public class UpdateTeamsPacket extends AbstractPacket {
private List<String> entities;
@NotNull
public static UpdateTeamsPacket create(@NotNull String teamName, @NotNull String member) {
public static UpdateTeamsPacket create(@NotNull String teamName, @NotNull String... teamMembers) {
return new UpdateTeamsPacket()
.teamName(teamName.length() > 16 ? teamName.substring(0, 16) : teamName)
.mode(UpdateMode.CREATE_TEAM)
@ -56,14 +56,23 @@ public class UpdateTeamsPacket extends AbstractPacket {
.color(15)
.prefix(getChatString(""))
.suffix(getChatString(""))
.entities(List.of(member));
.entities(Arrays.asList(teamMembers));
}
@NotNull
public static UpdateTeamsPacket remove(@NotNull String teamName) {
public static UpdateTeamsPacket addToTeam(@NotNull String teamName, @NotNull String... teamMembers) {
return new UpdateTeamsPacket()
.teamName(teamName.length() > 16 ? teamName.substring(0, 16) : teamName)
.mode(UpdateMode.REMOVE_TEAM);
.mode(UpdateMode.ADD_PLAYERS)
.entities(Arrays.asList(teamMembers));
}
@NotNull
public static UpdateTeamsPacket removeFromTeam(@NotNull String teamName, @NotNull String... teamMembers) {
return new UpdateTeamsPacket()
.teamName(teamName.length() > 16 ? teamName.substring(0, 16) : teamName)
.mode(UpdateMode.REMOVE_PLAYERS)
.entities(Arrays.asList(teamMembers));
}
@Override

View File

@ -41,7 +41,7 @@ public class Role implements Comparable<Role> {
}
@NotNull
public String getStringComparableWeight(int highestWeight) {
protected String getWeightString(int highestWeight) {
return String.format("%0" + (highestWeight + "").length() + "d", highestWeight - weight);
}
}

View File

@ -43,7 +43,7 @@ public final class TabPlayer implements Comparable<TabPlayer> {
@NotNull
public String getTeamName() {
return role.getStringComparableWeight(highestWeight) + "-" + getServerName() + "-" + player.getUsername();
return role.getWeightString(highestWeight) + role.getName().map(name -> "-" + name).orElse("");
}
public void sendHeaderAndFooter(@NotNull PlayerTabList tabList) {

View File

@ -1,11 +1,11 @@
package net.william278.velocitab.tab;
import com.google.common.collect.ImmutableList;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.player.ServerPostConnectEvent;
import com.velocitypowered.api.proxy.Player;
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.ServerInfo;
import de.themoep.minedown.adventure.MineDown;
@ -15,7 +15,8 @@ import net.william278.velocitab.config.Placeholder;
import net.william278.velocitab.player.TabPlayer;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
@ -32,6 +33,8 @@ public class PlayerTabList {
@Subscribe
public void onPlayerJoin(@NotNull ServerPostConnectEvent event) {
final Player joined = event.getPlayer();
plugin.getScoreboardManager().resetCache(joined);
// Remove the player from the tracking list if they are switching servers
if (event.getPreviousServer() == null) {
players.removeIf(player -> player.getPlayer().getUniqueId().equals(joined.getUniqueId()));
@ -46,14 +49,61 @@ public class PlayerTabList {
}
// Add the player to the tracking list
players.add(plugin.getTabPlayer(joined));
final TabPlayer tabPlayer = plugin.getTabPlayer(joined);
players.add(tabPlayer);
// Update the tab list of all players
plugin.getServer().getScheduler().buildTask(plugin, this::updateList)
// Update lists
plugin.getServer().getScheduler()
.buildTask(plugin, () -> {
final TabList tabList = joined.getTabList();
final Map<Player, String> playerRoles = new HashMap<>();
players.forEach(player -> {
playerRoles.put(player.getPlayer(), tabPlayer.getTeamName());
tabList.getEntries().stream()
.filter(e -> e.getProfile().getId().equals(player.getPlayer().getUniqueId())).findFirst()
.ifPresentOrElse(
entry -> entry.setDisplayName(player.getDisplayName(plugin)),
() -> tabList.addEntry(createEntry(player, tabList))
);
addPlayerToTabList(player, tabPlayer);
player.sendHeaderAndFooter(this);
});
plugin.getScoreboardManager().sendTeamPackets(joined, playerRoles);
})
.delay(500, TimeUnit.MILLISECONDS)
.schedule();
}
@NotNull
private TabListEntry createEntry(@NotNull TabPlayer player, @NotNull TabList tabList) {
return TabListEntry.builder()
.profile(player.getPlayer().getGameProfile())
.displayName(player.getDisplayName(plugin))
.latency(0)
.tabList(tabList)
.build();
}
private void addPlayerToTabList(@NotNull TabPlayer player, @NotNull TabPlayer newPlayer) {
if (newPlayer.getPlayer().getUniqueId().equals(player.getPlayer().getUniqueId())) {
return;
}
player.getPlayer()
.getTabList().getEntries().stream()
.filter(e -> e.getProfile().getId().equals(newPlayer.getPlayer().getUniqueId())).findFirst()
.ifPresentOrElse(
entry -> entry.setDisplayName(newPlayer.getDisplayName(plugin)),
() -> player.getPlayer().getTabList()
.addEntry(createEntry(newPlayer, player.getPlayer().getTabList()))
);
plugin.getScoreboardManager().updateRoles(
player.getPlayer(),
newPlayer.getTeamName(),
newPlayer.getPlayer().getUsername()
);
}
@Subscribe
public void onPlayerQuit(@NotNull DisconnectEvent event) {
// Remove the player from the tracking list
@ -63,56 +113,26 @@ public class PlayerTabList {
plugin.getServer().getAllPlayers().forEach(player -> player.getTabList().removeEntry(event.getPlayer().getUniqueId()));
// Update the tab list of all players
plugin.getServer().getScheduler().buildTask(plugin, () -> {
plugin.getScoreboardManager().removeTeam(event.getPlayer());
updateList();
})
.delay(500, TimeUnit.MILLISECONDS)
.schedule();
}
public void updatePlayer(@NotNull TabPlayer tabPlayer) {
plugin.getServer().getScheduler()
.buildTask(plugin, () -> {
// Update the player's team sorting
players.remove(tabPlayer);
players.add(tabPlayer);
plugin.getScoreboardManager().setPlayerTeam(tabPlayer);
updateList();
})
.buildTask(plugin, () -> players.forEach(player -> {
player.getPlayer().getTabList().removeEntry(event.getPlayer().getUniqueId());
player.sendHeaderAndFooter(this);
}))
.delay(500, TimeUnit.MILLISECONDS)
.schedule();
}
private void updateList() {
final ImmutableList<TabPlayer> players = ImmutableList.copyOf(this.players);
players.forEach(player -> {
player.sendHeaderAndFooter(this);
// Fill the tab list with the players
players.forEach(listedPlayer -> {
final Optional<TabListEntry> current = player.getPlayer().getTabList().getEntries().stream()
.filter(entry -> entry.getProfile().getId().equals(listedPlayer.getPlayer().getUniqueId()))
.findFirst();
current.ifPresentOrElse(
entry -> entry.setDisplayName(listedPlayer.getDisplayName(plugin)),
() -> player.getPlayer().getTabList().addEntry(TabListEntry.builder()
.profile(listedPlayer.getPlayer().getGameProfile())
.displayName(listedPlayer.getDisplayName(plugin))
.latency(0)
.tabList(player.getPlayer().getTabList())
.build()));
plugin.getScoreboardManager().setPlayerTeam(listedPlayer);
});
// Remove players in the tab list that are not in the players list
public void onPlayerRoleUpdate(@NotNull TabPlayer tabPlayer) {
plugin.getServer().getScheduler()
.buildTask(plugin, () -> players.forEach(player -> {
player.getPlayer().getTabList().getEntries().stream()
.filter(entry -> players.stream()
.noneMatch(listedPlayer -> listedPlayer.getPlayer().getUniqueId().equals(entry.getProfile().getId())))
.forEach(entry -> player.getPlayer().getTabList().removeEntry(entry.getProfile().getId()));
});
.filter(e -> e.getProfile().getId().equals(tabPlayer.getPlayer().getUniqueId())).findFirst()
.ifPresent(entry -> entry.setDisplayName(tabPlayer.getDisplayName(plugin)));
plugin.getScoreboardManager().updateRoles(player.getPlayer(),
tabPlayer.getTeamName(), tabPlayer.getPlayer().getUsername());
}))
.delay(500, TimeUnit.MILLISECONDS)
.schedule();
}
@NotNull