aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0666-Hide-unnecessary-itemmeta-from-clients.patch
blob: 6224365ef187d2eafac3300ac76e0a9f544036b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Tue, 3 Aug 2021 17:28:27 +0200
Subject: [PATCH] Hide unnecessary itemmeta from clients


diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 86f6e5bad325dd3d817b643388b196121624b8c7..062225ac8b5fbc44290352d78b215640691f3c23 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -337,7 +337,7 @@ public class ServerEntity {
                 if (!itemstack.isEmpty()) {
                     // Paper start - prevent oversized data
                     final ItemStack sanitized = LivingEntity.sanitizeItemStack(itemstack.copy(), false);
-                    list.add(Pair.of(enumitemslot, sanitized));
+                    list.add(Pair.of(enumitemslot, ((LivingEntity) this.entity).stripMeta(sanitized, false))); // Paper - Hide unnecessary item meta
                     // Paper end - prevent oversized data
                 }
             }
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index ace2cab310aa7d89e1b76bf5fdc9fd64f56b6cc7..cf173a2315f3a97a89dc2aabe81be285abe73603 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2565,8 +2565,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
                                 // Refresh the current entity metadata
                                 entity.getEntityData().refresh(ServerGamePacketListenerImpl.this.player);
                                 // SPIGOT-7136 - Allays
-                                if (entity instanceof Allay) {
-                                    ServerGamePacketListenerImpl.this.send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList())));
+                                if (entity instanceof Allay allay) { // Paper - Hide unnecessary item meta
+                                    ServerGamePacketListenerImpl.this.send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, allay.stripMeta(allay.getItemBySlot(slot), true))).collect(Collectors.toList()))); // Paper - Hide unnecessary item meta
                                     ServerGamePacketListenerImpl.this.player.containerMenu.sendAllDataToRemote();
                                 }
                             }
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index ccbafac8e5930571928e87f1c83f9f481fcfe8c4..9af308ef5e55df9ce08b25e358e48d1c6f67d663 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3210,7 +3210,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
 
             // Paper start - prevent oversized data
             ItemStack toSend = sanitizeItemStack(itemstack1, true);
-            list.add(Pair.of(enumitemslot, toSend));
+            list.add(Pair.of(enumitemslot, stripMeta(toSend, toSend == itemstack1))); // Paper - Hide unnecessary item meta
             // Paper end - prevent oversized data
             switch (enumitemslot.getType()) {
                 case HAND:
@@ -3224,6 +3224,77 @@ public abstract class LivingEntity extends Entity implements Attackable {
         ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list));
     }
 
+    // Paper start - Hide unnecessary item meta
+    public ItemStack stripMeta(final ItemStack itemStack, final boolean copyItemStack) {
+        if (itemStack.isEmpty() || (!itemStack.hasTag() && itemStack.getCount() < 2)) {
+            return itemStack;
+        }
+
+        final ItemStack copy = copyItemStack ? itemStack.copy() : itemStack;
+        if (this.level().paperConfig().anticheat.obfuscation.items.hideDurability) {
+            // Only show damage values for elytra's, since they show a different texture when broken.
+            if (!copy.is(Items.ELYTRA) || copy.getDamageValue() < copy.getMaxDamage() - 1) {
+                copy.setDamageValue(0);
+            }
+        }
+
+        final CompoundTag tag = copy.getTag();
+        if (this.level().paperConfig().anticheat.obfuscation.items.hideItemmeta) {
+            // Some resource packs show different textures when there is more than one item. Since this shouldn't provide a big advantage,
+            // we'll tell the client if there's one or (more than) two items.
+            copy.setCount(copy.getCount() > 1 ? 2 : 1);
+            // We can't just strip out display, leather helmets still use the display.color tag.
+            if (tag != null) {
+                if (tag.get("display") instanceof CompoundTag displayTag) {
+                    displayTag.remove("Lore");
+                    displayTag.remove("Name");
+                }
+
+                if (tag.get("Enchantments") instanceof ListTag enchantmentsTag && !enchantmentsTag.isEmpty()) {
+                    // The client still renders items with the enchantment glow if the enchantments tag contains at least one (empty) child.
+                    ListTag enchantments = new ListTag();
+                    CompoundTag fakeEnchantment = new CompoundTag();
+                    // Soul speed boots generate client side particles.
+                    if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SOUL_SPEED, itemStack) > 0) {
+                        fakeEnchantment.putString("id", org.bukkit.enchantments.Enchantment.SOUL_SPEED.getKey().asString());
+                        fakeEnchantment.putInt("lvl", 1);
+                    }
+                    enchantments.add(fakeEnchantment);
+                    tag.put("Enchantments", enchantments);
+                }
+                tag.remove("AttributeModifiers");
+                tag.remove("Unbreakable");
+                tag.remove("PublicBukkitValues"); // Persistent data container1
+
+                // Books
+                tag.remove("author");
+                tag.remove("filtered_title");
+                tag.remove("pages");
+                tag.remove("filtered_pages");
+                tag.remove("title");
+                tag.remove("generation");
+
+                // Filled maps
+                tag.remove("map");
+                tag.remove("map_scale_direction");
+                tag.remove("map_to_lock");
+            }
+        }
+
+        if (this.level().paperConfig().anticheat.obfuscation.items.hideItemmetaWithVisualEffects && tag != null) {
+            // Lodestone compasses
+            tag.remove("LodestonePos");
+            if (tag.contains("LodestoneDimension")) {
+                // The client shows the glint if either the position or the dimension is present, so we just wipe
+                // the position and fake the dimension
+                tag.putString("LodestoneDimension", "paper:paper");
+            }
+        }
+
+        return copy;
+    }
+    // Paper end - Hide unnecessary item meta
+
     // Paper start - prevent oversized data
     public static ItemStack sanitizeItemStack(final ItemStack itemStack, final boolean copyItemStack) {
         if (itemStack.isEmpty() || !itemStack.hasTag()) {