Add Listing API for Player

This commit is contained in:
Corey Shupe 2023-01-11 16:40:39 -05:00
parent 8e05d19854
commit 53fab9663b
3 changed files with 170 additions and 32 deletions

View File

@ -1,6 +1,72 @@
--- a/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
+++ b/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
@@ -116,7 +116,15 @@
@@ -38,7 +38,18 @@
this.actions = EnumSet.of(action);
this.entries = List.of(new ClientboundPlayerInfoUpdatePacket.Entry(player));
}
+ // Paper start - Add Listing API for Player
+ public ClientboundPlayerInfoUpdatePacket(EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions, List<ClientboundPlayerInfoUpdatePacket.Entry> entries) {
+ this.actions = actions;
+ this.entries = entries;
+ }
+ public ClientboundPlayerInfoUpdatePacket(EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions, ClientboundPlayerInfoUpdatePacket.Entry entry) {
+ this.actions = actions;
+ this.entries = List.of(entry);
+ }
+ // Paper end - Add Listing API for Player
+
public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection<ServerPlayer> players) {
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(
ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER,
@@ -53,6 +64,46 @@
return new ClientboundPlayerInfoUpdatePacket(enumSet, players);
}
+ // Paper start - Add Listing API for Player
+ public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection<ServerPlayer> players, ServerPlayer forPlayer) {
+ final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(
+ ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER,
+ ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_HAT,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LIST_ORDER
+ );
+ final List<ClientboundPlayerInfoUpdatePacket.Entry> entries = new java.util.ArrayList<>(players.size());
+ final org.bukkit.craftbukkit.entity.CraftPlayer bukkitEntity = forPlayer.getBukkitEntity();
+ for (final ServerPlayer player : players) {
+ entries.add(new ClientboundPlayerInfoUpdatePacket.Entry(player, bukkitEntity.isListed(player.getBukkitEntity())));
+ }
+ return new ClientboundPlayerInfoUpdatePacket(enumSet, entries);
+ }
+
+ public static ClientboundPlayerInfoUpdatePacket createSinglePlayerInitializing(ServerPlayer player, boolean listed) {
+ final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(
+ ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER,
+ ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_HAT,
+ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LIST_ORDER
+ );
+ final List<ClientboundPlayerInfoUpdatePacket.Entry> entries = List.of(new Entry(player, listed));
+ return new ClientboundPlayerInfoUpdatePacket(enumSet, entries);
+ }
+
+ public static ClientboundPlayerInfoUpdatePacket updateListed(UUID playerInfoId, boolean listed) {
+ EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
+ return new ClientboundPlayerInfoUpdatePacket(enumSet, new ClientboundPlayerInfoUpdatePacket.Entry(playerInfoId, listed));
+ }
+ // Paper end - Add Listing API for Player
private ClientboundPlayerInfoUpdatePacket(RegistryFriendlyByteBuf buf) {
this.actions = buf.readEnumSet(ClientboundPlayerInfoUpdatePacket.Action.class);
this.entries = buf.readList(buf2 -> {
@@ -116,7 +167,15 @@
}),
INITIALIZE_CHAT(
(serialized, buf) -> serialized.chatSession = buf.readNullable(RemoteChatSession.Data::read),
@ -17,3 +83,32 @@
),
UPDATE_GAME_MODE((serialized, buf) -> serialized.gameMode = GameType.byId(buf.readVarInt()), (buf, entry) -> buf.writeVarInt(entry.gameMode().getId())),
UPDATE_LISTED((serialized, buf) -> serialized.listed = buf.readBoolean(), (buf, entry) -> buf.writeBoolean(entry.listed())),
@@ -157,10 +216,15 @@
@Nullable RemoteChatSession.Data chatSession
) {
Entry(ServerPlayer player) {
+ // Paper start - Add Listing API for Player
+ this(player, true);
+ }
+ Entry(ServerPlayer player, boolean listed) {
this(
+ // Paper end - Add Listing API for Player
player.getUUID(),
player.getGameProfile(),
- true,
+ listed, // Paper - Add Listing API for Player
player.connection.latency(),
player.gameMode.getGameModeForPlayer(),
player.getTabListDisplayName(),
@@ -169,6 +233,11 @@
Optionull.map(player.getChatSession(), RemoteChatSession::asData)
);
}
+ // Paper start - Add Listing API for Player
+ Entry(UUID profileId, boolean listed) {
+ this(profileId, null, listed, 0, GameType.DEFAULT_MODE, null, true, 0, null);
+ }
+ // Paper end - Add Listing API for Player
}
static class EntryBuilder {

View File

@ -235,7 +235,7 @@
playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
ServerStatus serverping = this.server.getStatus();
@@ -222,17 +327,101 @@
@@ -222,17 +327,109 @@
player.sendServerStatus(serverping);
}
@ -279,14 +279,22 @@
+ // CraftBukkit end
+
+ // CraftBukkit start - sendAll above replaced with this loop
+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player));
+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player
+
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join
+ for (int i = 0; i < this.players.size(); ++i) {
+ ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
+
+ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
+ // Paper start - Add Listing API for Player
+ if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) {
+ // Paper end - Add Listing API for Player
+ entityplayer1.connection.send(packet);
+ // Paper start - Add Listing API for Player
+ } else {
+ entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false));
+ }
+ // Paper end - Add Listing API for Player
+ }
+
+ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player
@ -297,7 +305,7 @@
+ }
+ // Paper start - Use single player info update packet on join
+ if (!onlinePlayers.isEmpty()) {
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers));
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player
+ }
+ // Paper end - Use single player info update packet on join
+ player.sentListPacket = true;
@ -342,7 +350,7 @@
}
public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) {
@@ -269,30 +458,31 @@
@@ -269,30 +466,31 @@
}
public void addWorldborderListener(ServerLevel world) {
@ -379,7 +387,7 @@
}
@Override
@@ -319,14 +509,15 @@
@@ -319,14 +517,15 @@
}
protected void save(ServerPlayer player) {
@ -397,7 +405,7 @@
if (advancementdataplayer != null) {
advancementdataplayer.save();
@@ -334,95 +525,210 @@
@@ -334,95 +533,210 @@
}
@ -596,11 +604,10 @@
}
- return ichatmutablecomponent;
- } else {
- return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(profile) ? Component.translatable("multiplayer.disconnect.server_full") : null;
+ // return chatmessage;
+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, io.papermc.paper.adventure.PaperAdventure.asAdventure(ichatmutablecomponent)); // Paper - Adventure
+ } else {
} else {
- return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(profile) ? Component.translatable("multiplayer.disconnect.server_full") : null;
+ // return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile) ? IChatBaseComponent.translatable("multiplayer.disconnect.server_full") : null;
+ if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) {
+ event.disallow(PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure
@ -647,7 +654,7 @@
if (entityplayer1 != null) {
set.add(entityplayer1);
@@ -431,72 +737,160 @@
@@ -431,72 +745,160 @@
Iterator iterator1 = set.iterator();
while (iterator1.hasNext()) {
@ -829,7 +836,7 @@
return entityplayer1;
}
@@ -516,15 +910,32 @@
@@ -516,15 +918,32 @@
}
public void sendPlayerPermissionLevel(ServerPlayer player) {
@ -864,11 +871,10 @@
this.sendAllPlayerInfoIn = 0;
}
@@ -540,6 +951,25 @@
}
@@ -541,6 +960,25 @@
}
+
+ // CraftBukkit start - add a world/entity limited version
+ public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) {
+ for (int i = 0; i < this.players.size(); ++i) {
@ -887,10 +893,11 @@
+
+ }
+ // CraftBukkit end
+
public void broadcastAll(Packet<?> packet, ResourceKey<Level> dimension) {
Iterator iterator = this.players.iterator();
@@ -554,7 +984,7 @@
@@ -554,7 +992,7 @@
}
@ -899,7 +906,7 @@
PlayerTeam scoreboardteam = source.getTeam();
if (scoreboardteam != null) {
@@ -573,7 +1003,7 @@
@@ -573,7 +1011,7 @@
}
}
@ -908,7 +915,7 @@
PlayerTeam scoreboardteam = source.getTeam();
if (scoreboardteam == null) {
@@ -619,7 +1049,7 @@
@@ -619,7 +1057,7 @@
}
public void deop(GameProfile profile) {
@ -917,7 +924,7 @@
ServerPlayer entityplayer = this.getPlayer(profile.getId());
if (entityplayer != null) {
@@ -629,6 +1059,11 @@
@@ -629,6 +1067,11 @@
}
private void sendPlayerPermissionLevel(ServerPlayer player, int permissionLevel) {
@ -929,7 +936,7 @@
if (player.connection != null) {
byte b0;
@@ -643,35 +1078,52 @@
@@ -643,35 +1086,52 @@
player.connection.send(new ClientboundEntityEventPacket(player, b0));
}
@ -995,7 +1002,7 @@
if (entityplayer != player && entityplayer.level().dimension() == worldKey) {
double d4 = x - entityplayer.getX();
@@ -687,10 +1139,12 @@
@@ -687,10 +1147,12 @@
}
public void saveAll() {
@ -1008,7 +1015,7 @@
}
public UserWhiteList getWhiteList() {
@@ -712,15 +1166,19 @@
@@ -712,15 +1174,19 @@
public void reloadWhiteList() {}
public void sendLevelInfo(ServerPlayer player, ServerLevel world) {
@ -1032,7 +1039,7 @@
}
player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
@@ -729,8 +1187,16 @@
@@ -729,8 +1195,16 @@
public void sendAllPlayerInfo(ServerPlayer player) {
player.inventoryMenu.sendAllDataToRemote();
@ -1050,7 +1057,7 @@
}
public int getPlayerCount() {
@@ -746,6 +1212,7 @@
@@ -746,6 +1220,7 @@
}
public void setUsingWhiteList(boolean whitelistEnabled) {
@ -1058,7 +1065,7 @@
this.doWhiteList = whitelistEnabled;
}
@@ -786,12 +1253,36 @@
@@ -786,12 +1261,36 @@
}
public void removeAll() {
@ -1097,7 +1104,7 @@
public void broadcastSystemMessage(Component message, boolean overlay) {
this.broadcastSystemMessage(message, (entityplayer) -> {
return message;
@@ -819,24 +1310,43 @@
@@ -819,24 +1318,43 @@
}
public void broadcastChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound params) {
@ -1144,7 +1151,7 @@
}
if (flag1 && sender != null) {
@@ -845,20 +1355,27 @@
@@ -845,20 +1363,27 @@
}
@ -1177,7 +1184,7 @@
Path path = file2.toPath();
if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) {
@@ -867,7 +1384,7 @@
@@ -867,7 +1392,7 @@
}
serverstatisticmanager = new ServerStatsCounter(this.server, file1);
@ -1186,7 +1193,7 @@
}
return serverstatisticmanager;
@@ -875,13 +1392,13 @@
@@ -875,13 +1400,13 @@
public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) {
UUID uuid = player.getUUID();
@ -1202,7 +1209,7 @@
}
advancementdataplayer.setPlayer(player);
@@ -932,15 +1449,39 @@
@@ -932,15 +1457,39 @@
}
public void reloadResources() {

View File

@ -206,6 +206,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
private final ConversationTracker conversationTracker = new ConversationTracker();
private final Set<String> channels = new HashSet<String>();
private final Map<UUID, Set<WeakReference<Plugin>>> invertedVisibilityEntities = new HashMap<>();
private final Set<UUID> unlistedEntities = new HashSet<>(); // Paper - Add Listing API for Player
private static final WeakHashMap<Plugin, WeakReference<Plugin>> pluginWeakReferences = new WeakHashMap<>();
private int hash = 0;
private double health = 20;
@ -2104,7 +2105,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
otherPlayer.setUUID(uuidOverride);
}
// Paper end
this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer)));
this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer), this.getHandle())); // Paper - Add Listing API for Player
if (original != null) otherPlayer.setUUID(original); // Paper - uuid override
}
@ -2208,6 +2209,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return (entity != null) ? this.canSee(entity) : false; // If we can't find it, we can't see it
}
// Paper start - Add Listing API for Player
@Override
public boolean isListed(Player other) {
return !this.unlistedEntities.contains(other.getUniqueId());
}
@Override
public boolean unlistPlayer(@NotNull Player other) {
Preconditions.checkNotNull(other, "hidden entity cannot be null");
if (this.getHandle().connection == null) return false;
if (!this.canSee(other)) return false;
if (unlistedEntities.add(other.getUniqueId())) {
this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.updateListed(other.getUniqueId(), false));
return true;
} else {
return false;
}
}
@Override
public boolean listPlayer(@NotNull Player other) {
Preconditions.checkNotNull(other, "hidden entity cannot be null");
if (this.getHandle().connection == null) return false;
if (!this.canSee(other)) throw new IllegalStateException("Player cannot see other player");
if (this.unlistedEntities.remove(other.getUniqueId())) {
this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.updateListed(other.getUniqueId(), true));
return true;
} else {
return false;
}
}
// Paper end - Add Listing API for Player
@Override
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<String, Object>();