From af38fef7534806f7b25b2d73d1b421b7959aa041 Mon Sep 17 00:00:00 2001 From: Flo0 Date: Sat, 6 Apr 2024 23:16:04 +0200 Subject: [PATCH] Add listing API for PlayerProfile --- ...68-Add-listing-API-for-PlayerProfile.patch | 121 ++++++++++++++ ...55-Add-listing-API-for-PlayerProfile.patch | 150 ++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 patches/api/0468-Add-listing-API-for-PlayerProfile.patch create mode 100644 patches/server/1055-Add-listing-API-for-PlayerProfile.patch diff --git a/patches/api/0468-Add-listing-API-for-PlayerProfile.patch b/patches/api/0468-Add-listing-API-for-PlayerProfile.patch new file mode 100644 index 0000000000..799b5964c7 --- /dev/null +++ b/patches/api/0468-Add-listing-API-for-PlayerProfile.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Flo0 +Date: Sat, 6 Apr 2024 23:15:08 +0200 +Subject: [PATCH] Add listing API for PlayerProfile + + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index c6cb4f17469a8f2e60dd3e28d41402851ce5fb21..2c2802caea79f853ec14f0cfe382471d32417b19 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -54,7 +54,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a player, connected or not + */ +-public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, net.kyori.adventure.bossbar.BossBarViewer, com.destroystokyo.paper.network.NetworkClient { // Paper ++public interface Player extends org.bukkit.entity.HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, net.kyori.adventure.bossbar.BossBarViewer, com.destroystokyo.paper.network.NetworkClient { // Paper + + // Paper start + @Override +@@ -2054,6 +2054,69 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + boolean listPlayer(@NotNull Player other); + // Paper end + ++ // Paper start - Add Listing API for PlayerProfile ++ /** ++ * Lists the {@code profile} in the tablist. ++ * Burden of tracking the profile is on the caller. ++ * Using profiles of online players is an invalid operation. ++ * Use {@link #listPlayer(Player)} instead. ++ * ++ * @param profile The {@link com.destroystokyo.paper.profile.PlayerProfile} to list. ++ * @param latency The latency of the profile in milliseconds. ++ * @param gameMode The game mode of the profile. ++ * @param displayName The display name of the profile. ++ */ ++ void listProfile(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile, int latency, GameMode gameMode, @Nullable net.kyori.adventure.text.Component displayName); ++ ++ /** ++ * Lists the {@code profile} in the tablist. ++ * Burden of tracking the profile is on the caller. ++ * Using profiles of online players is an invalid operation. ++ * Use {@link #listPlayer(Player)} instead. ++ * ++ * @param profile The {@link com.destroystokyo.paper.profile.PlayerProfile} to list. ++ */ ++ default void listProfile(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile) { ++ listProfile(profile, 0, GameMode.SURVIVAL, null); ++ } ++ ++ /** ++ * Updates the latency of the {@code profile} in the tablist. ++ * If the {@code profile} is not listed, this method has no effect. ++ * ++ * @param profile The {@link com.destroystokyo.paper.profile.PlayerProfile} to update in the tablist. ++ * @param latency The new latency of the profile in milliseconds. ++ */ ++ void updateListedProfileLatency(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile, int latency); ++ ++ /** ++ * Updates the game mode of the {@code profile} in the tablist. ++ * If the {@code profile} is not listed, this method has no effect. ++ * ++ * @param profile The {@link com.destroystokyo.paper.profile.PlayerProfile} to update in the tablist. ++ * @param gameMode The new game mode of the profile. ++ */ ++ void updateListedProfileGameMode(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile, GameMode gameMode); ++ ++ /** ++ * Updates the display name of the {@code profile} in the tablist. ++ * If the {@code profile} is not listed, this method has no effect. ++ * ++ * @param profile The {@link com.destroystokyo.paper.profile.PlayerProfile} to update in the tablist. ++ * @param displayName The new display name of the profile. ++ */ ++ void updateListedProfileDisplayName(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile, @Nullable net.kyori.adventure.text.Component displayName); ++ ++ /** ++ * Unlists the {@code profile} from the tablist. ++ * Using profiles of online players is an invalid operation. ++ * Use {@link #unlistPlayer(Player)} instead. ++ * ++ * @param profile The {@link com.destroystokyo.paper.profile.PlayerProfile} to de-list. ++ */ ++ void unlistProfile(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile); ++ // Paper end - Add Listing API for PlayerProfile ++ + /** + * Checks to see if this player is currently flying or not. + * +@@ -3403,18 +3466,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + + // Paper start - elytra boost API + /** +- * Boost a Player that's {@link #isGliding()} using a {@link Firework}. ++ * Boost a Player that's {@link #isGliding()} using a {@link org.bukkit.entity.Firework}. + * If the creation of the entity is cancelled, no boosting is done. + * This method does not fire {@link com.destroystokyo.paper.event.player.PlayerElytraBoostEvent}. + * + * @param firework The {@link Material#FIREWORK_ROCKET} to boost the player with +- * @return The {@link Firework} boosting the Player or null if the spawning of the entity was cancelled ++ * @return The {@link org.bukkit.entity.Firework} boosting the Player or null if the spawning of the entity was cancelled + * @throws IllegalArgumentException if {@link #isGliding()} is false + * or if the {@code firework} isn't a {@link Material#FIREWORK_ROCKET} +- * @deprecated use {@link HumanEntity#fireworkBoost(ItemStack)} instead. Note that this method does not ++ * @deprecated use {@link org.bukkit.entity.HumanEntity#fireworkBoost(ItemStack)} instead. Note that this method does not + * check if the player is gliding or not. + */ +- default @Nullable Firework boostElytra(final @NotNull ItemStack firework) { ++ default @Nullable org.bukkit.entity.Firework boostElytra(final @NotNull ItemStack firework) { + com.google.common.base.Preconditions.checkState(this.isGliding(), "Player must be gliding"); + return this.fireworkBoost(firework); + } +@@ -3459,7 +3522,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + // Paper end - custom chat completions API + + // Spigot start +- public class Spigot extends Entity.Spigot { ++ public class Spigot extends org.bukkit.entity.Entity.Spigot { + + /** + * Gets the connection address of this player, regardless of whether it diff --git a/patches/server/1055-Add-listing-API-for-PlayerProfile.patch b/patches/server/1055-Add-listing-API-for-PlayerProfile.patch new file mode 100644 index 0000000000..a85b78871a --- /dev/null +++ b/patches/server/1055-Add-listing-API-for-PlayerProfile.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Flo0 +Date: Sat, 6 Apr 2024 23:15:24 +0200 +Subject: [PATCH] Add listing API for PlayerProfile + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java +index 56eddd28429cf42c02d88b8bf79f8b616fa45289..04a7ad0381cfdb9d5ff913f82553ecbc5dfbc78f 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java +@@ -68,6 +68,30 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet enumSet = EnumSet.of( ++ ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ++ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ++ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY, ++ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, ++ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME ++ ); ++ return new ClientboundPlayerInfoUpdatePacket(enumSet, new ClientboundPlayerInfoUpdatePacket.Entry(playerInfoId, true, latency, gameMode, displayName)); ++ } ++ public static ClientboundPlayerInfoUpdatePacket updateLatency(UUID playerInfoId, int latency) { ++ EnumSet enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY); ++ return new ClientboundPlayerInfoUpdatePacket(enumSet, new ClientboundPlayerInfoUpdatePacket.Entry(playerInfoId, true, latency, GameType.DEFAULT_MODE, null)); ++ } ++ public static ClientboundPlayerInfoUpdatePacket updateGameMode(UUID playerInfoId, GameType gameMode) { ++ EnumSet enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE); ++ return new ClientboundPlayerInfoUpdatePacket(enumSet, new ClientboundPlayerInfoUpdatePacket.Entry(playerInfoId, true, 0, gameMode, null)); ++ } ++ public static ClientboundPlayerInfoUpdatePacket updateDisplayName(UUID playerInfoId, @Nullable Component displayName) { ++ EnumSet enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME); ++ return new ClientboundPlayerInfoUpdatePacket(enumSet, new ClientboundPlayerInfoUpdatePacket.Entry(playerInfoId, true, 0, GameType.DEFAULT_MODE, displayName)); ++ } ++ // Paper end - Add Listing API for PlayerProfile + + public ClientboundPlayerInfoUpdatePacket(FriendlyByteBuf buf) { + this.actions = buf.readEnumSet(ClientboundPlayerInfoUpdatePacket.Action.class); +@@ -188,6 +212,11 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet enumSet = EnumSet.of( ++ ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ++ ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED ++ ); ++ UUID profileId = profile.getId(); ++ GameType type = GameType.byId(gameMode.getValue()); ++ net.minecraft.network.chat.Component name = io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName); ++ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.addAndList(profileId, latency, type, name); ++ this.getHandle().connection.send(packet); ++ } ++ ++ @Override ++ public void updateListedProfileLatency(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile, int latency) { ++ Preconditions.checkNotNull(profile, "profile cannot be null"); ++ Preconditions.checkArgument(isOfflineProfile(profile), "using the profile of an online player is not allowed"); ++ if (this.getHandle().connection == null) return; ++ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.updateLatency(profile.getId(), latency)); ++ } ++ ++ @Override ++ public void updateListedProfileGameMode(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile, GameMode gameMode) { ++ Preconditions.checkNotNull(profile, "profile cannot be null"); ++ Preconditions.checkArgument(isOfflineProfile(profile), "using the profile of an online player is not allowed"); ++ if (this.getHandle().connection == null) return; ++ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.updateGameMode(profile.getId(), GameType.byId(gameMode.getValue()))); ++ } ++ ++ @Override ++ public void updateListedProfileDisplayName(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile, @Nullable net.kyori.adventure.text.Component displayName) { ++ Preconditions.checkNotNull(profile, "profile cannot be null"); ++ Preconditions.checkArgument(isOfflineProfile(profile), "using the profile of an online player is not allowed"); ++ if (this.getHandle().connection == null) return; ++ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.updateDisplayName(profile.getId(), io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName))); ++ } ++ ++ @Override ++ public void unlistProfile(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile) { ++ Preconditions.checkNotNull(profile, "profile cannot be null"); ++ Preconditions.checkArgument(isOfflineProfile(profile), "using the profile of an online player is not allowed"); ++ if (this.getHandle().connection == null) return; ++ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.updateListed(profile.getId(), false)); ++ } ++ ++ private boolean isOfflineProfile(@NotNull com.destroystokyo.paper.profile.PlayerProfile profile) { ++ UUID profileId = profile.getId(); ++ return Bukkit.getPlayer(profileId) == null; ++ } ++ // Paper end - Add Listing API for PlayerProfile ++ + @Override + public Map serialize() { + Map result = new LinkedHashMap();