diff --git a/patches/unapplied/api/0185-Increase-custom-payload-channel-message-size.patch b/patches/api/0184-Increase-custom-payload-channel-message-size.patch similarity index 100% rename from patches/unapplied/api/0185-Increase-custom-payload-channel-message-size.patch rename to patches/api/0184-Increase-custom-payload-channel-message-size.patch diff --git a/patches/unapplied/api/0186-Expose-the-internal-current-tick.patch b/patches/api/0185-Expose-the-internal-current-tick.patch similarity index 79% rename from patches/unapplied/api/0186-Expose-the-internal-current-tick.patch rename to patches/api/0185-Expose-the-internal-current-tick.patch index 8c8cbca92..83ac82309 100644 --- a/patches/unapplied/api/0186-Expose-the-internal-current-tick.patch +++ b/patches/api/0185-Expose-the-internal-current-tick.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose the internal current tick diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 5c7681809a27796e398170fc72bf0a950e52a971..caa3d77b5906a2227f6409a877bd0ba14d05caba 100644 +index 50412ec90cd480b7457dd30723d4978fb90fae72..8580bc20e24c3bde5b57f0727f79051c9d7d0f2e 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1975,6 +1975,10 @@ public final class Bukkit { +@@ -1989,6 +1989,10 @@ public final class Bukkit { public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { return server.createProfile(uuid, name); } @@ -20,10 +20,10 @@ index 5c7681809a27796e398170fc72bf0a950e52a971..caa3d77b5906a2227f6409a877bd0ba1 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 5162e8b356e73ac41d6f4f5a0ea0efeda85382c7..bf1920857008c272d557f602544009986c3ed284 100644 +index 5d3479f494e874d9824b178bfc0664d81e9b5649..b765aa35680e67bb919c020b54830ee5aca9d27f 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1732,5 +1732,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1744,5 +1744,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ @NotNull com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name); diff --git a/patches/unapplied/server/0330-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch similarity index 91% rename from patches/unapplied/server/0330-Configurable-Keep-Spawn-Loaded-range-per-world.patch rename to patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch index 6214a7bea..ec7955e3a 100644 --- a/patches/unapplied/server/0330-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ b/patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Configurable Keep Spawn Loaded range per world This lets you disable it for some worlds and lower it for others. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 84b0304c538766949990f26f1e4a792a633f67f4..70fc301b25fb1e2271255b3d3b6facaf0cb87bad 100644 +index a5da82e0dea8a1ac5699179639fbd9ebe7b6e220..522c2a86c916f3558a8d5b34e456f8b5fb7d9d3b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -55,6 +55,12 @@ public class PaperWorldConfig { @@ -23,19 +23,19 @@ index 84b0304c538766949990f26f1e4a792a633f67f4..70fc301b25fb1e2271255b3d3b6facaf config.addDefault("world-settings.default." + path, def); return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 6c86d1d8c43448f4c83084a731bedd92d85b01fc..ad4ff2f7ee8d01ff3a49b9b2a8feb59131ae5afb 100644 +index beefed4d29fee9c20ee69bef88a7af2cc3770707..977dc521cff5b448665e00b953f4a02ecf04ee75 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -788,35 +788,36 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pendingFullStateConfirmation; @@ -17,12 +17,12 @@ index ffa3dc07ec566464ce10abe793de61efa9673fe9..d226247b93a2f1f7e039b0963d2e27b5 public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 48bb57d3a431ea466425eb7da821c0aea900bd4c..45c7ebe67019cdbe88b6617a95d5c40d3a68286c 100644 +index ef87c37633cee4ab438f1991144188ade1c4e65f..975f1aab48f04a9f3cae04141b3fb65247f0ffaf 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -47,7 +47,16 @@ public abstract class DistanceManager { - private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); +@@ -51,7 +51,16 @@ public abstract class DistanceManager { private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); + private final TickingTracker tickingTicketsTracker = new TickingTracker(); private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); - final Set chunksToUpdateFutures = Sets.newHashSet(); + // Paper start use a queue, but still keep unique requirement @@ -38,7 +38,7 @@ index 48bb57d3a431ea466425eb7da821c0aea900bd4c..45c7ebe67019cdbe88b6617a95d5c40d final ChunkTaskPriorityQueueSorter ticketThrottler; final ProcessorHandle> ticketThrottlerInput; final ProcessorHandle ticketThrottlerReleaser; -@@ -108,26 +117,14 @@ public abstract class DistanceManager { +@@ -124,26 +133,14 @@ public abstract class DistanceManager { ; } @@ -52,7 +52,7 @@ index 48bb57d3a431ea466425eb7da821c0aea900bd4c..45c7ebe67019cdbe88b6617a95d5c40d - iter.remove(); - expectedSize--; - -- playerchunk.updateFutures(playerchunkmap, this.mainThreadExecutor); +- playerchunk.updateFutures(chunkStorage, this.mainThreadExecutor); - - // Reset iterator if set was modified using add() - if (this.chunksToUpdateFutures.size() != expectedSize) { @@ -67,13 +67,13 @@ index 48bb57d3a431ea466425eb7da821c0aea900bd4c..45c7ebe67019cdbe88b6617a95d5c40d + while(!this.pendingChunkUpdates.isEmpty()) { + ChunkHolder remove = this.pendingChunkUpdates.remove(); + remove.isUpdateQueued = false; -+ remove.updateFutures(playerchunkmap, this.mainThreadExecutor); ++ remove.updateFutures(chunkStorage, this.mainThreadExecutor); + } + // Paper end return true; } else { if (!this.ticketsToRelease.isEmpty()) { -@@ -385,7 +382,7 @@ public abstract class DistanceManager { +@@ -432,7 +429,7 @@ public abstract class DistanceManager { if (k != level) { playerchunk = DistanceManager.this.updateChunkScheduling(id, level, playerchunk, k); if (playerchunk != null) { diff --git a/patches/unapplied/server/0333-Chunk-debug-command.patch b/patches/server/0331-Chunk-debug-command.patch similarity index 99% rename from patches/unapplied/server/0333-Chunk-debug-command.patch rename to patches/server/0331-Chunk-debug-command.patch index fafa15af7..13d30fbe3 100644 --- a/patches/unapplied/server/0333-Chunk-debug-command.patch +++ b/patches/server/0331-Chunk-debug-command.patch @@ -212,7 +212,7 @@ index 1eb45df9dca5d0c31ac46709e706136a246cb8ea..005361c38b02713fb823d0be40954400 * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 */ diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index f1135616657692a2611dde02e2dc5ac4d8127269..892524ffb54a3e4f43e1a6f259a736334bad9b58 100644 +index 3b10ef3801ffd47707836b3ed3482e99ddd0050b..2fe519d4059fac06781c30e140895b604e13104f 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java +++ b/src/main/java/net/minecraft/server/MCUtil.java @@ -9,13 +9,27 @@ import net.minecraft.core.BlockPos; diff --git a/patches/unapplied/server/0334-Allow-Saving-of-Oversized-Chunks.patch b/patches/server/0332-Allow-Saving-of-Oversized-Chunks.patch similarity index 81% rename from patches/unapplied/server/0334-Allow-Saving-of-Oversized-Chunks.patch rename to patches/server/0332-Allow-Saving-of-Oversized-Chunks.patch index bd5b4ebbe..e4ef91566 100644 --- a/patches/unapplied/server/0334-Allow-Saving-of-Oversized-Chunks.patch +++ b/patches/server/0332-Allow-Saving-of-Oversized-Chunks.patch @@ -33,10 +33,10 @@ this fix, as the data will remain in the oversized file. Once the server returns to a jar with this fix, the data will be restored. diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 298b5abbc792dd33be38acbd1c572c9778c4d2d2..46226dd2d16a9f4017661712fe2bfc0c46f63cb2 100644 +index 6f7bcf74b0ff42841e37f36561d6c54e1ee8c989..d511db5453b722f747cc24cf2b4d97a0be75ce6a 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -20,8 +20,12 @@ import java.nio.file.LinkOption; +@@ -17,8 +17,12 @@ import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; @@ -49,24 +49,24 @@ index 298b5abbc792dd33be38acbd1c572c9778c4d2d2..46226dd2d16a9f4017661712fe2bfc0c import net.minecraft.world.level.ChunkPos; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@@ -48,6 +52,7 @@ public class RegionFile implements AutoCloseable { +@@ -45,6 +49,7 @@ public class RegionFile implements AutoCloseable { @VisibleForTesting protected final RegionBitmap usedSectors; public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper -+ public final File regionFile; // Paper ++ public final Path regionFile; // Paper - public RegionFile(File file, File directory, boolean dsync) throws IOException { - this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); -@@ -55,6 +60,8 @@ public class RegionFile implements AutoCloseable { + public RegionFile(Path path, Path path1, boolean dsync) throws IOException { + this(path, path1, RegionFileVersion.VERSION_DEFLATE, dsync); +@@ -52,6 +57,8 @@ public class RegionFile implements AutoCloseable { public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync) throws IOException { this.header = ByteBuffer.allocateDirect(8192); -+ this.regionFile = file.toFile(); // Paper ++ this.regionFile = file; // Paper + initOversizedState(); // Paper this.usedSectors = new RegionBitmap(); this.version = outputChunkStreamVersion; if (!Files.isDirectory(directory, new LinkOption[0])) { -@@ -433,6 +440,74 @@ public class RegionFile implements AutoCloseable { +@@ -430,6 +437,74 @@ public class RegionFile implements AutoCloseable { } @@ -75,9 +75,9 @@ index 298b5abbc792dd33be38acbd1c572c9778c4d2d2..46226dd2d16a9f4017661712fe2bfc0c + private int oversizedCount = 0; + + private synchronized void initOversizedState() throws IOException { -+ File metaFile = getOversizedMetaFile(); -+ if (metaFile.exists()) { -+ final byte[] read = java.nio.file.Files.readAllBytes(metaFile.toPath()); ++ Path metaFile = getOversizedMetaFile(); ++ if (Files.exists(metaFile)) { ++ final byte[] read = java.nio.file.Files.readAllBytes(metaFile); + System.arraycopy(read, 0, oversized, 0, oversized.length); + for (byte temp : oversized) { + oversizedCount += temp; @@ -101,9 +101,9 @@ index 298b5abbc792dd33be38acbd1c572c9778c4d2d2..46226dd2d16a9f4017661712fe2bfc0c + oversizedCount--; + } + if (previous && !oversized) { -+ File oversizedFile = getOversizedFile(x, z); -+ if (oversizedFile.exists()) { -+ oversizedFile.delete(); ++ Path oversizedFile = getOversizedFile(x, z); ++ if (Files.exists(oversizedFile)) { ++ Files.delete(oversizedFile); + } + } + if (oversizedCount > 0) { @@ -111,28 +111,28 @@ index 298b5abbc792dd33be38acbd1c572c9778c4d2d2..46226dd2d16a9f4017661712fe2bfc0c + writeOversizedMeta(); + } + } else if (previous) { -+ File oversizedMetaFile = getOversizedMetaFile(); -+ if (oversizedMetaFile.exists()) { -+ oversizedMetaFile.delete(); ++ Path oversizedMetaFile = getOversizedMetaFile(); ++ if (Files.exists(oversizedMetaFile)) { ++ Files.delete(oversizedMetaFile); + } + } + } + + private void writeOversizedMeta() throws IOException { -+ java.nio.file.Files.write(getOversizedMetaFile().toPath(), oversized); ++ java.nio.file.Files.write(getOversizedMetaFile(), oversized); + } + -+ private File getOversizedMetaFile() { -+ return new File(this.regionFile.getParentFile(), this.regionFile.getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); ++ private Path getOversizedMetaFile() { ++ return this.regionFile.getParent().resolve(this.regionFile.getFileName().toString().replaceAll("\\.mca$", "") + ".oversized.nbt"); + } + -+ private File getOversizedFile(int x, int z) { -+ return new File(this.regionFile.getParentFile(), this.regionFile.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); ++ private Path getOversizedFile(int x, int z) { ++ return this.regionFile.getParent().resolve(this.regionFile.getFileName().toString().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); + } + + synchronized CompoundTag getOversizedData(int x, int z) throws IOException { -+ File file = getOversizedFile(x, z); -+ try (DataInputStream out = new DataInputStream(new BufferedInputStream(new InflaterInputStream(new java.io.FileInputStream(file))))) { ++ Path file = getOversizedFile(x, z); ++ try (DataInputStream out = new DataInputStream(new java.io.BufferedInputStream(new InflaterInputStream(Files.newInputStream(file))))) { + return NbtIo.read((java.io.DataInput) out); + } + @@ -142,25 +142,26 @@ index 298b5abbc792dd33be38acbd1c572c9778c4d2d2..46226dd2d16a9f4017661712fe2bfc0c private final ChunkPos pos; diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index ebb1a050beab9530942c4498335f084c89faef06..24092d3d3d234b6f1f2b90e22d90f297532358cc 100644 +index 40830a2b231df9bbf676d8325e76c8252a6c1d6c..164db987210aae06432a6abd9b22796c2168e212 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -10,7 +10,9 @@ import java.io.File; - import java.io.IOException; +@@ -11,8 +11,10 @@ import java.nio.file.Files; + import java.nio.file.Path; import javax.annotation.Nullable; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtIo; + import net.minecraft.nbt.StreamTagVisitor; +import net.minecraft.nbt.Tag; - import net.minecraft.server.MinecraftServer; import net.minecraft.util.ExceptionCollector; import net.minecraft.world.level.ChunkPos; -@@ -81,6 +83,74 @@ public class RegionFileStorage implements AutoCloseable { + +@@ -79,6 +81,74 @@ public class RegionFileStorage implements AutoCloseable { } } + // Paper start -+ private static void printOversizedLog(String msg, File file, int x, int z) { ++ private static void printOversizedLog(String msg, Path file, int x, int z) { + org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); + } + @@ -230,7 +231,7 @@ index ebb1a050beab9530942c4498335f084c89faef06..24092d3d3d234b6f1f2b90e22d90f297 @Nullable public CompoundTag read(ChunkPos pos) throws IOException { // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing -@@ -92,6 +162,12 @@ public class RegionFileStorage implements AutoCloseable { +@@ -90,6 +160,12 @@ public class RegionFileStorage implements AutoCloseable { try { // Paper DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); @@ -243,7 +244,7 @@ index ebb1a050beab9530942c4498335f084c89faef06..24092d3d3d234b6f1f2b90e22d90f297 CompoundTag nbttagcompound; label43: { -@@ -143,6 +219,7 @@ public class RegionFileStorage implements AutoCloseable { +@@ -172,6 +248,7 @@ public class RegionFileStorage implements AutoCloseable { try { NbtIo.write(nbt, (DataOutput) dataoutputstream); diff --git a/patches/unapplied/server/0335-Expose-the-internal-current-tick.patch b/patches/server/0333-Expose-the-internal-current-tick.patch similarity index 81% rename from patches/unapplied/server/0335-Expose-the-internal-current-tick.patch rename to patches/server/0333-Expose-the-internal-current-tick.patch index beaa10a65..075b596ba 100644 --- a/patches/unapplied/server/0335-Expose-the-internal-current-tick.patch +++ b/patches/server/0333-Expose-the-internal-current-tick.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose the internal current tick diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0dbab8b372d174f343c7d57b147692a68ba2fb95..8242d6d7471c78cc298d5c385f075e368ab80edf 100644 +index 634c50378d860808081868b2d20145d3b01259a7..8d1cbefc82f64a120eeea8c6bdd6361ffa513099 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2542,5 +2542,10 @@ public final class CraftServer implements Server { +@@ -2588,5 +2588,10 @@ public final class CraftServer implements Server { } return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); } diff --git a/patches/unapplied/server/0336-Fix-World-isChunkGenerated-calls.patch b/patches/server/0334-Fix-World-isChunkGenerated-calls.patch similarity index 73% rename from patches/unapplied/server/0336-Fix-World-isChunkGenerated-calls.patch rename to patches/server/0334-Fix-World-isChunkGenerated-calls.patch index 2e2439fb4..41748c568 100644 --- a/patches/unapplied/server/0336-Fix-World-isChunkGenerated-calls.patch +++ b/patches/server/0334-Fix-World-isChunkGenerated-calls.patch @@ -7,43 +7,19 @@ Optimize World#loadChunk() too This patch also adds a chunk status cache on region files (note that its only purpose is to cache the status on DISK) -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index d226247b93a2f1f7e039b0963d2e27b5dd11c15e..1ea32090783ac5b885b95ae2009dd61de3063ae0 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -110,6 +110,19 @@ public class ChunkHolder { - Either either = (Either) statusFuture.getNow(null); - return (either == null) ? null : (LevelChunk) either.left().orElse(null); - } -+ -+ public ChunkAccess getAvailableChunkNow() { -+ // TODO can we just getStatusFuture(EMPTY)? -+ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getParent(); curr != next; curr = next, next = next.getParent()) { -+ CompletableFuture> future = this.getFutureIfPresentUnchecked(curr); -+ Either either = future.getNow(null); -+ if (either == null || !either.left().isPresent()) { -+ continue; -+ } -+ return either.left().get(); -+ } -+ return null; -+ } - // CraftBukkit end - - public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 6d7f1fcd1709967acadd67b610c15f61d95a211b..6a676995b157702b4bd423ff8590b6c682102b61 100644 +index a605b0868b8214408e20419e336ad52659b12e4f..18d442feb77f7763d8f6c411b0e5cb0aeca1f725 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -84,6 +84,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; +@@ -86,6 +86,7 @@ import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.chunk.storage.ChunkSerializer; import net.minecraft.world.level.chunk.storage.ChunkStorage; +import net.minecraft.world.level.chunk.storage.RegionFile; import net.minecraft.world.level.entity.ChunkStatusUpdateListener; + import net.minecraft.world.level.levelgen.blending.BlendingData; import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; -@@ -1133,10 +1134,59 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1182,10 +1183,59 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @Nullable public CompoundTag readChunk(ChunkPos pos) throws IOException { CompoundTag nbttagcompound = this.read(pos); @@ -52,7 +28,7 @@ index 6d7f1fcd1709967acadd67b610c15f61d95a211b..6a676995b157702b4bd423ff8590b6c6 + return null; + } + -+ nbttagcompound = this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit ++ nbttagcompound = this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, this.generator.getTypeNameForDataFixer(), pos, level); // CraftBukkit + if (nbttagcompound == null) { + return null; + } @@ -67,12 +43,12 @@ index 6d7f1fcd1709967acadd67b610c15f61d95a211b..6a676995b157702b4bd423ff8590b6c6 + public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { + RegionFile regionFile = regionFileCache.getRegionFileIfLoaded(chunkPos); -- return nbttagcompound == null ? null : this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit +- return nbttagcompound == null ? null : this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, this.generator.getTypeNameForDataFixer(), pos, level); // CraftBukkit + return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); } + public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { -+ RegionFile regionFile = regionFileCache.getFile(chunkPos, true); ++ RegionFile regionFile = regionFileCache.getRegionFile(chunkPos, true); + + if (regionFile == null || !regionFileCache.chunkExists(chunkPos)) { + return null; @@ -90,7 +66,7 @@ index 6d7f1fcd1709967acadd67b610c15f61d95a211b..6a676995b157702b4bd423ff8590b6c6 + } + + public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { -+ RegionFile regionFile = regionFileCache.getFile(chunkPos, false); ++ RegionFile regionFile = regionFileCache.getRegionFile(chunkPos, false); + + regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); + } @@ -101,26 +77,14 @@ index 6d7f1fcd1709967acadd67b610c15f61d95a211b..6a676995b157702b4bd423ff8590b6c6 + } + // Paper end + - boolean noPlayersCloseForSpawning(ChunkPos chunkPos) { + boolean anyPlayerCloseEnoughForSpawning(ChunkPos pos) { // Spigot start - return this.isOutsideOfRange(chunkPos, false); -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 30b88f0e8ad40438af8a7d5bec1471a60ddd977b..5d920d7df52c12f5f1d1d8111340800cbddaac78 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -482,6 +482,7 @@ public class ServerChunkCache extends ChunkSource { - } - // Paper end - // Paper start - async chunk io -+ @Nullable - public ChunkAccess getChunkAtImmediately(int x, int z) { - ChunkHolder holder = this.chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); - if (holder == null) { + return this.anyPlayerCloseEnoughForSpawning(pos, false); diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index 6e0cf8ee76143301c939fc4af5eeb091abdcbc5c..1c7b18db0053bca6e7750225a79f7d95843edabe 100644 +index 328f482a0bae8d2f8013ae9a90f0500ef889ffb5..6c72854aa975800bd6160d104936a5ba978f4d67 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -224,6 +224,17 @@ public class ChunkStatus { +@@ -290,6 +290,17 @@ public class ChunkStatus { return this.chunkType; } @@ -139,15 +103,15 @@ index 6e0cf8ee76143301c939fc4af5eeb091abdcbc5c..1c7b18db0053bca6e7750225a79f7d95 return (ChunkStatus) Registry.CHUNK_STATUS.get(ResourceLocation.tryParse(id)); } 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 b8bdd69bda00ba0eb72c161d3b49101b8221ac41..1eaedda19b05e1ec429fa505c72c9e2743eb32b7 100644 +index ff53c9238325e025c502886cc5f4bc02b25f8fda..992a7d6c4372942711a1381ac08ee13910a62cb0 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 -@@ -561,6 +561,17 @@ public class ChunkSerializer { - return nbttagcompound; +@@ -595,6 +595,17 @@ public class ChunkSerializer { + })); } + // Paper start -+ public static ChunkStatus getStatus(CompoundTag compound) { ++ public static @Nullable ChunkStatus getStatus(@Nullable CompoundTag compound) { + if (compound == null) { + return null; + } @@ -158,13 +122,13 @@ index b8bdd69bda00ba0eb72c161d3b49101b8221ac41..1eaedda19b05e1ec429fa505c72c9e27 + // Paper end + public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag nbt) { - if (nbt != null) { - ChunkStatus chunkstatus = ChunkStatus.byName(nbt.getCompound("Level").getString("Status")); + return nbt != null ? ChunkStatus.byName(nbt.getString("Status")).getChunkType() : ChunkStatus.ChunkType.PROTOCHUNK; + } diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 46226dd2d16a9f4017661712fe2bfc0c46f63cb2..c22391a0d4b7db49bd3994b0887939a7d8019391 100644 +index d511db5453b722f747cc24cf2b4d97a0be75ce6a..988bc12ce011839dddbcb2f3ff96ed3829b3538e 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -27,6 +27,7 @@ import net.minecraft.Util; +@@ -24,6 +24,7 @@ import net.minecraft.Util; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtIo; import net.minecraft.world.level.ChunkPos; @@ -172,9 +136,9 @@ index 46226dd2d16a9f4017661712fe2bfc0c46f63cb2..c22391a0d4b7db49bd3994b0887939a7 import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@@ -54,6 +55,30 @@ public class RegionFile implements AutoCloseable { +@@ -51,6 +52,30 @@ public class RegionFile implements AutoCloseable { public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper - public final File regionFile; // Paper + public final Path regionFile; // Paper + // Paper start - Cache chunk status + private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; @@ -200,10 +164,10 @@ index 46226dd2d16a9f4017661712fe2bfc0c46f63cb2..c22391a0d4b7db49bd3994b0887939a7 + } + // Paper end + - public RegionFile(File file, File directory, boolean dsync) throws IOException { - this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); + public RegionFile(Path path, Path path1, boolean dsync) throws IOException { + this(path, path1, RegionFileVersion.VERSION_DEFLATE, dsync); } -@@ -401,6 +426,7 @@ public class RegionFile implements AutoCloseable { +@@ -398,6 +423,7 @@ public class RegionFile implements AutoCloseable { return this.getOffset(pos) != 0; } @@ -211,7 +175,7 @@ index 46226dd2d16a9f4017661712fe2bfc0c46f63cb2..c22391a0d4b7db49bd3994b0887939a7 private static int getOffsetIndex(ChunkPos pos) { return pos.getRegionLocalX() + pos.getRegionLocalZ() * 32; } -@@ -411,6 +437,7 @@ public class RegionFile implements AutoCloseable { +@@ -408,6 +434,7 @@ public class RegionFile implements AutoCloseable { synchronized (this) { try { // Paper end @@ -220,10 +184,10 @@ index 46226dd2d16a9f4017661712fe2bfc0c46f63cb2..c22391a0d4b7db49bd3994b0887939a7 this.padToFullSector(); } finally { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 24092d3d3d234b6f1f2b90e22d90f297532358cc..43510774d489bfdd30f10d521e424fa1363b8919 100644 +index 164db987210aae06432a6abd9b22796c2168e212..91cf5878dc13e1abca0c301d1346248bda251cbf 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -219,6 +219,7 @@ public class RegionFileStorage implements AutoCloseable { +@@ -248,6 +248,7 @@ public class RegionFileStorage implements AutoCloseable { try { NbtIo.write(nbt, (DataOutput) dataoutputstream); @@ -232,7 +196,7 @@ index 24092d3d3d234b6f1f2b90e22d90f297532358cc..43510774d489bfdd30f10d521e424fa1 } catch (Throwable throwable) { if (dataoutputstream != null) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 85bc46d7a2528254f888c027c2a4e2240f8e11d1..d580a66dd741b63dd8ed89d7b976b1612cfb4d90 100644 +index bb95fec09594f7e2d38619ae4055ec9964635622..c4d5d78064cbef9386c00dc962e0a7889ed73d9d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -19,6 +19,7 @@ import java.util.Objects; @@ -299,7 +263,7 @@ index 85bc46d7a2528254f888c027c2a4e2240f8e11d1..d580a66dd741b63dd8ed89d7b976b161 - return true; + net.minecraft.world.level.chunk.storage.RegionFile file; + try { -+ file = world.getChunkSource().chunkMap.regionFileCache.getFile(chunkPos, false); ++ file = world.getChunkSource().chunkMap.regionFileCache.getRegionFile(chunkPos, false); + } catch (IOException ex) { + throw new RuntimeException(ex); + }