diff --git a/patches/server/Add-Raw-Byte-Entity-Serialization.patch b/patches/server/Add-Raw-Byte-Entity-Serialization.patch index 2322dc5fd3..a24c73ea88 100644 --- a/patches/server/Add-Raw-Byte-Entity-Serialization.patch +++ b/patches/server/Add-Raw-Byte-Entity-Serialization.patch @@ -40,7 +40,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + entity.level = ((CraftWorld) location.getWorld()).getHandle(); + entity.setPos(location.getX(), location.getY(), location.getZ()); + entity.setRot(location.getYaw(), location.getPitch()); -+ return !entity.valid && entity.level.addEntity(entity, reason); ++ return !entity.valid && entity.level.addFreshEntity(entity, reason); + } // Paper end } diff --git a/patches/unapplied/server/Add-config-option-for-logging-player-ip-addresses.patch b/patches/server/Add-config-option-for-logging-player-ip-addresses.patch similarity index 100% rename from patches/unapplied/server/Add-config-option-for-logging-player-ip-addresses.patch rename to patches/server/Add-config-option-for-logging-player-ip-addresses.patch 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/Always-allow-item-changing-in-Fireball.patch b/patches/server/Always-allow-item-changing-in-Fireball.patch similarity index 92% rename from patches/unapplied/server/Always-allow-item-changing-in-Fireball.patch rename to patches/server/Always-allow-item-changing-in-Fireball.patch index 91a42cfbec..6c565ebc3d 100644 --- a/patches/unapplied/server/Always-allow-item-changing-in-Fireball.patch +++ b/patches/server/Always-allow-item-changing-in-Fireball.patch @@ -14,6 +14,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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, (ItemStack) Util.make(stack.copy(), (itemstack1) -> { // CraftBukkit - decompile error + this.getEntityData().set(Fireball.DATA_ITEM_STACK, (ItemStack) Util.make(stack.copy(), (itemstack1) -> { itemstack1.setCount(1); })); diff --git a/patches/unapplied/server/Async-catch-modifications-to-critical-entity-state.patch b/patches/server/Async-catch-modifications-to-critical-entity-state.patch similarity index 97% rename from patches/unapplied/server/Async-catch-modifications-to-critical-entity-state.patch rename to patches/server/Async-catch-modifications-to-critical-entity-state.patch index ad4dd5417c..e49eeceef7 100644 --- a/patches/unapplied/server/Async-catch-modifications-to-critical-entity-state.patch +++ b/patches/server/Async-catch-modifications-to-critical-entity-state.patch @@ -60,13 +60,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (trackingStatus == Visibility.HIDDEN) { @@ -0,0 +0,0 @@ public class PersistentEntitySectionManager implements A + } - private boolean storeChunkSections(long chunkPos, Consumer action, boolean callEvent) { - // CraftBukkit end + public void ensureChunkQueuedForLoad(long chunkPos) { + org.spigotmc.AsyncCatcher.catchOp("Entity chunk save"); // Paper PersistentEntitySectionManager.ChunkLoadStatus persistententitysectionmanager_b = (PersistentEntitySectionManager.ChunkLoadStatus) this.chunkLoadStatuses.get(chunkPos); - if (persistententitysectionmanager_b == PersistentEntitySectionManager.ChunkLoadStatus.PENDING) { + if (persistententitysectionmanager_b == PersistentEntitySectionManager.ChunkLoadStatus.FRESH) { @@ -0,0 +0,0 @@ public class PersistentEntitySectionManager implements A } diff --git a/patches/unapplied/server/Call-onRemove-logic-for-breakNaturally.patch b/patches/server/Call-onRemove-logic-for-breakNaturally.patch similarity index 100% rename from patches/unapplied/server/Call-onRemove-logic-for-breakNaturally.patch rename to patches/server/Call-onRemove-logic-for-breakNaturally.patch diff --git a/patches/unapplied/server/Check-requirement-before-suggesting-root-nodes.patch b/patches/server/Check-requirement-before-suggesting-root-nodes.patch similarity index 100% rename from patches/unapplied/server/Check-requirement-before-suggesting-root-nodes.patch rename to patches/server/Check-requirement-before-suggesting-root-nodes.patch diff --git a/patches/unapplied/server/Do-not-overload-I-O-threads-with-chunk-data-while-fl.patch b/patches/server/Do-not-overload-I-O-threads-with-chunk-data-while-fl.patch similarity index 99% rename from patches/unapplied/server/Do-not-overload-I-O-threads-with-chunk-data-while-fl.patch rename to patches/server/Do-not-overload-I-O-threads-with-chunk-data-while-fl.patch index a30e922275..a25fbb4d68 100644 --- a/patches/unapplied/server/Do-not-overload-I-O-threads-with-chunk-data-while-fl.patch +++ b/patches/server/Do-not-overload-I-O-threads-with-chunk-data-while-fl.patch @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper end + } protected void saveAllChunks(boolean flush) { + // Paper start - do not overload I/O threads with too much work when saving diff --git a/patches/unapplied/server/Do-not-process-entity-loads-in-CraftChunk-getEntitie.patch b/patches/server/Do-not-process-entity-loads-in-CraftChunk-getEntitie.patch similarity index 95% rename from patches/unapplied/server/Do-not-process-entity-loads-in-CraftChunk-getEntitie.patch rename to patches/server/Do-not-process-entity-loads-in-CraftChunk-getEntitie.patch index 1986d2db7e..0a2c4303cc 100644 --- a/patches/unapplied/server/Do-not-process-entity-loads-in-CraftChunk-getEntitie.patch +++ b/patches/server/Do-not-process-entity-loads-in-CraftChunk-getEntitie.patch @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - PersistentEntitySectionManager entityManager = this.getCraftWorld().getHandle().entityManager; - long pair = ChunkPos.asLong(x, z); - -- if (entityManager.areEntitiesLoaded(pair)) { // PAIL rename isEntitiesLoaded +- if (entityManager.areEntitiesLoaded(pair)) { - return getCraftWorld().getHandle().getChunkEntities(this.x, this.z); // Paper - optimise this - } - @@ -55,7 +55,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - // now we wait until the entities are loaded, - // the converting from NBT to entity object is done on the main Thread which is why we wait - while (!supplier.getAsBoolean()) { -- if (mailbox.size() != 0) { // PAIL rename size +- if (mailbox.size() != 0) { - mailbox.run(); - } else { - Thread.yield(); diff --git a/patches/unapplied/server/Don-t-log-debug-logging-being-disabled.patch b/patches/server/Don-t-log-debug-logging-being-disabled.patch similarity index 100% rename from patches/unapplied/server/Don-t-log-debug-logging-being-disabled.patch rename to patches/server/Don-t-log-debug-logging-being-disabled.patch diff --git a/patches/unapplied/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch b/patches/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch similarity index 100% rename from patches/unapplied/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch rename to patches/server/Don-t-respond-to-ServerboundCommandSuggestionPacket-.patch diff --git a/patches/unapplied/server/Dont-count-named-piglins-and-hoglins-towards-mob-cap.patch b/patches/server/Dont-count-named-piglins-and-hoglins-towards-mob-cap.patch similarity index 100% rename from patches/unapplied/server/Dont-count-named-piglins-and-hoglins-towards-mob-cap.patch rename to patches/server/Dont-count-named-piglins-and-hoglins-towards-mob-cap.patch diff --git a/patches/unapplied/server/Ensure-valid-vehicle-status.patch b/patches/server/Ensure-valid-vehicle-status.patch similarity index 100% rename from patches/unapplied/server/Ensure-valid-vehicle-status.patch rename to patches/server/Ensure-valid-vehicle-status.patch diff --git a/patches/unapplied/server/Fix-Bukkit-NamespacedKey-shenanigans.patch b/patches/server/Fix-Bukkit-NamespacedKey-shenanigans.patch similarity index 100% rename from patches/unapplied/server/Fix-Bukkit-NamespacedKey-shenanigans.patch rename to patches/server/Fix-Bukkit-NamespacedKey-shenanigans.patch diff --git a/patches/unapplied/server/Fix-CocaoDecorator-causing-a-crash-when-trying-to-ge.patch b/patches/server/Fix-CocaoDecorator-causing-a-crash-when-trying-to-ge.patch similarity index 100% rename from patches/unapplied/server/Fix-CocaoDecorator-causing-a-crash-when-trying-to-ge.patch rename to patches/server/Fix-CocaoDecorator-causing-a-crash-when-trying-to-ge.patch diff --git a/patches/unapplied/server/Fix-CraftCriteria-defaults-map.patch b/patches/server/Fix-CraftCriteria-defaults-map.patch similarity index 100% rename from patches/unapplied/server/Fix-CraftCriteria-defaults-map.patch rename to patches/server/Fix-CraftCriteria-defaults-map.patch diff --git a/patches/unapplied/server/Fix-anvil-prepare-event-not-working-with-zero-xp.patch b/patches/server/Fix-anvil-prepare-event-not-working-with-zero-xp.patch similarity index 100% rename from patches/unapplied/server/Fix-anvil-prepare-event-not-working-with-zero-xp.patch rename to patches/server/Fix-anvil-prepare-event-not-working-with-zero-xp.patch diff --git a/patches/unapplied/server/Fix-merchant-inventory-not-closing-on-entity-removal.patch b/patches/server/Fix-merchant-inventory-not-closing-on-entity-removal.patch similarity index 100% rename from patches/unapplied/server/Fix-merchant-inventory-not-closing-on-entity-removal.patch rename to patches/server/Fix-merchant-inventory-not-closing-on-entity-removal.patch diff --git a/patches/unapplied/server/Fix-setPatternColor-on-tropical-fish-bucket-meta.patch b/patches/server/Fix-setPatternColor-on-tropical-fish-bucket-meta.patch similarity index 100% rename from patches/unapplied/server/Fix-setPatternColor-on-tropical-fish-bucket-meta.patch rename to patches/server/Fix-setPatternColor-on-tropical-fish-bucket-meta.patch diff --git a/patches/unapplied/server/Fix-upstreams-block-state-factories.patch b/patches/server/Fix-upstreams-block-state-factories.patch similarity index 99% rename from patches/unapplied/server/Fix-upstreams-block-state-factories.patch rename to patches/server/Fix-upstreams-block-state-factories.patch index 6eecd70b93..f0d4771b25 100644 --- a/patches/unapplied/server/Fix-upstreams-block-state-factories.patch +++ b/patches/server/Fix-upstreams-block-state-factories.patch @@ -13,7 +13,7 @@ diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.ja index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { +@@ -0,0 +0,0 @@ public abstract class BlockEntity implements io.papermc.paper.util.KeyedObject { // Paper end if (this.level == null) return null; org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ()); diff --git a/patches/unapplied/server/Mark-fish-and-axolotls-from-buckets-as-persistent.patch b/patches/server/Mark-fish-and-axolotls-from-buckets-as-persistent.patch similarity index 100% rename from patches/unapplied/server/Mark-fish-and-axolotls-from-buckets-as-persistent.patch rename to patches/server/Mark-fish-and-axolotls-from-buckets-as-persistent.patch diff --git a/patches/unapplied/server/Preserve-overstacked-loot.patch b/patches/server/Preserve-overstacked-loot.patch similarity index 100% rename from patches/unapplied/server/Preserve-overstacked-loot.patch rename to patches/server/Preserve-overstacked-loot.patch diff --git a/patches/unapplied/server/Prevent-softlocked-end-exit-portal-generation.patch b/patches/server/Prevent-softlocked-end-exit-portal-generation.patch similarity index 100% rename from patches/unapplied/server/Prevent-softlocked-end-exit-portal-generation.patch rename to patches/server/Prevent-softlocked-end-exit-portal-generation.patch diff --git a/patches/unapplied/server/Reduce-worldgen-thread-worker-count-for-low-core-cou.patch b/patches/server/Reduce-worldgen-thread-worker-count-for-low-core-cou.patch similarity index 100% rename from patches/unapplied/server/Reduce-worldgen-thread-worker-count-for-low-core-cou.patch rename to patches/server/Reduce-worldgen-thread-worker-count-for-low-core-cou.patch diff --git a/patches/unapplied/server/Update-head-rotation-in-missing-places.patch b/patches/server/Update-head-rotation-in-missing-places.patch similarity index 95% rename from patches/unapplied/server/Update-head-rotation-in-missing-places.patch rename to patches/server/Update-head-rotation-in-missing-places.patch index 40725834ac..712541bf41 100644 --- a/patches/unapplied/server/Update-head-rotation-in-missing-places.patch +++ b/patches/server/Update-head-rotation-in-missing-places.patch @@ -11,7 +11,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, n +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i this.setXRot(Mth.clamp(pitch, -90.0F, 90.0F) % 360.0F); this.yRotO = this.getYRot(); this.xRotO = this.getXRot(); @@ -19,7 +19,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public void absMoveTo(double x, double y, double z) { -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i this.setXRot(pitch); this.setOldPosAndRot(); this.reapplyPosition(); diff --git a/patches/unapplied/server/Use-Velocity-compression-and-cipher-natives.patch b/patches/server/Use-Velocity-compression-and-cipher-natives.patch similarity index 96% rename from patches/unapplied/server/Use-Velocity-compression-and-cipher-natives.patch rename to patches/server/Use-Velocity-compression-and-cipher-natives.patch index 4a187b3f2c..ad61d5975a 100644 --- a/patches/unapplied/server/Use-Velocity-compression-and-cipher-natives.patch +++ b/patches/server/Use-Velocity-compression-and-cipher-natives.patch @@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -0,0 +0,0 @@ dependencies { - implementation("io.netty:netty-all:4.1.65.Final") // Paper + runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") implementation("net.fabricmc:mapping-io:0.3.0") // Paper - needed to read mappings for stacktrace deobfuscation + implementation("com.velocitypowered:velocity-native:1.1.0-SNAPSHOT") // Paper @@ -33,7 +33,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.cipher = cipher; // Paper } - @Override protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { - list.add(this.cipher.decipher(channelHandlerContext, byteBuf)); + // Paper start @@ -76,7 +75,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.cipher = cipher; // Paper } - @Override - protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { - this.cipher.encipher(byteBuf, byteBuf2); + protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { @@ -112,19 +110,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private boolean validateDecompressed; + // Paper start - public CompressionDecoder(int compressionThreshold, boolean bl) { -+ this(null, compressionThreshold, bl); + public CompressionDecoder(int compressionThreshold, boolean rejectsBadPackets) { ++ this(null, compressionThreshold, rejectsBadPackets); + } -+ public CompressionDecoder(com.velocitypowered.natives.compression.VelocityCompressor compressor, int compressionThreshold, boolean bl) { ++ public CompressionDecoder(com.velocitypowered.natives.compression.VelocityCompressor compressor, int compressionThreshold, boolean rejectsBadPackets) { this.threshold = compressionThreshold; - this.validateDecompressed = bl; + this.validateDecompressed = rejectsBadPackets; - this.inflater = new Inflater(); + this.inflater = compressor == null ? new Inflater() : null; + this.compressor = compressor; + // Paper end } - @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { @@ -0,0 +0,0 @@ public class CompressionDecoder extends ByteToMessageDecoder { } } @@ -168,9 +166,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end + - public void setThreshold(int compressionThreshold, boolean bl) { + public void setThreshold(int compressionThreshold, boolean rejectsBadPackets) { this.threshold = compressionThreshold; - this.validateDecompressed = bl; + this.validateDecompressed = rejectsBadPackets; diff --git a/src/main/java/net/minecraft/network/CompressionEncoder.java b/src/main/java/net/minecraft/network/CompressionEncoder.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/network/CompressionEncoder.java @@ -203,7 +201,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end } - @Override - protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) { + protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { // Paper int i = byteBuf.readableBytes(); @@ -305,14 +302,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return this.encrypted; @@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { - public void setupCompression(int compressionThreshold, boolean flag) { + public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) { if (compressionThreshold >= 0) { + com.velocitypowered.natives.compression.VelocityCompressor compressor = com.velocitypowered.natives.util.Natives.compress.get().create(-1); // Paper if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) { - ((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(compressionThreshold, flag); + ((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(compressionThreshold, rejectsBadPackets); } else { -- this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressionThreshold, flag)); -+ this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressor, compressionThreshold, flag)); // Paper +- this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressionThreshold, rejectsBadPackets)); ++ this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressor, compressionThreshold, rejectsBadPackets)); // Paper } if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) { diff --git a/patches/unapplied/server/VanillaCommandWrapper-didnt-account-for-entity-sende.patch b/patches/server/VanillaCommandWrapper-didnt-account-for-entity-sende.patch similarity index 100% rename from patches/unapplied/server/VanillaCommandWrapper-didnt-account-for-entity-sende.patch rename to patches/server/VanillaCommandWrapper-didnt-account-for-entity-sende.patch 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 96% 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 5a931411d0..b207694030 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, n +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i // 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/fix-various-menus-with-empty-level-accesses.patch b/patches/server/fix-various-menus-with-empty-level-accesses.patch similarity index 100% rename from patches/unapplied/server/fix-various-menus-with-empty-level-accesses.patch rename to patches/server/fix-various-menus-with-empty-level-accesses.patch diff --git a/patches/unapplied/server/prevent-unintended-light-block-manipulation.patch b/patches/server/prevent-unintended-light-block-manipulation.patch similarity index 100% rename from patches/unapplied/server/prevent-unintended-light-block-manipulation.patch rename to patches/server/prevent-unintended-light-block-manipulation.patch diff --git a/patches/unapplied/server/Cache-palette-array.patch b/patches/unapplied/server/Cache-palette-array.patch deleted file mode 100644 index 023ab0f0e4..0000000000 --- a/patches/unapplied/server/Cache-palette-array.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paul Sauve -Date: Thu, 4 Feb 2021 23:28:46 -0600 -Subject: [PATCH] Cache palette array - -Instead of allocating the 4KB for every chunk section, cache it locally and -reuse it for other chunk sections to save on allocations. These allocations add -up very quickly when saving chunks frequently. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { - - } - -+ // Paper start - allow reusing int array - public synchronized void write(CompoundTag nbt, String paletteKey, String dataKey) { // Paper - synchronize -+ this.write(nbt, paletteKey, dataKey, new int[4096]); -+ } -+ public synchronized void write(CompoundTag nbt, String paletteKey, String dataKey, int[] is) { // Paper - synchronize // Paper end - try { - this.acquire(); - HashMapPalette hashMapPalette = new HashMapPalette<>(this.registry, this.bits, this.dummyPaletteResize, this.reader, this.writer); - T object = this.defaultValue; - int i = hashMapPalette.idFor(this.defaultValue); -- int[] is = new int[4096]; -+ //int[] is = new int[4096]; // Paper - will now be pulled from ThreadLocal - - for(int j = 0; j < 4096; ++j) { - T object2 = this.get(j); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -0,0 +0,0 @@ public class ChunkSerializer { - return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, blockEntitiesSerialized, world.getGameTime()); - } - -+ private static final ThreadLocal PALETTE_ARRAY = ThreadLocal.withInitial(() -> new int[4096]); // Paper - maintain a per-thread cache for saving palettes - public static CompoundTag write(ServerLevel world, ChunkAccess chunk) { - return saveChunk(world, chunk, null); - } -@@ -0,0 +0,0 @@ public class ChunkSerializer { - ThreadedLevelLightEngine lightenginethreaded = world.getChunkSource().getLightEngine(); - boolean flag = chunk.isLightCorrect(); - -+ int[] is = PALETTE_ARRAY.get(); // Paper - use cached - for (int i = lightenginethreaded.getMinLightSection(); i < lightenginethreaded.getMaxLightSection(); ++i) { - int finalI = i; // CraftBukkit - decompile errors - LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { -@@ -0,0 +0,0 @@ public class ChunkSerializer { - - nbttagcompound2.putByte("Y", (byte) (i & 255)); - if (chunksection != LevelChunk.EMPTY_SECTION) { -- chunksection.getStates().write(nbttagcompound2, "Palette", "BlockStates"); -+ chunksection.getStates().write(nbttagcompound2, "Palette", "BlockStates", is); // Paper - reuse array - } - - // Paper start - replace light engine