From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 18 Mar 2018 12:29:48 -0400 Subject: [PATCH] Player.setPlayerProfile API This can be useful for changing name or skins after a player has logged in. == AT == public-f net.minecraft.world.entity.player.Player gameProfile diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java index e97e0ea9c44a959c17849eac3fcecf4eff04d275..3580ce27843ab4e379360e2f63c8783e66384956 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1540,7 +1540,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic this.internalTeleport(dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch(), Collections.emptySet()); } - private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { + public void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { // Paper // CraftBukkit start if (Float.isNaN(f)) { f = 0; diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java index 6b31b0894e52ad6fc397624e50587ec04e46c099..0c7f280bae81bbb492d5780a43e5ffda0f58756a 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -330,11 +330,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; // Paper start - com.destroystokyo.paper.profile.PlayerProfile profile = org.bukkit.Bukkit.createProfile(uniqueId, playerName); + com.destroystokyo.paper.profile.PlayerProfile profile = com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile); AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); 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/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java index b17fe83bcd7bde44ee8c1f872fffa8bf40707c50..aac78c13361b19efa7b43a0c95458390f1ba8340 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java @@ -81,8 +81,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 new com.destroystokyo.paper.profile.CraftPlayerProfile(this.profile); // Paper } public Server getServer() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 063150563e35a3eeb6999f1b5b34de3f60318f66..699413ec5f26f3ff175f8032357e334b97bb8f94 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -269,11 +269,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return server.getPlayer(getUniqueId()) != null; } - @Override - public PlayerProfile getPlayerProfile() { - return new CraftPlayerProfile(this.getProfile()); - } - @Override public InetSocketAddress getAddress() { if (this.getHandle().connection == null) return null; @@ -1688,8 +1683,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()); @@ -1702,8 +1704,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().connection.send(new ClientboundPlayerInfoRemovePacket(List.of(otherPlayer.getUUID()))); } } - - server.getPluginManager().callEvent(new PlayerHideEntityEvent(this, entity)); } void resetAndHideEntity(org.bukkit.entity.Entity entity) { @@ -1768,12 +1768,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()); @@ -1783,6 +1796,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { 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 @@ -1794,6 +1840,36 @@ 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(worldserver.dimensionTypeId(), worldserver.dimension(), net.minecraft.world.level.biome.BiomeManager.obfuscateSeed(worldserver.getSeed()), handle.gameMode.getGameModeForPlayer(), handle.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), net.minecraft.network.protocol.game.ClientboundRespawnPacket.KEEP_ALL_DATA, this.getHandle().getLastDeathLocation(), handle.getPortalCooldown())); + handle.onUpdateAbilities(); + connection.internalTeleport(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), java.util.Collections.emptySet()); + net.minecraft.server.MinecraftServer.getServer().getPlayerList().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)); + } + + if (this.isOp()) { + this.setOp(false); + this.setOp(true); + } + } + // Paper end public void onEntityRemove(Entity entity) { this.invertedVisibilityEntities.remove(entity.getUUID()); diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java index 173a2832f029e3d568208a1b56419c1b8501483c..48cdd483c25825571043800f3cfa41a4d723f649 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java @@ -329,6 +329,12 @@ public class Commodore return; } + // 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" ) )