Paper/patches/server/0176-Player.setPlayerProfile-API.patch
Jake Potrebic c6aa61ee18
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#11561)
Updated Upstream (Bukkit/CraftBukkit/Spigot)

Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
b9df8e9f SPIGOT-7933: Improve custom Minecart max speed
fc496179 Fix InstrumentTest
7c0ec598 PR-1075: Make Art an interface
c389f5a4 PR-1074: Make Sound an interface

CraftBukkit Changes:
df1efc0bb SPIGOT-7945: `Bukkit#dispatchCommand` throws `UnsupportedOperationException`
285df6e85 SPIGOT-7933: Improve custom Minecart max speed
a0f3d4e50 SPIGOT-7940: Recipe book errors after reload
9e0618ec2 SPIGOT-7937: Cannot spawn minecart during world generation with minecart_improvements enabled
1eb4d28da SPIGOT-7941: Fix resistance over 4 amplify causing issues in damage
52b99158a PR-1504: Make Art an interface
e18ae35f1 PR-1502: Make Sound an interface

Spigot Changes:
e65d67a7 SPIGOT-7934: Item entities start "bouncing" under certain conditions
2024-11-04 18:42:38 +01:00

227 lines
12 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
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 5cb84271abdabc0f2d44ad9425828431f8818a47..a929c809dc1dcb2bdab4db0d2a8ca794189e93d9 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 128fcd537783986d816dae6d1ce2afb7af07d45a..32eeca2467189c6c97f7da5529d4fe9375e8a848 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) {