From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Noah van der Aa Date: Tue, 3 Aug 2021 17:28:27 +0200 Subject: [PATCH] Hide unnecessary itemmeta from clients diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index b64fbce003c00a6371a849d4835632c18ad730bb..7e2d31737bd4977c9589541e1ebdcfe4ac40a335 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -912,6 +912,13 @@ public class PaperWorldConfig { behaviorTickRates = loadTickRates("behavior"); } + public boolean hideItemmetaFromClients = true; + public boolean hideDurabilityFromClients = false; + private void getHideItemmetaFromClients() { + hideItemmetaFromClients = getBoolean("anticheat.obfuscation.items.hide-itemmeta", hideItemmetaFromClients); + hideDurabilityFromClients = getBoolean("anticheat.obfuscation.items.hide-durability", hideDurabilityFromClients); + } + private com.google.common.collect.Table loadTickRates(String type) { log(" " + type + ":"); com.google.common.collect.Table table = com.google.common.collect.HashBasedTable.create(); diff --git a/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java b/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java index 3eb6bf4258b1de4697f96c2011df493cf7414a0c..0feadee6077dd6a8d8fd05b7a7d15ec1aa728fbb 100644 --- a/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java +++ b/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java @@ -127,6 +127,7 @@ public class EntityDataSerializers { public static final EntityDataSerializer ITEM_STACK = new EntityDataSerializer() { @Override public void write(FriendlyByteBuf buf, ItemStack value) { + net.minecraft.world.entity.LivingEntity.stripMeta(value, null); // Paper - strip items to prevent oversized data buf.writeItem(value); } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java index 62daf918d4ab00963041ca869ae718f14f2e3337..50d0280f3df59952d682f137197fd73644ba2cfe 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -3047,11 +3047,59 @@ public abstract class LivingEntity extends Entity { } + public static void stripMeta(ItemStack itemStack, @org.jetbrains.annotations.Nullable Level level) { + if (itemStack.getTag() != null) { + CompoundTag nbt = itemStack.getTag(); + if (level != null && level.paperConfig.hideDurabilityFromClients) { + // Only show damage values for elytra's, since they show a different texture when broken. + if (!itemStack.is(Items.ELYTRA) || itemStack.getDamageValue() < itemStack.getMaxDamage() - 1) { + itemStack.setDamageValue(0); + } + } + + if (level != null && level.paperConfig.hideItemmetaFromClients) { + // 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. + itemStack.setCount(itemStack.getCount() > 1 ? 2 : 1); + // We can't just strip out display, leather helmets still use the display.color tag. + if (nbt.get("display") instanceof CompoundTag displayTag) { + displayTag.remove("Lore"); + displayTag.remove("Name"); + } + + if (nbt.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(); + enchantments.add(new CompoundTag()); + nbt.put("Enchantments", enchantments); + } + nbt.remove("AttributeModifiers"); + } + // Always remove items to prevent oversized data + // Bundles change their texture based on their fullness. + if (itemStack.is(Items.BUNDLE) && nbt.get("Items") instanceof ListTag oldItems && !oldItems.isEmpty()) { + org.bukkit.inventory.meta.BundleMeta bundleMeta = (org.bukkit.inventory.meta.BundleMeta) itemStack.asBukkitMirror().getItemMeta(); + int sizeUsed = 0; + for (org.bukkit.inventory.ItemStack item : bundleMeta.getItems()) { + int scale = 64 / item.getMaxStackSize(); + sizeUsed += scale * item.getAmount(); + } + // Now we add a single fake item that uses the same amount of slots as all other items. + ListTag items = new ListTag(); + items.add(new ItemStack(Items.PAPER, sizeUsed).save(new CompoundTag())); + nbt.put("Items", items); + } + nbt.remove("BlockEntityTag"); + nbt.remove("EntityTag"); + } + } + private void handleEquipmentChanges(Map equipmentChanges) { List> list = Lists.newArrayListWithCapacity(equipmentChanges.size()); equipmentChanges.forEach((enumitemslot, itemstack) -> { ItemStack itemstack1 = itemstack.copy(); + stripMeta(itemstack1, this.level); // Paper - hide unnecessary itemmeta from clients list.add(Pair.of(enumitemslot, itemstack1)); switch (enumitemslot.getType()) {