diff --git a/paper-server/patches/sources/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch b/paper-server/patches/sources/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch index a6d65e120..810ca11bb 100644 --- a/paper-server/patches/sources/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch @@ -242,11 +242,11 @@ + + // Paper start - Add more fields to AsyncPlayerPreLoginEvent + final InetAddress rawAddress = ((InetSocketAddress) this.connection.channel.remoteAddress()).getAddress(); -+ com.destroystokyo.paper.profile.PlayerProfile profile = org.bukkit.Bukkit.createProfile(uniqueId, playerName); ++ com.destroystokyo.paper.profile.PlayerProfile profile = com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitMirror(gameprofile); // Paper - setPlayerProfileAPI + AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, this.transferred, profile, this.connection.hostname); + server.getPluginManager().callEvent(asyncEvent); + profile = asyncEvent.getPlayerProfile(); -+ profile.complete(); ++ profile.complete(true); // Paper - setPlayerProfileAPI + gameprofile = com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile); + playerName = gameprofile.getName(); + uniqueId = gameprofile.getId(); diff --git a/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch b/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch index b73b76f86..d8e7dcb5c 100644 --- a/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch @@ -709,7 +709,22 @@ return entityplayer1; } -@@ -524,7 +808,18 @@ +@@ -516,15 +800,32 @@ + } + + public void sendPlayerPermissionLevel(ServerPlayer player) { ++ // Paper start - avoid recalculating permissions if possible ++ this.sendPlayerPermissionLevel(player, true); ++ } ++ ++ public void sendPlayerPermissionLevel(ServerPlayer player, boolean recalculatePermissions) { ++ // Paper end - avoid recalculating permissions if possible + GameProfile gameprofile = player.getGameProfile(); + int i = this.server.getProfilePermissions(gameprofile); + +- this.sendPlayerPermissionLevel(player, i); ++ this.sendPlayerPermissionLevel(player, i, recalculatePermissions); // Paper - avoid recalculating permissions if possible + } public void tick() { if (++this.sendAllPlayerInfoIn > 600) { @@ -729,7 +744,7 @@ this.sendAllPlayerInfoIn = 0; } -@@ -541,6 +836,25 @@ +@@ -541,6 +842,25 @@ } @@ -755,7 +770,7 @@ public void broadcastAll(Packet packet, ResourceKey dimension) { Iterator iterator = this.players.iterator(); -@@ -554,7 +868,7 @@ +@@ -554,7 +874,7 @@ } @@ -764,7 +779,7 @@ PlayerTeam scoreboardteam = source.getTeam(); if (scoreboardteam != null) { -@@ -573,7 +887,7 @@ +@@ -573,7 +893,7 @@ } } @@ -773,7 +788,7 @@ PlayerTeam scoreboardteam = source.getTeam(); if (scoreboardteam == null) { -@@ -619,7 +933,7 @@ +@@ -619,7 +939,7 @@ } public void deop(GameProfile profile) { @@ -782,7 +797,7 @@ ServerPlayer entityplayer = this.getPlayer(profile.getId()); if (entityplayer != null) { -@@ -643,36 +957,51 @@ +@@ -643,36 +963,51 @@ player.connection.send(new ClientboundEntityEventPacket(player, b0)); } @@ -847,7 +862,7 @@ if (entityplayer != player && entityplayer.level().dimension() == worldKey) { double d4 = x - entityplayer.getX(); double d5 = y - entityplayer.getY(); -@@ -687,10 +1016,12 @@ +@@ -687,10 +1022,12 @@ } public void saveAll() { @@ -860,7 +875,7 @@ } public UserWhiteList getWhiteList() { -@@ -712,15 +1043,19 @@ +@@ -712,15 +1049,19 @@ public void reloadWhiteList() {} public void sendLevelInfo(ServerPlayer player, ServerLevel world) { @@ -884,7 +899,7 @@ } player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F)); -@@ -729,8 +1064,16 @@ +@@ -729,8 +1070,16 @@ public void sendAllPlayerInfo(ServerPlayer player) { player.inventoryMenu.sendAllDataToRemote(); @@ -902,7 +917,7 @@ } public int getPlayerCount() { -@@ -786,11 +1129,35 @@ +@@ -786,11 +1135,35 @@ } public void removeAll() { @@ -940,7 +955,7 @@ public void broadcastSystemMessage(Component message, boolean overlay) { this.broadcastSystemMessage(message, (entityplayer) -> { -@@ -819,24 +1186,43 @@ +@@ -819,24 +1192,43 @@ } public void broadcastChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound params) { @@ -987,7 +1002,7 @@ } if (flag1 && sender != null) { -@@ -845,20 +1231,27 @@ +@@ -845,20 +1237,27 @@ } @@ -1020,7 +1035,7 @@ Path path = file2.toPath(); if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) { -@@ -867,7 +1260,7 @@ +@@ -867,7 +1266,7 @@ } serverstatisticmanager = new ServerStatsCounter(this.server, file1); @@ -1029,7 +1044,7 @@ } return serverstatisticmanager; -@@ -875,13 +1268,13 @@ +@@ -875,13 +1274,13 @@ public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) { UUID uuid = player.getUUID(); @@ -1045,7 +1060,7 @@ } advancementdataplayer.setPlayer(player); -@@ -932,15 +1325,28 @@ +@@ -932,15 +1331,28 @@ } public void reloadResources() { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java index 818df09e9..f6b2ca92f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java @@ -82,8 +82,8 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa } @Override - public PlayerProfile getPlayerProfile() { - return new CraftPlayerProfile(this.profile); + public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() { // Paper + return com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitCopy(this.profile); // Paper } public Server getServer() { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 09974c95e..7bb315c45 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -254,11 +254,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this.server.getPlayer(this.getUniqueId()) != null; } - @Override - public PlayerProfile getPlayerProfile() { - return new CraftPlayerProfile(this.getProfile()); - } - @Override public InetSocketAddress getAddress() { if (this.getHandle().connection.protocol() == null) return null; @@ -1819,8 +1814,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private void untrackAndHideEntity(org.bukkit.entity.Entity entity) { // Remove this entity from the hidden player's EntityTrackerEntry - ChunkMap tracker = ((ServerLevel) this.getHandle().level()).getChunkSource().chunkMap; + // Paper start Entity other = ((CraftEntity) entity).getHandle(); + unregisterEntity(other); + + server.getPluginManager().callEvent(new PlayerHideEntityEvent(this, entity)); + } + private void unregisterEntity(Entity other) { + // Paper end + ChunkMap tracker = ((ServerLevel) this.getHandle().level()).getChunkSource().chunkMap; ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); if (entry != null) { entry.removePlayer(this.getHandle()); @@ -1833,8 +1835,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().connection.send(new ClientboundPlayerInfoRemovePacket(List.of(otherPlayer.getUUID()))); } } - - this.server.getPluginManager().callEvent(new PlayerHideEntityEvent(this, entity)); } void resetAndHideEntity(org.bukkit.entity.Entity entity) { @@ -1899,12 +1899,25 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } private void trackAndShowEntity(org.bukkit.entity.Entity entity) { + // Paper start - uuid override + this.trackAndShowEntity(entity, null); + } + private void trackAndShowEntity(org.bukkit.entity.Entity entity, final @Nullable UUID uuidOverride) { + // Paper end ChunkMap tracker = ((ServerLevel) this.getHandle().level()).getChunkSource().chunkMap; Entity other = ((CraftEntity) entity).getHandle(); if (other instanceof ServerPlayer) { ServerPlayer otherPlayer = (ServerPlayer) other; + // Paper start - uuid override + UUID original = null; + if (uuidOverride != null) { + original = otherPlayer.getUUID(); + otherPlayer.setUUID(uuidOverride); + } + // Paper end this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer))); + if (original != null) otherPlayer.setUUID(original); // Paper - uuid override } ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); @@ -1914,6 +1927,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.server.getPluginManager().callEvent(new PlayerShowEntityEvent(this, entity)); } + // Paper start + @Override + public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) { + ServerPlayer self = this.getHandle(); + GameProfile gameProfile = com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile); + if (!self.sentListPacket) { + self.gameProfile = gameProfile; + return; + } + List players = this.server.getServer().getPlayerList().players; + // First unregister the player for all players with the OLD game profile + for (ServerPlayer player : players) { + CraftPlayer bukkitPlayer = player.getBukkitEntity(); + if (bukkitPlayer.canSee(this)) { + bukkitPlayer.unregisterEntity(self); + } + } + + // Set the game profile here, we should have unregistered the entity via iterating all player entities above. + self.gameProfile = gameProfile; + + // Re-register the game profile for all players + for (ServerPlayer player : players) { + CraftPlayer bukkitPlayer = player.getBukkitEntity(); + if (bukkitPlayer.canSee(this)) { + bukkitPlayer.trackAndShowEntity(self.getBukkitEntity(), gameProfile.getId()); + } + } + + // Refresh misc player things AFTER sending game profile + this.refreshPlayer(); + } + // Paper end void resetAndShowEntity(org.bukkit.entity.Entity entity) { // SPIGOT-7312: Can't show/hide self @@ -1925,6 +1971,34 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.trackAndShowEntity(entity); } } + // Paper start + public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() { + return new com.destroystokyo.paper.profile.CraftPlayerProfile(this).clone(); + } + + private void refreshPlayer() { + ServerPlayer handle = this.getHandle(); + Location loc = this.getLocation(); + + ServerGamePacketListenerImpl connection = handle.connection; + + //Respawn the player then update their position and selected slot + ServerLevel worldserver = handle.serverLevel(); + connection.send(new net.minecraft.network.protocol.game.ClientboundRespawnPacket(handle.createCommonSpawnInfo(worldserver), net.minecraft.network.protocol.game.ClientboundRespawnPacket.KEEP_ALL_DATA)); + handle.onUpdateAbilities(); + connection.internalTeleport(net.minecraft.world.entity.PositionMoveRotation.of(this.getHandle()), java.util.Collections.emptySet()); + net.minecraft.server.players.PlayerList playerList = handle.server.getPlayerList(); + playerList.sendPlayerPermissionLevel(handle, false); + playerList.sendLevelInfo(handle, worldserver); + playerList.sendAllPlayerInfo(handle); + + // Resend their XP and effects because the respawn packet resets it + connection.send(new net.minecraft.network.protocol.game.ClientboundSetExperiencePacket(handle.experienceProgress, handle.totalExperience, handle.experienceLevel)); + for (net.minecraft.world.effect.MobEffectInstance mobEffect : handle.getActiveEffects()) { + connection.send(new net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket(handle.getId(), mobEffect, false)); + } + } + // Paper end public void onEntityRemove(Entity entity) { this.invertedVisibilityEntities.remove(entity.getUUID()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/paper-server/src/main/java/org/bukkit/craftbukkit/util/Commodore.java index 371d31266..61d617d4a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/util/Commodore.java @@ -472,6 +472,13 @@ public class Commodore { } // Paper end - Rewrite plugins + // Paper start - Rewrite plugins + if ((owner.equals("org/bukkit/OfflinePlayer") || owner.equals("org/bukkit/entity/Player")) && name.equals("getPlayerProfile") && desc.equals("()Lorg/bukkit/profile/PlayerProfile;")) { + super.visitMethodInsn(opcode, owner, name, "()Lcom/destroystokyo/paper/profile/PlayerProfile;", itf); + return; + } + // Paper end + if (modern) { if (owner.equals("org/bukkit/Material") || (instantiatedMethodType != null && instantiatedMethodType.getDescriptor().startsWith("(Lorg/bukkit/Material;)"))) { switch (name) {