aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0669-Hide-unnecessary-itemmeta-from-clients.patch
blob: 31a1c523e9ae64079e10a627dc5e86ca0318a8be (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 fe83e4b592e13bf325e76d051df6901f22221484..b07fbf0121c6f147ff6f59d13c2d976db9cedad1 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2561,8 +2561,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 8623d6a59445ab1cc0a04ca87ee7b3e3567e1ddc..37f35a576c4bdf22daf6f47b412d9147980762b0 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3189,7 +3189,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:
@@ -3203,6 +3203,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()) {