2023-08-21 10:51:31 +02:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Corey Shupe <coreyshupe101@gmail.com>
Date: Wed, 11 Jan 2023 16:40:39 -0500
Subject: [PATCH] Add Listing API for Player
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
2024-10-24 10:42:29 +02:00
index 29b465fc1dc50e0e84ddb889c5303e80fe662874..4d67d98257b2cb9045d03c999cfd4ba2caf8453c 100644
2023-08-21 10:51:31 +02:00
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
2024-04-25 00:36:49 +02:00
@@ -37,6 +37,17 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
2023-08-21 10:51:31 +02:00
this.actions = EnumSet.of(action);
this.entries = List.of(new ClientboundPlayerInfoUpdatePacket.Entry(player));
}
2024-01-14 16:31:39 +01:00
+ // Paper start - Add Listing API for Player
2023-08-21 10:51:31 +02:00
+ 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);
+ }
2024-01-14 16:31:39 +01:00
+ // Paper end - Add Listing API for Player
2023-08-21 10:51:31 +02:00
public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection<ServerPlayer> players) {
2024-04-12 21:14:06 +02:00
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(
2024-10-24 10:42:29 +02:00
@@ -51,6 +62,28 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
2023-08-21 10:51:31 +02:00
return new ClientboundPlayerInfoUpdatePacket(enumSet, players);
}
2024-01-14 16:31:39 +01:00
+ // Paper start - Add Listing API for Player
2023-08-21 10:51:31 +02:00
+ 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);
+ 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);
+ 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));
+ }
2024-01-14 16:31:39 +01:00
+ // Paper end - Add Listing API for Player
2024-04-25 00:36:49 +02:00
private ClientboundPlayerInfoUpdatePacket(RegistryFriendlyByteBuf buf) {
2023-08-21 10:51:31 +02:00
this.actions = buf.readEnumSet(ClientboundPlayerInfoUpdatePacket.Action.class);
2024-04-12 21:14:06 +02:00
this.entries = buf.readList(buf2 -> {
2024-10-24 10:42:29 +02:00
@@ -161,10 +194,15 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
2024-04-12 21:14:06 +02:00
@Nullable RemoteChatSession.Data chatSession
) {
2023-08-21 10:51:31 +02:00
Entry(ServerPlayer player) {
2024-10-24 10:42:29 +02:00
+ // Paper start - Add Listing API for Player
2023-08-21 10:51:31 +02:00
+ this(player, true);
+ }
+ Entry(ServerPlayer player, boolean listed) {
2024-04-12 21:14:06 +02:00
this(
2024-10-24 10:42:29 +02:00
+ // Paper end - Add Listing API for Player
2024-04-12 21:14:06 +02:00
player.getUUID(),
player.getGameProfile(),
- true,
2024-10-24 10:42:29 +02:00
+ listed, // Paper - Add Listing API for Player
2024-04-12 21:14:06 +02:00
player.connection.latency(),
player.gameMode.getGameModeForPlayer(),
player.getTabListDisplayName(),
2024-10-24 10:42:29 +02:00
@@ -172,6 +210,11 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
2024-04-12 21:14:06 +02:00
Optionull.map(player.getChatSession(), RemoteChatSession::asData)
);
}
2024-10-24 10:42:29 +02:00
+ // Paper start - Add Listing API for Player
2023-08-21 10:51:31 +02:00
+ Entry(UUID profileId, boolean listed) {
2024-10-24 10:42:29 +02:00
+ this(profileId, null, listed, 0, GameType.DEFAULT_MODE, null, 0, null);
2024-04-12 21:14:06 +02:00
+ }
2024-01-14 16:31:39 +01:00
+ // Paper end - Add Listing API for Player
2023-08-21 10:51:31 +02:00
}
static class EntryBuilder {
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
2024-11-09 21:17:42 +01:00
index efc12d629b71ba1da664d9ecfd4575bee9b45dc3..9067100a82a8c405cec0a19e53b3b245daa3bd75 100644
2023-08-21 10:51:31 +02:00
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
2024-10-27 18:11:15 +01:00
@@ -362,14 +362,22 @@ public abstract class PlayerList {
2023-08-21 10:51:31 +02:00
// CraftBukkit end
// CraftBukkit start - sendAll above replaced with this loop
- ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player));
2024-01-14 16:31:39 +01:00
+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player
2023-08-21 10:51:31 +02:00
2024-01-16 12:41:40 +01:00
final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join
2023-08-21 10:51:31 +02:00
for (int i = 0; i < this.players.size(); ++i) {
ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
2024-01-14 16:31:39 +01:00
+ // Paper start - Add Listing API for Player
2023-08-21 10:51:31 +02:00
+ if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) {
2024-01-14 16:31:39 +01:00
+ // Paper end - Add Listing API for Player
2023-08-21 10:51:31 +02:00
entityplayer1.connection.send(packet);
2024-01-14 16:31:39 +01:00
+ // Paper start - Add Listing API for Player
2023-08-21 10:51:31 +02:00
+ } else {
+ entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false));
+ }
2024-01-14 16:31:39 +01:00
+ // Paper end - Add Listing API for Player
2023-08-21 10:51:31 +02:00
}
2024-01-16 12:41:40 +01:00
if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player
2024-10-27 18:11:15 +01:00
@@ -380,7 +388,7 @@ public abstract class PlayerList {
2023-08-21 10:51:31 +02:00
}
2024-01-16 12:41:40 +01:00
// Paper start - Use single player info update packet on join
2023-08-21 10:51:31 +02:00
if (!onlinePlayers.isEmpty()) {
- player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers));
2024-01-14 16:31:39 +01:00
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player
2023-08-21 10:51:31 +02:00
}
2024-01-16 12:41:40 +01:00
// Paper end - Use single player info update packet on join
2023-08-21 10:51:31 +02:00
player.sentListPacket = true;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
Rework async chunk api implementation
Firstly, the old methods all routed to the CompletableFuture method.
However, the CF method could not guarantee that if the caller
was off-main that the future would be "completed" on-main. Since
the callback methods used the CF one, this meant that the callback
methods did not guarantee that the callbacks were to be called on
the main thread.
Now, all methods route to getChunkAtAsync(x, z, gen, urgent, cb)
so that the methods with the callback are guaranteed to invoke
the callback on the main thread. The CF behavior remains unchanged;
it may still appear to complete on main if invoked off-main.
Secondly, remove the scheduleOnMain invocation in the async
chunk completion. This unnecessarily delays the callback
by 1 tick.
Thirdly, add getChunksAtAsync(minX, minZ, maxX, maxZ, ...) which
will load chunks within an area. This method is provided as a helper
as keeping all chunks loaded within an area can be complicated to
implement for plugins (due to the lacking ticket API), and is
already implemented internally anyways.
Fourthly, remove the ticket addition that occured with getChunkAt
and getChunkAtAsync. The ticket addition may delay the unloading
of the chunk unnecessarily. It also fixes a very rare timing bug
where the future/callback would be completed after the chunk
unloads.
2024-11-19 07:34:32 +01:00
index b397f784510d832d300a777b4c4a4de03c904b72..76ee6dcf028720f22ca6d0ba5975a8f1555cca37 100644
2023-08-21 10:51:31 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
2024-10-24 19:29:35 +02:00
@@ -206,6 +206,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
2023-08-21 10:51:31 +02:00
private final ConversationTracker conversationTracker = new ConversationTracker();
private final Set<String> channels = new HashSet<String>();
private final Map<UUID, Set<WeakReference<Plugin>>> invertedVisibilityEntities = new HashMap<>();
2024-01-14 16:31:39 +01:00
+ private final Set<UUID> unlistedEntities = new HashSet<>(); // Paper - Add Listing API for Player
2023-08-21 10:51:31 +02:00
private static final WeakHashMap<Plugin, WeakReference<Plugin>> pluginWeakReferences = new WeakHashMap<>();
private int hash = 0;
private double health = 20;
2024-11-09 21:17:42 +01:00
@@ -2102,7 +2103,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
2023-08-21 10:51:31 +02:00
otherPlayer.setUUID(uuidOverride);
}
// Paper end
- this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer)));
2024-01-14 16:31:39 +01:00
+ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer), this.getHandle())); // Paper - Add Listing API for Player
2023-08-21 10:51:31 +02:00
if (original != null) otherPlayer.setUUID(original); // Paper - uuid override
}
2024-11-09 21:17:42 +01:00
@@ -2206,6 +2207,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
2023-08-21 10:51:31 +02:00
return (entity != null) ? this.canSee(entity) : false; // If we can't find it, we can't see it
}
2024-01-14 16:31:39 +01:00
+ // Paper start - Add Listing API for Player
2023-08-21 10:51:31 +02:00
+ @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;
+ }
+ }
2024-01-14 16:31:39 +01:00
+ // Paper end - Add Listing API for Player
2023-08-21 10:51:31 +02:00
+
@Override
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<String, Object>();