Paper/patches/server/0718-Hide-unnecessary-itemmeta-from-clients.patch
Jake Potrebic d8847bc1f3
Updated Upstream (Bukkit/CraftBukkit) (#9922)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
fde5602a PR-927: Add PlayerRecipeBookSettingsChangeEvent
949ff217 PR-930: Add methods to get/set evoker fang attack delay
f6f7c79d SPIGOT-7514, PR-929: Add "Enchantment Roll" API to enchant items according to Minecraft mechanics
d40e22da PR-712: Add API to get full result of crafting items

CraftBukkit Changes:
c8feb0629 PR-1291: Improve precondition message in Entity#playEffect
482c56a00 PR-1285: Add PlayerRecipeBookSettingsChangeEvent
cdf798800 PR-1290: Add methods to get/set evoker fang attack delay
2c1b5f78f SPIGOT-7514, PR-1289: Add "Enchantment Roll" API to enchant items according to Minecraft mechanics
6aa644ae9 PR-992: Add API to get full result of crafting items
ffb1319bc PR-1287: Fix scoreboards not updating in Player#setStatistic
2023-11-11 12:25:45 -08:00

126 lines
7.5 KiB
Diff

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 67d9e636b424a91ab1f1478b757016099ca915dc..2898712d34dc5dd1f2e505746c515f773de2b0d8 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2551,8 +2551,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()) {