aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0175-Player.setPlayerProfile-API.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0175-Player.setPlayerProfile-API.patch')
-rw-r--r--patches/server/0175-Player.setPlayerProfile-API.patch226
1 files changed, 226 insertions, 0 deletions
diff --git a/patches/server/0175-Player.setPlayerProfile-API.patch b/patches/server/0175-Player.setPlayerProfile-API.patch
new file mode 100644
index 0000000000..e555f43ee5
--- /dev/null
+++ b/patches/server/0175-Player.setPlayerProfile-API.patch
@@ -0,0 +1,226 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Aikar <[email protected]>
+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/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+index 4a62c1abc6f3c48bbda40325b4ce46632db3f28d..bab8c53041afb9606db55923e5466eab25640226 100644
+--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+@@ -341,11 +341,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
+
+ // 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/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
+index f4e08c6b20ba64402b8587bde3e01eedcc9c2568..ac5607fb1ac771f16b14d71e08a8d4183a39a002 100644
+--- a/src/main/java/net/minecraft/server/players/PlayerList.java
++++ b/src/main/java/net/minecraft/server/players/PlayerList.java
+@@ -799,10 +799,16 @@ public abstract class PlayerList {
+ }
+
+ 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() {
+diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
+index 818df09e9245b5d89b4180b1eaa51470b7539341..f6b2ca92fd3510a76cbf56d0ea55aa6caaf12ba1 100644
+--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
++++ b/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/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+index 09974c95ead0f1e38a3b3be2e7fccb3e227c21c9..7bb315c45a3b021ec6016c7ff70a88c1a371f799 100644
+--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
++++ b/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<ServerPlayer> 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/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
+index 371d31266a532e59c49dbb106e354296b119fa5e..61d617d4abb9c9cf5c711459aa98c8b173597a9a 100644
+--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
++++ b/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) {