PaperMC/Spigot-Server-Patches/0261-Fix-client-rendering-skulls-from-same-user.patch
Mariell Hoversholm c02c22fde5 fix: legacy component serialisation was wiped out
When merging 4e958e229f, nobody caught the
fact we removed the component serialisation of legacy BungeeCord Chat
API components in the PacketPlayOutTitle class.

Test plugin code:

```kotlin
class LegacyMessageCommand : BaseCommand() {
    override fun register(manager: PaperCommandManager<CommandSender>) {
        manager.command(manager.commandBuilder("legacymsg")
            .sender<Player>()
            .handler {
                val component = ComponentBuilder("Test")
                    .color(ChatColor.DARK_RED)
                    .bold(true)
                    .append(" message")
                    .bold(false)
                    .color(ChatColor.of("#f8a8a8"))
                    .event(
                        HoverEvent(
                            HoverEvent.Action.SHOW_TEXT,
                            Text(
                                ComponentBuilder("Test hover")
                                    .color(ChatColor.AQUA)
                                    .underlined(true)
                                    .create()
                            )
                        )
                    )
                    .event(
                        ClickEvent(
                            ClickEvent.Action.SUGGEST_COMMAND,
                            "/legacymsg"
                        )
                    )
                    .create()
                it.sender.sendMessage(*component)
                it.sender.sendActionBar(*component)
                it.sender.sendTitle(
                    Title.builder()
                        .title(component)
                        .subtitle(component)
                        .fadeIn(40)
                        .stay(60)
                        .fadeOut(40)
                        .build()
                )
            })
    }
}
```

Fixes GH-5271.
2021-02-27 12:46:57 +01:00

123 lines
6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
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 bdb6f9bf3477f85859e3f0dd761e2e895f1a8e2b..22568201a292edc8e25396e55cad1572d419b775 100644
--- a/src/main/java/net/minecraft/server/ItemStack.java
+++ b/src/main/java/net/minecraft/server/ItemStack.java
@@ -60,7 +60,7 @@ public final class ItemStack {
private int g;
@Deprecated
private Item item;
- private NBTTagCompound tag;
+ NBTTagCompound tag; // Paper -> package private
private boolean j;
private Entity k;
private ShapeDetectorBlock l;
diff --git a/src/main/java/net/minecraft/server/PacketDataSerializer.java b/src/main/java/net/minecraft/server/PacketDataSerializer.java
index 391f96e585d80f7921fd96f207b0b60d88961ae7..3a257d3b0a6adb4d0a43833b996d70765559eff8 100644
--- a/src/main/java/net/minecraft/server/PacketDataSerializer.java
+++ b/src/main/java/net/minecraft/server/PacketDataSerializer.java
@@ -298,9 +298,18 @@ public class PacketDataSerializer extends ByteBuf {
if (item.usesDurability() || item.n()) {
// Spigot start - filter
itemstack = itemstack.cloneItemStack();
- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack));
+ //CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported
// Spigot end
nbttagcompound = itemstack.getTag();
+ // Paper start
+ if (nbttagcompound != null && nbttagcompound.hasKeyOfType("SkullOwner", 10)) {
+ NBTTagCompound owner = nbttagcompound.getCompound("SkullOwner");
+ if (owner.hasUUID("Id")) {
+ nbttagcompound.setUUID("SkullOwnerOrig", owner.getUUID("Id"));
+ TileEntitySkull.sanitizeUUID(owner);
+ }
+ }
+ // Paper end
}
this.a(nbttagcompound);
@@ -320,7 +329,16 @@ public class PacketDataSerializer extends ByteBuf {
itemstack.setTag(this.l());
// CraftBukkit start
if (itemstack.getTag() != null) {
- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack));
+ // 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");
+ if (itemstack.tag.hasKey("SkullOwnerOrig")) {
+ owner.map.put("Id", itemstack.tag.map.get("SkullOwnerOrig"));
+ itemstack.tag.remove("SkullOwnerOrig");
+ }
+ }
+ // Paper end
+ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported
}
// CraftBukkit end
return itemstack;
diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java
index 36a7e41cc5036345929ebf4d2fa160a8c16c2c0a..0ef4fbb19fc816f578ad741c4406790f4185093d 100644
--- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java
+++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java
@@ -58,6 +58,7 @@ public class PacketPlayOutMapChunk implements Packet<PacketListenerPlayOut> {
if (this.f() || (i & 1 << j) != 0) {
NBTTagCompound nbttagcompound = tileentity.b();
+ if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper
this.g.add(nbttagcompound);
}
diff --git a/src/main/java/net/minecraft/server/TileEntitySkull.java b/src/main/java/net/minecraft/server/TileEntitySkull.java
index 4fae1b3274a96b871b39de083e9b28ab6129533f..579a81e521fdfabfa0318d06c6760a8ab7a88c1e 100644
--- a/src/main/java/net/minecraft/server/TileEntitySkull.java
+++ b/src/main/java/net/minecraft/server/TileEntitySkull.java
@@ -145,9 +145,37 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa
@Nullable
@Override
public PacketPlayOutTileEntityData getUpdatePacket() {
- return new PacketPlayOutTileEntityData(this.position, 4, this.b());
+ return new PacketPlayOutTileEntityData(this.position, 4, sanitizeTileEntityUUID(this.b())); // Paper
}
+ // 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) {
+ UUID uuid = UUID.nameUUIDFromBytes(textures.getBytes());
+ owner.setUUID("Id", uuid);
+ return;
+ }
+ }
+ owner.setUUID("Id", UUID.randomUUID());
+ }
+ // Paper end
+
@Override
public NBTTagCompound b() {
return this.save(new NBTTagCompound());