forked from Upstream/Velocitab
Move to using Protocolize for scoreboard team handling using fake scoreboard teams
This commit is contained in:
parent
8ad443f4fc
commit
51c7853b7b
@ -1,4 +1,4 @@
|
||||
# Velocitab
|
||||
[](https://discord.gg/tVYhJfyDWG)
|
||||
|
||||
A very simple (sorted) Velocity TAB plugin
|
||||
A very simple (sorted) Velocity TAB plugin. Requires [Protocolize](https://github.com/Exceptionflug/protocolize) v2.2.5 to be installed on your proxy.
|
@ -12,18 +12,23 @@ repositories {
|
||||
maven { url = 'https://repo.papermc.io/repository/maven-public/' }
|
||||
maven { url = 'https://jitpack.io' }
|
||||
maven { url = 'https://repo.minebench.de/' }
|
||||
maven { url = 'https://mvn.exceptionflug.de/repository/exceptionflug-public/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'com.velocitypowered:velocity-api:3.1.1'
|
||||
compileOnly 'net.luckperms:api:5.4'
|
||||
compileOnly 'dev.simplix:protocolize-api:2.2.5'
|
||||
compileOnly 'io.netty:netty-codec-http:4.1.86.Final'
|
||||
|
||||
implementation 'org.apache.commons:commons-text:1.10.0'
|
||||
implementation 'net.william278:Annotaml:2.0.1'
|
||||
implementation 'dev.dejvokep:boosted-yaml:1.3.1'
|
||||
implementation 'de.themoep:minedown-adventure:1.7.1-SNAPSHOT'
|
||||
implementation 'org.projectlombok:lombok:1.18.26'
|
||||
|
||||
annotationProcessor 'com.velocitypowered:velocity-api:3.1.1'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.26'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
|
@ -11,6 +11,7 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import net.william278.annotaml.Annotaml;
|
||||
import net.william278.velocitab.config.Settings;
|
||||
import net.william278.velocitab.luckperms.LuckPermsHook;
|
||||
import net.william278.velocitab.packet.ScoreboardManager;
|
||||
import net.william278.velocitab.player.Role;
|
||||
import net.william278.velocitab.player.TabPlayer;
|
||||
import net.william278.velocitab.tab.PlayerTabList;
|
||||
@ -30,7 +31,10 @@ import java.util.Optional;
|
||||
description = "Simple velocity TAB menu plugin",
|
||||
url = "https://william278.net/",
|
||||
authors = {"William278"},
|
||||
dependencies = {@Dependency(id = "luckperms", optional = true)}
|
||||
dependencies = {
|
||||
@Dependency(id = "protocolize"),
|
||||
@Dependency(id = "luckperms", optional = true)
|
||||
}
|
||||
)
|
||||
public class Velocitab {
|
||||
|
||||
@ -40,6 +44,7 @@ public class Velocitab {
|
||||
private final Path dataDirectory;
|
||||
private PlayerTabList tabList;
|
||||
private LuckPermsHook luckPerms;
|
||||
private ScoreboardManager scoreboardManager;
|
||||
|
||||
@Inject
|
||||
public Velocitab(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
|
||||
@ -52,6 +57,7 @@ public class Velocitab {
|
||||
public void onProxyInitialization(ProxyInitializeEvent event) {
|
||||
loadSettings();
|
||||
loadHooks();
|
||||
prepareScoreboardManager();
|
||||
prepareTabList();
|
||||
logger.info("Successfully enabled Velocitab v" + BuildConstants.VERSION);
|
||||
}
|
||||
@ -92,6 +98,16 @@ public class Velocitab {
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareScoreboardManager() {
|
||||
this.scoreboardManager = new ScoreboardManager(this);
|
||||
scoreboardManager.registerPacket();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ScoreboardManager getScoreboardManager() {
|
||||
return scoreboardManager;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PlayerTabList getTabList() {
|
||||
return tabList;
|
||||
|
@ -10,7 +10,6 @@ import net.luckperms.api.model.group.Group;
|
||||
import net.luckperms.api.model.user.User;
|
||||
import net.william278.velocitab.Velocitab;
|
||||
import net.william278.velocitab.player.Role;
|
||||
import net.william278.velocitab.tab.PlayerTabList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -45,12 +44,8 @@ public class LuckPermsHook {
|
||||
|
||||
@Subscribe
|
||||
public void onLuckPermsGroupUpdate(@NotNull UserDataRecalculateEvent event) {
|
||||
plugin.getServer().getPlayer(event.getUser().getUniqueId()).ifPresent(player -> {
|
||||
final PlayerTabList tabList = plugin.getTabList();
|
||||
tabList.removePlayer(player);
|
||||
tabList.addPlayer(plugin.getTabPlayer(player));
|
||||
tabList.refreshHeaderAndFooter();
|
||||
});
|
||||
plugin.getServer().getPlayer(event.getUser().getUniqueId())
|
||||
.ifPresent(player -> plugin.getTabList().updatePlayer(plugin.getTabPlayer(player)));
|
||||
}
|
||||
|
||||
private OptionalInt getWeight(@Nullable String groupName) {
|
||||
|
@ -0,0 +1,62 @@
|
||||
package net.william278.velocitab.packet;
|
||||
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
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.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ScoreboardManager {
|
||||
|
||||
private final Velocitab plugin;
|
||||
|
||||
private final HashMap<UUID, String> fauxTeams;
|
||||
|
||||
public ScoreboardManager(@NotNull Velocitab velocitab) {
|
||||
this.plugin = velocitab;
|
||||
this.fauxTeams = new HashMap<>();
|
||||
}
|
||||
|
||||
public void registerPacket() {
|
||||
Protocolize.protocolRegistration().registerPacket(
|
||||
UpdateTeamsPacket.MAPPINGS,
|
||||
Protocol.PLAY,
|
||||
PacketDirection.CLIENTBOUND,
|
||||
UpdateTeamsPacket.class
|
||||
);
|
||||
}
|
||||
|
||||
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();
|
||||
final UpdateTeamsPacket createTeamPacket = UpdateTeamsPacket.create(teamName, member.getUsername());
|
||||
plugin.getServer().getAllPlayers().stream()
|
||||
.map(Player::getUniqueId)
|
||||
.map(Protocolize.playerProvider()::player)
|
||||
.forEach(protocolPlayer -> protocolPlayer.sendPacket(createTeamPacket));
|
||||
fauxTeams.put(uuid, teamName);
|
||||
}
|
||||
|
||||
public void removeTeam(@NotNull Player member) {
|
||||
final UUID uuid = member.getUniqueId();
|
||||
if (!fauxTeams.containsKey(uuid)) {
|
||||
return;
|
||||
}
|
||||
final UpdateTeamsPacket removeTeamPacket = UpdateTeamsPacket.remove(fauxTeams.get(uuid));
|
||||
plugin.getServer().getAllPlayers().stream()
|
||||
.map(Player::getUniqueId)
|
||||
.map(Protocolize.playerProvider()::player)
|
||||
.forEach(protocolPlayer -> protocolPlayer.sendPacket(removeTeamPacket));
|
||||
fauxTeams.remove(uuid);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
package net.william278.velocitab.packet;
|
||||
|
||||
import dev.simplix.protocolize.api.PacketDirection;
|
||||
import dev.simplix.protocolize.api.mapping.AbstractProtocolMapping;
|
||||
import dev.simplix.protocolize.api.mapping.ProtocolIdMapping;
|
||||
import dev.simplix.protocolize.api.packet.AbstractPacket;
|
||||
import dev.simplix.protocolize.api.util.ProtocolUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.*;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.simplix.protocolize.api.util.ProtocolVersions.MINECRAFT_1_19;
|
||||
import static dev.simplix.protocolize.api.util.ProtocolVersions.MINECRAFT_1_19_3;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(fluent = true)
|
||||
public class UpdateTeamsPacket extends AbstractPacket {
|
||||
|
||||
protected static final List<ProtocolIdMapping> MAPPINGS = List.of(
|
||||
AbstractProtocolMapping.rangedIdMapping(MINECRAFT_1_19, MINECRAFT_1_19_3, 0x56)
|
||||
);
|
||||
|
||||
private String teamName;
|
||||
private UpdateMode mode;
|
||||
private String displayName;
|
||||
private List<FriendlyFlag> friendlyFlags;
|
||||
private NameTagVisibility nameTagVisibility;
|
||||
private CollisionRule collisionRule;
|
||||
private int color;
|
||||
private String prefix;
|
||||
private String suffix;
|
||||
private List<String> entities;
|
||||
|
||||
@NotNull
|
||||
public static UpdateTeamsPacket create(@NotNull String teamName, @NotNull String member) {
|
||||
if (teamName.length() > 16) {
|
||||
teamName = teamName.substring(0, 16);
|
||||
}
|
||||
final UpdateTeamsPacket updateTeamsPacket = new UpdateTeamsPacket();
|
||||
updateTeamsPacket.teamName(teamName);
|
||||
updateTeamsPacket.mode(UpdateMode.CREATE);
|
||||
updateTeamsPacket.displayName(getChatString(teamName));
|
||||
updateTeamsPacket.friendlyFlags(List.of(FriendlyFlag.CAN_HURT_FRIENDLY));
|
||||
updateTeamsPacket.nameTagVisibility(NameTagVisibility.ALWAYS);
|
||||
updateTeamsPacket.collisionRule(CollisionRule.ALWAYS);
|
||||
updateTeamsPacket.color(0);
|
||||
updateTeamsPacket.prefix(getChatString(""));
|
||||
updateTeamsPacket.suffix(getChatString(""));
|
||||
updateTeamsPacket.entities(List.of(member));
|
||||
return updateTeamsPacket;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static UpdateTeamsPacket remove(@NotNull String teamName) {
|
||||
if (teamName.length() > 16) {
|
||||
teamName = teamName.substring(0, 16);
|
||||
}
|
||||
final UpdateTeamsPacket updateTeamsPacket = new UpdateTeamsPacket();
|
||||
updateTeamsPacket.teamName(teamName);
|
||||
updateTeamsPacket.mode(UpdateMode.REMOVE);
|
||||
return updateTeamsPacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ByteBuf byteBuf, PacketDirection packetDirection, int i) {
|
||||
teamName = ProtocolUtil.readString(byteBuf);
|
||||
mode = UpdateMode.byId(byteBuf.readByte());
|
||||
if (mode == UpdateMode.REMOVE) {
|
||||
return;
|
||||
}
|
||||
if (mode == UpdateMode.CREATE || mode == UpdateMode.UPDATE_INFO) {
|
||||
displayName = ProtocolUtil.readString(byteBuf);
|
||||
friendlyFlags = FriendlyFlag.fromBitMask(byteBuf.readByte());
|
||||
nameTagVisibility = NameTagVisibility.byId(ProtocolUtil.readString(byteBuf));
|
||||
collisionRule = CollisionRule.byId(ProtocolUtil.readString(byteBuf));
|
||||
color = byteBuf.readByte();
|
||||
prefix = ProtocolUtil.readString(byteBuf);
|
||||
suffix = ProtocolUtil.readString(byteBuf);
|
||||
}
|
||||
if (mode == UpdateMode.CREATE || mode == UpdateMode.ADD_PLAYERS || mode == UpdateMode.REMOVE_PLAYERS) {
|
||||
int entityCount = ProtocolUtil.readVarInt(byteBuf);
|
||||
for (int j = 0; j < entityCount; j++) {
|
||||
entities.add(ProtocolUtil.readString(byteBuf));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf byteBuf, PacketDirection packetDirection, int i) {
|
||||
ProtocolUtil.writeString(byteBuf, teamName);
|
||||
byteBuf.writeByte(mode.id());
|
||||
if (mode == UpdateMode.REMOVE) {
|
||||
return;
|
||||
}
|
||||
if (mode == UpdateMode.CREATE || mode == UpdateMode.UPDATE_INFO) {
|
||||
ProtocolUtil.writeString(byteBuf, displayName);
|
||||
byteBuf.writeByte(FriendlyFlag.toBitMask(friendlyFlags));
|
||||
ProtocolUtil.writeString(byteBuf, nameTagVisibility.id());
|
||||
ProtocolUtil.writeString(byteBuf, collisionRule.id());
|
||||
byteBuf.writeByte(color);
|
||||
ProtocolUtil.writeString(byteBuf, prefix);
|
||||
ProtocolUtil.writeString(byteBuf, suffix);
|
||||
}
|
||||
if (mode == UpdateMode.CREATE || mode == UpdateMode.ADD_PLAYERS || mode == UpdateMode.REMOVE_PLAYERS) {
|
||||
ProtocolUtil.writeVarInt(byteBuf, entities.size());
|
||||
for (String entity : entities) {
|
||||
ProtocolUtil.writeString(byteBuf, entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getChatString(@NotNull String string) {
|
||||
return "{\"text\":\"" + StringEscapeUtils.escapeJson(string) + "\"}";
|
||||
}
|
||||
|
||||
public enum UpdateMode {
|
||||
CREATE(0),
|
||||
REMOVE(1),
|
||||
UPDATE_INFO(2),
|
||||
ADD_PLAYERS(3),
|
||||
REMOVE_PLAYERS(4);
|
||||
|
||||
private final int id;
|
||||
|
||||
UpdateMode(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static UpdateMode byId(int id) {
|
||||
return Arrays.stream(values())
|
||||
.filter(mode -> mode.id == id)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
public enum FriendlyFlag {
|
||||
CAN_HURT_FRIENDLY(0x01),
|
||||
CAN_HURT_FRIENDLY_FIRE(0x02);
|
||||
|
||||
private final int id;
|
||||
|
||||
FriendlyFlag(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<FriendlyFlag> fromBitMask(int bitMask) {
|
||||
return Arrays.stream(values())
|
||||
.filter(flag -> (bitMask & flag.id) != 0)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static int toBitMask(@NotNull List<FriendlyFlag> friendlyFlags) {
|
||||
int bitMask = 0;
|
||||
for (FriendlyFlag friendlyFlag : friendlyFlags) {
|
||||
bitMask |= friendlyFlag.id;
|
||||
}
|
||||
return bitMask;
|
||||
}
|
||||
}
|
||||
|
||||
public enum NameTagVisibility {
|
||||
ALWAYS("always"),
|
||||
NEVER("never"),
|
||||
HIDE_FOR_OTHER_TEAMS("hideForOtherTeams"),
|
||||
HIDE_FOR_OWN_TEAM("hideForOwnTeam");
|
||||
|
||||
private final String id;
|
||||
|
||||
NameTagVisibility(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static NameTagVisibility byId(String id) {
|
||||
return Arrays.stream(values())
|
||||
.filter(visibility -> visibility.id.equals(id))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
public enum CollisionRule {
|
||||
ALWAYS("always"),
|
||||
NEVER("never"),
|
||||
PUSH_OTHER_TEAMS("pushOtherTeams"),
|
||||
PUSH_OWN_TEAM("pushOwnTeam");
|
||||
|
||||
private final String id;
|
||||
|
||||
CollisionRule(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static CollisionRule byId(String id) {
|
||||
return Arrays.stream(values())
|
||||
.filter(rule -> rule.id.equals(id))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
package net.william278.velocitab.player;
|
||||
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.player.TabList;
|
||||
import com.velocitypowered.api.proxy.player.TabListEntry;
|
||||
import com.velocitypowered.api.util.GameProfile;
|
||||
import de.themoep.minedown.adventure.MineDown;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.william278.velocitab.Velocitab;
|
||||
@ -11,26 +8,15 @@ import net.william278.velocitab.config.Placeholder;
|
||||
import net.william278.velocitab.tab.PlayerTabList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class TabPlayer implements Comparable<TabPlayer> {
|
||||
private static final int DEFAULT_LATENCY = 3;
|
||||
private final Player player;
|
||||
private final Role role;
|
||||
private final GameProfile profile;
|
||||
private final int highestWeight;
|
||||
|
||||
public TabPlayer(@NotNull Player player, @NotNull Role role, int highestWeight) {
|
||||
this.player = player;
|
||||
this.role = role;
|
||||
final String profileName = role.getStringComparableWeight(highestWeight) + getServerName() + player.getUsername();
|
||||
this.profile = new GameProfile(
|
||||
new UUID(0, new Random().nextLong()),
|
||||
profileName.length() > 16 ? profileName.substring(0, 16) : profileName,
|
||||
player.getGameProfileProperties()
|
||||
);
|
||||
this.highestWeight = highestWeight;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@ -43,11 +29,6 @@ public final class TabPlayer implements Comparable<TabPlayer> {
|
||||
return role;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GameProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getServerName() {
|
||||
return player.getCurrentServer()
|
||||
@ -56,41 +37,19 @@ public final class TabPlayer implements Comparable<TabPlayer> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Component getDisplayName(@NotNull Velocitab plugin) {
|
||||
public Component getDisplayName(@NotNull Velocitab plugin) {
|
||||
return new MineDown(Placeholder.format(plugin.getSettings().getFormat(), plugin, this)).toComponent();
|
||||
}
|
||||
|
||||
private TabListEntry getEntry(@NotNull Velocitab plugin, @NotNull TabList tabList) {
|
||||
return TabListEntry.builder()
|
||||
.displayName(getDisplayName(plugin))
|
||||
.latency(DEFAULT_LATENCY)
|
||||
.profile(profile)
|
||||
.tabList(tabList)
|
||||
.build();
|
||||
@NotNull
|
||||
public String getTeamName() {
|
||||
return role.getStringComparableWeight(highestWeight) + "-" + getServerName() + "-" + player.getUsername();
|
||||
}
|
||||
|
||||
public void sendHeaderAndFooter(@NotNull PlayerTabList tabList) {
|
||||
this.player.sendPlayerListHeaderAndFooter(tabList.getHeader(this), tabList.getFooter(this));
|
||||
}
|
||||
|
||||
public void addPlayer(@NotNull TabPlayer player, @NotNull Velocitab plugin) {
|
||||
this.player.getTabList().addEntry(player.getEntry(plugin, this.player.getTabList()));
|
||||
removeUuidPlayer(plugin, player.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
public void removePlayer(@NotNull TabPlayer player, @NotNull Velocitab plugin) {
|
||||
this.player.getTabList().removeEntry(player.getProfile().getId());
|
||||
removeUuidPlayer(plugin, player.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
public void removeUuidPlayer(@NotNull Velocitab plugin, @NotNull UUID... uuid) {
|
||||
plugin.getServer().getScheduler()
|
||||
.buildTask(plugin, () -> Arrays.stream(uuid).forEach(this.player.getTabList()::removeEntry))
|
||||
.delay(500, TimeUnit.MILLISECONDS)
|
||||
.schedule();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull TabPlayer o) {
|
||||
final int roleDifference = role.compareTo(o.role);
|
||||
|
@ -3,7 +3,6 @@ package net.william278.velocitab.tab;
|
||||
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 de.themoep.minedown.adventure.MineDown;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.william278.velocitab.Velocitab;
|
||||
@ -13,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PlayerTabList {
|
||||
private final Velocitab plugin;
|
||||
@ -27,33 +26,66 @@ public class PlayerTabList {
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@Subscribe
|
||||
public void onPlayerJoin(@NotNull ServerPostConnectEvent event) {
|
||||
// Remove previous Tab entries for players when they move servers
|
||||
if (event.getPreviousServer() != null) {
|
||||
removePlayer(event.getPlayer());
|
||||
// Remove the player from the tracking list if they are switching servers
|
||||
if (event.getPreviousServer() == null) {
|
||||
players.removeIf(player -> player.getPlayer().getUniqueId().equals(event.getPlayer().getUniqueId()));
|
||||
}
|
||||
|
||||
final TabPlayer player = plugin.getTabPlayer(event.getPlayer());
|
||||
// Add the player to the tracking list
|
||||
players.add(plugin.getTabPlayer(event.getPlayer()));
|
||||
|
||||
// Reset existing tab list
|
||||
player.getPlayer().getTabList().clearHeaderAndFooter();
|
||||
if (!player.getPlayer().getTabList().getEntries().isEmpty()) {
|
||||
player.getPlayer().getTabList().getEntries().clear();
|
||||
}
|
||||
|
||||
// Show existing list to new player
|
||||
players.forEach(listPlayer -> player.addPlayer(listPlayer, plugin));
|
||||
addPlayer(player);
|
||||
refreshHeaderAndFooter();
|
||||
// Update the tab list of all players
|
||||
plugin.getServer().getScheduler().buildTask(plugin, this::updateList)
|
||||
.delay(500, TimeUnit.MILLISECONDS)
|
||||
.schedule();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPlayerQuit(@NotNull DisconnectEvent event) {
|
||||
try {
|
||||
removePlayer(event.getPlayer());
|
||||
refreshHeaderAndFooter();
|
||||
} catch (Exception ignored) {
|
||||
// Ignore when server shutting down
|
||||
}
|
||||
// Remove the player from the tracking list
|
||||
players.removeIf(player -> player.getPlayer().getUniqueId().equals(event.getPlayer().getUniqueId()));
|
||||
|
||||
// Remove the player from the tab list of all other players
|
||||
plugin.getScoreboardManager().removeTeam(event.getPlayer());
|
||||
plugin.getServer().getAllPlayers().forEach(player -> {
|
||||
if (player.getTabList().containsEntry(event.getPlayer().getUniqueId())) {
|
||||
player.getTabList().removeEntry(event.getPlayer().getUniqueId());
|
||||
}
|
||||
});
|
||||
|
||||
// Update the tab list of all players
|
||||
plugin.getServer().getScheduler().buildTask(plugin, this::updateList)
|
||||
.delay(500, TimeUnit.MILLISECONDS)
|
||||
.schedule();
|
||||
}
|
||||
|
||||
public void updatePlayer(@NotNull TabPlayer tabPlayer) {
|
||||
// Remove the existing player from the tracking list
|
||||
players.removeIf(player -> player.getPlayer().getUniqueId().equals(tabPlayer.getPlayer().getUniqueId()));
|
||||
|
||||
// Add the player to the tracking list
|
||||
players.add(tabPlayer);
|
||||
|
||||
// Update the player's team sorting
|
||||
plugin.getScoreboardManager().removeTeam(tabPlayer.getPlayer());
|
||||
|
||||
// Update the tab list of all players
|
||||
plugin.getServer().getScheduler().buildTask(plugin, this::updateList)
|
||||
.delay(500, TimeUnit.MILLISECONDS)
|
||||
.schedule();
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
players.forEach(player -> {
|
||||
player.sendHeaderAndFooter(this);
|
||||
player.getPlayer().getTabList().getEntries()
|
||||
.forEach(entry -> players.stream()
|
||||
.filter(p -> p.getPlayer().getGameProfile().getId().equals(entry.getProfile().getId()))
|
||||
.findFirst().ifPresent(tabPlayer -> {
|
||||
entry.setDisplayName(tabPlayer.getDisplayName(plugin));
|
||||
plugin.getScoreboardManager().setPlayerTeam(tabPlayer);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@ -66,22 +98,4 @@ public class PlayerTabList {
|
||||
return new MineDown(Placeholder.format(plugin.getSettings().getFooter(), plugin, player)).toComponent();
|
||||
}
|
||||
|
||||
// Add a new tab player to the list and update for online players
|
||||
public void addPlayer(@NotNull TabPlayer player) {
|
||||
players.add(player);
|
||||
players.forEach(tabPlayer -> tabPlayer.addPlayer(player, plugin));
|
||||
}
|
||||
|
||||
public void removePlayer(@NotNull Player playerToRemove) {
|
||||
final Optional<TabPlayer> quitTabPlayer = players.stream()
|
||||
.filter(player -> player.getPlayer().equals(playerToRemove)).findFirst();
|
||||
if (quitTabPlayer.isPresent()) {
|
||||
players.remove(quitTabPlayer.get());
|
||||
players.forEach(tabPlayer -> tabPlayer.removePlayer(quitTabPlayer.get(), plugin));
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshHeaderAndFooter() {
|
||||
players.forEach(tabPlayer -> tabPlayer.sendHeaderAndFooter(this));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user