aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0719-Hide-unnecessary-itemmeta-from-clients.patch
blob: 6553879c95c4066168543cf89b83cdf6e28167f8 (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 8d2870c780c4c253f6570c7ef73f6e7c2ccc46ad..0cbb5dd17c5b37ad90ce11a31b64470722026d06 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 - remove unnecessary item meta
                     // Paper end
                 }
             }
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index f1c0ff296b58aa020b00d6681ecf3cb4db09f561..88c543881c8e7453fffc08e1d5a3226505a8889e 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2550,8 +2550,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
+                                    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 - remove 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 c2d06bd94c829e1e9cf00c20e5e2547c60d4b0ff..e0e9a1a0becd4754f4ee1a53e7a91206da22ac45 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3193,7 +3193,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
             switch (enumitemslot.getType()) {
                 case HAND:
@@ -3207,6 +3207,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
+
     // Paper start - prevent oversized data
     public static ItemStack sanitizeItemStack(final ItemStack itemStack, final boolean copyItemStack) {
         if (itemStack.isEmpty() || !itemStack.hasTag()) {