13
0
geforkt von Mirrors/Paper

Fix itemmeta patch and move oversized fix into its own (#6980)

Dieser Commit ist enthalten in:
Nassim Jahnke 2021-12-01 13:32:36 +01:00
Ursprung 16ba421c40
Commit a89a84e6dd
2 geänderte Dateien mit 150 neuen und 77 gelöschten Zeilen

Datei anzeigen

@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
behaviorTickRates = loadTickRates("behavior");
}
+ public boolean hideItemmetaFromClients = true;
+ public boolean hideItemmetaFromClients = false;
+ public boolean hideDurabilityFromClients = false;
+ private void getHideItemmetaFromClients() {
+ hideItemmetaFromClients = getBoolean("anticheat.obfuscation.items.hide-itemmeta", hideItemmetaFromClients);
@ -22,88 +22,75 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private com.google.common.collect.Table<String, String, Integer> loadTickRates(String type) {
log(" " + type + ":");
com.google.common.collect.Table<String, String, Integer> 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
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java
+++ b/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java
@@ -0,0 +0,0 @@ public class EntityDataSerializers {
public static final EntityDataSerializer<ItemStack> ITEM_STACK = new EntityDataSerializer<ItemStack>() {
@Override
public void write(FriendlyByteBuf buf, ItemStack value) {
+ value = net.minecraft.world.entity.LivingEntity.stripMeta(value, null, false); // Paper - strip items to prevent oversized data
buf.writeItem(value);
}
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -0,0 +0,0 @@ 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/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity {
}
+ public static ItemStack stripMeta(ItemStack itemStack, @org.jetbrains.annotations.Nullable Level level, boolean copy) {
+ if ((itemStack.getCount() > 1 || itemStack.hasTag()) && !itemStack.isEmpty()) {
+ if (copy) itemStack = itemStack.copy();
+ 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 != null) {
+ 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 (nbt != null) {
+ 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");
+ }
+ }
+ return itemStack;
+ }
+
private void handleEquipmentChanges(Map<EquipmentSlot, ItemStack> equipmentChanges) {
List<Pair<EquipmentSlot, ItemStack>> list = Lists.newArrayListWithCapacity(equipmentChanges.size());
equipmentChanges.forEach((enumitemslot, itemstack) -> {
ItemStack itemstack1 = itemstack.copy();
+ final ItemStack toSend = stripMeta(itemstack1, this.level, true); // Paper - hide unnecessary itemmeta from clients
- list.add(Pair.of(enumitemslot, itemstack1));
+ list.add(Pair.of(enumitemslot, toSend)); // Paper - hide unnecessary itemmeta from clients
// 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:
this.setLastHandItem(enumitemslot, itemstack1);
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity {
((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 (level.paperConfig.hideDurabilityFromClients) {
+ // 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);
+ }
+ }
+
+ if (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.
+ copy.setCount(copy.getCount() > 1 ? 2 : 1);
+ // We can't just strip out display, leather helmets still use the display.color tag.
+ final CompoundTag tag = copy.getTag();
+ 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();
+ enchantments.add(new CompoundTag());
+ tag.put("Enchantments", enchantments);
+ }
+ tag.remove("AttributeModifiers");
+ }
+ }
+ return copy;
+ }
+ // Paper end
+
// Paper end - prevent oversized data
public static ItemStack sanitizeItemStack(final ItemStack itemStack, final boolean copyItemStack) {
if (itemStack.isEmpty() || !itemStack.hasTag()) {

Datei anzeigen

@ -0,0 +1,86 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Wed, 1 Dec 2021 12:36:25 +0100
Subject: [PATCH] Prevent sending oversized item data in equipment and metadata
diff --git a/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java b/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java
+++ b/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java
@@ -0,0 +0,0 @@ public class EntityDataSerializers {
public static final EntityDataSerializer<ItemStack> ITEM_STACK = new EntityDataSerializer<ItemStack>() {
@Override
public void write(FriendlyByteBuf buf, ItemStack value) {
- buf.writeItem(value);
+ buf.writeItem(net.minecraft.world.entity.LivingEntity.sanitizeItemStack(value, false)); // Paper - prevent oversized data
}
@Override
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -0,0 +0,0 @@ public class ServerEntity {
ItemStack itemstack = ((LivingEntity) this.entity).getItemBySlot(enumitemslot);
if (!itemstack.isEmpty()) {
- list.add(Pair.of(enumitemslot, itemstack.copy()));
+ // Paper start - prevent oversized data
+ final ItemStack sanitized = LivingEntity.sanitizeItemStack(itemstack.copy(), false);
+ list.add(Pair.of(enumitemslot, sanitized));
+ // Paper end
}
}
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity {
equipmentChanges.forEach((enumitemslot, itemstack) -> {
ItemStack itemstack1 = itemstack.copy();
- list.add(Pair.of(enumitemslot, itemstack1));
+ // Paper start - prevent oversized data
+ ItemStack toSend = sanitizeItemStack(itemstack1, true);
+ list.add(Pair.of(enumitemslot, toSend));
+ // Paper end
switch (enumitemslot.getType()) {
case HAND:
this.setLastHandItem(enumitemslot, itemstack1);
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity {
((ServerLevel) this.level).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list));
}
+ // Paper end - prevent oversized data
+ public static ItemStack sanitizeItemStack(final ItemStack itemStack, final boolean copyItemStack) {
+ if (itemStack.isEmpty() || !itemStack.hasTag()) {
+ return itemStack;
+ }
+
+ final ItemStack copy = copyItemStack ? itemStack.copy() : itemStack;
+ final CompoundTag tag = copy.getTag();
+ if (copy.is(Items.BUNDLE) && tag.get("Items") instanceof ListTag oldItems && !oldItems.isEmpty()) {
+ // Bundles change their texture based on their fullness.
+ org.bukkit.inventory.meta.BundleMeta bundleMeta = (org.bukkit.inventory.meta.BundleMeta) copy.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()));
+ tag.put("Items", items);
+ }
+ if (tag.get("BlockEntityTag") instanceof CompoundTag blockEntityTag) {
+ blockEntityTag.remove("Items");
+ }
+ return copy;
+ }
+ // Paper end
+
private ItemStack getLastArmorItem(EquipmentSlot slot) {
return (ItemStack) this.lastArmorItemStacks.get(slot.getIndex());
}