diff --git a/patches/api/Add-extended-PaperServerListPingEvent.patch b/patches/api/Add-extended-PaperServerListPingEvent.patch
index 02f3b734bb..3f3c93394b 100644
--- a/patches/api/Add-extended-PaperServerListPingEvent.patch
+++ b/patches/api/Add-extended-PaperServerListPingEvent.patch
@@ -18,10 +18,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +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..00000000000000000000000000000000
 +
 +    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..00000000000000000000000000000000
 +    }
 +
 +    /**
-+     * 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..00000000000000000000000000000000
 +     * @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..00000000000000000000000000000000
 +     *     <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..00000000000000000000000000000000
 +        }
 +    }
 +
++    /**
++     * 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..00000000000000000000000000000000
 +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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java
++++ b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java
+@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/util/CachedServerIcon.java
diff --git a/patches/server/Implement-extended-PaperServerListPingEvent.patch b/patches/server/Implement-extended-PaperServerListPingEvent.patch
index e2ce5c0497..a01c7051e7 100644
--- a/patches/server/Implement-extended-PaperServerListPingEvent.patch
+++ b/patches/server/Implement-extended-PaperServerListPingEvent.patch
@@ -66,17 +66,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 @@ -0,0 +0,0 @@
 +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..00000000000000000000000000000000
 +
 +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..00000000000000000000000000000000
 +
 +    @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..00000000000000000000000000000000
 +            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;
 +    }