diff --git a/leaf-api/paper-patches/features/0002-Leaf-config.patch b/leaf-api/paper-patches/features/0002-Leaf-config.patch index 14e745f9..890ee122 100644 --- a/leaf-api/paper-patches/features/0002-Leaf-config.patch +++ b/leaf-api/paper-patches/features/0002-Leaf-config.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Leaf config diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 3446d5bb24fac345b65ac78927155f60fe437b2c..0f4bc6a5b87a72f521f6ca04cfe14147b4e35fe4 100644 +index 52485a1bce522cf9a61c3e67673aafb1a5e1a82b..f2fcb836ca69bb0f49b79c92bf4e291f2a4448d6 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2414,6 +2414,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2412,6 +2412,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi // Paper end diff --git a/leaf-api/paper-patches/features/0004-Purpur-API-Changes.patch b/leaf-api/paper-patches/features/0004-Purpur-API-Changes.patch index b9d30f6c..173f3bb5 100644 --- a/leaf-api/paper-patches/features/0004-Purpur-API-Changes.patch +++ b/leaf-api/paper-patches/features/0004-Purpur-API-Changes.patch @@ -70,10 +70,10 @@ index 6b2f6ab137ae37ff0db4827886614436b7ed5dcb..66a9fc729182476c4f601cdb32bcb109 /** * The brand id for Pufferfish. diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index e4db2817be2411116ff29cc85ce97e515eb6e51f..0825a913b4f7d5e81d485df6415ab68a4e1530ce 100644 +index ee9985b276b0e5ac5fab871598a596e6c444b01e..d109070e6ea9057d031c2c8edfeeefb423dca9fb 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -3061,4 +3061,133 @@ public final class Bukkit { +@@ -3064,4 +3064,133 @@ public final class Bukkit { public static void restart() { server.restart(); } @@ -444,10 +444,10 @@ index ed8e11001c8d3c475dc851aedf6e6812a872dc54..c597c298795fb9893447bc822d941c17 + // Purpur end - OfflinePlayer API } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 0f4bc6a5b87a72f521f6ca04cfe14147b4e35fe4..42bc72411462f3699a7a60f987eeca6046f4cf75 100644 +index f2fcb836ca69bb0f49b79c92bf4e291f2a4448d6..2e750b3187d93d9001d5aa5c0d80a99a1a888377 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2414,6 +2414,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2412,6 +2412,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi // Paper end @@ -466,7 +466,7 @@ index 0f4bc6a5b87a72f521f6ca04cfe14147b4e35fe4..42bc72411462f3699a7a60f987eeca60 // Leaf start - Leaf config - API @NotNull public org.bukkit.configuration.file.YamlConfiguration getLeafConfig() -@@ -2783,4 +2795,111 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2781,4 +2793,111 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ long getLastTickOversleepTime(); // Gale end - YAPFA - last tick time - API @@ -1321,7 +1321,7 @@ index f1f97a85ec713c05c882d7588f4a3e4a017f4795..813f6cd253322538bdf96eb323dd23a7 + // Purpur end } diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 5644b350151570eb790472cb48e7c701f68204df..c27bbccf032b5dc2e3c845216b4c14627c83cca2 100644 +index dc50f83e9604b69a30b6c6f3495000e4b7082b0d..472806b902a90931293b96a558d27fc0b54412ae 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -21,6 +21,13 @@ import org.bukkit.material.MaterialData; diff --git a/leaf-api/paper-patches/features/0009-Leaves-Replay-Mod-API.patch b/leaf-api/paper-patches/features/0009-Leaves-Replay-Mod-API.patch index e0679329..1e737ae5 100644 --- a/leaf-api/paper-patches/features/0009-Leaves-Replay-Mod-API.patch +++ b/leaf-api/paper-patches/features/0009-Leaves-Replay-Mod-API.patch @@ -11,10 +11,10 @@ Original project: https://github.com/LeavesMC/Leaves This patch is Powered by ReplayMod(https://github.com/ReplayMod) diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 0825a913b4f7d5e81d485df6415ab68a4e1530ce..f40e06c63a82dbbd6bbcadf2a71b7d2825f2b3a9 100644 +index d109070e6ea9057d031c2c8edfeeefb423dca9fb..49ef3c579e8ccd51e463cabd0a3ac64434415028 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -3190,4 +3190,10 @@ public final class Bukkit { +@@ -3193,4 +3193,10 @@ public final class Bukkit { server.clearBlockHighlights(); } // Purpur end - Debug Marker API @@ -26,10 +26,10 @@ index 0825a913b4f7d5e81d485df6415ab68a4e1530ce..f40e06c63a82dbbd6bbcadf2a71b7d28 + // Leaves end - Photographer API } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 42bc72411462f3699a7a60f987eeca6046f4cf75..b4ef18cac662c089ac975a0fae0df93e692fc9bc 100644 +index 2e750b3187d93d9001d5aa5c0d80a99a1a888377..6044de3373d52455813b30305a47d523803e7ad5 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2902,4 +2902,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2900,4 +2900,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ void clearBlockHighlights(); // Purpur end - Debug Marker API diff --git a/leaf-server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch b/leaf-server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch index 8e459e34..2bb35dff 100644 --- a/leaf-server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch +++ b/leaf-server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch @@ -12,22 +12,14 @@ In non-strict test, this can give ~60-110% improvement (524ms on Paper, 204ms on under 625 villagers situation. diff --git a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java -index b0c5e41fefc7c9adf1a61bd5b52861736657d37e..7f9550af4dce9c6442080c39d19e824f63115d7c 100644 +index b0c5e41fefc7c9adf1a61bd5b52861736657d37e..83af90c7a2e425b775abd7907895d211ced07955 100644 --- a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +++ b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java -@@ -1,7 +1,7 @@ - package net.minecraft.world.entity.ai.sensing; - - import com.google.common.collect.ImmutableSet; --import java.util.Comparator; -+import java.util.Arrays; - import java.util.List; - import java.util.Set; - import net.minecraft.server.level.ServerLevel; -@@ -13,18 +13,101 @@ import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities; +@@ -13,18 +13,102 @@ import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities; import net.minecraft.world.phys.AABB; public class NearestLivingEntitySensor extends Sensor { ++ + // Leaf start - Optimized entity sorting with buffer reuse + private static final int SMALL_ARRAY_THRESHOLD = 2; + private LivingEntity[] entityBuffer = new LivingEntity[0]; @@ -49,7 +41,7 @@ index b0c5e41fefc7c9adf1a61bd5b52861736657d37e..7f9550af4dce9c6442080c39d19e824f - entitiesOfClass.sort(Comparator.comparingDouble(entity::distanceToSqr)); + + LivingEntity[] sorted = smartSort(entities, entity); -+ List sortedList = Arrays.asList(sorted); ++ List sortedList = java.util.Arrays.asList(sorted); + Brain brain = entity.getBrain(); - brain.setMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES, entitiesOfClass); @@ -76,7 +68,7 @@ index b0c5e41fefc7c9adf1a61bd5b52861736657d37e..7f9550af4dce9c6442080c39d19e824f + + fastRadixSort(entityBuffer, bitsBuffer, 0, size - 1, 62); + -+ return Arrays.copyOf(entityBuffer, size); ++ return java.util.Arrays.copyOf(entityBuffer, size); + } + + private void fastRadixSort(LivingEntity[] ents, long[] bits, int low, int high, int bit) { diff --git a/leaf-server/minecraft-patches/features/0141-SparklyPaper-Parallel-world-ticking.patch b/leaf-server/minecraft-patches/features/0141-SparklyPaper-Parallel-world-ticking.patch index 66afeaa7..eb3f2427 100644 --- a/leaf-server/minecraft-patches/features/0141-SparklyPaper-Parallel-world-ticking.patch +++ b/leaf-server/minecraft-patches/features/0141-SparklyPaper-Parallel-world-ticking.patch @@ -3,53 +3,46 @@ From: Altiami Date: Wed, 5 Mar 2025 13:13:24 -0800 Subject: [PATCH] SparklyPaper: Parallel world ticking +Original project: https://github.com/SparklyPower/SparklyPaper diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -index d6a30d6735d24f24a8108b6a5d15725587bb662a..1015344712ef6d13622348871418ef3f6efd8045 100644 +index d6a30d6735d24f24a8108b6a5d15725587bb662a..39517966935265bc4533d4ce414d2df72df5a614 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -@@ -40,6 +40,7 @@ import net.minecraft.util.SortedArraySet; - import net.minecraft.util.Unit; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.chunk.LevelChunk; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - import java.io.IOException; - import java.text.DecimalFormat; -@@ -1050,7 +1051,7 @@ public final class ChunkHolderManager { +@@ -1050,7 +1050,7 @@ public final class ChunkHolderManager { if (changedFullStatus.isEmpty()) { return; } - if (!TickThread.isTickThread()) { -+ if (SparklyPaperParallelWorldTicking.enabled && !TickThread.isTickThreadFor(world) || !TickThread.isTickThread()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && !TickThread.isTickThreadFor(world) || !TickThread.isTickThread()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (make configurable) this.taskScheduler.scheduleChunkTask(() -> { final ArrayDeque pendingFullLoadUpdate = ChunkHolderManager.this.pendingFullLoadUpdate; for (int i = 0, len = changedFullStatus.size(); i < len; ++i) { -@@ -1076,7 +1077,12 @@ public final class ChunkHolderManager { +@@ -1076,7 +1076,12 @@ public final class ChunkHolderManager { // note: never call while inside the chunk system, this will absolutely break everything public void processUnloads() { - TickThread.ensureTickThread("Cannot unload chunks off-main"); -+ // Leaf start - SparklyPaper parallel world ticking mod (make configurable) -+ if (SparklyPaperParallelWorldTicking.enabled) ++ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + TickThread.ensureTickThread(world, "Cannot unload chunks off-main"); // SparklyPaper - parallel world ticking + else + TickThread.ensureTickThread("Cannot unload chunks off-main"); -+ // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable) if (BLOCK_TICKET_UPDATES.get() == Boolean.TRUE) { throw new IllegalStateException("Cannot unload chunks recursively"); -@@ -1358,7 +1364,7 @@ public final class ChunkHolderManager { +@@ -1358,7 +1363,7 @@ public final class ChunkHolderManager { List changedFullStatus = null; - final boolean isTickThread = TickThread.isTickThread(); -+ final boolean isTickThread = SparklyPaperParallelWorldTicking.enabled && TickThread.isTickThreadFor(world) || TickThread.isTickThread(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ final boolean isTickThread = org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && TickThread.isTickThreadFor(world) || TickThread.isTickThread(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (make configurable) boolean ret = false; final boolean canProcessFullUpdates = processFullUpdates & isTickThread; diff --git a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java -index 4a881636ba21fae9e50950bbba2b4321b71d35ab..ef9b8e9b7a6156bc65a99a65da196c4acc6f12bb 100644 +index 4a881636ba21fae9e50950bbba2b4321b71d35ab..9b01cc21a7e7411b8d112b5b7d7061e66c9bde06 100644 --- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java @@ -46,7 +46,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { @@ -57,12 +50,12 @@ index 4a881636ba21fae9e50950bbba2b4321b71d35ab..ef9b8e9b7a6156bc65a99a65da196c4a org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) serverLevel.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -index bd5bbc7e55c6bea77991fe5a3c0c2580313d16c5..bc43ffda879b24b1467443aa86b68c28463ef19e 100644 +index bd5bbc7e55c6bea77991fe5a3c0c2580313d16c5..e0f0834dd899d0ead0ad3995a9f457f9f33449e0 100644 --- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java @@ -78,7 +78,7 @@ public class DefaultDispenseItemBehavior implements DispenseItemBehavior { @@ -70,12 +63,12 @@ index bd5bbc7e55c6bea77991fe5a3c0c2580313d16c5..bc43ffda879b24b1467443aa86b68c28 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(itemEntity.getDeltaMovement())); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) level.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/DispenseItemBehavior.java b/net/minecraft/core/dispenser/DispenseItemBehavior.java -index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0fda2ba0a 100644 +index f576449e8bc6fd92963cbe3954b0c853a02def3c..634a2a93569dc7e4bd2fe594cf611b278ef3a257 100644 --- a/net/minecraft/core/dispenser/DispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java @@ -89,7 +89,7 @@ public interface DispenseItemBehavior { @@ -83,7 +76,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) serverLevel.getCraftServer().getPluginManager().callEvent(event); } @@ -92,7 +85,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) serverLevel.getCraftServer().getPluginManager().callEvent(event); } @@ -101,7 +94,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity()); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) world.getCraftServer().getPluginManager().callEvent(event); } @@ -110,7 +103,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleCopy); org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), abstractChestedHorse.getBukkitLivingEntity()); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) world.getCraftServer().getPluginManager().callEvent(event); } @@ -119,7 +112,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) level.getCraftServer().getPluginManager().callEvent(event); } @@ -128,7 +121,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) levelAccessor.getMinecraftWorld().getCraftServer().getPluginManager().callEvent(event); } @@ -137,7 +130,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) serverLevel.getCraftServer().getPluginManager().callEvent(event); } @@ -146,7 +139,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) level.getCraftServer().getPluginManager().callEvent(event); } @@ -156,8 +149,8 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 if (level.capturedBlockStates.size() > 0) { - org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeType; - net.minecraft.world.level.block.SaplingBlock.treeType = null; -+ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.getTreeTypeRT(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) -+ net.minecraft.world.level.block.SaplingBlock.setTreeTypeRT(null); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.getTreeTypeRT(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) ++ net.minecraft.world.level.block.SaplingBlock.setTreeTypeRT(null); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(blockPos, level.getWorld()); List blocks = new java.util.ArrayList<>(level.capturedBlockStates.values()); level.capturedBlockStates.clear(); @@ -166,7 +159,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockPos.getX() + 0.5D, (double) blockPos.getY(), (double) blockPos.getZ() + 0.5D)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) level.getCraftServer().getPluginManager().callEvent(event); } @@ -175,7 +168,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) level.getCraftServer().getPluginManager().callEvent(event); } @@ -184,7 +177,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) level.getCraftServer().getPluginManager().callEvent(event); } @@ -193,7 +186,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) serverLevel.getCraftServer().getPluginManager().callEvent(event); } @@ -202,12 +195,12 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..7f93485c1e931de04f2609a7aab3ecf0 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity()); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) serverLevel.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java -index b91b2f5ea6a1da0477541dc65fdfbfa57b9af475..5f43f25001156c83d715c1976d3c01ae8182bf6f 100644 +index b91b2f5ea6a1da0477541dc65fdfbfa57b9af475..e8bf2884699be35330d5b72e2591629fe8318741 100644 --- a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java @@ -39,7 +39,7 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior { @@ -215,12 +208,12 @@ index b91b2f5ea6a1da0477541dc65fdfbfa57b9af475..5f43f25001156c83d715c1976d3c01ae org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) livingEntity.getBukkitEntity()); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) world.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java b/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java -index 116395b6c00a0814922516707544a9ff26d68835..cf828a772b768f158f132c32adb8781de12cd7b7 100644 +index 116395b6c00a0814922516707544a9ff26d68835..133ed3de05ee740836c83d6b49d7171e7fce155d 100644 --- a/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java @@ -62,7 +62,7 @@ public class MinecartDispenseItemBehavior extends DefaultDispenseItemBehavior { @@ -228,12 +221,12 @@ index 116395b6c00a0814922516707544a9ff26d68835..cf828a772b768f158f132c32adb8781d org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(vec31.x, vec31.y, vec31.z)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) serverLevel.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java b/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java -index 449d9b72ff4650961daa9d1bd25940f3914a6b12..195ba81fe7af9046fb07504768daf8f5825fe3e3 100644 +index 449d9b72ff4650961daa9d1bd25940f3914a6b12..bdb4974f1eca8e585ce5f588ab898e4cf9e30625 100644 --- a/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java +++ b/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java @@ -32,7 +32,7 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { @@ -241,12 +234,12 @@ index 449d9b72ff4650961daa9d1bd25940f3914a6b12..195ba81fe7af9046fb07504768daf8f5 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) direction.getStepX(), (double) direction.getStepY(), (double) direction.getStepZ())); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) serverLevel.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -index 626e9feb6a6e7a2cbc7c63e30ba4fb6b923e85c7..4814dd4340139020aae96f0286c4ac9ac0fb933e 100644 +index 626e9feb6a6e7a2cbc7c63e30ba4fb6b923e85c7..1d8d492fdd040595615b8e8b7ce3910b160762b2 100644 --- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java @@ -25,7 +25,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { @@ -254,12 +247,12 @@ index 626e9feb6a6e7a2cbc7c63e30ba4fb6b923e85c7..4814dd4340139020aae96f0286c4ac9a org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) serverLevel.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java -index 5ab2c8333178335515e619b87ae420f948c83bd1..3b378ef89bdf64190f21003ee3dc0f8723375418 100644 +index 5ab2c8333178335515e619b87ae420f948c83bd1..be3b2f023897a8823560ee059cb16ec91ffcb2d8 100644 --- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java @@ -27,7 +27,7 @@ public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { @@ -267,30 +260,15 @@ index 5ab2c8333178335515e619b87ae420f948c83bd1..3b378ef89bdf64190f21003ee3dc0f87 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockPos.getX(), blockPos.getY(), blockPos.getZ())); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) blockSource.level().getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 8744690b69be75f9dbcfe5a52bb90ed387eaffd7..fc6f6bc888018e879479ce24988d58f1f7e958f1 100644 +index 8744690b69be75f9dbcfe5a52bb90ed387eaffd7..f2d1025a13649c35991a662c267a7653e75d19a2 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1,5 +1,6 @@ - package net.minecraft.server; - -+import ca.spottedleaf.moonrise.common.util.TickThread; - import com.google.common.base.Preconditions; - import com.google.common.base.Splitter; - import com.google.common.collect.ImmutableList; -@@ -160,6 +161,7 @@ import net.minecraft.world.level.storage.ServerLevelData; - import net.minecraft.world.level.storage.WorldData; - import net.minecraft.world.phys.Vec2; - import net.minecraft.world.phys.Vec3; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - - public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, ChunkIOErrorReporter, CommandSource, ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer { // Paper - rewrite chunk system -@@ -291,6 +293,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (concurrent because plugins may schedule tasks async) @@ -298,22 +276,24 @@ index 8744690b69be75f9dbcfe5a52bb90ed387eaffd7..fc6f6bc888018e879479ce24988d58f1 public static S spin(Function threadFunction) { ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system -@@ -323,24 +326,34 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop serverPlayer1.connection.suspendFlushing()); this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit -@@ -1737,28 +1761,50 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { @@ -409,7 +390,7 @@ index 8744690b69be75f9dbcfe5a52bb90ed387eaffd7..fc6f6bc888018e879479ce24988d58f1 + currentThread.currentlyTickingServerLevel = serverLevel; + + try { -+ tickLevel(serverLevel, hasTimeLeft); // Leaf - SparklyPaper parallel world ticking mod (move level ticking logic out for branch convergence) ++ tickLevel(serverLevel, hasTimeLeft); // Leaf - SparklyPaper - parallel world ticking mod (move level ticking logic out for branch convergence) + } finally { + serverLevelTickingSemaphore.release(); + } @@ -417,7 +398,7 @@ index 8744690b69be75f9dbcfe5a52bb90ed387eaffd7..fc6f6bc888018e879479ce24988d58f1 + ); + } else + tickLevel(serverLevel, hasTimeLeft); -+ // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable) + + serverLevel.explosionDensityCache.clear(); // Paper - Optimize explosions } @@ -429,57 +410,41 @@ index 8744690b69be75f9dbcfe5a52bb90ed387eaffd7..fc6f6bc888018e879479ce24988d58f1 + } catch (java.lang.InterruptedException | java.util.concurrent.ExecutionException e) { + throw new RuntimeException(e); // Propagate exception } -+ // SparklyPaper end ++ // SparklyPaper end - parallel world ticking this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked this.tickConnection(); -@@ -1838,6 +1884,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop, ServerLevel> oldLevels = this.levels; Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); newLevels.remove(level.dimension()); -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + level.tickExecutor.shutdown(); // SparklyPaper - parallel world ticking (We remove it in here instead of ServerLevel.close() because ServerLevel.close() is never called!) this.levels = Collections.unmodifiableMap(newLevels); } // CraftBukkit end diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index d4048661575ebfaf128ba25da365843774364e0e..64f8824c378d92dbeab2558e6fdc5648e34ed98e 100644 +index d4048661575ebfaf128ba25da365843774364e0e..33dd16a26edd2974f04d9a868d3e58e8e3060032 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -57,6 +57,7 @@ import net.minecraft.world.level.GameType; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.entity.SkullBlockEntity; - import net.minecraft.world.level.storage.LevelStorageSource; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - - public class DedicatedServer extends MinecraftServer implements ServerInterface { -@@ -249,6 +250,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -249,6 +249,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } org.purpurmc.purpur.PurpurConfig.registerCommands(); */// Purpur end - Purpur config files // Purpur - Configurable void damage height and damage -+ // Leaf start - SparklyPaper parallel world ticking mod (make configurable) -+ if (SparklyPaperParallelWorldTicking.enabled) { -+ serverLevelTickingSemaphore = new java.util.concurrent.Semaphore(SparklyPaperParallelWorldTicking.threads); // SparklyPaper - parallel world ticking ++ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) { ++ serverLevelTickingSemaphore = new java.util.concurrent.Semaphore(org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.threads); // SparklyPaper - parallel world ticking + DedicatedServer.LOGGER.info("Using " + serverLevelTickingSemaphore.availablePermits() + " permits for parallel world ticking"); // SparklyPaper - parallel world ticking + } -+ // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable) com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now // Gale start - Pufferfish - SIMD support diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 5da07e22ef9dac7baca9d8450b7eae3f6fa141b1..3c0975e419b8ce58371e0cfae07abdad498bf5df 100644 +index 5da07e22ef9dac7baca9d8450b7eae3f6fa141b1..4ecb9a4125233f91379fd2792112aca6bbb3e33f 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -166,6 +166,7 @@ import net.minecraft.world.phys.shapes.BooleanOp; - import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.ticks.LevelTicks; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - - public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLevel, ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel, ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevelReader, ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel { // Paper - rewrite chunk system // Paper - chunk tick iteration -@@ -182,7 +183,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -182,7 +182,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe private final MinecraftServer server; public final net.minecraft.world.level.storage.PrimaryLevelData serverLevelData; // CraftBukkit - type private int lastSpawnChunkRadius; @@ -488,7 +453,7 @@ index 5da07e22ef9dac7baca9d8450b7eae3f6fa141b1..3c0975e419b8ce58371e0cfae07abdad // Paper - rewrite chunk system private final GameEventDispatcher gameEventDispatcher; public boolean noSave; -@@ -208,6 +209,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -208,6 +208,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe private double preciseTime; // Purpur - Configurable daylight cycle private boolean forceTime; // Purpur - Configurable daylight cycle private final RandomSequences randomSequences; @@ -496,7 +461,7 @@ index 5da07e22ef9dac7baca9d8450b7eae3f6fa141b1..3c0975e419b8ce58371e0cfae07abdad // CraftBukkit start public final LevelStorageSource.LevelStorageAccess levelStorageAccess; -@@ -703,6 +705,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -703,6 +704,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle this.realPlayers = Lists.newArrayList(); // Leaves - skip @@ -504,74 +469,64 @@ index 5da07e22ef9dac7baca9d8450b7eae3f6fa141b1..3c0975e419b8ce58371e0cfae07abdad } // Paper start -@@ -1286,11 +1289,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - if (fluidState.is(fluid)) { +@@ -1287,9 +1289,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe fluidState.tick(this, pos, blockState); } -- // Paper start - rewrite chunk system + // Paper start - rewrite chunk system - if ((++this.tickedBlocksOrFluids & 7L) != 0L) { -+ // Paper start - rewrite chunk system // SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) // Leaf start - SparklyPaper parallel world ticking mod (do not bother with condition work / make configurable) +- ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); ++ // Leaf start - SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) + ++this.tickedBlocksOrFluids; -+ if (!SparklyPaperParallelWorldTicking.enabled && (this.tickedBlocksOrFluids & 7L) != 0L) { - ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); ++ if (!org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && (this.tickedBlocksOrFluids & 7L) != 0L) { ++ this.server.moonrise$executeMidTickTasks(); } -- // Paper end - rewrite chunk system -+ // Paper end // SparklyPaper end // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) + // Paper end - rewrite chunk system } - -@@ -1299,11 +1303,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - if (blockState.is(block)) { +@@ -1300,9 +1305,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe blockState.tick(this, pos, this.random); } -- // Paper start - rewrite chunk system + // Paper start - rewrite chunk system - if ((++this.tickedBlocksOrFluids & 7L) != 0L) { -+ // Paper start - rewrite chunk system // SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) // Leaf start - SparklyPaper parallel world ticking mod (do not bother with condition work / make configurable) +- ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); ++ // Leaf start - SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) + ++this.tickedBlocksOrFluids; -+ if (!SparklyPaperParallelWorldTicking.enabled && (this.tickedBlocksOrFluids & 7L) != 0L) { - ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); ++ if (!org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && (this.tickedBlocksOrFluids & 7L) != 0L) { ++ this.server.moonrise$executeMidTickTasks(); } -- // Paper end - rewrite chunk system -+ // Paper end // SparklyPaper end // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) + // Paper end - rewrite chunk system } - -@@ -1553,6 +1558,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -1553,6 +1561,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } private void addPlayer(ServerPlayer player) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable / async is no longer safe; schedule on main) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable / async is no longer safe; schedule on main) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add player off-main"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) Entity entity = this.getEntities().get(player.getUUID()); if (entity != null) { LOGGER.warn("Force-added player with duplicate UUID {}", player.getUUID()); -@@ -1565,7 +1572,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -1565,7 +1575,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // CraftBukkit start private boolean addEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ // Leaf start - SparklyPaper parallel world ticking mod (make configurable -+ if (SparklyPaperParallelWorldTicking.enabled) ++ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add entity off-main"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) + else + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable) entity.generation = false; // Paper - Don't fire sync event during generation; Reset flag if it was added during a ServerLevel generation process // Paper start - extra debug info if (entity.valid) { diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index e2b15968e89a532ec21c786f41b7f9322fd65a04..f792e0f898f5310697eea44b5ec8258e30bd3567 100644 +index e2b15968e89a532ec21c786f41b7f9322fd65a04..915498dcb08a678256e6cc1659642d6126851365 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -174,6 +174,7 @@ import net.minecraft.world.scores.ScoreAccess; - import net.minecraft.world.scores.ScoreHolder; - import net.minecraft.world.scores.Team; - import net.minecraft.world.scores.criteria.ObjectiveCriteria; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - - public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system -@@ -434,6 +435,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -434,6 +434,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc return this.viewDistanceHolder; } // Paper end - rewrite chunk system @@ -579,7 +534,7 @@ index e2b15968e89a532ec21c786f41b7f9322fd65a04..f792e0f898f5310697eea44b5ec8258e public ServerPlayer(MinecraftServer server, ServerLevel level, GameProfile gameProfile, ClientInformation clientInformation) { super(level, level.getSharedSpawnPos(), level.getSharedSpawnAngle(), gameProfile); -@@ -810,6 +812,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -810,6 +811,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc @Override public void tick() { @@ -587,97 +542,72 @@ index e2b15968e89a532ec21c786f41b7f9322fd65a04..f792e0f898f5310697eea44b5ec8258e // CraftBukkit start if (this.joining) { this.joining = false; -@@ -1454,6 +1457,8 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1454,6 +1456,8 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc teleportTransition.postTeleportTransition().onTransition(this); return this; } else { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot change dimension of a player off-main, from world " + serverLevel().getWorld().getName() + " to world " + level.getWorld().getName()); // SparklyPaper - parallel world ticking (additional concurrency issues logs) // CraftBukkit start /* this.isChangingDimension = true; -@@ -1825,6 +1830,12 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1825,6 +1829,12 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc return OptionalInt.empty(); } else { // CraftBukkit start + // SparklyPaper start - parallel world ticking (see: PARALLEL_NOTES.md - Opening an inventory after a world switch) -+ if (SparklyPaperParallelWorldTicking.enabled && !hasTickedAtLeastOnceInNewWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && !hasTickedAtLeastOnceInNewWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + MinecraftServer.LOGGER.warn("Ignoring request to open container " + abstractContainerMenu + " because we haven't ticked in the current world yet!", new Throwable()); + return OptionalInt.empty(); + } -+ // SparklyPaper end ++ // SparklyPaper end - parallel world ticking (see: PARALLEL_NOTES.md - Opening an inventory after a world switch) this.containerMenu = abstractContainerMenu; // Moved up if (!this.isImmobile()) this.connection -@@ -1889,6 +1900,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1889,6 +1899,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc } @Override public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { + // SparklyPaper start - parallel world ticking (debugging) -+ if (SparklyPaperParallelWorldTicking.logContainerCreationStacktraces) { ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.logContainerCreationStacktraces) { + MinecraftServer.LOGGER.warn("Closing " + this.getBukkitEntity().getName() + " inventory that was created at", this.containerMenu.containerCreationStacktrace); + } -+ // SparklyPaper end ++ // SparklyPaper end - parallel world ticking (debugging) org.bukkit.craftbukkit.event.CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit // Paper end - Inventory close reason this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index f59662da0bbfe0e768c4ac5c7491d13263ac5cac..1643b3af9b33931277c03dbfa2f85e36b53978d6 100644 +index f59662da0bbfe0e768c4ac5c7491d13263ac5cac..bc412a62184757547140860617b8845263905710 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -1,5 +1,6 @@ - package net.minecraft.server.players; - -+import ca.spottedleaf.moonrise.common.util.TickThread; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -17,6 +18,9 @@ import java.util.Map; - import java.util.Optional; - import java.util.Set; - import java.util.UUID; -+import java.util.concurrent.CompletionException; -+import java.util.concurrent.ExecutionException; -+import java.util.concurrent.FutureTask; - import java.util.function.Function; - import java.util.function.Predicate; - import javax.annotation.Nullable; -@@ -99,6 +103,7 @@ import net.minecraft.world.scores.DisplaySlot; - import net.minecraft.world.scores.Objective; - import net.minecraft.world.scores.PlayerTeam; - import net.minecraft.world.scores.Team; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - - public abstract class PlayerList { -@@ -252,6 +257,8 @@ public abstract class PlayerList { +@@ -252,6 +252,8 @@ public abstract class PlayerList { // Leaves end - replay mod api public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) { -+ if (SparklyPaperParallelWorldTicking.enabled)// Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot place new player off-main"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) player.isRealPlayer = true; // Paper player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed GameProfile gameProfile = player.getGameProfile(); -@@ -891,6 +898,17 @@ public abstract class PlayerList { +@@ -891,6 +893,17 @@ public abstract class PlayerList { return this.respawn(player, keepInventory, reason, eventReason, null); } public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason, org.bukkit.Location location) { -+ // Leaf start - SparklyPaper parallel world ticking mod (make configurable) -+ if (SparklyPaperParallelWorldTicking.enabled) { ++ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) { + // SparklyPaper - parallel world ticking (additional concurrency issues logs) + System.out.println("respawning player - current player container is " + player.containerMenu + " but their inventory is " + player.inventoryMenu); + if (location != null) // Leaf - THIS CAN BE NULL; see PlayerList::respawn(ServerPlayer, boolean, Entity.RemovalReason, PlayerRespawnEvent.RespawnReason) + ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot respawn player off-main, from world " + player.serverLevel().getWorld().getName() + " to world " + location.getWorld().getName()); + else + ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot respawn player off-main, respawning in world " + player.serverLevel().getWorld().getName()); -+ // SparklyPaper end ++ // SparklyPaper end - parallel world ticking (additional concurrency issues logs) + } -+ // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable) player.stopRiding(); // CraftBukkit this.players.remove(player); this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -902,6 +920,7 @@ public abstract class PlayerList { +@@ -902,6 +915,7 @@ public abstract class PlayerList { ServerPlayer serverPlayer = player; Level fromWorld = player.level(); player.wonGame = false; @@ -686,26 +616,10 @@ index f59662da0bbfe0e768c4ac5c7491d13263ac5cac..1643b3af9b33931277c03dbfa2f85e36 serverPlayer.connection = player.connection; serverPlayer.restoreFrom(player, keepInventory); diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 9bc978ca290ca772b0367e89b69fe16b502b0cd2..762f6b3a7763a635c370a84baa68ba790e0f1323 100644 +index 9bc978ca290ca772b0367e89b69fe16b502b0cd2..17ff57db6f90b3f4facef691ad4347e67a9f5836 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -25,6 +25,7 @@ import java.util.Set; - import java.util.UUID; - import java.util.concurrent.atomic.AtomicInteger; - import java.util.function.BiConsumer; -+import java.util.function.Consumer; - import java.util.function.Predicate; - import java.util.stream.Stream; - import javax.annotation.Nullable; -@@ -131,6 +132,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.scores.PlayerTeam; - import net.minecraft.world.scores.ScoreHolder; - import net.minecraft.world.scores.Team; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - - public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker -@@ -3370,15 +3372,32 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3370,15 +3370,33 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess if (this.portalProcess != null) { if (this.portalProcess.processPortalTeleportation(serverLevel, this, this.canUsePortal(false))) { this.setPortalCooldown(); @@ -715,8 +629,9 @@ index 9bc978ca290ca772b0367e89b69fe16b502b0cd2..762f6b3a7763a635c370a84baa68ba79 - if (this instanceof ServerPlayer // CraftBukkit - always call event for players - || (level != null && (level.dimension() == serverLevel.dimension() || this.canTeleport(serverLevel, level)))) { // CraftBukkit - this.teleport(portalDestination); -+ // TCRF SparklyPaper (Pathothingi) start - parallel world ticking // Leaf start - SparklyPaper parallel world ticking mod (mark pending teleport to prevent clearing portal process) -+ Consumer portalEntityTask = entity -> { ++ // Leaf start - SparklyPaper - parallel world ticking mod (mark pending teleport to prevent clearing portal process) ++ // TCRF SparklyPaper (Pathothingi) start - parallel world ticking ++ java.util.function.Consumer portalEntityTask = entity -> { + assert entity.portalProcess != null; + + if (entity.portalProcess.isParallelCancelledByPlugin()) { @@ -736,62 +651,60 @@ index 9bc978ca290ca772b0367e89b69fe16b502b0cd2..762f6b3a7763a635c370a84baa68ba79 + if (this.portalProcess != null) + entity.portalProcess.confirmParallelAsHandled(); + }; -+ if (SparklyPaperParallelWorldTicking.enabled) { ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) { + this.portalProcess.setParallelAsScheduled(); + this.getBukkitEntity().taskScheduler.schedule(portalEntityTask, entity -> {}, 0); + } else + portalEntityTask.accept(this); -+ // TCRF SparklyPaper (Pathothingi) end // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (mark pending teleport to prevent clearing portal process) } else if (this.portalProcess.hasExpired()) { this.portalProcess = null; } -@@ -3908,6 +3927,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3908,6 +3926,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } private Entity teleportCrossDimension(ServerLevel level, TeleportTransition teleportTransition) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(level, "Cannot teleport entity to another world off-main, from world " + this.level.getWorld().getName() + " to world " + level.getWorld().getName()); // SparklyPaper - parallel world ticking (additional concurrency issues logs) List passengers = this.getPassengers(); List list = new ArrayList<>(passengers.size()); this.ejectPassengers(); diff --git a/net/minecraft/world/entity/PortalProcessor.java b/net/minecraft/world/entity/PortalProcessor.java -index 88b07fbb96b20124777889830afa480673629d43..5979ffe3fa30a6c2473f976423123fecb1ead442 100644 +index 88b07fbb96b20124777889830afa480673629d43..f8bb32840129e57b7799f883cb4570d274520390 100644 --- a/net/minecraft/world/entity/PortalProcessor.java +++ b/net/minecraft/world/entity/PortalProcessor.java -@@ -11,6 +11,9 @@ public class PortalProcessor { +@@ -11,6 +11,7 @@ public class PortalProcessor { private BlockPos entryPosition; private int portalTime; private boolean insidePortalThisTick; -+ // Leaf start - SparklyPaper parallel world ticking mod (prevent clearing portal process) -+ private ParallelPendingTeleportState pendingTeleport = ParallelPendingTeleportState.INACTIVE; -+ // Leaf end ++ private ParallelPendingTeleportState pendingTeleport = ParallelPendingTeleportState.INACTIVE; // Leaf - SparklyPaper - parallel world ticking mod (prevent clearing portal process) public PortalProcessor(Portal portal, BlockPos entryPosition) { this.portal = portal; -@@ -19,6 +22,8 @@ public class PortalProcessor { +@@ -19,6 +20,8 @@ public class PortalProcessor { } public boolean processPortalTeleportation(ServerLevel level, Entity entity, boolean canChangeDimensions) { -+ if (this.isParallelTeleportScheduled()) return false; // Leaf - SparklyPaper parallel world ticking mod (prevent clearing portal process) ++ if (this.isParallelTeleportScheduled()) return false; // Leaf - SparklyPaper - parallel world ticking mod (prevent clearing portal process) + if (!this.insidePortalThisTick) { this.decayTick(); return false; -@@ -42,7 +47,7 @@ public class PortalProcessor { +@@ -42,7 +45,7 @@ public class PortalProcessor { } public boolean hasExpired() { - return this.portalTime <= 0; -+ return !this.isParallelTeleportScheduled() && this.portalTime <= 0; // Leaf - SparklyPaper parallel world ticking mod (prevent clearing portal process) ++ return !this.isParallelTeleportScheduled() && this.portalTime <= 0; // Leaf - SparklyPaper - parallel world ticking mod (prevent clearing portal process) } public BlockPos getEntryPosition() { -@@ -68,4 +73,36 @@ public class PortalProcessor { +@@ -68,4 +71,36 @@ public class PortalProcessor { public boolean isSamePortal(Portal portal) { return this.portal == portal; } + -+ // Leaf start - SparklyPaper parallel world ticking mod (prevent clearing portal process) ++ // Leaf start - SparklyPaper - parallel world ticking mod (prevent clearing portal process) + public boolean isParallelTeleportPending() { + return this.pendingTeleport == ParallelPendingTeleportState.PENDING; + } @@ -821,36 +734,13 @@ index 88b07fbb96b20124777889830afa480673629d43..5979ffe3fa30a6c2473f976423123fec + PENDING, + CANCELLED + } -+ // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (prevent clearing portal process) } diff --git a/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java b/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java -index 3614551856c594f3c0cfee984fcf03fad672b007..57511640d26742f408236ca781814f2ba61599e3 100644 +index 3614551856c594f3c0cfee984fcf03fad672b007..1a41dd00a1ea4d0587d833c85545baf1b5f660d5 100644 --- a/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java +++ b/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java -@@ -1,16 +1,22 @@ - package net.minecraft.world.entity.ai.behavior; - -+import ca.spottedleaf.concurrentutil.util.Priority; - import com.google.common.collect.ImmutableMap; - import java.util.Optional; -+import java.util.function.BiPredicate; -+ - import net.minecraft.core.BlockPos; - import net.minecraft.core.GlobalPos; -+import net.minecraft.core.Holder; - import net.minecraft.network.protocol.game.DebugPackets; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.entity.ai.memory.MemoryModuleType; - import net.minecraft.world.entity.ai.memory.MemoryStatus; - import net.minecraft.world.entity.ai.village.poi.PoiManager; -+import net.minecraft.world.entity.ai.village.poi.PoiType; - import net.minecraft.world.entity.npc.Villager; - import net.minecraft.world.entity.schedule.Activity; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - - public class GoToPotentialJobSite extends Behavior { - private static final int TICKS_UNTIL_TIMEOUT = 1200; -@@ -46,12 +52,18 @@ public class GoToPotentialJobSite extends Behavior { +@@ -46,12 +46,20 @@ public class GoToPotentialJobSite extends Behavior { BlockPos blockPos = globalPos.pos(); ServerLevel level1 = level.getServer().getLevel(globalPos.dimension()); if (level1 != null) { @@ -858,6 +748,7 @@ index 3614551856c594f3c0cfee984fcf03fad672b007..57511640d26742f408236ca781814f2b - if (poiManager.exists(blockPos, holder -> true)) { - poiManager.release(blockPos); - } ++ // Leaf start - SparklyPaper - parallel world ticking mod (handling for navigating to potential job site cross-dimension) + Runnable releasePoiTask = () -> { + PoiManager poiManager = level1.getPoiManager(); + if (poiManager.exists(blockPos, holder -> true)) { @@ -867,33 +758,19 @@ index 3614551856c594f3c0cfee984fcf03fad672b007..57511640d26742f408236ca781814f2b - DebugPackets.sendPoiTicketCountPacket(level, blockPos); + DebugPackets.sendPoiTicketCountPacket(level, blockPos); + }; -+ if (SparklyPaperParallelWorldTicking.enabled) -+ level.moonrise$getChunkTaskScheduler().scheduleChunkTask(0, 0, releasePoiTask, Priority.BLOCKING); ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) ++ level.moonrise$getChunkTaskScheduler().scheduleChunkTask(0, 0, releasePoiTask, ca.spottedleaf.concurrentutil.util.Priority.BLOCKING); + else + releasePoiTask.run(); ++ // Leaf end - SparklyPaper - parallel world ticking mod (handling for navigating to potential job site cross-dimension) } }); entity.getBrain().eraseMemory(MemoryModuleType.POTENTIAL_JOB_SITE); diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java -index 0b4c4707139c9c72929799818ec1a1b25575d70e..ade7f0853ec78a214fe8d846604574726f1a767a 100644 +index 0b4c4707139c9c72929799818ec1a1b25575d70e..acf8059017f4e45c307a113abed36c59b231d9a6 100644 --- a/net/minecraft/world/entity/npc/Villager.java +++ b/net/minecraft/world/entity/npc/Villager.java -@@ -1,5 +1,6 @@ - package net.minecraft.world.entity.npc; - -+import ca.spottedleaf.concurrentutil.util.Priority; - import com.google.common.annotations.VisibleForTesting; - import com.google.common.collect.ImmutableList; - import com.google.common.collect.ImmutableMap; -@@ -86,6 +87,7 @@ import net.minecraft.world.item.trading.MerchantOffers; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.ServerLevelAccessor; - import net.minecraft.world.phys.AABB; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - - // CraftBukkit start -@@ -806,13 +808,20 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -806,13 +806,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler this.brain.getMemory(moduleType).ifPresent(globalPos -> { ServerLevel level = server.getLevel(globalPos.dimension()); if (level != null) { @@ -904,6 +781,7 @@ index 0b4c4707139c9c72929799818ec1a1b25575d70e..ade7f0853ec78a214fe8d84660457472 - poiManager.release(globalPos.pos()); - DebugPackets.sendPoiTicketCountPacket(level, globalPos.pos()); - } ++ // Leaf start - SparklyPaper - parallel world ticking mod (handling for releasing poi cross-dimension) + Runnable releasePoiTask = () -> { + PoiManager poiManager = level.getPoiManager(); + Optional> type = poiManager.getType(globalPos.pos()); @@ -913,35 +791,19 @@ index 0b4c4707139c9c72929799818ec1a1b25575d70e..ade7f0853ec78a214fe8d84660457472 + DebugPackets.sendPoiTicketCountPacket(level, globalPos.pos()); + } + }; -+ if (SparklyPaperParallelWorldTicking.enabled) -+ level.moonrise$getChunkTaskScheduler().scheduleChunkTask(0, 0, releasePoiTask, Priority.BLOCKING); ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) ++ level.moonrise$getChunkTaskScheduler().scheduleChunkTask(0, 0, releasePoiTask, ca.spottedleaf.concurrentutil.util.Priority.BLOCKING); + else + releasePoiTask.run(); -+ ++ // Leaf end - SparklyPaper - parallel world ticking mod (handling for releasing poi cross-dimension) } }); } diff --git a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -index d212f57c8c0b2086f567fd30237b110203d9e8cb..23b831b993255a727ea275f4026e4e86579b5b1e 100644 +index d212f57c8c0b2086f567fd30237b110203d9e8cb..ed4df82581b5411e54068ccc59ea85a78404fa2b 100644 --- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -@@ -1,6 +1,7 @@ - package net.minecraft.world.entity.projectile; - - import java.util.UUID; -+import java.util.function.Consumer; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.core.SectionPos; -@@ -26,6 +27,7 @@ import net.minecraft.world.level.portal.TeleportTransition; - import net.minecraft.world.phys.EntityHitResult; - import net.minecraft.world.phys.HitResult; - import net.minecraft.world.phys.Vec3; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - - public class ThrownEnderpearl extends ThrowableItemProjectile { - private long ticketTimer = 0L; -@@ -126,40 +128,46 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { +@@ -126,40 +126,48 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { Vec3 vec3 = this.oldPosition(); if (owner instanceof ServerPlayer serverPlayer) { if (serverPlayer.connection.isAcceptingMessages()) { @@ -958,7 +820,8 @@ index d212f57c8c0b2086f567fd30237b110203d9e8cb..23b831b993255a727ea275f4026e4e86 - endermite.setPlayerSpawned(true); // Purpur - Add back player spawned endermite API - endermite.moveTo(owner.getX(), owner.getY(), owner.getZ(), owner.getYRot(), owner.getXRot()); - serverLevel.addFreshEntity(endermite, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.ENDER_PEARL); -+ Consumer teleportPlayerCrossDimensionTask = (taskServerPlayer) -> { ++ // Leaf start - SparklyPaper - parallel world ticking mod (handling for pearl teleportation cross-dimension) ++ java.util.function.Consumer teleportPlayerCrossDimensionTask = taskServerPlayer -> { + // CraftBukkit start + ServerPlayer serverPlayer1 = taskServerPlayer.teleport(new TeleportTransition(serverLevel, vec3, Vec3.ZERO, 0.0F, 0.0F, Relative.union(Relative.ROTATION, Relative.DELTA), TeleportTransition.DO_NOTHING, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.ENDER_PEARL)); + if (serverPlayer1 == null) { @@ -1011,26 +874,19 @@ index d212f57c8c0b2086f567fd30237b110203d9e8cb..23b831b993255a727ea275f4026e4e86 - this.playSound(serverLevel, vec3); + this.playSound(serverLevel, vec3); + }; -+ if (SparklyPaperParallelWorldTicking.enabled) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + serverPlayer.getBukkitEntity().taskScheduler.schedule(teleportPlayerCrossDimensionTask, entity -> {}, 0); + else + teleportPlayerCrossDimensionTask.accept(serverPlayer); ++ // Leaf end - SparklyPaper - parallel world ticking mod (handling for pearl teleportation cross-dimension) } } else { Entity entity = owner.teleport( diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index 8a0d1aebad1f92c43112e279b9c5922fdd1fd432..1fc83d18ab8c6d7a65fcd314f00414e638a417e9 100644 +index 8a0d1aebad1f92c43112e279b9c5922fdd1fd432..d4fc9466d61a680b85859965a8f7dc795b8c7130 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -33,6 +33,7 @@ import net.minecraft.world.item.BundleItem; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.entity.BlockEntity; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - - public abstract class AbstractContainerMenu { -@@ -92,8 +93,14 @@ public abstract class AbstractContainerMenu { +@@ -92,8 +92,14 @@ public abstract class AbstractContainerMenu { } public void startOpen() {} // CraftBukkit end @@ -1038,15 +894,15 @@ index 8a0d1aebad1f92c43112e279b9c5922fdd1fd432..1fc83d18ab8c6d7a65fcd314f00414e6 protected AbstractContainerMenu(@Nullable MenuType menuType, int containerId) { + // SparklyPaper - parallel world ticking (debugging) -+ if (SparklyPaperParallelWorldTicking.logContainerCreationStacktraces) { ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.logContainerCreationStacktraces) { + this.containerCreationStacktrace = new Throwable(); + } -+ // SparklyPaper end ++ // SparklyPaper end - parallel world ticking (debugging) this.menuType = menuType; this.containerId = containerId; } diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index fd7c1e800cbd4919a1a47f6c468c8776535bd028..3a583e838f7b9019624c3bbc23154c1c5b070a30 100644 +index fd7c1e800cbd4919a1a47f6c468c8776535bd028..ba369d605ae50906d11d32e6f1b7132b061a9835 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java @@ -412,8 +412,8 @@ public final class ItemStack implements DataComponentHolder, net.caffeinemc.mods @@ -1055,24 +911,16 @@ index fd7c1e800cbd4919a1a47f6c468c8776535bd028..3a583e838f7b9019624c3bbc23154c1c org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(clickedPos, serverLevel.getWorld()); - org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeType; - net.minecraft.world.level.block.SaplingBlock.treeType = null; -+ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.getTreeTypeRT(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) -+ net.minecraft.world.level.block.SaplingBlock.setTreeTypeRT(null); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.getTreeTypeRT(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) ++ net.minecraft.world.level.block.SaplingBlock.setTreeTypeRT(null); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) List blocks = new java.util.ArrayList<>(serverLevel.capturedBlockStates.values()); serverLevel.capturedBlockStates.clear(); org.bukkit.event.world.StructureGrowEvent structureEvent = null; diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 7d3163802640449b6bdaa93595518d7d0f62488b..da579769cee175cfbf342efd643efe6f87e0a822 100644 +index 7d3163802640449b6bdaa93595518d7d0f62488b..4821ab14c6a7d5738f0fc93523aede5ea904aa84 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java -@@ -99,6 +99,7 @@ import org.bukkit.craftbukkit.block.data.CraftBlockData; - import org.bukkit.craftbukkit.util.CraftSpawnCategory; - import org.bukkit.entity.SpawnCategory; - import org.bukkit.event.block.BlockPhysicsEvent; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - // CraftBukkit end - - public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel, ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemEntityGetter { // Paper - rewrite chunk system // Paper - optimise collisions -@@ -175,6 +176,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -175,6 +175,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray public final org.purpurmc.purpur.PurpurWorldConfig purpurConfig; // Purpur - Purpur config files @@ -1080,108 +928,99 @@ index 7d3163802640449b6bdaa93595518d7d0f62488b..da579769cee175cfbf342efd643efe6f public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; private org.spigotmc.TickLimiter tileLimiter; -@@ -1153,6 +1155,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1153,6 +1154,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf start - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, pos, "Updating block asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) // CraftBukkit start - tree generation if (this.captureTreeGeneration) { // Paper start - Protect Bedrock and End Portal/Frames from being destroyed -@@ -1531,11 +1535,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - this.blockEntityTickers.markAsRemoved(this.tileTickPosition); // toRemove.add(tickingBlockEntity); // SparklyPaper - optimize block entity removals // Paper - Fix MC-117075; use removeAll +@@ -1532,9 +1535,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } else if (runsNormally && this.shouldTickBlocksAt(tickingBlockEntity.getPos())) { tickingBlockEntity.tick(); -- // Paper start - rewrite chunk system + // Paper start - rewrite chunk system - if ((++tickedEntities & 7) == 0) { -+ // Paper start - rewrite chunk system // SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) // Leaf - SparklyPaper parallel world ticking mod (do not bother with condition work / make configurable) +- ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)(Level)(Object)this).moonrise$midTickTasks(); ++ // Leaf start - SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) - do not bother with condition work / make configurable + ++tickedEntities; -+ if (!SparklyPaperParallelWorldTicking.enabled && (tickedEntities & 7) == 0) { - ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)(Level)(Object)this).moonrise$midTickTasks(); ++ if (!org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && (tickedEntities & 7) == 0) { ++ this.moonrise$midTickTasks(); } -- // Paper end - rewrite chunk system -+ // Paper end - rewrite chunk system // SparklyPaper end // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) - do not bother with condition work / make configurable + // Paper end - rewrite chunk system } } - this.blockEntityTickers.removeMarkedEntries(); // SparklyPaper - optimize block entity removals -@@ -1555,7 +1560,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1555,7 +1561,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); // Gale - Airplane - remove lambda from ticking guard - diff on change ServerLevel#tick // Paper end - Prevent block entity and entity crashes } - this.moonrise$midTickTasks(); // Paper - rewrite chunk system // Gale - Airplane - remove lambda from ticking guard - diff on change ServerLevel#tick -+ if (!SparklyPaperParallelWorldTicking.enabled) // SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) // Leaf start - SparklyPaper parallel world ticking mod (make configurable) ++ if (!org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) + this.moonrise$midTickTasks(); // Paper - rewrite chunk system // Gale - Airplane - remove lambda from ticking guard - diff on change ServerLevel#tick } // Paper start - Option to prevent armor stands from doing entity lookups -@@ -1698,6 +1704,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1698,6 +1705,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Nullable public BlockEntity getBlockEntity(BlockPos pos, boolean validate) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf start - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThreadOrAsyncThread((ServerLevel) this, "Cannot read world asynchronously"); // SparklyPaper - parallel world ticking // Paper start - Perf: Optimize capturedTileEntities lookup net.minecraft.world.level.block.entity.BlockEntity blockEntity; if (!this.capturedTileEntities.isEmpty() && (blockEntity = this.capturedTileEntities.get(pos)) != null) { -@@ -1715,6 +1723,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1715,6 +1724,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } public void setBlockEntity(BlockEntity blockEntity) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf start - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel) this, "Cannot modify world asynchronously"); // SparklyPaper - parallel world ticking BlockPos blockPos = blockEntity.getBlockPos(); if (!this.isOutsideBuildHeight(blockPos)) { // CraftBukkit start -@@ -1799,6 +1809,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1799,6 +1810,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public List getEntities(@Nullable Entity entity, AABB boundingBox, Predicate predicate) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf start - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, boundingBox, "Cannot getEntities asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) List list = Lists.newArrayList(); // Paper start - rewrite chunk system -@@ -2108,8 +2120,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -2108,8 +2121,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public abstract RecipeAccess recipeAccess(); public BlockPos getBlockRandomPos(int x, int y, int z, int yMask) { - this.randValue = this.randValue * 3 + 1013904223; - int i = this.randValue >> 2; -+ // Leaf start - SparklyPaper parallel world ticking mod (make configurable) ++ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) + int i; -+ if (SparklyPaperParallelWorldTicking.enabled) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + i = this.random.nextInt() >> 2; // SparklyPaper - parallel world ticking + else { + this.randValue = this.randValue * 3 + 1013904223; + i = this.randValue >> 2; + } -+ // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable) return new BlockPos(x + (i & 15), y + (i >> 16 & yMask), z + (i >> 8 & 15)); } diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java -index e0a4d41e5bcf144ea4c10d6f633c3a95ed2c5aec..719ec758f96241b64f93d93d6a7013522998f3a8 100644 +index e0a4d41e5bcf144ea4c10d6f633c3a95ed2c5aec..fae9a880727207e2b5ecf553f22db650dac1b811 100644 --- a/net/minecraft/world/level/block/DispenserBlock.java +++ b/net/minecraft/world/level/block/DispenserBlock.java -@@ -40,6 +40,7 @@ import net.minecraft.world.level.gameevent.GameEvent; - import net.minecraft.world.level.redstone.Orientation; - import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.Vec3; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - - public class DispenserBlock extends BaseEntityBlock { -@@ -51,6 +52,26 @@ public class DispenserBlock extends BaseEntityBlock { +@@ -51,6 +51,27 @@ public class DispenserBlock extends BaseEntityBlock { public static final Map DISPENSER_REGISTRY = new IdentityHashMap<>(); private static final int TRIGGER_DURATION = 4; public static boolean eventFired = false; // CraftBukkit -+ public static ThreadLocal eventFiredTL = ThreadLocal.withInitial(() -> Boolean.FALSE); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (distinguish name) ++ public static ThreadLocal eventFiredTL = ThreadLocal.withInitial(() -> Boolean.FALSE); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (distinguish name) + -+ // Leaf - SparklyPaper parallel world ticking mod ++ // Leaf start - SparklyPaper - parallel world ticking mod + // refer to original field in case plugins attempt to modify it + public static boolean getEventFiredTL() { -+ if (SparklyPaperParallelWorldTicking.enabled && eventFiredTL.get()) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && eventFiredTL.get()) + return true; + synchronized (DispenserBlock.class) { + return eventFired; @@ -1190,12 +1029,13 @@ index e0a4d41e5bcf144ea4c10d6f633c3a95ed2c5aec..719ec758f96241b64f93d93d6a701352 + + // update original field in case plugins attempt to access it + public static void setEventFiredTL(boolean value) { -+ if (SparklyPaperParallelWorldTicking.enabled) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + eventFiredTL.set(value); + synchronized (DispenserBlock.class) { + eventFired = value; + } + } ++ // Leaf end - SparklyPaper - parallel world ticking mod @Override public MapCodec codec() { @@ -1204,12 +1044,12 @@ index e0a4d41e5bcf144ea4c10d6f633c3a95ed2c5aec..719ec758f96241b64f93d93d6a701352 if (dispenseMethod != DispenseItemBehavior.NOOP) { if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(level, pos, item, randomSlot)) return; // Paper - Add BlockPreDispenseEvent - DispenserBlock.eventFired = false; // CraftBukkit - reset event status -+ DispenserBlock.setEventFiredTL(Boolean.FALSE); // CraftBukkit - reset event status // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ DispenserBlock.setEventFiredTL(Boolean.FALSE); // CraftBukkit - reset event status // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) dispenserBlockEntity.setItem(randomSlot, dispenseMethod.dispense(blockSource, item)); } } diff --git a/net/minecraft/world/level/block/FungusBlock.java b/net/minecraft/world/level/block/FungusBlock.java -index 85f0eac75784565c658c5178c544f969db3d6f54..70084510fd591e1c3221f09d67f622201b29a54a 100644 +index 85f0eac75784565c658c5178c544f969db3d6f54..690cb4f712d609e90fc2d4814f15c55145666701 100644 --- a/net/minecraft/world/level/block/FungusBlock.java +++ b/net/minecraft/world/level/block/FungusBlock.java @@ -76,9 +76,9 @@ public class FungusBlock extends BushBlock implements BonemealableBlock { @@ -1217,15 +1057,15 @@ index 85f0eac75784565c658c5178c544f969db3d6f54..70084510fd591e1c3221f09d67f62220 .map((value) -> { if (this == Blocks.WARPED_FUNGUS) { - SaplingBlock.treeType = org.bukkit.TreeType.WARPED_FUNGUS; -+ SaplingBlock.setTreeTypeRT(org.bukkit.TreeType.WARPED_FUNGUS); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ SaplingBlock.setTreeTypeRT(org.bukkit.TreeType.WARPED_FUNGUS); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) } else if (this == Blocks.CRIMSON_FUNGUS) { - SaplingBlock.treeType = org.bukkit.TreeType.CRIMSON_FUNGUS; -+ SaplingBlock.setTreeTypeRT(org.bukkit.TreeType.CRIMSON_FUNGUS); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ SaplingBlock.setTreeTypeRT(org.bukkit.TreeType.CRIMSON_FUNGUS); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) } return value; }) diff --git a/net/minecraft/world/level/block/MushroomBlock.java b/net/minecraft/world/level/block/MushroomBlock.java -index 904369f4d7db41026183f2de7c96c2f0f4dc204d..7b1815c498be07f4b1365736791063125675eab2 100644 +index 904369f4d7db41026183f2de7c96c2f0f4dc204d..afd952ddc8942818ec01d1c750413776b6537cc2 100644 --- a/net/minecraft/world/level/block/MushroomBlock.java +++ b/net/minecraft/world/level/block/MushroomBlock.java @@ -94,7 +94,7 @@ public class MushroomBlock extends BushBlock implements BonemealableBlock { @@ -1233,74 +1073,57 @@ index 904369f4d7db41026183f2de7c96c2f0f4dc204d..7b1815c498be07f4b136573679106312 } else { level.removeBlock(pos, false); - SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? org.bukkit.TreeType.BROWN_MUSHROOM : org.bukkit.TreeType.RED_MUSHROOM; // CraftBukkit -+ SaplingBlock.setTreeTypeRT((this == Blocks.BROWN_MUSHROOM) ? org.bukkit.TreeType.BROWN_MUSHROOM : org.bukkit.TreeType.RED_MUSHROOM); // CraftBukkit // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ SaplingBlock.setTreeTypeRT((this == Blocks.BROWN_MUSHROOM) ? org.bukkit.TreeType.BROWN_MUSHROOM : org.bukkit.TreeType.RED_MUSHROOM); // CraftBukkit // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) if (optional.get().value().place(level, level.getChunkSource().getGenerator(), random, pos)) { return true; } else { diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java -index 12c9d60314c99fb65e640d255a2d0c6b7790ad4d..10a969b6901e47f71a4ba2e5543822ef9c87a165 100644 +index 12c9d60314c99fb65e640d255a2d0c6b7790ad4d..33a096ca7d175a714f874901d0152d0ecbc7f2a5 100644 --- a/net/minecraft/world/level/block/RedStoneWireBlock.java +++ b/net/minecraft/world/level/block/RedStoneWireBlock.java -@@ -37,6 +37,7 @@ import net.minecraft.world.phys.BlockHitResult; - import net.minecraft.world.phys.shapes.CollisionContext; - import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - - public class RedStoneWireBlock extends Block { - public static final MapCodec CODEC = simpleCodec(RedStoneWireBlock::new); -@@ -308,7 +309,12 @@ public class RedStoneWireBlock extends Block { +@@ -308,7 +308,12 @@ public class RedStoneWireBlock extends Block { if (orientation != null) { source = pos.relative(orientation.getFront().getOpposite()); } - turbo.updateSurroundingRedstone(worldIn, pos, state, source); -+ // Leaf - SparklyPaper parallel world ticking mod (make configurable) -+ if (SparklyPaperParallelWorldTicking.enabled) ++ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + worldIn.turbo.updateSurroundingRedstone(worldIn, pos, state, source); // SparklyPaper - parallel world ticking + else + turbo.updateSurroundingRedstone(worldIn, pos, state, source); -+ // Leaf end ++ // Leaf end - parallel world ticking mod (make configurable) return; } updatePowerStrength(worldIn, pos, state, orientation, blockAdded); -@@ -336,7 +342,12 @@ public class RedStoneWireBlock extends Block { +@@ -336,7 +341,12 @@ public class RedStoneWireBlock extends Block { // [Space Walker] suppress shape updates and emit those manually to // bypass the new neighbor update stack. if (level.setBlock(pos, state, Block.UPDATE_KNOWN_SHAPE | Block.UPDATE_CLIENTS)) { - turbo.updateNeighborShapes(level, pos, state); -+ // Leaf - SparklyPaper parallel world ticking mod (make configurable) -+ if (SparklyPaperParallelWorldTicking.enabled) ++ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + level.turbo.updateNeighborShapes(level, pos, state); // SparklyPaper - parallel world ticking + else + turbo.updateNeighborShapes(level, pos, state); -+ // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable) } } } diff --git a/net/minecraft/world/level/block/SaplingBlock.java b/net/minecraft/world/level/block/SaplingBlock.java -index e014f052e9b0f5ca6b28044e2389782b7d0e0cb8..7532456b306cff53cd43e631960a093b8e3cc693 100644 +index e014f052e9b0f5ca6b28044e2389782b7d0e0cb8..5485e27b881ab0e4d6d00c088bae094d1232eec7 100644 --- a/net/minecraft/world/level/block/SaplingBlock.java +++ b/net/minecraft/world/level/block/SaplingBlock.java -@@ -16,6 +16,8 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; - import net.minecraft.world.level.block.state.properties.IntegerProperty; - import net.minecraft.world.phys.shapes.CollisionContext; - import net.minecraft.world.phys.shapes.VoxelShape; -+import org.bukkit.TreeType; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - - public class SaplingBlock extends BushBlock implements BonemealableBlock { - public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( -@@ -27,6 +29,27 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { +@@ -27,6 +27,28 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { protected static final VoxelShape SHAPE = Block.box(2.0, 0.0, 2.0, 14.0, 12.0, 14.0); protected final TreeGrower treeGrower; public static org.bukkit.TreeType treeType; // CraftBukkit + public static final ThreadLocal treeTypeRT = new ThreadLocal<>(); // SparklyPaper - parallel world ticking (from Folia) + -+ // Leaf - SparklyPaper parallel world ticking mod ++ // Leaf start - SparklyPaper - parallel world ticking mod + // refer to original field in case plugins attempt to modify it -+ public static TreeType getTreeTypeRT() { -+ TreeType treeTypeRTCopy; -+ if (SparklyPaperParallelWorldTicking.enabled && (treeTypeRTCopy = treeTypeRT.get()) != null) ++ public static org.bukkit.TreeType getTreeTypeRT() { ++ org.bukkit.TreeType treeTypeRTCopy; ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && (treeTypeRTCopy = treeTypeRT.get()) != null) + return treeTypeRTCopy; + synchronized (SaplingBlock.class) { + return treeType; @@ -1308,62 +1131,55 @@ index e014f052e9b0f5ca6b28044e2389782b7d0e0cb8..7532456b306cff53cd43e631960a093b + } + + // update original field in case plugins attempt to access it -+ public static void setTreeTypeRT(TreeType value) { -+ if (SparklyPaperParallelWorldTicking.enabled) ++ public static void setTreeTypeRT(org.bukkit.TreeType value) { ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + treeTypeRT.set(value); + synchronized (SaplingBlock.class) { + treeType = value; + } + } ++ // Leaf end - SparklyPaper - parallel world ticking mod @Override public MapCodec codec() { -@@ -63,14 +86,14 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { +@@ -63,14 +85,14 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); level.captureTreeGeneration = false; if (!level.capturedBlockStates.isEmpty()) { - org.bukkit.TreeType treeType = SaplingBlock.treeType; - SaplingBlock.treeType = null; -+ org.bukkit.TreeType treeTypeLocal = SaplingBlock.getTreeTypeRT(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) -+ SaplingBlock.setTreeTypeRT(null); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ org.bukkit.TreeType treeTypeLocal = SaplingBlock.getTreeTypeRT(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) ++ SaplingBlock.setTreeTypeRT(null); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level.getWorld()); java.util.List blocks = new java.util.ArrayList<>(level.capturedBlockStates.values()); level.capturedBlockStates.clear(); org.bukkit.event.world.StructureGrowEvent event = null; - if (treeType != null) { - event = new org.bukkit.event.world.StructureGrowEvent(location, treeType, false, null, blocks); -+ if (treeTypeLocal != null) { -+ event = new org.bukkit.event.world.StructureGrowEvent(location, treeTypeLocal, false, null, blocks); ++ if (treeTypeLocal != null) { // Leaf - SparklyPaper - parallel world ticking mod (fix missing stuff from original sparkly paper) ++ event = new org.bukkit.event.world.StructureGrowEvent(location, treeTypeLocal, false, null, blocks); // Leaf - SparklyPaper - parallel world ticking mod (fix missing stuff from original sparkly paper) org.bukkit.Bukkit.getPluginManager().callEvent(event); } if (event == null || !event.isCancelled()) { diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -index 26db603ed681a6c302596627d4dd5bf8a9bafc4e..97c2620f7d9d0631961224334377739ca683a00c 100644 +index 26db603ed681a6c302596627d4dd5bf8a9bafc4e..7796c98ad7b9b3a0c97b177d34a3a2225409d147 100644 --- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -@@ -21,6 +21,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.component.ItemContainerContents; - import net.minecraft.world.level.block.state.BlockState; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - - public abstract class BaseContainerBlockEntity extends BlockEntity implements Container, MenuProvider, Nameable { - public LockCode lockKey = LockCode.NO_LOCK; -@@ -77,6 +78,12 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co +@@ -77,6 +77,12 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co return canUnlock(player, code, displayName, null); } public static boolean canUnlock(Player player, LockCode code, Component displayName, @Nullable BlockEntity blockEntity) { + // SparklyPaper - parallel world ticking (see: PARALLEL_NOTES.md - Opening an inventory after a world switch) -+ if (SparklyPaperParallelWorldTicking.enabled && player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != serverPlayer.serverLevel()) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != serverPlayer.serverLevel()) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + net.minecraft.server.MinecraftServer.LOGGER.warn("Player " + serverPlayer.getScoreboardName() + " (" + serverPlayer.getStringUUID() + ") attempted to open a BlockEntity @ " + blockEntity.getLevel().getWorld().getName() + " " + blockEntity.getBlockPos().getX() + ", " + blockEntity.getBlockPos().getY() + ", " + blockEntity.getBlockPos().getZ() + " while they were in a different world " + serverPlayer.level().getWorld().getName() + " than the block themselves!"); + return false; + } -+ // SparklyPaper end ++ // SparklyPaper end - parallel world ticking (see: PARALLEL_NOTES.md - Opening an inventory after a world switch) if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != null && blockEntity.getLevel().getBlockEntity(blockEntity.getBlockPos()) == blockEntity) { final org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos()); net.kyori.adventure.text.Component lockedMessage = net.kyori.adventure.text.Component.translatable("container.isLocked", io.papermc.paper.adventure.PaperAdventure.asAdventure(displayName)); diff --git a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -index 62038854696bd946f58e0e8d26da02415c34e4b1..0f7ac30a53d38fc970d7317b6ed7a83bd9e3f37c 100644 +index 62038854696bd946f58e0e8d26da02415c34e4b1..2ef3c59196f5d75a97a08604c3bb47b670338d15 100644 --- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java @@ -43,9 +43,9 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi @@ -1371,15 +1187,15 @@ index 62038854696bd946f58e0e8d26da02415c34e4b1..0f7ac30a53d38fc970d7317b6ed7a83b public static void serverTick(Level level, BlockPos pos, BlockState state, SculkCatalystBlockEntity sculkCatalyst) { - org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = sculkCatalyst.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. -+ org.bukkit.craftbukkit.event.CraftEventFactory.setSourceBlockOverrideRT(pos); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ org.bukkit.craftbukkit.event.CraftEventFactory.setSourceBlockOverrideRT(pos); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) sculkCatalyst.catalystListener.getSculkSpreader().updateCursors(level, pos, level.getRandom(), true); - org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.setSourceBlockOverrideRT(null); // CraftBukkit // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ org.bukkit.craftbukkit.event.CraftEventFactory.setSourceBlockOverrideRT(null); // CraftBukkit // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) } @Override diff --git a/net/minecraft/world/level/block/grower/TreeGrower.java b/net/minecraft/world/level/block/grower/TreeGrower.java -index cf7311c507de09a8f89934e430b2201e8bdffe51..ad90ff29928c4415e17d84fb4e8bae68c215b781 100644 +index cf7311c507de09a8f89934e430b2201e8bdffe51..e9936860323a23f989d554bcc5d483521e25415b 100644 --- a/net/minecraft/world/level/block/grower/TreeGrower.java +++ b/net/minecraft/world/level/block/grower/TreeGrower.java @@ -204,55 +204,59 @@ public final class TreeGrower { @@ -1460,73 +1276,61 @@ index cf7311c507de09a8f89934e430b2201e8bdffe51..ad90ff29928c4415e17d84fb4e8bae68 } else { throw new IllegalArgumentException("Unknown tree generator " + treeFeature); } -+ net.minecraft.world.level.block.SaplingBlock.setTreeTypeRT(treeType); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) -+ // SparklyPaper end ++ net.minecraft.world.level.block.SaplingBlock.setTreeTypeRT(treeType); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) ++ // SparklyPaper end - parallel world ticking } // CraftBukkit end } diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index 238e015d4ff5fabb99e569118f253366d545d269..23446968f9b42f904da189fb6bc3a6fe15c01fe7 100644 +index 238e015d4ff5fabb99e569118f253366d545d269..47528dec6b1a2b36e71013a9372425a70cbc6a33 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java -@@ -48,6 +48,7 @@ import net.minecraft.world.level.material.FluidState; - import net.minecraft.world.level.material.Fluids; - import net.minecraft.world.ticks.LevelChunkTicks; - import net.minecraft.world.ticks.TickContainerAccess; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - - public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk, ca.spottedleaf.moonrise.patches.starlight.chunk.StarlightChunk, ca.spottedleaf.moonrise.patches.getblock.GetBlockChunk { // Paper - rewrite chunk system // Paper - get block chunk optimisation -@@ -401,6 +402,8 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -401,6 +401,8 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Nullable public BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving, boolean doPlace) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, pos, "Updating block asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) // CraftBukkit end int y = pos.getY(); LevelChunkSection section = this.getSection(this.getSectionIndex(y)); diff --git a/net/minecraft/world/level/entity/EntityTickList.java b/net/minecraft/world/level/entity/EntityTickList.java -index dec51066fc3f57b7bdc56195313c219f45a7fbee..0d45962fd2a3f05319fe6aca93e9a1ee58152259 100644 +index dec51066fc3f57b7bdc56195313c219f45a7fbee..359ead3bd32862206bccb4504ad5b4d027dba7a9 100644 --- a/net/minecraft/world/level/entity/EntityTickList.java +++ b/net/minecraft/world/level/entity/EntityTickList.java -@@ -7,20 +7,40 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; - import java.util.function.Consumer; - import javax.annotation.Nullable; - import net.minecraft.world.entity.Entity; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - +@@ -11,16 +11,36 @@ import net.minecraft.world.entity.Entity; public class EntityTickList { public final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system // Pufferfish - private->public -+ // Leaf - SparklyPaper parallel world ticking mod ++ // Leaf start - SparklyPaper - parallel world ticking mod + // preserve original constructor + public EntityTickList() { + this(null); + } ++ // Leaf end - SparklyPaper - parallel world ticking mod + + // SparklyPaper start - parallel world ticking + // Used to track async entity additions/removals/loops -+ @Nullable // Leaf - SparklyPaper parallel world ticking mod (preserve original constructor) ++ @Nullable // Leaf - SparklyPaper - parallel world ticking mod (preserve original constructor) + private final net.minecraft.server.level.ServerLevel serverLevel; -+ public EntityTickList(@Nullable net.minecraft.server.level.ServerLevel serverLevel) { // Leaf - SparklyPaper parallel world ticking mod (preserve original constructor) ++ public EntityTickList(@Nullable net.minecraft.server.level.ServerLevel serverLevel) { // Leaf - SparklyPaper - parallel world ticking mod (preserve original constructor) + this.serverLevel = serverLevel; + } -+ // SparklyPaper end ++ // SparklyPaper end - parallel world ticking + private void ensureActiveIsNotIterated() { // Paper - rewrite chunk system } public void add(Entity entity) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(entity, "Asynchronous entity ticklist addition"); // Paper // SparklyPaper - parallel world ticking (additional concurrency issues logs) this.ensureActiveIsNotIterated(); this.entities.add(entity); // Paper - rewrite chunk system } public void remove(Entity entity) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(entity, "Asynchronous entity ticklist removal"); // Paper // SparklyPaper - parallel world ticking (additional concurrency issues logs) this.ensureActiveIsNotIterated(); this.entities.remove(entity); // Paper - rewrite chunk system @@ -1535,27 +1339,28 @@ index dec51066fc3f57b7bdc56195313c219f45a7fbee..0d45962fd2a3f05319fe6aca93e9a1ee } public void forEach(Consumer entity) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverLevel, "Asynchronous entity ticklist iteration"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) // Paper start - rewrite chunk system // To ensure nothing weird happens with dimension travelling, do not iterate over new entries... // (by dfl iterator() is configured to not iterate over new entries) diff --git a/net/minecraft/world/level/saveddata/maps/MapIndex.java b/net/minecraft/world/level/saveddata/maps/MapIndex.java -index ffe604f8397a002800e6ecc2f878d0f6f1c98703..ae5dcff21b597182af457c07c8a995d77ae32f5d 100644 +index ffe604f8397a002800e6ecc2f878d0f6f1c98703..147cae56b4db456bbbe7cb2522568e007620df12 100644 --- a/net/minecraft/world/level/saveddata/maps/MapIndex.java +++ b/net/minecraft/world/level/saveddata/maps/MapIndex.java -@@ -34,17 +34,21 @@ public class MapIndex extends SavedData { +@@ -34,17 +34,25 @@ public class MapIndex extends SavedData { @Override public CompoundTag save(CompoundTag tag, HolderLookup.Provider registries) { - for (Entry entry : this.usedAuxIds.object2IntEntrySet()) { - tag.putInt(entry.getKey(), entry.getIntValue()); -- } -+ synchronized (this.usedAuxIds) { // SparklyPaper start - make map data thread-safe ++ // SparklyPaper start - make map data thread-safe ++ synchronized (this.usedAuxIds) { + for (Entry entry : this.usedAuxIds.object2IntEntrySet()) { + tag.putInt(entry.getKey(), entry.getIntValue()); + } -+ } // SparklyPaper end - make map data thread-safe + } ++ // SparklyPaper end - make map data thread-safe return tag; } @@ -1565,11 +1370,13 @@ index ffe604f8397a002800e6ecc2f878d0f6f1c98703..ae5dcff21b597182af457c07c8a995d7 - this.usedAuxIds.put("map", i); - this.setDirty(); - return new MapId(i); -+ synchronized (this.usedAuxIds) { // SparklyPaper start - make map data thread-safe ++ // SparklyPaper start - make map data thread-safe ++ synchronized (this.usedAuxIds) { + int i = this.usedAuxIds.getInt("map") + 1; + this.usedAuxIds.put("map", i); + this.setDirty(); + return new MapId(i); -+ } // SparklyPaper end - make map data thread-safe ++ } ++ // SparklyPaper end - make map data thread-safe } } diff --git a/leaf-server/minecraft-patches/features/0142-Track-each-world-MSPT.patch b/leaf-server/minecraft-patches/features/0142-SparklyPaper-Track-each-world-MSPT.patch similarity index 72% rename from leaf-server/minecraft-patches/features/0142-Track-each-world-MSPT.patch rename to leaf-server/minecraft-patches/features/0142-SparklyPaper-Track-each-world-MSPT.patch index 378399ac..011966d7 100644 --- a/leaf-server/minecraft-patches/features/0142-Track-each-world-MSPT.patch +++ b/leaf-server/minecraft-patches/features/0142-SparklyPaper-Track-each-world-MSPT.patch @@ -1,15 +1,16 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Taiyou06 Date: Thu, 6 Mar 2025 00:26:19 +0100 -Subject: [PATCH] Track each world MSPT +Subject: [PATCH] SparklyPaper: Track each world MSPT +Original project: https://github.com/SparklyPower/SparklyPaper diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index dd1c55e983bc1ddc9a77a0b825b78eba62c201ec..f7a3cdb3953a959fb258fcb0eeea81ea2c8b217a 100644 +index f2d1025a13649c35991a662c267a7653e75d19a2..7739b4955dcb489c6bba9c9db65ba87025f7c669 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -1687,7 +1687,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Faster redstone torch rapid clock removal; Move from Map in BlockRedstoneTorch to here diff --git a/leaf-server/minecraft-patches/features/0149-Improve-BlockEntity-ticking-isRemoved-check.patch b/leaf-server/minecraft-patches/features/0149-Improve-BlockEntity-ticking-isRemoved-check.patch index 3fa24715..14f6f0fc 100644 --- a/leaf-server/minecraft-patches/features/0149-Improve-BlockEntity-ticking-isRemoved-check.patch +++ b/leaf-server/minecraft-patches/features/0149-Improve-BlockEntity-ticking-isRemoved-check.patch @@ -10,10 +10,10 @@ Leaf (After): ~628ms (-96%) This should help for massive hopper chains or hopper matrix. diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index 23446968f9b42f904da189fb6bc3a6fe15c01fe7..919ad58aef8f3c9705cb67f209e22760ec50ab1d 100644 +index 47528dec6b1a2b36e71013a9372425a70cbc6a33..546fb78339c005ed71142cb3c894f816b8c72d08 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java -@@ -1013,15 +1013,29 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -1012,15 +1012,29 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p static class RebindableTickingBlockEntityWrapper implements TickingBlockEntity { private TickingBlockEntity ticker; private BlockPos cachedPos; // Leaf - Cache tile entity position @@ -43,7 +43,7 @@ index 23446968f9b42f904da189fb6bc3a6fe15c01fe7..919ad58aef8f3c9705cb67f209e22760 } @Override -@@ -1031,6 +1045,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -1030,6 +1044,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Override public boolean isRemoved() { diff --git a/leaf-server/paper-patches/features/0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch b/leaf-server/paper-patches/features/0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch index 3846c779..e7af2191 100644 --- a/leaf-server/paper-patches/features/0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch +++ b/leaf-server/paper-patches/features/0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch @@ -13,7 +13,7 @@ To avoid the hefty ArrayDeque's size() call, we check if we *really* need to exe Most entities won't have any scheduled tasks, so this is a nice performance bonus. These optimizations, however, wouldn't work in a Folia environment, but because in SparklyPaper executeTick is always executed on the main thread, it ain't an issue for us (yay). diff --git a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java -index c03608fec96b51e1867f43d8f42e5aefb1520e46..bb56c56cdbd8a15803e85412b9c15b59a28e9e59 100644 +index c03608fec96b51e1867f43d8f42e5aefb1520e46..56268cf8d184e0b6cd46de8c2e893ad3da8ec64f 100644 --- a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java +++ b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java @@ -36,6 +36,7 @@ public final class EntityScheduler { @@ -74,6 +74,19 @@ index c03608fec96b51e1867f43d8f42e5aefb1520e46..bb56c56cdbd8a15803e85412b9c15b59 if (this.tickCount == RETIRED_TICK_COUNT) { throw new IllegalStateException("Ticking retired scheduler"); } +@@ -178,4 +190,12 @@ public final class EntityScheduler { + } + } + } ++ ++ // Leaf start - SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run ++ public boolean hasTasks() { ++ synchronized (this.stateLock) { ++ return !this.currentlyExecuting.isEmpty() || !this.oneTimeDelayed.isEmpty(); ++ } ++ } ++ // Leaf end - SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run + } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java index cc024874fbde9678bdddfdca7c25080869d66de2..edcd209798740f31cb302f36d7864a0d8ea1d561 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java diff --git a/leaf-server/paper-patches/features/0031-SparklyPaper-Parallel-world-ticking.patch b/leaf-server/paper-patches/features/0031-SparklyPaper-Parallel-world-ticking.patch index 4f0f5f9f..8beb9561 100644 --- a/leaf-server/paper-patches/features/0031-SparklyPaper-Parallel-world-ticking.patch +++ b/leaf-server/paper-patches/features/0031-SparklyPaper-Parallel-world-ticking.patch @@ -3,34 +3,26 @@ From: Altiami Date: Wed, 5 Mar 2025 13:16:44 -0800 Subject: [PATCH] SparklyPaper: Parallel world ticking +Original project: https://github.com/SparklyPower/SparklyPaper diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java -index a4aa2615823d77920ff55b8aa0bcc27a54b8c3e1..8d2694977f29b680d9daf83f2c8cc3502d3cb7dd 100644 +index a4aa2615823d77920ff55b8aa0bcc27a54b8c3e1..2fb65ce228da94eb7d9364ee0f94582300178f1d 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java -@@ -6,6 +6,7 @@ import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.Level; - import net.minecraft.world.phys.AABB; - import net.minecraft.world.phys.Vec3; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.slf4j.Logger; - import org.slf4j.LoggerFactory; - -@@ -14,6 +15,7 @@ import java.util.concurrent.atomic.AtomicInteger; +@@ -14,6 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger; public class TickThread extends Thread { private static final Logger LOGGER = LoggerFactory.getLogger(TickThread.class); -+ public static final boolean HARD_THROW = !SparklyPaperParallelWorldTicking.disableHardThrow; // SparklyPaper - parallel world ticking - THIS SHOULD NOT BE DISABLED SINCE IT CAN CAUSE DATA CORRUPTION!!! Anyhow, for production servers, if you want to make a test run to see if the server could crash, you can test it with this disabled ++ private static final boolean HARD_THROW = !org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.disableHardThrow; // SparklyPaper - parallel world ticking - THIS SHOULD NOT BE DISABLED SINCE IT CAN CAUSE DATA CORRUPTION!!! Anyhow, for production servers, if you want to make a test run to see if the server could crash, you can test it with this disabled private static String getThreadContext() { return "thread=" + Thread.currentThread().getName(); -@@ -26,14 +28,15 @@ public class TickThread extends Thread { +@@ -26,14 +27,14 @@ public class TickThread extends Thread { public static void ensureTickThread(final String reason) { if (!isTickThread()) { LOGGER.error("Thread failed main thread check: " + reason + ", context=" + getThreadContext(), new Throwable()); - throw new IllegalStateException(reason); -+ if (HARD_THROW) -+ throw new IllegalStateException(reason); // SparklyPaper - parallel world ticking ++ if (HARD_THROW) throw new IllegalStateException(reason); // SparklyPaper - parallel world ticking } } @@ -38,90 +30,86 @@ index a4aa2615823d77920ff55b8aa0bcc27a54b8c3e1..8d2694977f29b680d9daf83f2c8cc350 if (!isTickThreadFor(world, pos)) { final String ex = "Thread failed main thread check: " + - reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos; -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + " - " + getTickThreadInformation(world.getServer()); ++ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } -@@ -42,7 +45,7 @@ public class TickThread extends Thread { +@@ -42,7 +43,7 @@ public class TickThread extends Thread { public static void ensureTickThread(final Level world, final BlockPos pos, final int blockRadius, final String reason) { if (!isTickThreadFor(world, pos, blockRadius)) { final String ex = "Thread failed main thread check: " + - reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius; -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius + " - " + getTickThreadInformation(world.getServer()); ++ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } -@@ -51,7 +54,7 @@ public class TickThread extends Thread { +@@ -51,7 +52,7 @@ public class TickThread extends Thread { public static void ensureTickThread(final Level world, final ChunkPos pos, final String reason) { if (!isTickThreadFor(world, pos)) { final String ex = "Thread failed main thread check: " + - reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos; -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos + " - " + getTickThreadInformation(world.getServer()); ++ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } -@@ -60,7 +63,7 @@ public class TickThread extends Thread { +@@ -60,7 +61,7 @@ public class TickThread extends Thread { public static void ensureTickThread(final Level world, final int chunkX, final int chunkZ, final String reason) { if (!isTickThreadFor(world, chunkX, chunkZ)) { final String ex = "Thread failed main thread check: " + - reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ); -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ) + " - " + getTickThreadInformation(world.getServer()); ++ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ) + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } -@@ -69,7 +72,7 @@ public class TickThread extends Thread { +@@ -69,7 +70,7 @@ public class TickThread extends Thread { public static void ensureTickThread(final Entity entity, final String reason) { if (!isTickThreadFor(entity)) { final String ex = "Thread failed main thread check: " + - reason + ", context=" + getThreadContext() + ", entity=" + EntityUtil.dumpEntity(entity); -+ reason + ", context=" + getThreadContext() + ", entity=" + EntityUtil.dumpEntity(entity) + " - " + getTickThreadInformation(entity.getServer()); ++ reason + ", context=" + getThreadContext() + ", entity=" + EntityUtil.dumpEntity(entity) + " - " + getTickThreadInformation(entity.getServer()); // SparklyPaper - parallel world ticking LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } -@@ -78,7 +81,7 @@ public class TickThread extends Thread { +@@ -78,7 +79,7 @@ public class TickThread extends Thread { public static void ensureTickThread(final Level world, final AABB aabb, final String reason) { if (!isTickThreadFor(world, aabb)) { final String ex = "Thread failed main thread check: " + - reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb; -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb + " - " + getTickThreadInformation(world.getServer()); ++ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } -@@ -87,12 +90,74 @@ public class TickThread extends Thread { +@@ -87,12 +88,70 @@ public class TickThread extends Thread { public static void ensureTickThread(final Level world, final double blockX, final double blockZ, final String reason) { if (!isTickThreadFor(world, blockX, blockZ)) { final String ex = "Thread failed main thread check: " + - reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ); -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ) + " - " + getTickThreadInformation(world.getServer()); ++ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ) + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } } -+ // SparklyPaper - parallel world ticking ++ // SparklyPaper start - parallel world ticking + // This is an additional method to check if the tick thread is bound to a specific world because, by default, Paper's isTickThread methods do not provide this information + // Because we only tick worlds in parallel (instead of regions), we can use this for our checks + public static void ensureTickThread(final net.minecraft.server.level.ServerLevel world, final String reason) { + if (!isTickThreadFor(world)) { -+ LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason + " @ world " + world.getWorld().getName() + " - " + getTickThreadInformation(world.getServer()), new Throwable()); -+ if (HARD_THROW) -+ throw new IllegalStateException(reason); ++ LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason + " @ world " + world.getWorld().getName() + " - " + getTickThreadInformation(world.getServer()), new Throwable()); // SparklyPaper - parallel world ticking ++ if (HARD_THROW) throw new IllegalStateException(reason); + } + } + -+ // SparklyPaper - parallel world ticking + // This is an additional method to check if it is a tick thread but ONLY a tick thread + public static void ensureOnlyTickThread(final String reason) { + boolean isTickThread = isTickThread(); + boolean isServerLevelTickThread = isServerLevelTickThread(); + if (!isTickThread || isServerLevelTickThread) { + LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread ONLY tick thread check: " + reason, new Throwable()); -+ if (HARD_THROW) -+ throw new IllegalStateException(reason); ++ if (HARD_THROW) throw new IllegalStateException(reason); + } + } + -+ // SparklyPaper - parallel world ticking + // This is an additional method to check if the tick thread is bound to a specific world or if it is an async thread. + public static void ensureTickThreadOrAsyncThread(final net.minecraft.server.level.ServerLevel world, final String reason) { + boolean isValidTickThread = isTickThreadFor(world); @@ -129,8 +117,7 @@ index a4aa2615823d77920ff55b8aa0bcc27a54b8c3e1..8d2694977f29b680d9daf83f2c8cc350 + boolean isValid = isAsyncThread || isValidTickThread; + if (!isValid) { + LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread or async thread check: " + reason + " @ world " + world.getWorld().getName() + " - " + getTickThreadInformation(world.getServer()), new Throwable()); -+ if (HARD_THROW) -+ throw new IllegalStateException(reason); ++ if (HARD_THROW) throw new IllegalStateException(reason); + } + } + @@ -159,70 +146,73 @@ index a4aa2615823d77920ff55b8aa0bcc27a54b8c3e1..8d2694977f29b680d9daf83f2c8cc350 + public static boolean isServerLevelTickThread() { + return Thread.currentThread() instanceof ServerLevelTickThread; + } ++ // SparklyPaper end - parallel world ticking + public final int id; /* We don't override getId as the spec requires that it be unique (with respect to all other threads) */ private static final AtomicInteger ID_GENERATOR = new AtomicInteger(); -@@ -133,46 +198,73 @@ public class TickThread extends Thread { +@@ -133,46 +192,74 @@ public class TickThread extends Thread { } public static boolean isTickThreadFor(final Level world, final BlockPos pos) { - return isTickThread(); -+ return isTickThreadFor(world); // Leaf - SparklyPaper parallel world ticking mod (use methods for what they were made for) ++ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for) } public static boolean isTickThreadFor(final Level world, final BlockPos pos, final int blockRadius) { - return isTickThread(); -+ return isTickThreadFor(world); // Leaf - SparklyPaper parallel world ticking mod (add missing replacement / use methods for what they were made for) ++ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (add missing replacement / use methods for what they were made for) } public static boolean isTickThreadFor(final Level world, final ChunkPos pos) { - return isTickThread(); -+ return isTickThreadFor(world); // Leaf - SparklyPaper parallel world ticking mod (use methods for what they were made for) ++ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for) } public static boolean isTickThreadFor(final Level world, final Vec3 pos) { - return isTickThread(); -+ return isTickThreadFor(world); // Leaf - SparklyPaper parallel world ticking mod (use methods for what they were made for) ++ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for) } public static boolean isTickThreadFor(final Level world, final int chunkX, final int chunkZ) { - return isTickThread(); -+ return isTickThreadFor(world); // Leaf - SparklyPaper parallel world ticking mod (use methods for what they were made for) ++ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for) } public static boolean isTickThreadFor(final Level world, final AABB aabb) { - return isTickThread(); -+ return isTickThreadFor(world); // Leaf - SparklyPaper parallel world ticking mod (use methods for what they were made for) ++ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for) } public static boolean isTickThreadFor(final Level world, final double blockX, final double blockZ) { - return isTickThread(); -+ return isTickThreadFor(world); // Leaf - SparklyPaper parallel world ticking mod (use methods for what they were made for) ++ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for) } public static boolean isTickThreadFor(final Level world, final Vec3 position, final Vec3 deltaMovement, final int buffer) { - return isTickThread(); -+ return isTickThreadFor(world); // Leaf - SparklyPaper parallel world ticking mod (use methods for what they were made for) ++ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for) } public static boolean isTickThreadFor(final Level world, final int fromChunkX, final int fromChunkZ, final int toChunkX, final int toChunkZ) { - return isTickThread(); -+ return isTickThreadFor(world); // Leaf - SparklyPaper parallel world ticking mod (use methods for what they were made for) ++ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for) } public static boolean isTickThreadFor(final Level world, final int chunkX, final int chunkZ, final int radius) { - return isTickThread(); -+ return isTickThreadFor(world); // Leaf - SparklyPaper parallel world ticking mod (use methods for what they were made for) ++ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for) + } + -+ // SparklyPaper - parallel world ticking ++ // SparklyPaper start - parallel world ticking + // This is an additional method to check if the tick thread is bound to a specific world because, by default, Paper's isTickThread methods do not provide this information + // Because we only tick worlds in parallel (instead of regions), we can use this for our checks + public static boolean isTickThreadFor(final Level world) { + if (Thread.currentThread() instanceof ServerLevelTickThread serverLevelTickThread) { + return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return isTickThread(); ++ } else { ++ return isTickThread(); ++ } } public static boolean isTickThreadFor(final Entity entity) { @@ -231,10 +221,9 @@ index a4aa2615823d77920ff55b8aa0bcc27a54b8c3e1..8d2694977f29b680d9daf83f2c8cc350 + return true; + } + -+ return isTickThreadFor(entity.level()); // Leaf - SparklyPaper parallel world ticking mod (use methods for what they were made for) ++ return isTickThreadFor(entity.level()); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for) + } + -+ // SparklyPaper start - parallel world ticking + public static class ServerLevelTickThread extends TickThread { + public ServerLevelTickThread(String name) { + super(name); @@ -246,144 +235,128 @@ index a4aa2615823d77920ff55b8aa0bcc27a54b8c3e1..8d2694977f29b680d9daf83f2c8cc350 + + public net.minecraft.server.level.ServerLevel currentlyTickingServerLevel; } -+ // SparklyPaper end ++ // SparklyPaper end - parallel world ticking } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 15673166e566b2a6d5093210d99b154e69fab0ad..3c80b73f969318ec12b4f39b50cf1e215b5ca23f 100644 +index 15673166e566b2a6d5093210d99b154e69fab0ad..49abf1100271452e9c79c8643a25af3ce519773b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -145,6 +145,7 @@ import org.bukkit.util.NumberConversions; - import org.bukkit.util.RayTraceResult; - import org.bukkit.util.StructureSearchResult; - import org.bukkit.util.Vector; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -@@ -455,7 +456,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -455,7 +455,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { } private boolean unloadChunk0(int x, int z, boolean save) { - org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot -+ // Leaf start - SparklyPaper parallel world ticking mod (make configurable) -+ if (SparklyPaperParallelWorldTicking.enabled) ++ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot unload chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) + else + org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot -+ // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable) if (!this.isChunkLoaded(x, z)) { return true; } -@@ -472,6 +478,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -472,6 +477,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean refreshChunk(int x, int z) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot refresh chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); if (playerChunk == null) return false; -@@ -522,7 +530,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -522,7 +529,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -+ // Leaf start - SparklyPaper parallel world ticking mod (make configurable) -+ if (SparklyPaperParallelWorldTicking.enabled) ++ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.getHandle(), x, z, "May not sync load chunks asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) + else + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -+ // Leaf end ++ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable) warnUnsafeChunk("loading a faraway chunk", x, z); // Paper ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper -@@ -750,6 +763,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -750,6 +762,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, loc.getX(), loc.getZ(), "Cannot generate tree asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) this.world.captureTreeGeneration = true; this.world.captureBlockStates = true; boolean grownTree = this.generateTree(loc, type); -@@ -865,6 +880,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -865,6 +879,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { } public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source, Consumer configurator) { // Paper end - expand explosion API -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot create explosion asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) net.minecraft.world.level.Level.ExplosionInteraction explosionType; if (!breakBlocks) { explosionType = net.minecraft.world.level.Level.ExplosionInteraction.NONE; // Don't break blocks -@@ -956,6 +973,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -956,6 +972,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getHighestBlockYAt(int x, int z, org.bukkit.HeightMap heightMap) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x >> 4, z >> 4, "Cannot retrieve chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) warnUnsafeChunk("getting a faraway chunk", x >> 4, z >> 4); // Paper // Transient load for this tick return this.world.getChunk(x >> 4, z >> 4).getHeight(CraftHeightMap.toNMS(heightMap), x, z); -@@ -986,6 +1005,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -986,6 +1004,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setBiome(int x, int y, int z, Holder bb) { BlockPos pos = new BlockPos(x, 0, z); -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, pos, "Cannot retrieve chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) if (this.world.hasChunkAt(pos)) { net.minecraft.world.level.chunk.LevelChunk chunk = this.world.getChunkAt(pos); -@@ -2328,6 +2349,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2328,6 +2348,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void sendGameEvent(Entity sourceEntity, org.bukkit.GameEvent gameEvent, Vector position) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, position.getX(), position.getZ(), "Cannot send game event asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) getHandle().gameEvent(sourceEntity != null ? ((CraftEntity) sourceEntity).getHandle(): null, net.minecraft.core.registries.BuiltInRegistries.GAME_EVENT.get(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(gameEvent.getKey())).orElseThrow(), org.bukkit.craftbukkit.util.CraftVector.toBlockPos(position)); } // Paper end diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 973b297a22c0cc53f966582c67c3688f4b2205c7..747f20d080b602ab9a1c551c648bf54682e584e0 100644 +index 973b297a22c0cc53f966582c67c3688f4b2205c7..61f9e88a7760b4bf23674ac8594dd31557768217 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -60,6 +60,7 @@ import org.bukkit.util.BlockVector; - import org.bukkit.util.BoundingBox; - import org.bukkit.util.RayTraceResult; - import org.bukkit.util.Vector; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - - public class CraftBlock implements Block { - private final net.minecraft.world.level.LevelAccessor world; -@@ -75,6 +76,11 @@ public class CraftBlock implements Block { +@@ -75,6 +75,11 @@ public class CraftBlock implements Block { } public net.minecraft.world.level.block.state.BlockState getNMS() { -+ // Folia start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ // SparklyPaper start - parallel world ticking ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } -+ // Folia end - parallel world ticking ++ // SparklyPaper end - parallel world ticking return this.world.getBlockState(this.position); } -@@ -157,6 +163,11 @@ public class CraftBlock implements Block { +@@ -157,6 +162,11 @@ public class CraftBlock implements Block { } private void setData(final byte data, int flag) { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } + // SparklyPaper end - parallel world ticking this.world.setBlock(this.position, CraftMagicNumbers.getBlock(this.getType(), data), flag); } -@@ -198,6 +209,12 @@ public class CraftBlock implements Block { +@@ -198,6 +208,12 @@ public class CraftBlock implements Block { } public static boolean setTypeAndData(LevelAccessor world, BlockPos position, net.minecraft.world.level.block.state.BlockState old, net.minecraft.world.level.block.state.BlockState blockData, boolean applyPhysics) { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } + // SparklyPaper end - parallel world ticking @@ -391,12 +364,12 @@ index 973b297a22c0cc53f966582c67c3688f4b2205c7..747f20d080b602ab9a1c551c648bf546 // SPIGOT-611: need to do this to prevent glitchiness. Easier to handle this here (like /setblock) than to fix weirdness in tile entity cleanup if (old.hasBlockEntity() && blockData.getBlock() != old.getBlock()) { // SPIGOT-3725 remove old tile entity if block changes // SPIGOT-4612: faster - just clear tile -@@ -343,18 +360,33 @@ public class CraftBlock implements Block { +@@ -343,18 +359,33 @@ public class CraftBlock implements Block { @Override public Biome getBiome() { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } + // SparklyPaper end - parallel world ticking @@ -407,7 +380,7 @@ index 973b297a22c0cc53f966582c67c3688f4b2205c7..747f20d080b602ab9a1c551c648bf546 @Override public Biome getComputedBiome() { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } + // SparklyPaper end - parallel world ticking @@ -418,102 +391,102 @@ index 973b297a22c0cc53f966582c67c3688f4b2205c7..747f20d080b602ab9a1c551c648bf546 @Override public void setBiome(Biome bio) { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } + // SparklyPaper end - parallel world ticking this.getWorld().setBiome(this.getX(), this.getY(), this.getZ(), bio); } -@@ -375,6 +407,11 @@ public class CraftBlock implements Block { +@@ -375,6 +406,11 @@ public class CraftBlock implements Block { @Override public boolean isBlockIndirectlyPowered() { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } + // SparklyPaper end - parallel world ticking return this.world.getMinecraftWorld().hasNeighborSignal(this.position); } -@@ -414,6 +451,11 @@ public class CraftBlock implements Block { +@@ -414,6 +450,11 @@ public class CraftBlock implements Block { @Override public int getBlockPower(BlockFace face) { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } + // SparklyPaper end - parallel world ticking int power = 0; net.minecraft.world.level.Level world = this.world.getMinecraftWorld(); int x = this.getX(); -@@ -484,6 +526,11 @@ public class CraftBlock implements Block { +@@ -484,6 +525,11 @@ public class CraftBlock implements Block { @Override public boolean breakNaturally() { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } + // SparklyPaper end - parallel world ticking return this.breakNaturally(null); } -@@ -543,6 +590,11 @@ public class CraftBlock implements Block { +@@ -543,6 +589,11 @@ public class CraftBlock implements Block { @Override public boolean applyBoneMeal(BlockFace face) { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } + // SparklyPaper end - parallel world ticking Direction direction = CraftBlock.blockFaceToNotch(face); BlockFertilizeEvent event = null; ServerLevel world = this.getCraftWorld().getHandle(); -@@ -554,8 +606,8 @@ public class CraftBlock implements Block { +@@ -554,8 +605,8 @@ public class CraftBlock implements Block { world.captureTreeGeneration = false; if (world.capturedBlockStates.size() > 0) { - TreeType treeType = SaplingBlock.treeType; - SaplingBlock.treeType = null; -+ TreeType treeType = SaplingBlock.getTreeTypeRT(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) -+ SaplingBlock.setTreeTypeRT(null); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ TreeType treeType = SaplingBlock.getTreeTypeRT(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) ++ SaplingBlock.setTreeTypeRT(null); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) List blocks = new ArrayList<>(world.capturedBlockStates.values()); world.capturedBlockStates.clear(); StructureGrowEvent structureEvent = null; -@@ -644,6 +696,11 @@ public class CraftBlock implements Block { +@@ -644,6 +695,11 @@ public class CraftBlock implements Block { @Override public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode) { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } + // SparklyPaper end - parallel world ticking Preconditions.checkArgument(start != null, "Location start cannot be null"); Preconditions.checkArgument(this.getWorld().equals(start.getWorld()), "Location start cannot be a different world"); start.checkFinite(); -@@ -685,6 +742,11 @@ public class CraftBlock implements Block { +@@ -685,6 +741,11 @@ public class CraftBlock implements Block { @Override public boolean canPlace(BlockData data) { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } + // SparklyPaper end - parallel world ticking Preconditions.checkArgument(data != null, "BlockData cannot be null"); net.minecraft.world.level.block.state.BlockState iblockdata = ((CraftBlockData) data).getState(); net.minecraft.world.level.Level world = this.world.getMinecraftWorld(); -@@ -719,6 +781,11 @@ public class CraftBlock implements Block { +@@ -719,6 +780,11 @@ public class CraftBlock implements Block { @Override public void tick() { + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } + // SparklyPaper end - parallel world ticking @@ -521,34 +494,19 @@ index 973b297a22c0cc53f966582c67c3688f4b2205c7..747f20d080b602ab9a1c551c648bf546 this.getNMS().tick(level, this.position, level.random); } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 768d3f93da2522d467183654260a8bd8653588b1..bad74104dcfde34ae0dec99adfe81e71132b7c28 100644 +index 768d3f93da2522d467183654260a8bd8653588b1..58fdc0e7bb5d377c6dad1af6307d5d0d11b1ee45 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -11,12 +11,14 @@ import net.minecraft.network.protocol.game.ClientGamePacketListener; - import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; - import net.minecraft.server.MinecraftServer; - import net.minecraft.world.level.LevelAccessor; -+import net.minecraft.world.level.block.DispenserBlock; - import net.minecraft.world.level.block.entity.BlockEntity; - import org.bukkit.Location; - import org.bukkit.World; - import org.bukkit.block.TileState; - import org.bukkit.craftbukkit.util.CraftLocation; - import org.bukkit.persistence.PersistentDataContainer; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - -@@ -26,6 +28,26 @@ public abstract class CraftBlockEntityState extends Craft +@@ -26,6 +26,27 @@ public abstract class CraftBlockEntityState extends Craft private final T snapshot; public boolean snapshotDisabled; // Paper public static boolean DISABLE_SNAPSHOT = false; // Paper -+ public static ThreadLocal DISABLE_SNAPSHOT_TL = ThreadLocal.withInitial(() -> Boolean.FALSE); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (distinguish name) ++ public static ThreadLocal DISABLE_SNAPSHOT_TL = ThreadLocal.withInitial(() -> Boolean.FALSE); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (distinguish name) + -+ // Leaf - SparklyPaper parallel world ticking mod ++ // Leaf start - SparklyPaper - parallel world ticking mod + // refer to original field in case plugins attempt to modify it + public static boolean getDisableSnapshotTL() { -+ if (SparklyPaperParallelWorldTicking.enabled && DISABLE_SNAPSHOT_TL.get()) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && DISABLE_SNAPSHOT_TL.get()) + return true; + synchronized (CraftBlockEntityState.class) { + return DISABLE_SNAPSHOT; @@ -557,44 +515,37 @@ index 768d3f93da2522d467183654260a8bd8653588b1..bad74104dcfde34ae0dec99adfe81e71 + + // update original field in case plugins attempt to access it + public static void setDisableSnapshotTL(boolean value) { -+ if (SparklyPaperParallelWorldTicking.enabled) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + DISABLE_SNAPSHOT_TL.set(value); + synchronized (CraftBlockEntityState.class) { + DISABLE_SNAPSHOT = value; + } + } ++ // Leaf end - SparklyPaper - parallel world ticking mod public CraftBlockEntityState(World world, T tileEntity) { super(world, tileEntity.getBlockPos(), tileEntity.getBlockState()); -@@ -34,8 +56,8 @@ public abstract class CraftBlockEntityState extends Craft +@@ -34,8 +55,8 @@ public abstract class CraftBlockEntityState extends Craft try { // Paper - Show blockstate location if we failed to read it // Paper start - this.snapshotDisabled = DISABLE_SNAPSHOT; - if (DISABLE_SNAPSHOT) { -+ this.snapshotDisabled = getDisableSnapshotTL(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) -+ if (getDisableSnapshotTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ this.snapshotDisabled = getDisableSnapshotTL(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) ++ if (getDisableSnapshotTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) this.snapshot = this.tileEntity; } else { this.snapshot = this.createSnapshot(tileEntity); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..bc0f999f89fedebe58b6fa554c2abbacb65adbeb 100644 +index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..d106f65e4b745242484a195958fc559268a7dee0 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -@@ -21,6 +21,7 @@ import org.bukkit.material.Attachable; - import org.bukkit.material.MaterialData; - import org.bukkit.metadata.MetadataValue; - import org.bukkit.plugin.Plugin; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - - public class CraftBlockState implements BlockState { - -@@ -215,6 +216,12 @@ public class CraftBlockState implements BlockState { +@@ -215,6 +215,12 @@ public class CraftBlockState implements BlockState { LevelAccessor access = this.getWorldHandle(); CraftBlock block = this.getBlock(); + // SparklyPaper start - parallel world ticking -+ if (SparklyPaperParallelWorldTicking.enabled && access instanceof net.minecraft.server.level.ServerLevel serverWorld) { ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && access instanceof net.minecraft.server.level.ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } + // SparklyPaper end - parallel world ticking @@ -602,17 +553,17 @@ index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..bc0f999f89fedebe58b6fa554c2abbac if (block.getType() != this.getType()) { if (!force) { return false; -@@ -350,6 +357,8 @@ public class CraftBlockState implements BlockState { +@@ -350,6 +356,8 @@ public class CraftBlockState implements BlockState { @Override public java.util.Collection getDrops(org.bukkit.inventory.ItemStack item, org.bukkit.entity.Entity entity) { -+ if (SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper parallel world ticking mod (make configurable) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable) + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(world.getHandle(), position, "Cannot modify world asynchronously"); // SparklyPaper - parallel world ticking this.requirePlaced(); net.minecraft.world.item.ItemStack nms = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java -index 55572e799b5c8a74a546ac8febc14f80d5731c52..11a3970a9f3bee1d05327b8a5c5dde4f746929ac 100644 +index 55572e799b5c8a74a546ac8febc14f80d5731c52..08a06c23c831a4de45b3e537228b837911019da8 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java @@ -249,8 +249,8 @@ public final class CraftBlockStates { @@ -621,8 +572,8 @@ index 55572e799b5c8a74a546ac8febc14f80d5731c52..11a3970a9f3bee1d05327b8a5c5dde4f // Paper start - block state snapshots - boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; - CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; -+ boolean prev = CraftBlockEntityState.getDisableSnapshotTL(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) -+ CraftBlockEntityState.setDisableSnapshotTL(!useSnapshot); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ boolean prev = CraftBlockEntityState.getDisableSnapshotTL(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) ++ CraftBlockEntityState.setDisableSnapshotTL(!useSnapshot); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) try { // Paper end CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockPosition, blockData, tileEntity); @@ -631,33 +582,25 @@ index 55572e799b5c8a74a546ac8febc14f80d5731c52..11a3970a9f3bee1d05327b8a5c5dde4f // Paper start } finally { - CraftBlockEntityState.DISABLE_SNAPSHOT = prev; -+ CraftBlockEntityState.setDisableSnapshotTL(prev); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ CraftBlockEntityState.setDisableSnapshotTL(prev); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) } // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index fbb4dd93c263c898731902b73dbd1c62df1eea4b..d19f87f1bbad8832db10d4d49186fe260728b40e 100644 +index fbb4dd93c263c898731902b73dbd1c62df1eea4b..138662f3e57f9741a41701b5a5a65a859a31dfc8 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -254,6 +254,7 @@ import org.bukkit.inventory.meta.BookMeta; - import org.bukkit.inventory.view.AnvilView; - import org.bukkit.potion.PotionEffect; - import org.bukkit.util.Vector; -+import org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking; - - public class CraftEventFactory { - -@@ -961,6 +962,27 @@ public class CraftEventFactory { +@@ -961,6 +961,28 @@ public class CraftEventFactory { } public static BlockPos sourceBlockOverride = null; // SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. + public static final ThreadLocal sourceBlockOverrideRT = new ThreadLocal<>(); // SparklyPaper - parallel world ticking (this is from Folia, fixes concurrency bugs with sculk catalysts) + -+ // Leaf - SparklyPaper parallel world ticking mod ++ // Leaf start - SparklyPaper - parallel world ticking mod + // refer to original field in case plugins attempt to modify it + public static BlockPos getSourceBlockOverrideRT() { + BlockPos sourceBlockOverrideRTCopy; -+ if (SparklyPaperParallelWorldTicking.enabled && (sourceBlockOverrideRTCopy = sourceBlockOverrideRT.get()) != null) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && (sourceBlockOverrideRTCopy = sourceBlockOverrideRT.get()) != null) + return sourceBlockOverrideRTCopy; + synchronized (CraftEventFactory.class) { + return sourceBlockOverride; @@ -666,12 +609,13 @@ index fbb4dd93c263c898731902b73dbd1c62df1eea4b..d19f87f1bbad8832db10d4d49186fe26 + + // update original field in case plugins attempt to access it + public static void setSourceBlockOverrideRT(BlockPos value) { -+ if (SparklyPaperParallelWorldTicking.enabled) ++ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) + sourceBlockOverrideRT.set(value); + synchronized (CraftEventFactory.class) { + sourceBlockOverride = value; + } + } ++ // Leaf end - SparklyPaper - parallel world ticking mod public static boolean handleBlockSpreadEvent(LevelAccessor world, BlockPos source, BlockPos target, net.minecraft.world.level.block.state.BlockState block, int flag) { // Suppress during worldgen @@ -680,7 +624,7 @@ index fbb4dd93c263c898731902b73dbd1c62df1eea4b..d19f87f1bbad8832db10d4d49186fe26 state.setData(block); - BlockSpreadEvent event = new BlockSpreadEvent(state.getBlock(), CraftBlock.at(world, CraftEventFactory.sourceBlockOverride != null ? CraftEventFactory.sourceBlockOverride : source), state); -+ BlockSpreadEvent event = new BlockSpreadEvent(state.getBlock(), CraftBlock.at(world, CraftEventFactory.getSourceBlockOverrideRT() != null ? CraftEventFactory.getSourceBlockOverrideRT() : source), state); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ BlockSpreadEvent event = new BlockSpreadEvent(state.getBlock(), CraftBlock.at(world, CraftEventFactory.getSourceBlockOverrideRT() != null ? CraftEventFactory.getSourceBlockOverrideRT() : source), state); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { @@ -689,7 +633,7 @@ index fbb4dd93c263c898731902b73dbd1c62df1eea4b..d19f87f1bbad8832db10d4d49186fe26 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), CraftVector.toBukkit(to)); - if (!net.minecraft.world.level.block.DispenserBlock.eventFired) { -+ if (!net.minecraft.world.level.block.DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper parallel world ticking mod (collapse original behavior) ++ if (!net.minecraft.world.level.block.DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior) if (!event.callEvent()) { return itemStack; } diff --git a/leaf-server/paper-patches/features/0033-Fix-SparklyPaper-skip-EntityScheduler-s-executeTick-.patch b/leaf-server/paper-patches/features/0033-Fix-SparklyPaper-skip-EntityScheduler-s-executeTick-.patch deleted file mode 100644 index 3c19c1a3..00000000 --- a/leaf-server/paper-patches/features/0033-Fix-SparklyPaper-skip-EntityScheduler-s-executeTick-.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Taiyou06 -Date: Thu, 20 Mar 2025 00:16:49 +0100 -Subject: [PATCH] Fix SparklyPaper - skip EntityScheduler's executeTick checks - if there isn't any tasks to be run - - -diff --git a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java -index bb56c56cdbd8a15803e85412b9c15b59a28e9e59..59becabc96366d97abbc3edf388bfaab1b1461da 100644 ---- a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java -+++ b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java -@@ -190,4 +190,9 @@ public final class EntityScheduler { - } - } - } -+ public boolean hasTasks() { -+ synchronized (this.stateLock) { -+ return !this.currentlyExecuting.isEmpty() || !this.oneTimeDelayed.isEmpty(); -+ } -+ } - } diff --git a/leaf-server/src/main/java/org/dreeam/leaf/async/world/SparklyPaperServerLevelTickExecutorThreadFactory.java b/leaf-server/src/main/java/org/dreeam/leaf/async/world/SparklyPaperServerLevelTickExecutorThreadFactory.java index 2a359fee..e7dcacba 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/async/world/SparklyPaperServerLevelTickExecutorThreadFactory.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/async/world/SparklyPaperServerLevelTickExecutorThreadFactory.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.NotNull; import java.util.concurrent.ThreadFactory; public class SparklyPaperServerLevelTickExecutorThreadFactory implements ThreadFactory { + private final String worldName; public SparklyPaperServerLevelTickExecutorThreadFactory(final String worldName) { diff --git a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/AsyncChunkSend.java b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/AsyncChunkSend.java index ec41f9a3..2e2dae90 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/AsyncChunkSend.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/AsyncChunkSend.java @@ -10,7 +10,6 @@ public class AsyncChunkSend extends ConfigModules { return EnumConfigCategory.ASYNC.getBaseKeyName() + ".async-chunk-send"; } - @Experimental public static boolean enabled = false; @Override diff --git a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/SparklyPaperParallelWorldTicking.java b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/SparklyPaperParallelWorldTicking.java index c93d5f46..2bac9ff8 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/SparklyPaperParallelWorldTicking.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/SparklyPaperParallelWorldTicking.java @@ -2,12 +2,15 @@ package org.dreeam.leaf.config.modules.async; import org.dreeam.leaf.config.ConfigModules; import org.dreeam.leaf.config.EnumConfigCategory; +import org.dreeam.leaf.config.annotations.Experimental; public class SparklyPaperParallelWorldTicking extends ConfigModules { + public String getBasePath() { return EnumConfigCategory.ASYNC.getBaseKeyName() + ".parallel-world-tracking"; } + @Experimental public static boolean enabled = false; public static int threads = 8; public static boolean logContainerCreationStacktraces = false;