diff --git a/Spigot-Server-Patches/0002-Paper-config-files.patch b/Spigot-Server-Patches/0002-Paper-config-files.patch index 3ee8ed488..9c1c968f3 100644 --- a/Spigot-Server-Patches/0002-Paper-config-files.patch +++ b/Spigot-Server-Patches/0002-Paper-config-files.patch @@ -1,4 +1,4 @@ -From 800d7c783d6ed1be96b675b15a31a04c0cf3bb6e Mon Sep 17 00:00:00 2001 +From a8159e0501c03d8ee285f2bd6d19bdf3e52d5cf8 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 29 Feb 2016 21:02:09 -0600 Subject: [PATCH] Paper config files @@ -6,7 +6,7 @@ Subject: [PATCH] Paper config files diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java new file mode 100644 -index 000000000..961966e16 +index 0000000000..961966e169 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java @@ -0,0 +1,237 @@ @@ -249,7 +249,7 @@ index 000000000..961966e16 +} diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java new file mode 100644 -index 000000000..104abab84 +index 0000000000..92e44befe0 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java @@ -0,0 +1,177 @@ @@ -313,7 +313,7 @@ index 000000000..104abab84 + commands.put("paper", new PaperCommand("paper")); + + version = getInt("config-version", 14); -+ set("config-version", 14); ++ set("config-version", 15); + readConfig(PaperConfig.class, null); + } + @@ -432,7 +432,7 @@ index 000000000..104abab84 +} diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java new file mode 100644 -index 000000000..a73865739 +index 0000000000..a738657394 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -0,0 +1,67 @@ @@ -504,7 +504,7 @@ index 000000000..a73865739 + } +} diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java -index 8b3988fc0..d8535fdd9 100644 +index 8b3988fc0a..d8535fdd9e 100644 --- a/src/main/java/net/minecraft/server/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/DedicatedServer.java @@ -192,6 +192,10 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer @@ -519,7 +519,7 @@ index 8b3988fc0..d8535fdd9 100644 DedicatedServer.LOGGER.info("Generating keypair"); this.a(MinecraftEncryption.b()); diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 709b28d78..4ba748ae2 100644 +index 3c7537d013..ffaa425ec8 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -135,9 +135,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener { @@ -536,7 +536,7 @@ index 709b28d78..4ba748ae2 100644 public boolean impulse; public int portalCooldown; diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java -index c6434ec37..17bfa356f 100644 +index c6434ec371..17bfa356f1 100644 --- a/src/main/java/net/minecraft/server/EntityTypes.java +++ b/src/main/java/net/minecraft/server/EntityTypes.java @@ -2,6 +2,8 @@ package net.minecraft.server; @@ -560,7 +560,7 @@ index c6434ec37..17bfa356f 100644 + // Paper end } diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index ed77641e4..f381e23be 100644 +index ed77641e46..f381e23beb 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -134,6 +134,8 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc @@ -581,7 +581,7 @@ index ed77641e4..f381e23be 100644 this.world = new CraftWorld((WorldServer) this, gen, env); this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e28ce05fb..e659f3f33 100644 +index e28ce05fb9..e659f3f339 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -750,6 +750,7 @@ public final class CraftServer implements Server { @@ -636,7 +636,7 @@ index e28ce05fb..e659f3f33 100644 + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 4a998593b..e354245f7 100644 +index 4a998593bd..e354245f73 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -128,6 +128,14 @@ public class Main { @@ -655,7 +655,7 @@ index 4a998593b..e354245f7 100644 }; diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 95f7a9587..87bc8e2d9 100644 +index 95f7a9587a..87bc8e2d9c 100644 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java @@ -39,31 +39,31 @@ public class SpigotWorldConfig diff --git a/Spigot-Server-Patches/0377-Async-Chunk-Loading-and-Generation.patch b/Spigot-Server-Patches/0377-Async-Chunk-Loading-and-Generation.patch index 6aba229aa..b859d3ab1 100644 --- a/Spigot-Server-Patches/0377-Async-Chunk-Loading-and-Generation.patch +++ b/Spigot-Server-Patches/0377-Async-Chunk-Loading-and-Generation.patch @@ -1,4 +1,4 @@ -From 523a76f0b9a204e83620100df735b2228c22306e Mon Sep 17 00:00:00 2001 +From 5b1ddb18ea0397774eed24f27ab4d3fe2449141c 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 @@ -43,22 +43,64 @@ reading or writing to the chunk will be safe, so plugins still should not be touching chunks asynchronously! diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index da710cc6fe..6b65364e22 100644 +index 912c990404..2f6d7f2976 100644 --- a/src/main/java/com/destroystokyo/paper/PaperConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -372,4 +372,15 @@ public class PaperConfig { +@@ -372,4 +372,57 @@ public class PaperConfig { } } } + -+ // Temporary opt out, will be removed later + public static boolean asyncChunks = false; -+ private static void disableAsyncChunks() { -+ asyncChunks = config.getBoolean("settings.async-chunks", true); ++ public static boolean asyncChunkGeneration = true; ++ public static boolean asyncChunkGenThreadPerWorld = true; ++ public static int asyncChunkLoadThreads = -1; ++ private static void asyncChunks() { ++ if (version < 15) { ++ boolean enabled = config.getBoolean("settings.async-chunks", true); ++ ConfigurationSection section = config.createSection("settings.async-chunks"); ++ section.set("enable", enabled); ++ section.set("load-threads", -1); ++ section.set("generation", true); ++ section.set("thread-per-world-generation", true); ++ } ++ ++ asyncChunks = getBoolean("settings.async-chunks.enable", true); ++ asyncChunkGeneration = getBoolean("settings.async-chunks.generation", true); ++ asyncChunkGenThreadPerWorld = getBoolean("settings.async-chunks.thread-per-world-generation", true); ++ asyncChunkLoadThreads = getInt("settings.async-chunks.load-threads", -1); ++ if (asyncChunkLoadThreads <= 0) { ++ asyncChunkLoadThreads = (int) Math.min(Integer.getInteger("paper.maxchunkthreads", 8), Runtime.getRuntime().availableProcessors() * 1.5); ++ } ++ ++ // Let Shared Host set some limits ++ String sharedHostEnvGen = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_GEN"); ++ String sharedHostEnvLoad = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_LOAD"); ++ if ("1".equals(sharedHostEnvGen)) { ++ log("Async Chunks - Generation: Your host has requested to use a single thread world generation"); ++ asyncChunkGenThreadPerWorld = false; ++ } else if ("2".equals(sharedHostEnvGen)) { ++ log("Async Chunks - Generation: Your host has disabled async world generation - You will experience lag from world generation"); ++ asyncChunkGeneration = false; ++ } ++ ++ if (sharedHostEnvLoad != null) { ++ try { ++ asyncChunkLoadThreads = Math.max(1, Math.min(asyncChunkLoadThreads, Integer.parseInt(sharedHostEnvLoad))); ++ } catch (NumberFormatException ignored) {} ++ } ++ + if (!asyncChunks) { + log("Async Chunks: Disabled - Chunks will be managed synchronosuly, and will cause tremendous lag."); + } else { -+ log("Async Chunks: Enabled - Chunks will be loaded and generated much faster, without lag."); ++ log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); ++ if (!asyncChunkGeneration) { ++ log("Async Chunks - Generation: Disabled - Chunks will be generated synchronosuly, and will cause tremendous lag."); ++ } else if (asyncChunkGenThreadPerWorld) { ++ log("Async Chunks - Generation: Enabled - Chunks will be generated much faster, without lag."); ++ } else { ++ log("Async Chunks - Generation: Enabled (Single Thread) - Chunks will be generated much faster, without lag."); ++ } + } + } } @@ -794,10 +836,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..a3fc989832 +index 0000000000..1c592c7956 --- /dev/null +++ b/src/main/java/net/minecraft/server/PaperAsyncChunkProvider.java -@@ -0,0 +1,478 @@ +@@ -0,0 +1,477 @@ +/* + * This file is licensed under the MIT License (MIT). + * @@ -846,8 +888,8 @@ index 0000000000..a3fc989832 +public class PaperAsyncChunkProvider extends ChunkProviderServer { + + private static final PriorityQueuedExecutor.RejectionHandler IGNORE_HANDLER = (run, executor) -> {}; -+ private static final int CHUNK_THREADS = (int) Math.min(Integer.getInteger("paper.maxchunkthreads", 8), Runtime.getRuntime().availableProcessors() * 1.5); -+ private static final PriorityQueuedExecutor EXECUTOR = new PriorityQueuedExecutor("PaperChunkLoader", PaperConfig.asyncChunks ? CHUNK_THREADS : 0, IGNORE_HANDLER); ++ private static final PriorityQueuedExecutor EXECUTOR = new PriorityQueuedExecutor("PaperChunkLoader", PaperConfig.asyncChunks ? PaperConfig.asyncChunkLoadThreads : 0, IGNORE_HANDLER); ++ private static final PriorityQueuedExecutor SINGLE_GEN_EXECUTOR = new PriorityQueuedExecutor("PaperChunkGenerator", PaperConfig.asyncChunks && PaperConfig.asyncChunkGeneration && !PaperConfig.asyncChunkGenThreadPerWorld ? 1 : 0, IGNORE_HANDLER); + + private final PriorityQueuedExecutor generationExecutor; + //private static final PriorityQueuedExecutor generationExecutor = new PriorityQueuedExecutor("PaperChunkGen", 1); @@ -868,8 +910,8 @@ index 0000000000..a3fc989832 + this.asyncHandler = server; + this.chunkLoader = chunkLoader; + String worldName = this.world.getWorld().getName(); -+ this.shouldGenSync = generator instanceof CustomChunkGenerator && !(((CustomChunkGenerator) generator).asyncSupported); -+ this.generationExecutor = new PriorityQueuedExecutor("PaperChunkGen-" + worldName, shouldGenSync ? 0 : 1, IGNORE_HANDLER); ++ this.shouldGenSync = generator instanceof CustomChunkGenerator && !(((CustomChunkGenerator) generator).asyncSupported) || !PaperConfig.asyncChunkGeneration; ++ this.generationExecutor = PaperConfig.asyncChunkGenThreadPerWorld ? new PriorityQueuedExecutor("PaperChunkGen-" + worldName, shouldGenSync ? 0 : 1, IGNORE_HANDLER) : SINGLE_GEN_EXECUTOR; + } + + static void processChunkLoads(MinecraftServer server) { @@ -1176,13 +1218,12 @@ index 0000000000..a3fc989832 + this.chunk = chunk; + this.hasFinished = true; + } -+ if (Bukkit.isPrimaryThread()) { -+ postChunk(); -+ } else { -+ synchronized (mainThreadQueue) { -+ mainThreadQueue.add(this::postChunk); -+ mainThreadQueue.notify(); -+ } ++ ++ // Don't post here, even if on main, it must enter the queue so we can exit any open batch ++ // schedulers, as post stage may trigger a new generation and cause errors ++ synchronized (mainThreadQueue) { ++ mainThreadQueue.add(this::postChunk); ++ mainThreadQueue.notify(); + } + } + @@ -1410,7 +1451,7 @@ index 3c35c0f481..187ca2813a 100644 this.m = world.getChunkProvider().getChunkGenerator().getSettings(); this.i = world.getSeaLevel(); diff --git a/src/main/java/net/minecraft/server/SchedulerBatch.java b/src/main/java/net/minecraft/server/SchedulerBatch.java -index d868149d1a..0d94b262ac 100644 +index d868149d1a..0d45d933ee 100644 --- a/src/main/java/net/minecraft/server/SchedulerBatch.java +++ b/src/main/java/net/minecraft/server/SchedulerBatch.java @@ -9,6 +9,7 @@ public class SchedulerBatch, R> { @@ -1421,16 +1462,18 @@ index d868149d1a..0d94b262ac 100644 public SchedulerBatch(Scheduler scheduler) { this.b = scheduler; -@@ -18,7 +19,9 @@ public class SchedulerBatch, R> { +@@ -18,8 +19,10 @@ public class SchedulerBatch, R> { this.b.b(); } + public void startBatch() { b(); } // Paper - OBFHELPER public void b() { +- if (this.c) { + lock.lock(); // Paper - if (this.c) { ++ if (false && this.c) { // Paper throw new RuntimeException("Batch already started."); } else { + this.d = 1000; @@ -27,6 +30,7 @@ public class SchedulerBatch, R> { } } @@ -1439,20 +1482,22 @@ index d868149d1a..0d94b262ac 100644 public CompletableFuture a(K object) { if (!this.c) { throw new RuntimeException("Batch not properly started. Please use startBatch to create a new batch."); -@@ -42,7 +46,13 @@ public class SchedulerBatch, R> { +@@ -42,8 +46,14 @@ public class SchedulerBatch, R> { } } + public CompletableFuture executeBatch() { return c(); } // Paper - OBFHELPER public CompletableFuture c() { +- if (!this.c) { + // Paper start + if (!lock.isHeldByCurrentThread()) { + throw new IllegalStateException("Current thread does not hold the write lock"); + } + try {// Paper end - if (!this.c) { ++ if (false && !this.c) { // Paper throw new RuntimeException("Batch not properly started. Please use startBatch to create a new batch."); } else { + if (this.d != 1000) { @@ -53,5 +63,6 @@ public class SchedulerBatch, R> { this.c = false; return this.b.c();