diff --git a/patches/unapplied/server/Add-API-for-item-entity-health.patch b/patches/server/Add-API-for-item-entity-health.patch similarity index 100% rename from patches/unapplied/server/Add-API-for-item-entity-health.patch rename to patches/server/Add-API-for-item-entity-health.patch diff --git a/patches/server/Add-ItemFactory-getSpawnEgg-API.patch b/patches/server/Add-ItemFactory-getSpawnEgg-API.patch index 347b99d45a..95758c63fa 100644 --- a/patches/server/Add-ItemFactory-getSpawnEgg-API.patch +++ b/patches/server/Add-ItemFactory-getSpawnEgg-API.patch @@ -39,9 +39,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start - ItemFactory#getSpawnEgg (paper had original method that returned ItemStack, upstream added identical but returned Material) + if (owner.equals("org/bukkit/inventory/ItemFactory") && name.equals("getSpawnEgg") && desc.equals("(Lorg/bukkit/entity/EntityType;)Lorg/bukkit/inventory/ItemStack;")) { + super.visitInsn(Opcodes.SWAP); // has 1 param, this moves the owner instance to the top for the checkcast -+ super.visitTypeInsn(Opcodes.CHECKCAST, CB_PACKAGE + "/inventory/CraftItemFactory"); ++ super.visitTypeInsn(Opcodes.CHECKCAST, CB_PACKAGE_PREFIX + "inventory/CraftItemFactory"); + super.visitInsn(Opcodes.SWAP); // moves param back to the the top of stack -+ super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CB_PACKAGE + "/inventory/CraftItemFactory", "getSpawnEgg0", desc, false); ++ super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CB_PACKAGE_PREFIX + "inventory/CraftItemFactory", "getSpawnEgg0", desc, false); + return; + } + // Paper end - ItemFactory#getSpawnEgg diff --git a/patches/unapplied/server/Add-PlayerItemFrameChangeEvent.patch b/patches/server/Add-PlayerItemFrameChangeEvent.patch similarity index 94% rename from patches/unapplied/server/Add-PlayerItemFrameChangeEvent.patch rename to patches/server/Add-PlayerItemFrameChangeEvent.patch index fa1dac8e04..8bc4567103 100644 --- a/patches/unapplied/server/Add-PlayerItemFrameChangeEvent.patch +++ b/patches/server/Add-PlayerItemFrameChangeEvent.patch @@ -9,13 +9,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java @@ -0,0 +0,0 @@ package net.minecraft.world.entity.decoration; + import com.mojang.logging.LogUtils; - import java.util.OptionalInt; import javax.annotation.Nullable; +import io.papermc.paper.event.player.PlayerItemFrameChangeEvent; // Paper - Add PlayerItemFrameChangeEvent import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; - import net.minecraft.nbt.CompoundTag; + import net.minecraft.core.component.DataComponents; @@ -0,0 +0,0 @@ public class ItemFrame extends HangingEntity { return true; } @@ -43,9 +43,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.setItem(ItemStack.fromBukkitCopy(event.getItemStack())); + // Paper end - Add PlayerItemFrameChangeEvent this.gameEvent(GameEvent.BLOCK_CHANGE, player); - if (!player.getAbilities().instabuild) { - itemstack.shrink(1); - } + itemstack.consume(1, player); } } else { + // Paper start - Add PlayerItemFrameChangeEvent diff --git a/patches/unapplied/server/Add-config-option-for-worlds-affected-by-time-cmd.patch b/patches/server/Add-config-option-for-worlds-affected-by-time-cmd.patch similarity index 100% rename from patches/unapplied/server/Add-config-option-for-worlds-affected-by-time-cmd.patch rename to patches/server/Add-config-option-for-worlds-affected-by-time-cmd.patch diff --git a/patches/unapplied/server/Add-missing-IAE-check-for-PersistentDataContainer-ha.patch b/patches/server/Add-missing-IAE-check-for-PersistentDataContainer-ha.patch similarity index 100% rename from patches/unapplied/server/Add-missing-IAE-check-for-PersistentDataContainer-ha.patch rename to patches/server/Add-missing-IAE-check-for-PersistentDataContainer-ha.patch diff --git a/patches/unapplied/server/Add-more-Campfire-API.patch b/patches/server/Add-more-Campfire-API.patch similarity index 96% rename from patches/unapplied/server/Add-more-Campfire-API.patch rename to patches/server/Add-more-Campfire-API.patch index a06f915a8e..1dbeb339ca 100644 --- a/patches/unapplied/server/Add-more-Campfire-API.patch +++ b/patches/server/Add-more-Campfire-API.patch @@ -52,7 +52,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override @@ -0,0 +0,0 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { - ContainerHelper.saveAllItems(nbt, this.items, true); + ContainerHelper.saveAllItems(nbt, this.items, true, registryLookup); nbt.putIntArray("CookingTimes", this.cookingProgress); nbt.putIntArray("CookingTotalTimes", this.cookingTime); + // Paper start - Add more Campfire API @@ -70,8 +70,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftCampfire.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCampfire.java @@ -0,0 +0,0 @@ public class CraftCampfire extends CraftBlockEntityState im - public CraftCampfire copy() { - return new CraftCampfire(this); + public CraftCampfire copy(Location location) { + return new CraftCampfire(this, location); } + + // Paper start diff --git a/patches/unapplied/server/Add-root-admin-user-detection.patch b/patches/server/Add-root-admin-user-detection.patch similarity index 100% rename from patches/unapplied/server/Add-root-admin-user-detection.patch rename to patches/server/Add-root-admin-user-detection.patch diff --git a/patches/unapplied/server/Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from patches/unapplied/server/Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/server/Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/patches/unapplied/server/Bucketable-API.patch b/patches/server/Bucketable-API.patch similarity index 100% rename from patches/unapplied/server/Bucketable-API.patch rename to patches/server/Bucketable-API.patch diff --git a/patches/unapplied/server/Configurable-feature-seeds.patch b/patches/server/Configurable-feature-seeds.patch similarity index 100% rename from patches/unapplied/server/Configurable-feature-seeds.patch rename to patches/server/Configurable-feature-seeds.patch diff --git a/patches/unapplied/server/Configurable-max-block-light-for-monster-spawning.patch b/patches/server/Configurable-max-block-light-for-monster-spawning.patch similarity index 100% rename from patches/unapplied/server/Configurable-max-block-light-for-monster-spawning.patch rename to patches/server/Configurable-max-block-light-for-monster-spawning.patch diff --git a/patches/unapplied/server/Entity-powdered-snow-API.patch b/patches/server/Entity-powdered-snow-API.patch similarity index 100% rename from patches/unapplied/server/Entity-powdered-snow-API.patch rename to patches/server/Entity-powdered-snow-API.patch diff --git a/patches/unapplied/server/Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch b/patches/server/Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch similarity index 100% rename from patches/unapplied/server/Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch rename to patches/server/Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch diff --git a/patches/unapplied/server/Expose-vanilla-BiomeProvider-from-WorldInfo.patch b/patches/server/Expose-vanilla-BiomeProvider-from-WorldInfo.patch similarity index 100% rename from patches/unapplied/server/Expose-vanilla-BiomeProvider-from-WorldInfo.patch rename to patches/server/Expose-vanilla-BiomeProvider-from-WorldInfo.patch diff --git a/patches/unapplied/server/Fix-ChunkSnapshot-isSectionEmpty-int-and-optimize-Pa.patch b/patches/server/Fix-ChunkSnapshot-isSectionEmpty-int-and-optimize-Pa.patch similarity index 92% rename from patches/unapplied/server/Fix-ChunkSnapshot-isSectionEmpty-int-and-optimize-Pa.patch rename to patches/server/Fix-ChunkSnapshot-isSectionEmpty-int-and-optimize-Pa.patch index f1e375e3bb..e169875477 100644 --- a/patches/unapplied/server/Fix-ChunkSnapshot-isSectionEmpty-int-and-optimize-Pa.patch +++ b/patches/server/Fix-ChunkSnapshot-isSectionEmpty-int-and-optimize-Pa.patch @@ -18,8 +18,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 for (int i = 0; i < cs.length; i++) { - CompoundTag data = new CompoundTag(); -- data.put("block_states", ChunkSerializer.BLOCK_STATE_CODEC.encodeStart(NbtOps.INSTANCE, cs[i].getStates()).get().left().get()); -- sectionBlockIDs[i] = ChunkSerializer.BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, data.getCompound("block_states")).get().left().get(); +- data.put("block_states", ChunkSerializer.BLOCK_STATE_CODEC.encodeStart(NbtOps.INSTANCE, cs[i].getStates()).getOrThrow()); +- sectionBlockIDs[i] = ChunkSerializer.BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, data.getCompound("block_states")).getOrThrow(ChunkSerializer.ChunkReadException::new); + // Paper start - Fix ChunkSnapshot#isSectionEmpty(int); and remove codec usage + sectionEmpty[i] = cs[i].hasOnlyAir(); // fix sectionEmpty array not being filled + if (!sectionEmpty[i]) { @@ -35,8 +35,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } if (biome != null) { -- data.put("biomes", biomeCodec.encodeStart(NbtOps.INSTANCE, cs[i].getBiomes()).get().left().get()); -- biome[i] = biomeCodec.parse(NbtOps.INSTANCE, data.getCompound("biomes")).get().left().get(); +- data.put("biomes", biomeCodec.encodeStart(NbtOps.INSTANCE, cs[i].getBiomes()).getOrThrow()); +- biome[i] = biomeCodec.parse(NbtOps.INSTANCE, data.getCompound("biomes")).getOrThrow(ChunkSerializer.ChunkReadException::new); + biome[i] = ((PalettedContainer>) cs[i].getBiomes()).copy(); // Paper - Perf: use copy instead of round tripping with codecs } } diff --git a/patches/unapplied/server/Fix-Spigot-growth-modifiers.patch b/patches/server/Fix-Spigot-growth-modifiers.patch similarity index 98% rename from patches/unapplied/server/Fix-Spigot-growth-modifiers.patch rename to patches/server/Fix-Spigot-growth-modifiers.patch index 30071fa159..93a80a1d74 100644 --- a/patches/unapplied/server/Fix-Spigot-growth-modifiers.patch +++ b/patches/server/Fix-Spigot-growth-modifiers.patch @@ -81,7 +81,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/net/minecraft/world/level/block/MangrovePropaguleBlock.java @@ -0,0 +0,0 @@ public class MangrovePropaguleBlock extends SaplingBlock implements SimpleWaterl @Override - public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { + protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { if (!isHanging(state)) { - if (random.nextInt(7) == 0) { + if (random.nextFloat() < (world.spigotConfig.saplingModifier / (100.0F * 7))) { // Paper - Fix Spigot growth modifiers diff --git a/patches/unapplied/server/Fix-sticky-pistons-and-BlockPistonRetractEvent.patch b/patches/server/Fix-sticky-pistons-and-BlockPistonRetractEvent.patch similarity index 100% rename from patches/unapplied/server/Fix-sticky-pistons-and-BlockPistonRetractEvent.patch rename to patches/server/Fix-sticky-pistons-and-BlockPistonRetractEvent.patch diff --git a/patches/unapplied/server/Forward-CraftEntity-in-teleport-command.patch b/patches/server/Forward-CraftEntity-in-teleport-command.patch similarity index 90% rename from patches/unapplied/server/Forward-CraftEntity-in-teleport-command.patch rename to patches/server/Forward-CraftEntity-in-teleport-command.patch index a5733b37bc..348d39aa32 100644 --- a/patches/unapplied/server/Forward-CraftEntity-in-teleport-command.patch +++ b/patches/server/Forward-CraftEntity-in-teleport-command.patch @@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public void restoreFrom(Entity original) { @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 CompoundTag nbttagcompound = original.saveWithoutId(new CompoundTag()); nbttagcompound.remove("Dimension"); -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } // CraftBukkit end diff --git a/patches/unapplied/server/Improve-scoreboard-entries.patch b/patches/server/Improve-scoreboard-entries.patch similarity index 100% rename from patches/unapplied/server/Improve-scoreboard-entries.patch rename to patches/server/Improve-scoreboard-entries.patch diff --git a/patches/unapplied/server/Make-water-animal-spawn-height-configurable.patch b/patches/server/Make-water-animal-spawn-height-configurable.patch similarity index 100% rename from patches/unapplied/server/Make-water-animal-spawn-height-configurable.patch rename to patches/server/Make-water-animal-spawn-height-configurable.patch diff --git a/patches/unapplied/server/Multiple-Entries-with-Scoreboards.patch b/patches/server/Multiple-Entries-with-Scoreboards.patch similarity index 98% rename from patches/unapplied/server/Multiple-Entries-with-Scoreboards.patch rename to patches/server/Multiple-Entries-with-Scoreboards.patch index ad0e6c847a..35ac228687 100644 --- a/patches/unapplied/server/Multiple-Entries-with-Scoreboards.patch +++ b/patches/server/Multiple-Entries-with-Scoreboards.patch @@ -17,8 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return new ClientboundSetPlayerTeamPacket(team.getName(), operation == ClientboundSetPlayerTeamPacket.Action.ADD ? 3 : 4, Optional.empty(), players); + } + // Paper end - Multiple Entries with Scoreboards -+ - public ClientboundSetPlayerTeamPacket(FriendlyByteBuf buf) { + private ClientboundSetPlayerTeamPacket(RegistryFriendlyByteBuf buf) { this.name = buf.readUtf(); this.method = buf.readByte(); diff --git a/src/main/java/net/minecraft/server/ServerScoreboard.java b/src/main/java/net/minecraft/server/ServerScoreboard.java diff --git a/patches/unapplied/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch b/patches/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch similarity index 100% rename from patches/unapplied/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch rename to patches/server/Only-write-chunk-data-to-disk-if-it-serializes-witho.patch diff --git a/patches/unapplied/server/Optimize-HashMapPalette.patch b/patches/server/Optimize-HashMapPalette.patch similarity index 100% rename from patches/unapplied/server/Optimize-HashMapPalette.patch rename to patches/server/Optimize-HashMapPalette.patch diff --git a/patches/unapplied/server/Prevent-ContainerOpenersCounter-openCount-from-going.patch b/patches/server/Prevent-ContainerOpenersCounter-openCount-from-going.patch similarity index 100% rename from patches/unapplied/server/Prevent-ContainerOpenersCounter-openCount-from-going.patch rename to patches/server/Prevent-ContainerOpenersCounter-openCount-from-going.patch diff --git a/patches/server/Prevent-excessive-velocity-through-repeated-crits.patch b/patches/server/Prevent-excessive-velocity-through-repeated-crits.patch new file mode 100644 index 0000000000..65e4bccdeb --- /dev/null +++ b/patches/server/Prevent-excessive-velocity-through-repeated-crits.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nassim Jahnke +Date: Thu, 25 Nov 2021 10:25:09 +0100 +Subject: [PATCH] Prevent excessive velocity through repeated crits + + +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 implements Attackable { + return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float) this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F; + } + ++ protected long lastJumpTime = 0L; // Paper - Prevent excessive velocity through repeated crits + protected void jumpFromGround() { + float f = this.getJumpPower(); + + if (f > 1.0E-5F) { + Vec3 vec3d = this.getDeltaMovement(); ++ // Paper start - Prevent excessive velocity through repeated crits ++ long time = System.nanoTime(); ++ boolean canCrit = true; ++ if (this instanceof net.minecraft.world.entity.player.Player) { ++ canCrit = false; ++ if (time - this.lastJumpTime > (long)(0.250e9)) { ++ this.lastJumpTime = time; ++ canCrit = true; ++ } ++ } ++ // Paper end - Prevent excessive velocity through repeated crits + + this.setDeltaMovement(vec3d.x, (double) f, vec3d.z); + if (this.isSprinting()) { + float f1 = this.getYRot() * 0.017453292F; +- ++ if (canCrit) // Paper - Prevent excessive velocity through repeated crits + this.addDeltaMovement(new Vec3((double) (-Mth.sin(f1)) * 0.2D, 0.0D, (double) Mth.cos(f1) * 0.2D)); + } + diff --git a/patches/unapplied/server/Remove-client-side-code-using-deprecated-for-removal.patch b/patches/server/Remove-client-side-code-using-deprecated-for-removal.patch similarity index 100% rename from patches/unapplied/server/Remove-client-side-code-using-deprecated-for-removal.patch rename to patches/server/Remove-client-side-code-using-deprecated-for-removal.patch diff --git a/patches/unapplied/server/Validate-usernames.patch b/patches/server/Validate-usernames.patch similarity index 77% rename from patches/unapplied/server/Validate-usernames.patch rename to patches/server/Validate-usernames.patch index 8ff46dc44f..2efab13b04 100644 --- a/patches/unapplied/server/Validate-usernames.patch +++ b/patches/server/Validate-usernames.patch @@ -9,19 +9,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, - public GameProfile authenticatedProfile; // Paper - public private final String serverId; + private final boolean transferred; private ServerPlayer player; // CraftBukkit + public boolean iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation = false; // Paper - username validation overriding - public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) { + public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection, boolean transferred) { this.state = ServerLoginPacketListenerImpl.State.HELLO; @@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, @Override public void handleHello(ServerboundHelloPacket packet) { Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet", new Object[0]); -- Validate.validState(Player.isValidUsername(packet.name()), "Invalid characters in username", new Object[0]); -+ if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation && !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) Validate.validState(Player.isValidUsername(packet.name()), "Invalid characters in username", new Object[0]); // Paper - config username validation +- Validate.validState(StringUtil.isValidPlayerName(packet.name()), "Invalid characters in username", new Object[0]); ++ if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation && !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) Validate.validState(StringUtil.isValidPlayerName(packet.name()), "Invalid characters in username", new Object[0]); // Paper - config username validation this.requestedUsername = packet.name(); GameProfile gameprofile = this.server.getSingleplayerProfile(); @@ -38,17 +38,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 list.add(entityplayer); } } -diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +diff --git a/src/main/java/net/minecraft/util/StringUtil.java b/src/main/java/net/minecraft/util/StringUtil.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { +--- a/src/main/java/net/minecraft/util/StringUtil.java ++++ b/src/main/java/net/minecraft/util/StringUtil.java +@@ -0,0 +0,0 @@ public class StringUtil { } - public static boolean isValidUsername(String name) { -- return name.length() > 16 ? false : name.chars().filter((i) -> { -- return i <= 32 || i >= 127; -- }).findAny().isEmpty(); + public static boolean isValidPlayerName(String name) { +- return name.length() <= 16 && name.chars().filter(c -> c <= 32 || c >= 127).findAny().isEmpty(); + // Paper start - username validation overriding + if (name == null || name.isEmpty() || name.length() > 16) { + return false; @@ -68,4 +66,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - username validation overriding } - public static float getPickRange(boolean creative) { + public static String filterText(String string) { diff --git a/patches/unapplied/server/don-t-attempt-to-teleport-dead-entities.patch b/patches/server/don-t-attempt-to-teleport-dead-entities.patch similarity index 90% rename from patches/unapplied/server/don-t-attempt-to-teleport-dead-entities.patch rename to patches/server/don-t-attempt-to-teleport-dead-entities.patch index 1fe0c06822..a18e4840d5 100644 --- a/patches/unapplied/server/don-t-attempt-to-teleport-dead-entities.patch +++ b/patches/server/don-t-attempt-to-teleport-dead-entities.patch @@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // CraftBukkit start public void postTick() { // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle diff --git a/patches/unapplied/server/Always-allow-item-changing-in-Fireball.patch b/patches/unapplied/server/Always-allow-item-changing-in-Fireball.patch deleted file mode 100644 index 1669e55bbe..0000000000 --- a/patches/unapplied/server/Always-allow-item-changing-in-Fireball.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Mon, 21 Jun 2021 22:12:53 -0400 -Subject: [PATCH] Always allow item changing in Fireball - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/Fireball.java b/src/main/java/net/minecraft/world/entity/projectile/Fireball.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/Fireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/Fireball.java -@@ -0,0 +0,0 @@ public abstract class Fireball extends AbstractHurtingProjectile implements Item - } - - public void setItem(ItemStack stack) { -- if (!stack.is(Items.FIRE_CHARGE) || stack.hasTag()) { -+ if (true || !stack.is(Items.FIRE_CHARGE) || stack.hasTag()) { // Paper - always allow item changing - this.getEntityData().set(Fireball.DATA_ITEM_STACK, stack.copyWithCount(1)); - } - diff --git a/patches/unapplied/server/Fix-bees-aging-inside-hives.patch b/patches/unapplied/server/Fix-bees-aging-inside-hives.patch deleted file mode 100644 index 2eb980ba0d..0000000000 --- a/patches/unapplied/server/Fix-bees-aging-inside-hives.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 21 Aug 2021 21:54:16 -0700 -Subject: [PATCH] Fix bees aging inside hives - -Fixes bees incorrectly being aged up due to upstream's -resetting the ticks inside hive on a failed release - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -@@ -0,0 +0,0 @@ public class BeehiveBlockEntity extends BlockEntity { - - for (Iterator iterator = bees.iterator(); iterator.hasNext(); ++tileentitybeehive_hivebee.ticksInHive) { - tileentitybeehive_hivebee = (BeehiveBlockEntity.BeeData) iterator.next(); -- if (tileentitybeehive_hivebee.ticksInHive > tileentitybeehive_hivebee.minOccupationTicks) { -+ if (tileentitybeehive_hivebee.exitTickCounter > tileentitybeehive_hivebee.minOccupationTicks) { // Paper - Fix bees aging inside hives; use exitTickCounter - BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus = tileentitybeehive_hivebee.entityData.getBoolean("HasNectar") ? BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED : BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED; - - if (BeehiveBlockEntity.releaseOccupant(world, pos, state, tileentitybeehive_hivebee, (List) null, tileentitybeehive_releasestatus, flowerPos)) { -@@ -0,0 +0,0 @@ public class BeehiveBlockEntity extends BlockEntity { - iterator.remove(); - // CraftBukkit start - } else { -- tileentitybeehive_hivebee.ticksInHive = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable -+ tileentitybeehive_hivebee.exitTickCounter = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable // Paper - Fix bees aging inside hives; use exitTickCounter to keep actual bee life - // CraftBukkit end - } - } -+ tileentitybeehive_hivebee.exitTickCounter++; // Paper - Fix bees aging inside hives - } - - if (flag) { -@@ -0,0 +0,0 @@ public class BeehiveBlockEntity extends BlockEntity { - - final CompoundTag entityData; - int ticksInHive; -+ int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts - final int minOccupationTicks; - - BeeData(CompoundTag entityData, int ticksInHive, int minOccupationTicks) { - BeehiveBlockEntity.removeIgnoredBeeTags(entityData); - this.entityData = entityData; - this.ticksInHive = ticksInHive; -+ this.exitTickCounter = ticksInHive; // Paper - Fix bees aging inside hives - this.minOccupationTicks = minOccupationTicks; - } - } diff --git a/patches/unapplied/server/Fix-removing-recipes-from-RecipeIterator.patch b/patches/unapplied/server/Fix-removing-recipes-from-RecipeIterator.patch deleted file mode 100644 index bae3f7ca7c..0000000000 --- a/patches/unapplied/server/Fix-removing-recipes-from-RecipeIterator.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 30 Nov 2021 12:01:56 -0800 -Subject: [PATCH] Fix removing recipes from RecipeIterator - -== AT == -public net.minecraft.world.item.crafting.RecipeManager byName - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java b/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java -@@ -0,0 +0,0 @@ import org.bukkit.inventory.Recipe; - public class RecipeIterator implements Iterator { - private final Iterator, Object2ObjectLinkedOpenHashMap>>> recipes; - private Iterator> current; -+ private Recipe currentRecipe; // Paper - fix removing recipes from RecipeIterator - - public RecipeIterator() { - this.recipes = MinecraftServer.getServer().getRecipeManager().recipes.entrySet().iterator(); -@@ -0,0 +0,0 @@ public class RecipeIterator implements Iterator { - public Recipe next() { - if (this.current == null || !this.current.hasNext()) { - this.current = this.recipes.next().getValue().values().iterator(); -- return this.next(); -+ // Paper start - fix removing recipes from RecipeIterator -+ this.currentRecipe = this.next(); -+ return this.currentRecipe; -+ // Paper end - fix removing recipes from RecipeIterator - } - -- return this.current.next().toBukkitRecipe(); -+ // Paper start - fix removing recipes from RecipeIterator -+ this.currentRecipe = this.current.next().toBukkitRecipe(); -+ return this.currentRecipe; -+ // Paper end - fix removing recipes from RecipeIterator - } - - @Override - public void remove() { - Preconditions.checkState(this.current != null, "next() not yet called"); -+ -+ // Paper start - fix removing recipes from RecipeIterator -+ if (this.currentRecipe instanceof org.bukkit.Keyed keyed) { -+ MinecraftServer.getServer().getRecipeManager().byName.remove(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(keyed.getKey())); -+ } -+ // Paper end - fix removing recipes from RecipeIterator - this.current.remove(); - } - } diff --git a/patches/unapplied/server/Hide-unnecessary-itemmeta-from-clients.patch b/patches/unapplied/server/Hide-unnecessary-itemmeta-from-clients.patch deleted file mode 100644 index 8b81f5d8d9..0000000000 --- a/patches/unapplied/server/Hide-unnecessary-itemmeta-from-clients.patch +++ /dev/null @@ -1,125 +0,0 @@ -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/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 { - 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -0,0 +0,0 @@ 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 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 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: -@@ -0,0 +0,0 @@ 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()) { diff --git a/patches/unapplied/server/Load-effect-amplifiers-greater-than-127-correctly.patch b/patches/unapplied/server/Load-effect-amplifiers-greater-than-127-correctly.patch deleted file mode 100644 index 50f42836e5..0000000000 --- a/patches/unapplied/server/Load-effect-amplifiers-greater-than-127-correctly.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 21 Dec 2021 22:13:26 -0800 -Subject: [PATCH] Load effect amplifiers greater than 127 correctly - -MOJIRA: MC-118857 - -diff --git a/src/main/java/net/minecraft/world/effect/MobEffectInstance.java b/src/main/java/net/minecraft/world/effect/MobEffectInstance.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/effect/MobEffectInstance.java -+++ b/src/main/java/net/minecraft/world/effect/MobEffectInstance.java -@@ -0,0 +0,0 @@ public class MobEffectInstance implements Comparable { - } - - private static MobEffectInstance loadSpecifiedEffect(MobEffect type, CompoundTag nbt) { -- int i = nbt.getByte("amplifier"); -+ int i = Byte.toUnsignedInt(nbt.getByte("amplifier")); // Paper - correctly load amplifiers > 127 - int j = nbt.getInt("duration"); - boolean bl = nbt.getBoolean("ambient"); - boolean bl2 = true; diff --git a/patches/unapplied/server/Prevent-excessive-velocity-through-repeated-crits.patch b/patches/unapplied/server/Prevent-excessive-velocity-through-repeated-crits.patch deleted file mode 100644 index 6dcdc0fa84..0000000000 --- a/patches/unapplied/server/Prevent-excessive-velocity-through-repeated-crits.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nassim Jahnke -Date: Thu, 25 Nov 2021 10:25:09 +0100 -Subject: [PATCH] Prevent excessive velocity through repeated crits - - -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 implements Attackable { - return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float) this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F; - } - -+ protected long lastJumpTime = 0L; // Paper - Prevent excessive velocity through repeated crits - protected void jumpFromGround() { - Vec3 vec3d = this.getDeltaMovement(); -+ // Paper start - Prevent excessive velocity through repeated crits -+ long time = System.nanoTime(); -+ boolean canCrit = true; -+ if (this instanceof net.minecraft.world.entity.player.Player) { -+ canCrit = false; -+ if (time - this.lastJumpTime > (long)(0.250e9)) { -+ this.lastJumpTime = time; -+ canCrit = true; -+ } -+ } -+ // Paper end - Prevent excessive velocity through repeated crits - - this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); - if (this.isSprinting()) { - float f = this.getYRot() * 0.017453292F; - -+ if (canCrit) // Paper - Prevent excessive velocity through repeated crits - this.setDeltaMovement(this.getDeltaMovement().add((double) (-Mth.sin(f) * 0.2F), 0.0D, (double) (Mth.cos(f) * 0.2F))); - } - diff --git a/patches/unapplied/server/Prevent-sending-oversized-item-data-in-equipment-and.patch b/patches/unapplied/server/Prevent-sending-oversized-item-data-in-equipment-and.patch deleted file mode 100644 index 3af15e1a8e..0000000000 --- a/patches/unapplied/server/Prevent-sending-oversized-item-data-in-equipment-and.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nassim Jahnke -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 ITEM_STACK = new EntityDataSerializer() { - @Override - public void write(FriendlyByteBuf buf, ItemStack value) { -- buf.writeItem(value); -+ buf.writeItem(net.minecraft.world.entity.LivingEntity.sanitizeItemStack(value, true)); // 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 - prevent oversized data - } - } - -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 implements Attackable { - 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 - prevent oversized data - switch (enumitemslot.getType()) { - case HAND: - this.setLastHandItem(enumitemslot, itemstack1); -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list)); - } - -+ // Paper start - 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 - prevent oversized data -+ - private ItemStack getLastArmorItem(EquipmentSlot slot) { - return (ItemStack) this.lastArmorItemStacks.get(slot.getIndex()); - }