diff --git a/Spigot-Server-Patches/0326-Detect-and-repair-corrupt-Region-Files.patch b/Spigot-Server-Patches/0326-Detect-and-repair-corrupt-Region-Files.patch index 7fddd1a4472..a2dd80e82e7 100644 --- a/Spigot-Server-Patches/0326-Detect-and-repair-corrupt-Region-Files.patch +++ b/Spigot-Server-Patches/0326-Detect-and-repair-corrupt-Region-Files.patch @@ -1,4 +1,4 @@ -From 56d73274d938d16968b54d62069ba376b53d818e Mon Sep 17 00:00:00 2001 +From 8375c097918c91e3a4ff945847903ff33c1f770f Mon Sep 17 00:00:00 2001 From: Aikar Date: Sat, 11 Aug 2018 00:49:20 -0400 Subject: [PATCH] Detect and repair corrupt Region Files @@ -11,7 +11,7 @@ I don't know why mojang only checks for 4096, when anything less than 8192 is a But to be safe, it will attempt to back up the file. diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java -index 5d2853b9ce..5c0d4f912a 100644 +index 5d2853b9ce..6a2edfd1e1 100644 --- a/src/main/java/net/minecraft/server/RegionFile.java +++ b/src/main/java/net/minecraft/server/RegionFile.java @@ -22,10 +22,10 @@ import javax.annotation.Nullable; @@ -58,14 +58,11 @@ index 5d2853b9ce..5c0d4f912a 100644 } } catch (IOException ioexception) { ioexception.printStackTrace(); -@@ -276,6 +276,58 @@ public class RegionFile { +@@ -276,6 +276,55 @@ public class RegionFile { } + // Paper start -+ public void deleteChunk(int x, int z) { -+ deleteChunk(x + z * 32); -+ } + public synchronized void deleteChunk(int j1) { + backup(); + int k = offsets[j1]; diff --git a/Spigot-Server-Patches/0375-Async-Chunk-Loading-and-Generation.patch b/Spigot-Server-Patches/0375-Async-Chunk-Loading-and-Generation.patch index c9239d0b500..a5e527c0610 100644 --- a/Spigot-Server-Patches/0375-Async-Chunk-Loading-and-Generation.patch +++ b/Spigot-Server-Patches/0375-Async-Chunk-Loading-and-Generation.patch @@ -1,4 +1,4 @@ -From f7cdbb488e556812e697024408c1ac7e9c57a18b Mon Sep 17 00:00:00 2001 +From 1248921187e1c418988fe86a9e28b2ae810a092f Mon Sep 17 00:00:00 2001 From: Aikar Date: Sat, 21 Jul 2018 16:55:04 -0400 Subject: [PATCH] Async Chunk Loading and Generation @@ -904,10 +904,10 @@ index 98d182fdb8..487d98eb1b 100644 diff --git a/src/main/java/net/minecraft/server/PaperAsyncChunkProvider.java b/src/main/java/net/minecraft/server/PaperAsyncChunkProvider.java new file mode 100644 -index 0000000000..2dfa59b204 +index 0000000000..4fc5fad09e --- /dev/null +++ b/src/main/java/net/minecraft/server/PaperAsyncChunkProvider.java -@@ -0,0 +1,568 @@ +@@ -0,0 +1,593 @@ +/* + * This file is licensed under the MIT License (MIT). + * @@ -965,6 +965,8 @@ index 0000000000..2dfa59b204 + private final Long2ObjectMap pendingChunks = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>()); + private final ConcurrentLinkedQueue mainThreadQueue = new ConcurrentLinkedQueue<>(); + private final IAsyncTaskHandler asyncHandler; ++ private final ThreadLocal isChunkThread = ThreadLocal.withInitial(() -> false); ++ private final ThreadLocal isChunkGenThread = ThreadLocal.withInitial(() -> false); + + private final WorldServer world; + private final IChunkLoader chunkLoader; @@ -1069,6 +1071,9 @@ index 0000000000..2dfa59b204 + // Listen for when result is ready + final CompletableFuture future = new CompletableFuture<>(); + PendingChunkRequest request = pending.addListener(future, gen); ++ if (isChunkThread.get()) { ++ pending.loadTask.run(); ++ } + + if (isBlockingMain && pending.hasFinished) { + processChunkLoads(); @@ -1248,6 +1253,11 @@ index 0000000000..2dfa59b204 + } + } + ++ private Chunk generateChunkExecutor() { ++ isChunkThread.set(true); ++ isChunkGenThread.set(true); ++ return generateChunk(); ++ } + private Chunk generateChunk() { + synchronized (this) { + if (requests.get() <= 0) { @@ -1405,8 +1415,16 @@ index 0000000000..2dfa59b204 + if (loadTask == null) { + // Take care of a race condition in that a request could be cancelled after the synchronize + // on pendingChunks, but before a listener is added, which would erase these pending tasks. -+ genTask = generationExecutor.createPendingTask(this::generateChunk, taskPriority); -+ loadTask = EXECUTOR.submitTask(this, taskPriority); ++ if (shouldGenSync) { ++ genTask = generationExecutor.createPendingTask(this::generateChunk, taskPriority); ++ } else { ++ genTask = generationExecutor.createPendingTask(this::generateChunkExecutor, taskPriority); ++ } ++ loadTask = EXECUTOR.createPendingTask(this, taskPriority); ++ if (!isChunkThread.get()) { ++ // We will execute it outside of the synchronized context immediately after ++ EXECUTOR.submitTask(loadTask); ++ } + } + return new PendingChunkRequest(this, gen); + } @@ -1414,6 +1432,7 @@ index 0000000000..2dfa59b204 + + @Override + public void run() { ++ isChunkThread.set(true); + try { + if (!loadFinished(loadChunk(x, z))) { + return; @@ -1435,7 +1454,13 @@ index 0000000000..2dfa59b204 + mainThreadQueue.notify(); + } + } else { -+ generationExecutor.submitTask(genTask); ++ if (isChunkGenThread.get()) { ++ // ideally we should never run into 1 chunk generating another chunk... ++ // but if we do, let's apply same solution ++ genTask.run(); ++ } else { ++ generationExecutor.submitTask(genTask); ++ } + } + } +