Fixup and deprecate player profiles in ping event (#10880)
This commit is contained in:
parent
79e2cb620e
commit
9e7f6c3f7e
2 changed files with 193 additions and 32 deletions
|
@ -8,20 +8,28 @@ and allows full control of the response sent to the client.
|
|||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java b/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0bb6fdbdd05ae6a8fb413e0f6b8d84302d697267
|
||||
index 0000000000000000000000000000000000000000..acff2ff570f8419ffa4dfefe890795c63d75325d
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/server/PaperServerListPingEvent.java
|
||||
@@ -0,0 +1,338 @@
|
||||
@@ -0,0 +1,502 @@
|
||||
+package com.destroystokyo.paper.event.server;
|
||||
+
|
||||
+import static java.util.Objects.requireNonNull;
|
||||
+
|
||||
+import com.destroystokyo.paper.network.StatusClient;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.ProfileProperty;
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import io.papermc.paper.util.TransformingRandomAccessList;
|
||||
+import java.util.Collection;
|
||||
+import java.util.Map;
|
||||
+import java.util.Set;
|
||||
+import java.util.concurrent.CompletableFuture;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.server.ServerListPingEvent;
|
||||
+import org.bukkit.profile.PlayerTextures;
|
||||
+import org.bukkit.util.CachedServerIcon;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
|
@ -44,7 +52,12 @@ index 0000000000000000000000000000000000000000..0bb6fdbdd05ae6a8fb413e0f6b8d8430
|
|||
+
|
||||
+ private int numPlayers;
|
||||
+ private boolean hidePlayers;
|
||||
+ @NotNull private final List<PlayerProfile> playerSample = new ArrayList<>();
|
||||
+ @NotNull private final List<ListedPlayerInfo> listedPlayers = new ArrayList<>();
|
||||
+ @NotNull private final TransformingRandomAccessList<ListedPlayerInfo, PlayerProfile> playerSample = new TransformingRandomAccessList<>(
|
||||
+ listedPlayers,
|
||||
+ info -> new UncheckedPlayerProfile(info.name(), info.id()),
|
||||
+ profile -> new ListedPlayerInfo(profile.getName(), profile.getId())
|
||||
+ );
|
||||
+
|
||||
+ @NotNull private String version;
|
||||
+ private int protocolVersion;
|
||||
|
@ -163,7 +176,7 @@ index 0000000000000000000000000000000000000000..0bb6fdbdd05ae6a8fb413e0f6b8d8430
|
|||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns a mutable list of {@link PlayerProfile} that will be displayed
|
||||
+ * Returns a mutable list of {@link ListedPlayerInfo} that will be displayed
|
||||
+ * as online players on the client.
|
||||
+ * <p>
|
||||
+ * The Vanilla Minecraft client will display them when hovering the
|
||||
|
@ -172,6 +185,22 @@ index 0000000000000000000000000000000000000000..0bb6fdbdd05ae6a8fb413e0f6b8d8430
|
|||
+ * @return The mutable player sample list
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public List<ListedPlayerInfo> getListedPlayers() {
|
||||
+ return this.listedPlayers;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns a mutable list of {@link PlayerProfile} that will be displayed
|
||||
+ * as online players on the client.
|
||||
+ * <p>
|
||||
+ * The Vanilla Minecraft client will display them when hovering the
|
||||
+ * player count with the mouse.
|
||||
+ *
|
||||
+ * @return The mutable player sample list
|
||||
+ * @deprecated Use {@link #getListedPlayers()}, as this does not contain real player profiles
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ @Deprecated(forRemoval = true, since = "1.20.6")
|
||||
+ public List<PlayerProfile> getPlayerSample() {
|
||||
+ return this.playerSample;
|
||||
+ }
|
||||
|
@ -276,9 +305,11 @@ index 0000000000000000000000000000000000000000..0bb6fdbdd05ae6a8fb413e0f6b8d8430
|
|||
+ * <li>Remove all entries from {@link #getPlayerSample()} that refer to
|
||||
+ * the removed player (based on their {@link UUID}).</li>
|
||||
+ * </ul>
|
||||
+ * @deprecated the Iterable interface will be removed at some point
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ @Deprecated(forRemoval = true, since = "1.20.6")
|
||||
+ public Iterator<Player> iterator() {
|
||||
+ if (this.players == null) {
|
||||
+ this.players = getOnlinePlayers();
|
||||
|
@ -349,6 +380,139 @@ index 0000000000000000000000000000000000000000..0bb6fdbdd05ae6a8fb413e0f6b8d8430
|
|||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Represents a player that will be displayed in the player sample of the server list.
|
||||
+ *
|
||||
+ * @param name name of the listed player
|
||||
+ * @param id UUID of the listed player
|
||||
+ */
|
||||
+ public record ListedPlayerInfo(@NotNull String name, @NotNull UUID id) {
|
||||
+ }
|
||||
+
|
||||
+ @ApiStatus.Internal
|
||||
+ private static final class UncheckedPlayerProfile implements PlayerProfile {
|
||||
+ private String name;
|
||||
+ private UUID uuid;
|
||||
+
|
||||
+ public UncheckedPlayerProfile(final @NotNull String name, final @NotNull UUID uuid) {
|
||||
+ Preconditions.checkNotNull(name, "name cannot be null");
|
||||
+ Preconditions.checkNotNull(uuid, "uuid cannot be null");
|
||||
+ this.name = name;
|
||||
+ this.uuid = uuid;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @Nullable UUID getUniqueId() {
|
||||
+ return uuid;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @Nullable String getName() {
|
||||
+ return name;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull String setName(@Nullable final String name) {
|
||||
+ Preconditions.checkNotNull(name, "name cannot be null");
|
||||
+ return this.name = name;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @Nullable UUID getId() {
|
||||
+ return uuid;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @Nullable UUID setId(@Nullable final UUID uuid) {
|
||||
+ Preconditions.checkNotNull(uuid, "uuid cannot be null");
|
||||
+ return this.uuid = uuid;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull PlayerTextures getTextures() {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTextures(@Nullable final PlayerTextures textures) {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Set<ProfileProperty> getProperties() {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasProperty(@Nullable final String property) {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setProperty(@NotNull final ProfileProperty property) {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setProperties(@NotNull final Collection<ProfileProperty> properties) {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean removeProperty(@Nullable final String property) {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void clearProperties() {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isComplete() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean completeFromCache() {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean completeFromCache(final boolean onlineMode) {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean completeFromCache(final boolean lookupUUID, final boolean onlineMode) {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean complete(final boolean textures) {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean complete(final boolean textures, final boolean onlineMode) {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull CompletableFuture<PlayerProfile> update() {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.profile.@NotNull PlayerProfile clone() {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull Map<String, Object> serialize() {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/network/StatusClient.java b/src/main/java/com/destroystokyo/paper/network/StatusClient.java
|
||||
new file mode 100644
|
||||
|
@ -369,6 +533,22 @@ index 0000000000000000000000000000000000000000..517d15238ed117f38bbd39f570874014
|
|||
+public interface StatusClient extends NetworkClient {
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java
|
||||
index 72ebc29db42d08d1d0361dba462fc8a573fbf918..d351f62971f8f1317b3fc92f8b1d446e48149c3a 100644
|
||||
--- a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java
|
||||
@@ -248,9 +248,11 @@ public class ServerListPingEvent extends ServerEvent implements Iterable<Player>
|
||||
*
|
||||
* @throws UnsupportedOperationException if the caller of this event does
|
||||
* not support removing players
|
||||
+ * @deprecated the Iterable interface will be removed at some point
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
+ @Deprecated(forRemoval = true, since = "1.20.6")
|
||||
public Iterator<Player> iterator() throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java
|
||||
index 9a7768d41270714d4a1c89b4dcb436cc66f57545..b74b21a1ac7798e847b6d34ff45026e1c9cfed14 100644
|
||||
--- a/src/main/java/org/bukkit/util/CachedServerIcon.java
|
||||
|
|
|
@ -60,23 +60,18 @@ index 0000000000000000000000000000000000000000..d926ad804355ee2fdc5910b2505e8671
|
|||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6b0bdc266109cdfb874f08bf74323603921d2260
|
||||
index 0000000000000000000000000000000000000000..aa2aff62c873ba85b0cbced5382398c858420e59
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java
|
||||
@@ -0,0 +1,116 @@
|
||||
@@ -0,0 +1,97 @@
|
||||
+package com.destroystokyo.paper.network;
|
||||
+
|
||||
+import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
+import com.google.common.base.MoreObjects;
|
||||
+import com.google.common.base.Strings;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
+import io.papermc.paper.adventure.AdventureComponent;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Collections;
|
||||
+import java.util.List;
|
||||
+import java.util.Optional;
|
||||
+import java.util.UUID;
|
||||
+import javax.annotation.Nonnull;
|
||||
+import net.minecraft.network.Connection;
|
||||
+import net.minecraft.network.chat.Component;
|
||||
|
@ -87,9 +82,6 @@ index 0000000000000000000000000000000000000000..6b0bdc266109cdfb874f08bf74323603
|
|||
+
|
||||
+public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl {
|
||||
+
|
||||
+ // private static final GameProfile[] EMPTY_PROFILES = new GameProfile[0];
|
||||
+ private static final UUID FAKE_UUID = new UUID(0, 0);
|
||||
+
|
||||
+ private List<GameProfile> originalSample;
|
||||
+
|
||||
+ private StandardPaperServerListPingEventImpl(MinecraftServer server, Connection networkManager, ServerStatus ping) {
|
||||
|
@ -99,12 +91,12 @@ index 0000000000000000000000000000000000000000..6b0bdc266109cdfb874f08bf74323603
|
|||
+
|
||||
+ @Nonnull
|
||||
+ @Override
|
||||
+ public List<PlayerProfile> getPlayerSample() {
|
||||
+ List<PlayerProfile> sample = super.getPlayerSample();
|
||||
+ public List<ListedPlayerInfo> getListedPlayers() {
|
||||
+ List<ListedPlayerInfo> sample = super.getListedPlayers();
|
||||
+
|
||||
+ if (this.originalSample != null) {
|
||||
+ for (GameProfile profile : this.originalSample) {
|
||||
+ sample.add(CraftPlayerProfile.asBukkitCopy(profile));
|
||||
+ sample.add(new ListedPlayerInfo(profile.getName(), profile.getId()));
|
||||
+ }
|
||||
+ this.originalSample = null;
|
||||
+ }
|
||||
|
@ -117,25 +109,14 @@ index 0000000000000000000000000000000000000000..6b0bdc266109cdfb874f08bf74323603
|
|||
+ return this.originalSample;
|
||||
+ }
|
||||
+
|
||||
+ List<PlayerProfile> entries = super.getPlayerSample();
|
||||
+ List<ListedPlayerInfo> entries = super.getListedPlayers();
|
||||
+ if (entries.isEmpty()) {
|
||||
+ return Collections.emptyList();
|
||||
+ }
|
||||
+
|
||||
+ final List<GameProfile> profiles = new ArrayList<>();
|
||||
+ for (PlayerProfile profile : entries) {
|
||||
+ /*
|
||||
+ * Avoid null UUIDs/names since that will make the response invalid
|
||||
+ * on the client.
|
||||
+ * Instead, fall back to a fake/empty UUID and an empty string as name.
|
||||
+ * This can be used to create custom lines in the player list that do not
|
||||
+ * refer to a specific player.
|
||||
+ */
|
||||
+ if (profile.getId() != null && profile.getName() != null) {
|
||||
+ profiles.add(CraftPlayerProfile.asAuthlib(profile));
|
||||
+ } else {
|
||||
+ profiles.add(new GameProfile(MoreObjects.firstNonNull(profile.getId(), FAKE_UUID), Strings.nullToEmpty(profile.getName())));
|
||||
+ }
|
||||
+ for (ListedPlayerInfo playerInfo : entries) {
|
||||
+ profiles.add(new GameProfile(playerInfo.id(), playerInfo.name()));
|
||||
+ }
|
||||
+ return profiles;
|
||||
+ }
|
||||
|
@ -181,7 +162,7 @@ index 0000000000000000000000000000000000000000..6b0bdc266109cdfb874f08bf74323603
|
|||
+
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 260e364c91d8c3d774681f9f0ecba63df5dd3f5c..2ae6eb3a05bd0574143699e1286f63f5fd699f30 100644
|
||||
index 1fdd088f0bb6606f2a9a482d276aa3e9261be012..b6c5656665e492a7fdec0ae15545ecbabf585336 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -3,6 +3,9 @@ package net.minecraft.server;
|
||||
|
|
Loading…
Reference in a new issue