From 7abf02b17c7199de7a6b22473fafd31677be5464 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sat, 4 Aug 2018 20:42:27 -0400 Subject: [PATCH] Fix client rendering skulls from same user See: https://github.com/PaperMC/Paper/issues/1304 Changes the UUID sent to client to be based on either the texture payload, or random. This allows the client to render multiple skull textures from the same user, for when different skins were used when skull was made. Closes #1304 --- ...ient-rendering-skulls-from-same-user.patch | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 Spigot-Server-Patches/0331-Fix-client-rendering-skulls-from-same-user.patch diff --git a/Spigot-Server-Patches/0331-Fix-client-rendering-skulls-from-same-user.patch b/Spigot-Server-Patches/0331-Fix-client-rendering-skulls-from-same-user.patch new file mode 100644 index 0000000000..99693c3b04 --- /dev/null +++ b/Spigot-Server-Patches/0331-Fix-client-rendering-skulls-from-same-user.patch @@ -0,0 +1,130 @@ +From a70e309b53e72f03208ea7a96c2bb195a716d2ef Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 22 Nov 2016 00:40:42 -0500 +Subject: [PATCH] Fix client rendering skulls from same user + +See: https://github.com/PaperMC/Paper/issues/1304 + +Changes the UUID sent to client to be based on either +the texture payload, or random. + +This allows the client to render multiple skull textures from the same user, +for when different skins were used when skull was made. + +diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java +index e52014fd8f..da11ec1672 100644 +--- a/src/main/java/net/minecraft/server/ItemStack.java ++++ b/src/main/java/net/minecraft/server/ItemStack.java +@@ -44,7 +44,7 @@ public final class ItemStack { + private int e; + @Deprecated + private Item item; +- private NBTTagCompound tag; ++ NBTTagCompound tag; // Paper -> package private + private boolean h; + private EntityItemFrame i; + private ShapeDetectorBlock j; +diff --git a/src/main/java/net/minecraft/server/PacketDataSerializer.java b/src/main/java/net/minecraft/server/PacketDataSerializer.java +index d04afceb70..b0e8ffc4b1 100644 +--- a/src/main/java/net/minecraft/server/PacketDataSerializer.java ++++ b/src/main/java/net/minecraft/server/PacketDataSerializer.java +@@ -251,6 +251,15 @@ public class PacketDataSerializer extends ByteBuf { + CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); + // Spigot end + nbttagcompound = itemstack.getTag(); ++ // Paper start ++ if (nbttagcompound != null && nbttagcompound.hasKeyOfType("SkullOwner", 10)) { ++ NBTTagCompound owner = nbttagcompound.getCompound("SkullOwner"); ++ if (owner.hasKey("Id")) { ++ nbttagcompound.setString("SkullOwnerOrig", owner.getString("Id")); ++ TileEntitySkull.sanitizeUUID(owner); ++ } ++ } ++ // Paper end + } + + this.a(nbttagcompound); +@@ -271,6 +280,16 @@ public class PacketDataSerializer extends ByteBuf { + itemstack.setTag(this.j()); + // CraftBukkit start + if (itemstack.getTag() != null) { ++ // Paper start - Fix skulls of same owner - restore orig ID since we changed it on send to client ++ if (itemstack.tag.hasKey("SkullOwnerOrig")) { ++ NBTTagCompound owner = itemstack.tag.getCompound("SkullOwner"); ++ String ownerOrig = itemstack.tag.getString("SkullOwnerOrig"); ++ if (!owner.isEmpty() && !ownerOrig.isEmpty()) { ++ owner.setString("Id", ownerOrig); ++ } ++ itemstack.tag.remove("SkullOwnerOrig"); ++ } ++ // Paper end + CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +index 1aa36156a8..c5f0b85309 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +@@ -38,6 +38,7 @@ public class PacketPlayOutMapChunk implements Packet { + + if (this.f() || (i & 1 << j) != 0) { + NBTTagCompound nbttagcompound = tileentity.aa_(); ++ if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper + + this.e.add(nbttagcompound); + } +@@ -121,7 +122,7 @@ public class PacketPlayOutMapChunk implements Packet { + BiomeBase[] abiomebase = chunk.getBiomeIndex(); + + for (l = 0; l < abiomebase.length; ++l) { +- packetdataserializer.writeInt(BiomeBase.REGISTRY_ID.a((Object) abiomebase[l])); ++ packetdataserializer.writeInt(BiomeBase.REGISTRY_ID.a(abiomebase[l])); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java +index 85fd8dab60..16a5537ce0 100644 +--- a/src/main/java/net/minecraft/server/TileEntitySkull.java ++++ b/src/main/java/net/minecraft/server/TileEntitySkull.java +@@ -143,9 +143,37 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa + return this.a; + } + ++ // Paper start ++ static NBTTagCompound sanitizeTileEntityUUID(NBTTagCompound cmp) { ++ NBTTagCompound owner = cmp.getCompound("Owner"); ++ if (!owner.isEmpty()) { ++ sanitizeUUID(owner); ++ } ++ return cmp; ++ } ++ ++ static void sanitizeUUID(NBTTagCompound owner) { ++ NBTTagCompound properties = owner.getCompound("Properties"); ++ NBTTagList list = null; ++ if (!properties.isEmpty()) { ++ list = properties.getList("textures", 10); ++ } ++ ++ if (list != null && !list.isEmpty()) { ++ String textures = ((NBTTagCompound)list.get(0)).getString("Value"); ++ if (textures != null && textures.length() > 3) { ++ String uuid = UUID.nameUUIDFromBytes(textures.getBytes()).toString(); ++ owner.setString("Id", uuid); ++ return; ++ } ++ } ++ owner.setString("Id", UUID.randomUUID().toString()); ++ } ++ // Paper end ++ + @Nullable + public PacketPlayOutTileEntityData getUpdatePacket() { +- return new PacketPlayOutTileEntityData(this.position, 4, this.aa_()); ++ return new PacketPlayOutTileEntityData(this.position, 4, sanitizeTileEntityUUID(this.aa_())); // Paper + } + + public NBTTagCompound aa_() { +-- +2.18.0 +