diff --git a/divinemc-server/minecraft-patches/features/0008-Parallel-world-ticking.patch b/divinemc-server/minecraft-patches/features/0008-Parallel-world-ticking.patch index 893b3e8..9284877 100644 --- a/divinemc-server/minecraft-patches/features/0008-Parallel-world-ticking.patch +++ b/divinemc-server/minecraft-patches/features/0008-Parallel-world-ticking.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Parallel world ticking diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -index b5817aa8f537593f6d9fc6b612c82ccccb250ac7..0c99bffa769d53562a10d23c4a9b37dc59c7f478 100644 +index b5817aa8f537593f6d9fc6b612c82ccccb250ac7..5683395e09a65b1b39748df5152fffef630ac083 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java @@ -1031,7 +1031,7 @@ public final class ChunkHolderManager { @@ -13,30 +13,36 @@ index b5817aa8f537593f6d9fc6b612c82ccccb250ac7..0c99bffa769d53562a10d23c4a9b37dc return; } - if (!TickThread.isTickThread()) { -+ if (!TickThread.isTickThreadFor(world)) { // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && !TickThread.isTickThreadFor(world)) { // DivineMC - Parallel world ticking this.taskScheduler.scheduleChunkTask(() -> { final ArrayDeque pendingFullLoadUpdate = ChunkHolderManager.this.pendingFullLoadUpdate; for (int i = 0, len = changedFullStatus.size(); i < len; ++i) { -@@ -1057,7 +1057,7 @@ public final class ChunkHolderManager { +@@ -1057,7 +1057,13 @@ 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"); -+ TickThread.ensureTickThread(world, "Cannot unload chunks off-main"); // DivineMC - parallel world ticking ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { ++ TickThread.ensureTickThread(world, "Cannot unload chunks off-main"); ++ } else { ++ TickThread.ensureTickThread("Cannot unload chunks off-main"); ++ } ++ // DivineMC end - Parallel world ticking if (BLOCK_TICKET_UPDATES.get() == Boolean.TRUE) { throw new IllegalStateException("Cannot unload chunks recursively"); -@@ -1339,7 +1339,7 @@ public final class ChunkHolderManager { +@@ -1339,7 +1345,7 @@ public final class ChunkHolderManager { List changedFullStatus = null; - final boolean isTickThread = TickThread.isTickThread(); -+ final boolean isTickThread = TickThread.isTickThreadFor(world); // DivineMC - parallel world ticking ++ final boolean isTickThread = org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && TickThread.isTickThreadFor(world) || TickThread.isTickThread(); // DivineMC - Parallel world ticking 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..d019e6cd603c918b576b950a3c678862b2248c93 100644 +index 4a881636ba21fae9e50950bbba2b4321b71d35ab..ebcd52da2228893f7a2d96f61e71906f8d2783ba 100644 --- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java @@ -46,7 +46,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { @@ -44,12 +50,12 @@ index 4a881636ba21fae9e50950bbba2b4321b71d35ab..d019e6cd603c918b576b950a3c678862 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking serverLevel.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -index bd5bbc7e55c6bea77991fe5a3c0c2580313d16c5..10ab4be4b8d7e488148bab395e344fca0d09fbb0 100644 +index bd5bbc7e55c6bea77991fe5a3c0c2580313d16c5..b822dd53138c9cde3e7248afb7589ca32a1b178a 100644 --- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java @@ -78,7 +78,7 @@ public class DefaultDispenseItemBehavior implements DispenseItemBehavior { @@ -57,12 +63,12 @@ index bd5bbc7e55c6bea77991fe5a3c0c2580313d16c5..10ab4be4b8d7e488148bab395e344fca 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking level.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/DispenseItemBehavior.java b/net/minecraft/core/dispenser/DispenseItemBehavior.java -index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c072546ad329c6 100644 +index f576449e8bc6fd92963cbe3954b0c853a02def3c..075987ec1eabb7385918049c54d7210ff2b38847 100644 --- a/net/minecraft/core/dispenser/DispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java @@ -89,7 +89,7 @@ public interface DispenseItemBehavior { @@ -70,7 +76,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking serverLevel.getCraftServer().getPluginManager().callEvent(event); } @@ -79,7 +85,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking serverLevel.getCraftServer().getPluginManager().callEvent(event); } @@ -88,7 +94,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity()); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking world.getCraftServer().getPluginManager().callEvent(event); } @@ -97,7 +103,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking world.getCraftServer().getPluginManager().callEvent(event); } @@ -106,7 +112,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking level.getCraftServer().getPluginManager().callEvent(event); } @@ -115,7 +121,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking levelAccessor.getMinecraftWorld().getCraftServer().getPluginManager().callEvent(event); } @@ -124,7 +130,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking serverLevel.getCraftServer().getPluginManager().callEvent(event); } @@ -133,7 +139,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking level.getCraftServer().getPluginManager().callEvent(event); } @@ -143,10 +149,10 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 if (level.capturedBlockStates.size() > 0) { - org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeType; - net.minecraft.world.level.block.SaplingBlock.treeType = null; -+ // DivineMC start - parallel world ticking -+ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeTypeRT.get(); -+ net.minecraft.world.level.block.SaplingBlock.treeTypeRT.set(null); -+ // DivineMC end - parallel world ticking ++ // DivineMC start - Parallel world ticking ++ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.getTreeTypeTL(); ++ net.minecraft.world.level.block.SaplingBlock.setTreeTypeTL(null); ++ // DivineMC end - Parallel world ticking 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(); @@ -155,7 +161,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking level.getCraftServer().getPluginManager().callEvent(event); } @@ -164,7 +170,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking level.getCraftServer().getPluginManager().callEvent(event); } @@ -173,7 +179,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking level.getCraftServer().getPluginManager().callEvent(event); } @@ -182,7 +188,7 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking serverLevel.getCraftServer().getPluginManager().callEvent(event); } @@ -191,12 +197,12 @@ index f576449e8bc6fd92963cbe3954b0c853a02def3c..c8c8351f5645cf4041d26b0e02c07254 org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity()); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking serverLevel.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java -index b91b2f5ea6a1da0477541dc65fdfbfa57b9af475..e2b7ee10569812c94a5ff6d6e731941f24527c55 100644 +index b91b2f5ea6a1da0477541dc65fdfbfa57b9af475..136c52cab0097fb68e8d12f653f1dab934de9bde 100644 --- a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java @@ -39,7 +39,7 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior { @@ -204,12 +210,12 @@ index b91b2f5ea6a1da0477541dc65fdfbfa57b9af475..e2b7ee10569812c94a5ff6d6e731941f 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking world.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java b/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java -index 116395b6c00a0814922516707544a9ff26d68835..37f710bfa8a9388351d1d32f6f2eeac7c8bfd4bd 100644 +index 116395b6c00a0814922516707544a9ff26d68835..11d4da87aa80aa338d5f3048285079777bae7d3d 100644 --- a/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java @@ -62,7 +62,7 @@ public class MinecartDispenseItemBehavior extends DefaultDispenseItemBehavior { @@ -217,12 +223,12 @@ index 116395b6c00a0814922516707544a9ff26d68835..37f710bfa8a9388351d1d32f6f2eeac7 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking serverLevel.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java b/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java -index 449d9b72ff4650961daa9d1bd25940f3914a6b12..097528f85e5c0393c8b20a68aede99b4b949cb24 100644 +index 449d9b72ff4650961daa9d1bd25940f3914a6b12..ce12d4729d100be7dffaf4bdfc1c999d68c07bac 100644 --- a/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java +++ b/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java @@ -32,7 +32,7 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { @@ -230,12 +236,12 @@ index 449d9b72ff4650961daa9d1bd25940f3914a6b12..097528f85e5c0393c8b20a68aede99b4 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking serverLevel.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -index 626e9feb6a6e7a2cbc7c63e30ba4fb6b923e85c7..6fad185f34c4614f16012ec008add241f188d462 100644 +index 626e9feb6a6e7a2cbc7c63e30ba4fb6b923e85c7..81b37cf681ff0220263628b390910d9597662a3a 100644 --- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java @@ -25,7 +25,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { @@ -243,12 +249,12 @@ index 626e9feb6a6e7a2cbc7c63e30ba4fb6b923e85c7..6fad185f34c4614f16012ec008add241 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking serverLevel.getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java -index 5ab2c8333178335515e619b87ae420f948c83bd1..9d2bc41befd0f73b6a0f097d45fbe771e13be86f 100644 +index 5ab2c8333178335515e619b87ae420f948c83bd1..e3034132c9119956e15a6a0342173d70e44ad669 100644 --- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java @@ -27,7 +27,7 @@ public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { @@ -256,19 +262,19 @@ index 5ab2c8333178335515e619b87ae420f948c83bd1..9d2bc41befd0f73b6a0f097d45fbe771 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking blockSource.level().getCraftServer().getPluginManager().callEvent(event); } diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 4cb26cb312802ffc00426293014ed3994793a391..9f7698f8ce56d5d89cf86f6ea2d5b4d51b18c9a2 100644 +index 4cb26cb312802ffc00426293014ed3994793a391..5a726da8535aa939f043829a3c60fdd9d4ed154a 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -288,6 +288,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function threadFunction) { ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system @@ -407,29 +413,29 @@ index 4cb26cb312802ffc00426293014ed3994793a391..9f7698f8ce56d5d89cf86f6ea2d5b4d5 Map, ServerLevel> oldLevels = this.levels; Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); newLevels.remove(level.dimension()); -+ level.tickExecutor.shutdown(); // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) level.tickExecutor.shutdown(); // DivineMC - Parallel world ticking this.levels = Collections.unmodifiableMap(newLevels); } // CraftBukkit end diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 0d889730641fd88d4da0c9116226a4dae385e846..9fcdff2be139296f4e14b54c33cc795efdff0c7f 100644 +index 0d889730641fd88d4da0c9116226a4dae385e846..f7a061ad623fa909389c60c1d5b4be840f99e2bf 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java @@ -243,6 +243,12 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics -+ // DivineMC start - parallel world ticking ++ // DivineMC start - Parallel world ticking + if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { + serverLevelTickingSemaphore = new java.util.concurrent.Semaphore(org.bxteam.divinemc.DivineConfig.parallelThreadCount); -+ DedicatedServer.LOGGER.info("Using {} permits for parallel world ticking", serverLevelTickingSemaphore.availablePermits()); ++ DedicatedServer.LOGGER.info("Using {} permits for Parallel world ticking", serverLevelTickingSemaphore.availablePermits()); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking /*// Purpur start - Purpur config files // Purpur - Configurable void damage height and damage try { org.purpurmc.purpur.PurpurConfig.init((java.io.File) options.valueOf("purpur-settings")); diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 6e1ed33463c6280159d7f8187b9a9210d6b85e0c..973198ae0a73d6747e73548bdcbc1de46b6fb107 100644 +index d4b44e0fdf113e66c45cc86221df20fe2d3bb9f0..50ea7f4a0428cbc49fb13a31b1fa643e00ef9434 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -182,7 +182,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -437,7 +443,7 @@ index 6e1ed33463c6280159d7f8187b9a9210d6b85e0c..973198ae0a73d6747e73548bdcbc1de4 public final net.minecraft.world.level.storage.PrimaryLevelData serverLevelData; // CraftBukkit - type private int lastSpawnChunkRadius; - final EntityTickList entityTickList = new EntityTickList(); -+ final EntityTickList entityTickList = new EntityTickList(this); // DivineMC - parallel world ticking ++ final EntityTickList entityTickList = new EntityTickList(this); // DivineMC - Parallel world ticking // Paper - rewrite chunk system private final GameEventDispatcher gameEventDispatcher; public boolean noSave; @@ -445,7 +451,7 @@ index 6e1ed33463c6280159d7f8187b9a9210d6b85e0c..973198ae0a73d6747e73548bdcbc1de4 private double preciseTime; // Purpur - Configurable daylight cycle private boolean forceTime; // Purpur - Configurable daylight cycle private final RandomSequences randomSequences; -+ public java.util.concurrent.ExecutorService tickExecutor; // DivineMC - parallel world ticking ++ public java.util.concurrent.ExecutorService tickExecutor; // DivineMC - Parallel world ticking // CraftBukkit start public final LevelStorageSource.LevelStorageAccess levelStorageAccess; @@ -453,7 +459,7 @@ index 6e1ed33463c6280159d7f8187b9a9210d6b85e0c..973198ae0a73d6747e73548bdcbc1de4 this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler); // Paper end - rewrite chunk system this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit -+ this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new org.bxteam.divinemc.server.ServerLevelTickExecutorThreadFactory(getWorld().getName())); // DivineMC - parallel world ticking ++ this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new org.bxteam.divinemc.server.ServerLevelTickExecutorThreadFactory(getWorld().getName())); // DivineMC - Parallel world ticking this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle } @@ -463,10 +469,11 @@ index 6e1ed33463c6280159d7f8187b9a9210d6b85e0c..973198ae0a73d6747e73548bdcbc1de4 } - // Paper start - rewrite chunk system - if ((++this.tickedBlocksOrFluids & 7L) != 0L) { +- ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); + // DivineMC start - Parallel world ticking + ++this.tickedBlocksOrFluids; + if (!org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && (this.tickedBlocksOrFluids & 7L) != 0L) { - ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); ++ this.server.moonrise$executeMidTickTasks(); } - // Paper end - rewrite chunk system - @@ -480,10 +487,11 @@ index 6e1ed33463c6280159d7f8187b9a9210d6b85e0c..973198ae0a73d6747e73548bdcbc1de4 } - // Paper start - rewrite chunk system - if ((++this.tickedBlocksOrFluids & 7L) != 0L) { +- ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); + // DivineMC start - Parallel world ticking + ++this.tickedBlocksOrFluids; + if (!org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && (this.tickedBlocksOrFluids & 7L) != 0L) { - ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); ++ this.server.moonrise$executeMidTickTasks(); } - // Paper end - rewrite chunk system - @@ -495,28 +503,34 @@ index 6e1ed33463c6280159d7f8187b9a9210d6b85e0c..973198ae0a73d6747e73548bdcbc1de4 } private void addPlayer(ServerPlayer player) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add player off-main"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add player off-main"); // DivineMC - 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()); -@@ -1534,7 +1537,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -1534,7 +1537,13 @@ 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 -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add entity off-main"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add entity off-main"); ++ } else { ++ org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot ++ } ++ // DivineMC end - Parallel world ticking 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 21d41b477cc0e8d2476d1e3141bdf23d0c06f3e0..307cfbc754aa933d7bec51ac8b1b8ee46867fb41 100644 +index 21d41b477cc0e8d2476d1e3141bdf23d0c06f3e0..195d9dc696a9a7da0bb041612b73c0bbacf2919e 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -432,6 +432,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc return this.viewDistanceHolder; } // Paper end - rewrite chunk system -+ public boolean hasTickedAtLeastOnceInNewWorld = false; // DivineMC - parallel world ticking ++ public boolean hasTickedAtLeastOnceInNewWorld = false; // DivineMC - Parallel world ticking public ServerPlayer(MinecraftServer server, ServerLevel level, GameProfile gameProfile, ClientInformation clientInformation) { super(level, level.getSharedSpawnPos(), level.getSharedSpawnAngle(), gameProfile); @@ -524,7 +538,7 @@ index 21d41b477cc0e8d2476d1e3141bdf23d0c06f3e0..307cfbc754aa933d7bec51ac8b1b8ee4 @Override public void tick() { -+ hasTickedAtLeastOnceInNewWorld = true; // DivineMC - parallel world ticking ++ hasTickedAtLeastOnceInNewWorld = true; // DivineMC - Parallel world ticking // CraftBukkit start if (this.joining) { this.joining = false; @@ -532,7 +546,7 @@ index 21d41b477cc0e8d2476d1e3141bdf23d0c06f3e0..307cfbc754aa933d7bec51ac8b1b8ee4 return this; } else { // CraftBukkit start -+ 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()); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) 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()); // DivineMC - Parallel world ticking (additional concurrency issues logs) /* this.isChangingDimension = true; LevelData levelData = level.getLevelData(); @@ -540,12 +554,12 @@ index 21d41b477cc0e8d2476d1e3141bdf23d0c06f3e0..307cfbc754aa933d7bec51ac8b1b8ee4 return OptionalInt.empty(); } else { // CraftBukkit start -+ // DivineMC start - parallel world ticking ++ // DivineMC start - Parallel world ticking + if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && !hasTickedAtLeastOnceInNewWorld) { + MinecraftServer.LOGGER.warn("Ignoring request to open container {} because we haven't ticked in the current world yet!", abstractContainerMenu, new Throwable()); + return OptionalInt.empty(); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking this.containerMenu = abstractContainerMenu; // Moved up if (!this.isImmobile()) this.connection @@ -553,23 +567,23 @@ index 21d41b477cc0e8d2476d1e3141bdf23d0c06f3e0..307cfbc754aa933d7bec51ac8b1b8ee4 } @Override public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ // DivineMC start - parallel world ticking (debugging) ++ // DivineMC start - Parallel world ticking (debugging) + if (org.bxteam.divinemc.DivineConfig.logContainerCreationStacktraces) { + MinecraftServer.LOGGER.warn("Closing {} inventory that was created at", this.getBukkitEntity().getName(), this.containerMenu.containerCreationStacktrace); + } -+ // DivineMC end - parallel world ticking (debugging) ++ // DivineMC 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 6f66c5a93383b2897425e117c32add9a34054add..3d8c1c5aa922ec0417388a1ff27d423cdb6d1351 100644 +index 6f66c5a93383b2897425e117c32add9a34054add..5ff0ce34cfacb745748d3dc627127842ac1df9fa 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java @@ -150,6 +150,7 @@ public abstract class PlayerList { abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot place new player off-main"); // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot place new player off-main"); // DivineMC - Parallel world ticking player.isRealPlayer = true; // Paper player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed GameProfile gameProfile = player.getGameProfile(); @@ -577,14 +591,14 @@ index 6f66c5a93383b2897425e117c32add9a34054add..3d8c1c5aa922ec0417388a1ff27d423c 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) { -+ // DivineMC start - parallel world ticking (additional concurrency issues logs) ++ // DivineMC start - Parallel world ticking (additional concurrency issues logs) + if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { + if (location != null) + 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()); + } -+ // DivineMC end - parallel world ticking (additional concurrency issues logs) ++ // DivineMC end - Parallel world ticking (additional concurrency issues logs) this.players.remove(player); this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot player.serverLevel().removePlayerImmediately(player, reason); @@ -592,74 +606,320 @@ index 6f66c5a93383b2897425e117c32add9a34054add..3d8c1c5aa922ec0417388a1ff27d423c ServerPlayer serverPlayer = player; Level fromWorld = player.level(); player.wonGame = false; -+ serverPlayer.hasTickedAtLeastOnceInNewWorld = false; // DivineMC - parallel world ticking ++ serverPlayer.hasTickedAtLeastOnceInNewWorld = false; // DivineMC - Parallel world ticking // CraftBukkit end 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 4c4bed85db28d92ca55593a19ac23616619e4bd1..258cb45f1f959b75c1bcdb130811af2f8fddf07d 100644 +index 4c4bed85db28d92ca55593a19ac23616619e4bd1..7e29f1f1972f2fb4f9a779653467bc85ce37c7bc 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -848,7 +848,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - // CraftBukkit start - public void postTick() { - // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle -- if (!(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities -+ if (false && !(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities // DivineMC - parallel world ticking - this.handlePortal(); - } - } -@@ -3851,6 +3851,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3314,14 +3314,34 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + if (this.portalProcess != null) { + if (this.portalProcess.processPortalTeleportation(serverLevel, this, this.canUsePortal(false))) { + this.setPortalCooldown(); +- TeleportTransition portalDestination = this.portalProcess.getPortalDestination(serverLevel, this); +- if (portalDestination != null) { +- ServerLevel level = portalDestination.newLevel(); +- if (this instanceof ServerPlayer // CraftBukkit - always call event for players +- || (level != null && (level.dimension() == serverLevel.dimension() || this.canTeleport(serverLevel, level)))) { // CraftBukkit +- this.teleport(portalDestination); ++ // DivineMC start - Parallel world ticking ++ java.util.function.Consumer portalEntityTask = entity -> { ++ assert entity.portalProcess != null; ++ ++ if (entity.portalProcess.isParallelCancelledByPlugin()) { ++ entity.portalProcess = null; ++ return; ++ } ++ ++ TeleportTransition portalDestination = entity.portalProcess.getPortalDestination(serverLevel, entity); ++ if (portalDestination != null) { ++ ServerLevel level = portalDestination.newLevel(); ++ if (entity instanceof ServerPlayer // CraftBukkit - always call event for players ++ || (level != null && (level.dimension() == serverLevel.dimension() || entity.canTeleport(serverLevel, level)))) { // CraftBukkit ++ entity.teleport(portalDestination); ++ } + } ++ if (this.portalProcess != null) ++ entity.portalProcess.confirmParallelAsHandled(); ++ }; ++ ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { ++ this.portalProcess.setParallelAsScheduled(); ++ this.getBukkitEntity().taskScheduler.schedule(portalEntityTask, entity -> {}, 0); ++ } else { ++ portalEntityTask.accept(this); + } ++ // DivineMC end - Parallel world ticking + } else if (this.portalProcess.hasExpired()) { + this.portalProcess = null; + } +@@ -3851,6 +3871,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } private Entity teleportCrossDimension(ServerLevel level, TeleportTransition teleportTransition) { -+ 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()); // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) 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()); // DivineMC - Parallel world ticking 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..be357d9e3c5327ceec12c31830551a564c8cea1b 100644 +--- a/net/minecraft/world/entity/PortalProcessor.java ++++ b/net/minecraft/world/entity/PortalProcessor.java +@@ -11,6 +11,7 @@ public class PortalProcessor { + private BlockPos entryPosition; + private int portalTime; + private boolean insidePortalThisTick; ++ private org.bxteam.divinemc.util.PWTTeleportState teleportState = org.bxteam.divinemc.util.PWTTeleportState.INACTIVE; // DivineMC - Parallel world ticking + + public PortalProcessor(Portal portal, BlockPos entryPosition) { + this.portal = portal; +@@ -19,6 +20,7 @@ public class PortalProcessor { + } + + public boolean processPortalTeleportation(ServerLevel level, Entity entity, boolean canChangeDimensions) { ++ if (this.isParallelTeleportScheduled()) return false; // DivineMC - Parallel world ticking + if (!this.insidePortalThisTick) { + this.decayTick(); + return false; +@@ -42,7 +44,7 @@ public class PortalProcessor { + } + + public boolean hasExpired() { +- return this.portalTime <= 0; ++ return !this.isParallelTeleportScheduled() && this.portalTime <= 0; // DivineMC - Parallel world ticking + } + + public BlockPos getEntryPosition() { +@@ -68,4 +70,30 @@ public class PortalProcessor { + public boolean isSamePortal(Portal portal) { + return this.portal == portal; + } ++ ++ // DivineMC start - Parallel world ticking ++ public boolean isParallelTeleportPending() { ++ return this.teleportState == org.bxteam.divinemc.util.PWTTeleportState.PENDING; ++ } ++ ++ public boolean isParallelTeleportScheduled() { ++ return this.teleportState != org.bxteam.divinemc.util.PWTTeleportState.INACTIVE; ++ } ++ ++ public boolean isParallelCancelledByPlugin() { ++ return this.teleportState == org.bxteam.divinemc.util.PWTTeleportState.CANCELLED; ++ } ++ ++ public void setParallelAsScheduled() { ++ this.teleportState = org.bxteam.divinemc.util.PWTTeleportState.PENDING; ++ } ++ ++ public void confirmParallelAsHandled() { ++ this.teleportState = org.bxteam.divinemc.util.PWTTeleportState.INACTIVE; ++ } ++ ++ public void setParallelAsCancelled() { ++ this.teleportState = org.bxteam.divinemc.util.PWTTeleportState.CANCELLED; ++ } ++ // DivineMC end - Parallel world ticking + } +diff --git a/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java b/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java +index 3614551856c594f3c0cfee984fcf03fad672b007..6add256046e392d8eb797e3fa9d1cbe7cca575df 100644 +--- a/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java ++++ b/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java +@@ -46,12 +46,22 @@ public class GoToPotentialJobSite extends Behavior { + BlockPos blockPos = globalPos.pos(); + ServerLevel level1 = level.getServer().getLevel(globalPos.dimension()); + if (level1 != null) { +- PoiManager poiManager = level1.getPoiManager(); +- if (poiManager.exists(blockPos, holder -> true)) { +- poiManager.release(blockPos); +- } ++ // DivineMC start - Parallel world ticking ++ Runnable releasePoiTask = () -> { ++ PoiManager poiManager = level1.getPoiManager(); ++ if (poiManager.exists(blockPos, holder -> true)) { ++ poiManager.release(blockPos); ++ } ++ ++ DebugPackets.sendPoiTicketCountPacket(level, blockPos); ++ }; + +- DebugPackets.sendPoiTicketCountPacket(level, blockPos); ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { ++ level.moonrise$getChunkTaskScheduler().scheduleChunkTask(0, 0, releasePoiTask, ca.spottedleaf.concurrentutil.util.Priority.BLOCKING); ++ } else { ++ releasePoiTask.run(); ++ } ++ // DivineMC end - Parallel world ticking + } + }); + 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 fec90e482c8935dfca609bbf90e67f86a1586221..4ee1791f293ba3abdbfe69824b85566fd9a36586 100644 +--- a/net/minecraft/world/entity/npc/Villager.java ++++ b/net/minecraft/world/entity/npc/Villager.java +@@ -803,13 +803,24 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.brain.getMemory(moduleType).ifPresent(globalPos -> { + ServerLevel level = server.getLevel(globalPos.dimension()); + if (level != null) { +- PoiManager poiManager = level.getPoiManager(); +- Optional> type = poiManager.getType(globalPos.pos()); +- BiPredicate> biPredicate = POI_MEMORIES.get(moduleType); +- if (type.isPresent() && biPredicate.test(this, type.get())) { +- poiManager.release(globalPos.pos()); +- DebugPackets.sendPoiTicketCountPacket(level, globalPos.pos()); ++ // DivineMC start - Parallel world ticking ++ Runnable releasePoiTask = () -> { ++ PoiManager poiManager = level.getPoiManager(); ++ Optional> type = poiManager.getType(globalPos.pos()); ++ BiPredicate> biPredicate = POI_MEMORIES.get(moduleType); ++ if (type.isPresent() && biPredicate.test(this, type.get())) { ++ poiManager.release(globalPos.pos()); ++ DebugPackets.sendPoiTicketCountPacket(level, globalPos.pos()); ++ } ++ }; ++ ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { ++ level.moonrise$getChunkTaskScheduler().scheduleChunkTask(0, 0, releasePoiTask, ca.spottedleaf.concurrentutil.util.Priority.BLOCKING); ++ } ++ else { ++ releasePoiTask.run(); + } ++ // DivineMC end - Parallel world ticking + } + }); + } +diff --git a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +index d212f57c8c0b2086f567fd30237b110203d9e8cb..d59bdab65c034bab443ea9448930fdff85a85392 100644 +--- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java ++++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +@@ -126,40 +126,50 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { + Vec3 vec3 = this.oldPosition(); + if (owner instanceof ServerPlayer serverPlayer) { + if (serverPlayer.connection.isAcceptingMessages()) { +- // CraftBukkit start +- ServerPlayer serverPlayer1 = serverPlayer.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) { +- this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.HIT); +- return; +- } +- // CraftBukkit end +- if (this.random.nextFloat() < serverLevel.purpurConfig.enderPearlEndermiteChance && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { // Purpur - Configurable Ender Pearl RNG +- Endermite endermite = EntityType.ENDERMITE.create(serverLevel, EntitySpawnReason.TRIGGERED); +- if (endermite != null) { +- 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); ++ // DivineMC start - Parallel world ticking ++ java.util.function.Consumer teleportPlayerCrossDimensionTask = taskServerPlayer -> { ++ // CraftBukkit start ++ ServerPlayer serverPlayer1 = serverPlayer.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) { ++ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.HIT); ++ return; ++ } ++ // CraftBukkit end ++ if (this.random.nextFloat() < serverLevel.purpurConfig.enderPearlEndermiteChance && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { // Purpur - Configurable Ender Pearl RNG ++ Endermite endermite = EntityType.ENDERMITE.create(serverLevel, EntitySpawnReason.TRIGGERED); ++ if (endermite != null) { ++ 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); ++ } + } +- } + +- if (this.isOnPortalCooldown()) { +- owner.setPortalCooldown(); +- } ++ if (this.isOnPortalCooldown()) { ++ owner.setPortalCooldown(); ++ } + +- // CraftBukkit start - moved up +- // ServerPlayer serverPlayer1 = serverPlayer.teleport( +- // new TeleportTransition( +- // serverLevel, vec3, Vec3.ZERO, 0.0F, 0.0F, Relative.union(Relative.ROTATION, Relative.DELTA), TeleportTransition.DO_NOTHING +- // ) +- // ); +- // CraftBukkit end - moved up +- if (serverPlayer1 != null) { +- serverPlayer1.resetFallDistance(); +- serverPlayer1.resetCurrentImpulseContext(); +- serverPlayer1.hurtServer(serverPlayer.serverLevel(), this.damageSources().enderPearl().eventEntityDamager(this), this.level().purpurConfig.enderPearlDamage); // CraftBukkit // Paper - fix DamageSource API // Purpur - Configurable Ender Pearl damage +- } ++ // CraftBukkit start - moved up ++ // ServerPlayer serverPlayer1 = serverPlayer.teleport( ++ // new TeleportTransition( ++ // serverLevel, vec3, Vec3.ZERO, 0.0F, 0.0F, Relative.union(Relative.ROTATION, Relative.DELTA), TeleportTransition.DO_NOTHING ++ // ) ++ // ); ++ // CraftBukkit end - moved up ++ if (serverPlayer1 != null) { ++ serverPlayer1.resetFallDistance(); ++ serverPlayer1.resetCurrentImpulseContext(); ++ serverPlayer1.hurtServer(serverPlayer.serverLevel(), this.damageSources().enderPearl().eventEntityDamager(this), this.level().purpurConfig.enderPearlDamage); // CraftBukkit // Paper - fix DamageSource API // Purpur - Configurable Ender Pearl damage ++ } + +- this.playSound(serverLevel, vec3); ++ this.playSound(serverLevel, vec3); ++ }; ++ ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { ++ serverPlayer.getBukkitEntity().taskScheduler.schedule(teleportPlayerCrossDimensionTask, entity -> {}, 0); ++ } else { ++ teleportPlayerCrossDimensionTask.accept(serverPlayer); ++ } ++ // DivineMC end - Parallel world ticking + } + } else { + Entity entity = owner.teleport( diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index e6419715fab462b12790ecb175ce1e1a1fceed8f..40040b1e78765a4a686f9e430d16361c8c31fb14 100644 +index e6419715fab462b12790ecb175ce1e1a1fceed8f..b03068bb94c785db51da660361ce28b9f4b45898 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -92,8 +92,14 @@ public abstract class AbstractContainerMenu { } public void startOpen() {} // CraftBukkit end -+ public Throwable containerCreationStacktrace; // DivineMC - parallel world ticking ++ public Throwable containerCreationStacktrace; // DivineMC - Parallel world ticking protected AbstractContainerMenu(@Nullable MenuType menuType, int containerId) { -+ // DivineMC start - parallel world ticking (debugging) ++ // DivineMC start - Parallel world ticking (debugging) + if (org.bxteam.divinemc.DivineConfig.logContainerCreationStacktraces) { + this.containerCreationStacktrace = new Throwable(); + } -+ // DivineMC start - parallel world ticking (debugging) ++ // DivineMC start - 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 264b713e8b7c3d5f7d8e1facc90a60349f2cf414..f461b060e03edf4102290a424ab008b88d80bdc2 100644 +index 264b713e8b7c3d5f7d8e1facc90a60349f2cf414..596abdcda01e412d995d150ca9d056a5278ea691 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java -@@ -407,8 +407,8 @@ public final class ItemStack implements DataComponentHolder { +@@ -407,8 +407,10 @@ public final class ItemStack implements DataComponentHolder { if (interactionResult.consumesAction() && serverLevel.captureTreeGeneration && !serverLevel.capturedBlockStates.isEmpty()) { serverLevel.captureTreeGeneration = false; 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.treeTypeRT.get(); // DivineMC - parallel world ticking -+ net.minecraft.world.level.block.SaplingBlock.treeTypeRT.set(null); // DivineMC - parallel world ticking ++ // DivineMC start - Parallel world ticking ++ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.getTreeTypeTL(); ++ net.minecraft.world.level.block.SaplingBlock.setTreeTypeTL(null); ++ // DivineMC end - Parallel world ticking 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 0c58919e8242317ba276e103b81d07006c41deca..9608aa7231e1e19ac34f7fcf6cc4051da01f2f3e 100644 +index 0c58919e8242317ba276e103b81d07006c41deca..788e83078e9e430b84bf5dc9df877eb7ef46543b 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -170,6 +170,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 public final org.bxteam.divinemc.DivineWorldConfig divineConfig; // DivineMC - Configuration -+ public io.papermc.paper.redstone.RedstoneWireTurbo turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((net.minecraft.world.level.block.RedStoneWireBlock) net.minecraft.world.level.block.Blocks.REDSTONE_WIRE); // DivineMC - parallel world ticking (moved to world) ++ public io.papermc.paper.redstone.RedstoneWireTurbo turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((net.minecraft.world.level.block.RedStoneWireBlock) net.minecraft.world.level.block.Blocks.REDSTONE_WIRE); // DivineMC - Parallel world ticking (moved to world) public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; private org.spigotmc.TickLimiter tileLimiter; @@ -667,7 +927,7 @@ index 0c58919e8242317ba276e103b81d07006c41deca..9608aa7231e1e19ac34f7fcf6cc4051d @Override public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, pos, "Updating block asynchronously"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, pos, "Updating block asynchronously"); // DivineMC - 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 @@ -677,50 +937,55 @@ index 0c58919e8242317ba276e103b81d07006c41deca..9608aa7231e1e19ac34f7fcf6cc4051d tickingBlockEntity.tick(); - // Paper start - rewrite chunk system - if ((++tickedEntities & 7) == 0) { +- ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)(Level)(Object)this).moonrise$midTickTasks(); + // DivineMC start - Parallel world ticking + ++tickedEntities; + if (!org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && (tickedEntities & 7) == 0) { - ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)(Level)(Object)this).moonrise$midTickTasks(); ++ this.moonrise$midTickTasks(); } - // Paper end - rewrite chunk system + // DivineMC end - Parallel world ticking } } this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 -@@ -1553,7 +1556,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1553,7 +1556,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); // Paper end - Prevent block entity and entity crashes } - this.moonrise$midTickTasks(); // Paper - rewrite chunk system -+ // this.moonrise$midTickTasks(); // Paper - rewrite chunk system // DivineMC - Parallel world ticking - commented out ++ // DivineMC start - Parallel world ticking ++ if (!org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { ++ this.moonrise$midTickTasks(); // Paper - rewrite chunk system ++ } ++ // DivineMC end - Parallel world ticking } // Paper start - Option to prevent armor stands from doing entity lookups -@@ -1696,6 +1699,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1696,6 +1703,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Nullable public BlockEntity getBlockEntity(BlockPos pos, boolean validate) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThreadOrAsyncThread((ServerLevel) this, "Cannot read world asynchronously"); // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThreadOrAsyncThread((ServerLevel) this, "Cannot read world asynchronously"); // DivineMC - 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) { -@@ -1713,6 +1717,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1713,6 +1721,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } public void setBlockEntity(BlockEntity blockEntity) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel) this, "Cannot modify world asynchronously"); // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel) this, "Cannot modify world asynchronously"); // DivineMC - Parallel world ticking BlockPos blockPos = blockEntity.getBlockPos(); if (!this.isOutsideBuildHeight(blockPos)) { // CraftBukkit start -@@ -1797,6 +1802,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1797,6 +1806,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public List getEntities(@Nullable Entity entity, AABB boundingBox, Predicate predicate) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, boundingBox, "Cannot getEntities asynchronously"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, boundingBox, "Cannot getEntities asynchronously"); // DivineMC - Parallel world ticking (additional concurrency issues logs) List list = Lists.newArrayList(); // Paper start - rewrite chunk system -@@ -2106,8 +2112,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -2106,8 +2116,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) { @@ -739,29 +1004,46 @@ index 0c58919e8242317ba276e103b81d07006c41deca..9608aa7231e1e19ac34f7fcf6cc4051d } diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java -index e0a4d41e5bcf144ea4c10d6f633c3a95ed2c5aec..274f36581e7040c67bf8649258660228a3e8cce0 100644 +index e0a4d41e5bcf144ea4c10d6f633c3a95ed2c5aec..12ead3dc17828558b2e6b67a5f306a5948f7b2cf 100644 --- a/net/minecraft/world/level/block/DispenserBlock.java +++ b/net/minecraft/world/level/block/DispenserBlock.java -@@ -50,7 +50,7 @@ public class DispenserBlock extends BaseEntityBlock { - private static final DefaultDispenseItemBehavior DEFAULT_BEHAVIOR = new DefaultDispenseItemBehavior(); +@@ -51,6 +51,25 @@ 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 eventFired = ThreadLocal.withInitial(() -> Boolean.FALSE); // DivineMC - parallel world ticking + public static boolean eventFired = false; // CraftBukkit ++ // DivineMC start - Parallel world ticking ++ public static ThreadLocal eventFiredTL = ThreadLocal.withInitial(() -> Boolean.FALSE); ++ ++ public static boolean getEventFiredTL() { ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && eventFiredTL.get()) return true; ++ ++ synchronized (DispenserBlock.class) { ++ return eventFired; ++ } ++ } ++ ++ public static void setEventFiredTL(boolean value) { ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) eventFiredTL.set(value); ++ ++ synchronized (DispenserBlock.class) { ++ eventFired = value; ++ } ++ } ++ // DivineMC end - Parallel world ticking @Override public MapCodec codec() { -@@ -96,7 +96,7 @@ public class DispenserBlock extends BaseEntityBlock { +@@ -96,7 +115,7 @@ public class DispenserBlock extends BaseEntityBlock { DispenseItemBehavior dispenseMethod = this.getDispenseMethod(level, item); 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.eventFired.set(Boolean.FALSE); // CraftBukkit - reset event status // DivineMC - parallel world ticking ++ DispenserBlock.setEventFiredTL(Boolean.FALSE); // CraftBukkit - reset event status // DivineMC - Parallel world ticking 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..22c527a7b44a434b66a2217ed88eca79703b2036 100644 +index 85f0eac75784565c658c5178c544f969db3d6f54..fc900a7c382f825110c561070155c1f6451557ed 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 { @@ -769,15 +1051,15 @@ index 85f0eac75784565c658c5178c544f969db3d6f54..22c527a7b44a434b66a2217ed88eca79 .map((value) -> { if (this == Blocks.WARPED_FUNGUS) { - SaplingBlock.treeType = org.bukkit.TreeType.WARPED_FUNGUS; -+ SaplingBlock.treeTypeRT.set(org.bukkit.TreeType.WARPED_FUNGUS); // DivineMC - parallel world ticking ++ SaplingBlock.setTreeTypeTL(org.bukkit.TreeType.WARPED_FUNGUS); // DivineMC - Parallel world ticking } else if (this == Blocks.CRIMSON_FUNGUS) { - SaplingBlock.treeType = org.bukkit.TreeType.CRIMSON_FUNGUS; -+ SaplingBlock.treeTypeRT.set(org.bukkit.TreeType.CRIMSON_FUNGUS); // DivineMC - parallel world ticking ++ SaplingBlock.setTreeTypeTL(org.bukkit.TreeType.CRIMSON_FUNGUS); // DivineMC - Parallel world ticking } return value; }) diff --git a/net/minecraft/world/level/block/MushroomBlock.java b/net/minecraft/world/level/block/MushroomBlock.java -index 904369f4d7db41026183f2de7c96c2f0f4dc204d..1a3f07834fd1483aa77f7733512908b62583edda 100644 +index 904369f4d7db41026183f2de7c96c2f0f4dc204d..371334bc3a1ea505b3293f13542aef4cf8f2a2d2 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 { @@ -785,7 +1067,7 @@ index 904369f4d7db41026183f2de7c96c2f0f4dc204d..1a3f07834fd1483aa77f7733512908b6 } else { level.removeBlock(pos, false); - SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? org.bukkit.TreeType.BROWN_MUSHROOM : org.bukkit.TreeType.RED_MUSHROOM; // CraftBukkit -+ SaplingBlock.treeTypeRT.set((this == Blocks.BROWN_MUSHROOM) ? org.bukkit.TreeType.BROWN_MUSHROOM : org.bukkit.TreeType.RED_MUSHROOM); // CraftBukkit // DivineMC - parallel world ticking ++ SaplingBlock.setTreeTypeTL((this == Blocks.BROWN_MUSHROOM) ? org.bukkit.TreeType.BROWN_MUSHROOM : org.bukkit.TreeType.RED_MUSHROOM); // CraftBukkit // DivineMC - Parallel world ticking if (optional.get().value().place(level, level.getChunkSource().getGenerator(), random, pos)) { return true; } else { @@ -824,50 +1106,76 @@ index 12c9d60314c99fb65e640d255a2d0c6b7790ad4d..4293c5f11a17500353b63cad399727ec } } diff --git a/net/minecraft/world/level/block/SaplingBlock.java b/net/minecraft/world/level/block/SaplingBlock.java -index e014f052e9b0f5ca6b28044e2389782b7d0e0cb8..d10f8909fcfa930c726f2620e3ffc912baa40be7 100644 +index e014f052e9b0f5ca6b28044e2389782b7d0e0cb8..4ad0e278a348407beed1ec4381bfeacf4de32a0d 100644 --- a/net/minecraft/world/level/block/SaplingBlock.java +++ b/net/minecraft/world/level/block/SaplingBlock.java -@@ -26,7 +26,7 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { - protected static final float AABB_OFFSET = 6.0F; +@@ -27,6 +27,26 @@ 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<>(); // CraftBukkit // DivineMC - parallel world ticking (from Folia) + public static org.bukkit.TreeType treeType; // CraftBukkit ++ // DivineMC start - Parallel world ticking ++ public static final ThreadLocal treeTypeTL = new ThreadLocal<>(); ++ ++ public static org.bukkit.TreeType getTreeTypeTL() { ++ org.bukkit.TreeType treeTypeRTCopy; ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && (treeTypeRTCopy = treeTypeTL.get()) != null) return treeTypeRTCopy; ++ ++ synchronized (SaplingBlock.class) { ++ return treeType; ++ } ++ } ++ ++ public static void setTreeTypeTL(org.bukkit.TreeType value) { ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) treeTypeTL.set(value); ++ ++ synchronized (SaplingBlock.class) { ++ treeType = value; ++ } ++ } ++ // DivineMC end - Parallel world ticking @Override public MapCodec codec() { -@@ -63,8 +63,10 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { +@@ -63,14 +83,16 @@ 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; -+ // DivineMC start - parallel world ticking -+ org.bukkit.TreeType treeType = SaplingBlock.treeTypeRT.get(); -+ SaplingBlock.treeTypeRT.set(null); -+ // DivineMC end - parallel world ticking ++ // DivineMC start - Parallel world ticking ++ org.bukkit.TreeType treeTypeLocal = SaplingBlock.getTreeTypeTL(); ++ SaplingBlock.setTreeTypeTL(null); ++ // DivineMC end - Parallel world ticking 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) { // DivineMC - Parallel world ticking ++ event = new org.bukkit.event.world.StructureGrowEvent(location, treeTypeLocal, false, null, blocks); // DivineMC - Parallel world ticking + 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..b761f12131699bdd075a39f19d96cb70ae8f4eda 100644 +index 26db603ed681a6c302596627d4dd5bf8a9bafc4e..20e8155c0c5f4bd60344c1bbd15f7555ad9ef554 100644 --- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java @@ -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) { -+ // DivineMC start - parallel world ticking ++ // DivineMC start - Parallel world ticking + if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != serverPlayer.serverLevel()) { + net.minecraft.server.MinecraftServer.LOGGER.warn("Player {} ({}) attempted to open a BlockEntity @ {} {}, {}, {} while they were in a different world {} than the block themselves!", serverPlayer.getScoreboardName(), serverPlayer.getStringUUID(), blockEntity.getLevel().getWorld().getName(), blockEntity.getBlockPos().getX(), blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getZ(), serverPlayer.level().getWorld().getName()); + return false; + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking 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 1638eccef431fb68775af624110f1968f0c6dabd..8f3eb265adcacf6d4f71db9a298ba8a7ce99c941 100644 +index 1638eccef431fb68775af624110f1968f0c6dabd..491ac8be8fdaa573fe1b3a234a14110d89b43345 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 @@ -875,22 +1183,22 @@ index 1638eccef431fb68775af624110f1968f0c6dabd..8f3eb265adcacf6d4f71db9a298ba8a7 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.sourceBlockOverrideRT.set(pos); // DivineMC - parallel world ticking // 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.setSourceBlockOverrideTL(pos); // DivineMC - Parallel world ticking // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. sculkCatalyst.catalystListener.getSculkSpreader().updateCursors(level, pos, level.getRandom(), true); - org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverrideRT.set(null); // DivineMC - parallel world ticking // CraftBukkit ++ org.bukkit.craftbukkit.event.CraftEventFactory.setSourceBlockOverrideTL(null); // DivineMC - Parallel world ticking // CraftBukkit } @Override diff --git a/net/minecraft/world/level/block/grower/TreeGrower.java b/net/minecraft/world/level/block/grower/TreeGrower.java -index cf7311c507de09a8f89934e430b2201e8bdffe51..30bd72ad2f66616a89b78fb0677109b8341eb132 100644 +index cf7311c507de09a8f89934e430b2201e8bdffe51..e76cb020471f28c29f1b24addb5cd101ddc9630f 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 { // CraftBukkit start private void setTreeType(Holder> holder) { ResourceKey> treeFeature = holder.unwrapKey().get(); -+ // DivineMC start - parallel world ticking ++ // DivineMC start - Parallel world ticking + org.bukkit.TreeType treeType; if (treeFeature == TreeFeatures.OAK || treeFeature == TreeFeatures.OAK_BEES_005) { - net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.TREE; @@ -964,60 +1272,59 @@ index cf7311c507de09a8f89934e430b2201e8bdffe51..30bd72ad2f66616a89b78fb0677109b8 } else { throw new IllegalArgumentException("Unknown tree generator " + treeFeature); } -+ net.minecraft.world.level.block.SaplingBlock.treeTypeRT.set(treeType); -+ // DivineMC end - parallel world ticking ++ net.minecraft.world.level.block.SaplingBlock.setTreeTypeTL(treeType); ++ // DivineMC 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 e3d71604c161373ef44164606602290af1bd1cb0..ba88a3aed79543f69a5bf30cfd03f30983d229cf 100644 +index e3d71604c161373ef44164606602290af1bd1cb0..b245f594ff91e2d29c83f56b9ed5165f37387e7e 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java @@ -365,6 +365,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Nullable public BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving, boolean doPlace) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, pos, "Updating block asynchronously"); // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, pos, "Updating block asynchronously"); // DivineMC - Parallel world ticking // 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 c89701d7bdc9b889038d3c52f2232fb17624b113..3c6ec711bf9a75657c13da647e4ae7947257b627 100644 +index c89701d7bdc9b889038d3c52f2232fb17624b113..018a04674897cfcec0e8de5cb2ab06243a994ae3 100644 --- a/net/minecraft/world/level/entity/EntityTickList.java +++ b/net/minecraft/world/level/entity/EntityTickList.java -@@ -10,17 +10,27 @@ import net.minecraft.world.entity.Entity; +@@ -10,17 +10,26 @@ 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 -+ // DivineMC start - parallel world ticking -+ // Used to track async entity additions/removals/loops ++ // DivineMC start - Parallel world ticking + private final net.minecraft.server.level.ServerLevel serverLevel; + + public EntityTickList(net.minecraft.server.level.ServerLevel serverLevel) { + this.serverLevel = serverLevel; + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking private void ensureActiveIsNotIterated() { // Paper - rewrite chunk system } public void add(Entity entity) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(entity, "Asynchronous entity ticklist addition"); // Paper // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(entity, "Asynchronous entity ticklist addition"); // Paper // DivineMC - Parallel world ticking this.ensureActiveIsNotIterated(); this.entities.add(entity); // Paper - rewrite chunk system } public void remove(Entity entity) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(entity, "Asynchronous entity ticklist removal"); // Paper // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(entity, "Asynchronous entity ticklist removal"); // Paper // DivineMC - Parallel world ticking this.ensureActiveIsNotIterated(); this.entities.remove(entity); // Paper - rewrite chunk system } -@@ -30,6 +40,7 @@ public class EntityTickList { +@@ -30,6 +39,7 @@ public class EntityTickList { } public void forEach(Consumer entity) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverLevel, "Asynchronous entity ticklist iteration"); // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverLevel, "Asynchronous entity ticklist iteration"); // DivineMC - Parallel world ticking // 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/divinemc-server/minecraft-patches/features/0010-Chunk-System-Optimizations.patch b/divinemc-server/minecraft-patches/features/0010-Chunk-System-Optimizations.patch index 5c15062..2002671 100644 --- a/divinemc-server/minecraft-patches/features/0010-Chunk-System-Optimizations.patch +++ b/divinemc-server/minecraft-patches/features/0010-Chunk-System-Optimizations.patch @@ -273,7 +273,7 @@ index 8ef5a1aaac9c27873ce746eb281f77bb318a3c69..76b8d42ae530b59cdaba0583365a557d } } diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..f4fcc3b2676b17ebc276dcb177285f18a0cdfe99 100644 +index 5683395e09a65b1b39748df5152fffef630ac083..6aea99f071bd1a6a1ea9507bb70739d56318eb22 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java @@ -71,36 +71,49 @@ public final class ChunkHolderManager { @@ -464,7 +464,7 @@ index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..f4fcc3b2676b17ebc276dcb177285f18 // removed concurrently @@ -1033,7 +1046,7 @@ public final class ChunkHolderManager { } - if (!TickThread.isTickThreadFor(world)) { // DivineMC - parallel world ticking + if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && !TickThread.isTickThreadFor(world)) { // DivineMC - Parallel world ticking this.taskScheduler.scheduleChunkTask(() -> { - final ArrayDeque pendingFullLoadUpdate = ChunkHolderManager.this.pendingFullLoadUpdate; + final java.util.Deque pendingFullLoadUpdate = ChunkHolderManager.this.getData().pendingFullLoadUpdate; // DivineMC - Chunk System optimization @@ -491,7 +491,7 @@ index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..f4fcc3b2676b17ebc276dcb177285f18 PlatformHooks.get().onChunkHolderDelete(this.world, holder.vanillaChunkHolder); this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ)); } -@@ -1208,6 +1221,27 @@ public final class ChunkHolderManager { +@@ -1214,6 +1227,27 @@ public final class ChunkHolderManager { } } @@ -519,7 +519,7 @@ index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..f4fcc3b2676b17ebc276dcb177285f18 public enum TicketOperationType { ADD, REMOVE, ADD_IF_REMOVED, ADD_AND_REMOVE } -@@ -1381,7 +1415,7 @@ public final class ChunkHolderManager { +@@ -1387,7 +1421,7 @@ public final class ChunkHolderManager { // only call on tick thread private boolean processPendingFullUpdate() { @@ -528,7 +528,7 @@ index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..f4fcc3b2676b17ebc276dcb177285f18 boolean ret = false; -@@ -1417,8 +1451,7 @@ public final class ChunkHolderManager { +@@ -1423,8 +1457,7 @@ public final class ChunkHolderManager { final JsonArray allTicketsJson = new JsonArray(); ret.add("tickets", allTicketsJson); @@ -1092,7 +1092,7 @@ index ab30af9cd58ff7310e05be87b08f42bacf69e11e..ae0e36d198ad8243920c8e8a55c0be49 } diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 8c566a587be3a384979cf10aabd0536c88bf69ac..bab5834741d0f11732ef1d1723868b8701d84961 100644 +index 50ea7f4a0428cbc49fb13a31b1fa643e00ef9434..a70007d324e2169d1b2a1a11046500196b8b5660 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -181,6 +181,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -1101,7 +1101,7 @@ index 8c566a587be3a384979cf10aabd0536c88bf69ac..bab5834741d0f11732ef1d1723868b87 public final net.minecraft.world.level.storage.PrimaryLevelData serverLevelData; // CraftBukkit - type + public final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.LevelHolderData chunkHolderData; // DivineMC - Chunk System optimization private int lastSpawnChunkRadius; - final EntityTickList entityTickList = new EntityTickList(this); // DivineMC - parallel world ticking + final EntityTickList entityTickList = new EntityTickList(this); // DivineMC - Parallel world ticking // Paper - rewrite chunk system @@ -291,6 +292,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } @@ -1121,7 +1121,7 @@ index 8c566a587be3a384979cf10aabd0536c88bf69ac..bab5834741d0f11732ef1d1723868b87 new RegionStorageInfo(levelStorageAccess.getLevelId(), dimension, "entities"), @@ -703,6 +706,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit - this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new org.bxteam.divinemc.server.ServerLevelTickExecutorThreadFactory(getWorld().getName())); // DivineMC - parallel world ticking + this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new org.bxteam.divinemc.server.ServerLevelTickExecutorThreadFactory(getWorld().getName())); // DivineMC - Parallel world ticking this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle + this.chunkSystemPriorities = new org.bxteam.divinemc.server.chunk.PriorityHandler(this); // DivineMC - Chunk System optimizations } @@ -1199,7 +1199,7 @@ index 8c566a587be3a384979cf10aabd0536c88bf69ac..bab5834741d0f11732ef1d1723868b87 } // Paper end - optimise random ticking -@@ -2525,30 +2527,25 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2531,30 +2533,25 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe private boolean isPositionTickingWithEntitiesLoaded(long chunkPos) { // Paper start - rewrite chunk system diff --git a/divinemc-server/minecraft-patches/features/0016-Lag-compensation.patch b/divinemc-server/minecraft-patches/features/0016-Lag-compensation.patch index 78f76a9..b19fcea 100644 --- a/divinemc-server/minecraft-patches/features/0016-Lag-compensation.patch +++ b/divinemc-server/minecraft-patches/features/0016-Lag-compensation.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Lag compensation diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 9f7698f8ce56d5d89cf86f6ea2d5b4d51b18c9a2..11b89a625b942f5f2f882c54dbfc08c16e983425 100644 +index 5a726da8535aa939f043829a3c60fdd9d4ed154a..0aebdd1cb0e1b63ff9a867bdcda7cbdc3c194b56 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -289,6 +289,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function threadFunction) { @@ -25,7 +25,7 @@ index 9f7698f8ce56d5d89cf86f6ea2d5b4d51b18c9a2..11b89a625b942f5f2f882c54dbfc08c1 this.tickCount++; this.tickRateManager.tick(); diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index bab5834741d0f11732ef1d1723868b8701d84961..e034d9f903728cdf7356629694c9f528ba5ebae3 100644 +index a70007d324e2169d1b2a1a11046500196b8b5660..53b606c34f65b80a676ddd26d64028dbdebecb43 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -218,6 +218,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -96,10 +96,10 @@ index 04a1c17a34b495b71eb1b0ccd597cef83480464d..edb128a3f454e7b3009ca360509decd7 protected float getBlockSpeedFactor() { return Mth.lerp((float)this.getAttributeValue(Attributes.MOVEMENT_EFFICIENCY), super.getBlockSpeedFactor(), 1.0F); diff --git a/net/minecraft/world/entity/PortalProcessor.java b/net/minecraft/world/entity/PortalProcessor.java -index 88b07fbb96b20124777889830afa480673629d43..d2661ea79536010414f77256332f214d19106dd9 100644 +index be357d9e3c5327ceec12c31830551a564c8cea1b..f77da420bc88df6ec304086fc1eba0690fe278b1 100644 --- a/net/minecraft/world/entity/PortalProcessor.java +++ b/net/minecraft/world/entity/PortalProcessor.java -@@ -24,10 +24,20 @@ public class PortalProcessor { +@@ -26,10 +26,20 @@ public class PortalProcessor { return false; } else { this.insidePortalThisTick = false; @@ -244,7 +244,7 @@ index b631e35e965b1914cdeeddab8bd6bdbfd2465079..bb7dab597850fba8f0dff4461fc518e0 } diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index ba88a3aed79543f69a5bf30cfd03f30983d229cf..0337f4b9ca3c9c9a1e2a7cf19fcbad5e78b949dc 100644 +index b245f594ff91e2d29c83f56b9ed5165f37387e7e..534384727e852dc8ea822f49f182af49eb3a40c1 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java @@ -907,6 +907,19 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p diff --git a/divinemc-server/minecraft-patches/features/0018-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch b/divinemc-server/minecraft-patches/features/0018-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch index c6598da..553afe2 100644 --- a/divinemc-server/minecraft-patches/features/0018-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch +++ b/divinemc-server/minecraft-patches/features/0018-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch @@ -6,12 +6,12 @@ Subject: [PATCH] Skip EntityScheduler's executeTick checks if there isn't any diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index fc9de137ed1681afd1ef51391cf8f30fd4c61c4b..804de864da13ae0be6a1caee88e95a19e35d08c0 100644 +index df07a4a62bd518f3a13995a3ccc7970c714bad7b..851f943cddad03ae12e1ed85f64072682447a367 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -290,6 +290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // DivineMC - Skip EntityScheduler's executeTick checks if there isn't any tasks to be run diff --git a/divinemc-server/minecraft-patches/features/0028-Configurable-MC-67.patch b/divinemc-server/minecraft-patches/features/0028-Configurable-MC-67.patch index 3dedb7c..0804d57 100644 --- a/divinemc-server/minecraft-patches/features/0028-Configurable-MC-67.patch +++ b/divinemc-server/minecraft-patches/features/0028-Configurable-MC-67.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable MC-67 diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 9c0e539f09bddac018f93d212e3cdbc446f3c672..04ae7636d14a40a427b5d9b746632b0c489efa21 100644 +index 3943789e241f6bb6bc165099b1fb585463cf3d86..07e8bda8eb200d5a7554e0319e1a00dc85454e1a 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -3997,6 +3997,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4017,6 +4017,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public boolean canTeleport(Level fromLevel, Level toLevel) { diff --git a/divinemc-server/minecraft-patches/features/0040-Async-mob-spawning.patch b/divinemc-server/minecraft-patches/features/0040-Async-mob-spawning.patch index b8a725b..ccd9bae 100644 --- a/divinemc-server/minecraft-patches/features/0040-Async-mob-spawning.patch +++ b/divinemc-server/minecraft-patches/features/0040-Async-mob-spawning.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Async mob spawning diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 34bc5d54de26608e64170bd902baa87da137dab6..ec09a21a71b00031efdd2561a14594b4013a2025 100644 +index 51b79f614417f231951e9ba05b29ff0044e081e7..dee93ae262a2a06e68dfe8ae1b7193172c436990 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -291,6 +291,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // DivineMC - Skip EntityScheduler's executeTick checks if there isn't any tasks to be run + public org.bxteam.divinemc.util.AsyncProcessor mobSpawnExecutor = new org.bxteam.divinemc.util.AsyncProcessor("mob_spawning"); // DivineMC - Async mob spawning @@ -173,7 +173,7 @@ index d3f5242fc66529bf3137da4d505a6cf55e749e43..650dfce05bfc68d4c664471b430bd5c0 } } diff --git a/net/minecraft/world/level/entity/EntityTickList.java b/net/minecraft/world/level/entity/EntityTickList.java -index 3c6ec711bf9a75657c13da647e4ae7947257b627..564a00938ef45837b1f8fa90504c54a6dc9bb383 100644 +index 018a04674897cfcec0e8de5cb2ab06243a994ae3..8c1de4654a3a29e75716a03efd476b8a3b7fe9e9 100644 --- a/net/minecraft/world/level/entity/EntityTickList.java +++ b/net/minecraft/world/level/entity/EntityTickList.java @@ -9,7 +9,7 @@ import javax.annotation.Nullable; @@ -182,10 +182,10 @@ index 3c6ec711bf9a75657c13da647e4ae7947257b627..564a00938ef45837b1f8fa90504c54a6 public class EntityTickList { - public final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system + public final java.util.concurrent.ConcurrentLinkedQueue entities = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - rewrite chunk system // DivineMC - Async mob spawning - // DivineMC start - parallel world ticking - // Used to track async entity additions/removals/loops + // DivineMC start - Parallel world ticking private final net.minecraft.server.level.ServerLevel serverLevel; -@@ -44,13 +44,13 @@ public class EntityTickList { + +@@ -43,13 +43,13 @@ public class EntityTickList { // 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/divinemc-server/minecraft-patches/features/0046-Optimize-Raids.patch b/divinemc-server/minecraft-patches/features/0046-Optimize-Raids.patch index a1ad83b..c380052 100644 --- a/divinemc-server/minecraft-patches/features/0046-Optimize-Raids.patch +++ b/divinemc-server/minecraft-patches/features/0046-Optimize-Raids.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Optimize Raids diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 5fe908ce51f95e1eab024dcd41ed108373f17fea..ca740891611fca528b69bc634c4b1f66407eb763 100644 +index 92e35158b68dcb8d1f34fb1b748c12d1d39468c7..c87d1f81bd1b4b9756bd2f4c1dbc58a2dc85c63b 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -219,6 +219,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -17,7 +17,7 @@ index 5fe908ce51f95e1eab024dcd41ed108373f17fea..ca740891611fca528b69bc634c4b1f66 public LevelChunk getChunkIfLoaded(int x, int z) { return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately @@ -714,6 +715,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new org.bxteam.divinemc.server.ServerLevelTickExecutorThreadFactory(getWorld().getName())); // DivineMC - parallel world ticking + this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new org.bxteam.divinemc.server.ServerLevelTickExecutorThreadFactory(getWorld().getName())); // DivineMC - Parallel world ticking this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle this.chunkSystemPriorities = new org.bxteam.divinemc.server.chunk.PriorityHandler(this); // DivineMC - Chunk System optimizations + this.ominousBanner = Objects.requireNonNullElse(this.registryAccess(), net.minecraft.core.RegistryAccess.EMPTY).lookup(Registries.BANNER_PATTERN).map(Raid::getOminousBannerInstance).orElse(null); // DivineMC - Optimize Raids diff --git a/divinemc-server/paper-patches/features/0005-Parallel-world-ticking.patch b/divinemc-server/paper-patches/features/0005-Parallel-world-ticking.patch index 9133d9d..c282fb3 100644 --- a/divinemc-server/paper-patches/features/0005-Parallel-world-ticking.patch +++ b/divinemc-server/paper-patches/features/0005-Parallel-world-ticking.patch @@ -221,89 +221,126 @@ index 69cdd304d255d52c9b7dc9b6a33ffdb630b79abe..c153e79ebe1f2338f0d0ca6b45b39279 } + // DivineMC end - Parallel world ticking } +diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java +index d7398b1ecf2660c29fb7d106b48fe02d3736603e..124715b53090085fc0a9f50bb2df196d31d89bed 100644 +--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java ++++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java +@@ -28,6 +28,7 @@ import java.util.logging.Level; + class PaperEventManager { + + private final Server server; ++ private final org.purpurmc.purpur.util.MinecraftInternalPlugin minecraftInternalPlugin = new org.purpurmc.purpur.util.MinecraftInternalPlugin(); // DivineMC - Parallel world ticking + + public PaperEventManager(Server server) { + this.server = server; +@@ -40,6 +41,12 @@ class PaperEventManager { + if (listeners.length == 0) return; + // DivineMC end - Skip event if no listeners + if (event.isAsynchronous() && this.server.isPrimaryThread()) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && org.bxteam.divinemc.DivineConfig.pwtCompatabilityMode) { ++ org.bukkit.Bukkit.getAsyncScheduler().runNow(minecraftInternalPlugin, task -> event.callEvent()); ++ return; ++ } ++ // DivineMC end - Parallel world ticking + throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously."); + } else if (!event.isAsynchronous() && !this.server.isPrimaryThread() && !this.server.isStopping()) { + throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously."); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index bc2522968205d0c701a2fa23f29565a500881492..fc4fd93632cbeea929ee866673d721cf4ef1f418 100644 +index bc2522968205d0c701a2fa23f29565a500881492..312018206729b623a7c854af1c11a2d0bc888372 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -446,7 +446,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -446,7 +446,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean unloadChunkRequest(int x, int z) { - org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot unload chunk asynchronously"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot unload chunk asynchronously"); ++ } else { ++ org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot ++ } ++ // DivineMC end - Parallel world ticking if (this.isChunkLoaded(x, z)) { this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); } -@@ -471,6 +471,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -471,6 +477,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean refreshChunk(int x, int z) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot refresh chunk asynchronously"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot refresh chunk asynchronously"); // DivineMC - Parallel world ticking ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); if (playerChunk == null) return false; -@@ -521,7 +522,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -521,7 +528,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.getHandle(), x, z, "May not sync load chunks asynchronously"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.getHandle(), x, z, "May not sync load chunks asynchronously"); ++ } else { ++ org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot ++ } ++ // DivineMC end - Parallel world ticking 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 -@@ -749,6 +750,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -749,6 +762,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, loc.getX(), loc.getZ(), "Cannot generate tree asynchronously"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, loc.getX(), loc.getZ(), "Cannot generate tree asynchronously"); // DivineMC - Parallel world ticking this.world.captureTreeGeneration = true; this.world.captureBlockStates = true; boolean grownTree = this.generateTree(loc, type); -@@ -864,6 +866,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -864,6 +878,7 @@ 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 -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot create explosion asynchronously"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot create explosion asynchronously"); // DivineMC - Parallel world ticking net.minecraft.world.level.Level.ExplosionInteraction explosionType; if (!breakBlocks) { explosionType = net.minecraft.world.level.Level.ExplosionInteraction.NONE; // Don't break blocks -@@ -955,6 +958,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -955,6 +970,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getHighestBlockYAt(int x, int z, org.bukkit.HeightMap heightMap) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x >> 4, z >> 4, "Cannot retrieve chunk asynchronously"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x >> 4, z >> 4, "Cannot retrieve chunk asynchronously"); // DivineMC - Parallel world ticking 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); -@@ -985,6 +989,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -985,6 +1001,7 @@ 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); -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, pos, "Cannot retrieve chunk asynchronously"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, pos, "Cannot retrieve chunk asynchronously"); // DivineMC - Parallel world ticking if (this.world.hasChunkAt(pos)) { net.minecraft.world.level.chunk.LevelChunk chunk = this.world.getChunkAt(pos); -@@ -2288,6 +2293,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2288,6 +2305,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void sendGameEvent(Entity sourceEntity, org.bukkit.GameEvent gameEvent, Vector position) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, position.getX(), position.getZ(), "Cannot send game event asynchronously"); // DivineMC - parallel world ticking (additional concurrency issues logs) ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, position.getX(), position.getZ(), "Cannot send game event asynchronously"); // DivineMC - Parallel world ticking 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 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b330450fbc 100644 +index 5cb69d0b822e11a99a96aef4f59986d083b079f4..0e47184336f63123211e24a966908a16aa27d6c6 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -75,6 +75,11 @@ public class CraftBlock implements Block { } public net.minecraft.world.level.block.state.BlockState getNMS() { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking return this.world.getBlockState(this.position); } @@ -311,11 +348,11 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 } private void setData(final byte data, int flag) { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking this.world.setBlock(this.position, CraftMagicNumbers.getBlock(this.getType(), data), flag); } @@ -323,11 +360,11 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 } 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) { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking // 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 @@ -335,33 +372,33 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 @Override public Biome getBiome() { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking return this.getWorld().getBiome(this.getX(), this.getY(), this.getZ()); } // Paper start @Override public Biome getComputedBiome() { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking return this.getWorld().getComputedBiome(this.getX(), this.getY(), this.getZ()); } // Paper end @Override public void setBiome(Biome bio) { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking this.getWorld().setBiome(this.getX(), this.getY(), this.getZ(), bio); } @@ -369,11 +406,11 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 @Override public boolean isBlockFaceIndirectlyPowered(BlockFace face) { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking int power = this.world.getMinecraftWorld().getSignal(this.position, CraftBlock.blockFaceToNotch(face)); Block relative = this.getRelative(face); @@ -381,11 +418,11 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 @Override public int getBlockPower(BlockFace face) { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking int power = 0; net.minecraft.world.level.Level world = this.world.getMinecraftWorld(); int x = this.getX(); @@ -393,11 +430,11 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 @Override public boolean breakNaturally() { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking return this.breakNaturally(null); } @@ -405,11 +442,11 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 @Override public boolean applyBoneMeal(BlockFace face) { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking Direction direction = CraftBlock.blockFaceToNotch(face); BlockFertilizeEvent event = null; ServerLevel world = this.getCraftWorld().getHandle(); @@ -419,10 +456,10 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 if (world.capturedBlockStates.size() > 0) { - TreeType treeType = SaplingBlock.treeType; - SaplingBlock.treeType = null; -+ // DivineMC start - parallel world ticking -+ TreeType treeType = SaplingBlock.treeTypeRT.get(); -+ SaplingBlock.treeTypeRT.set(null); -+ // DivineMC end - parallel world ticking ++ // DivineMC start - Parallel world ticking ++ TreeType treeType = SaplingBlock.getTreeTypeTL(); ++ SaplingBlock.setTreeTypeTL(null); ++ // DivineMC end - Parallel world ticking List blocks = new ArrayList<>(world.capturedBlockStates.values()); world.capturedBlockStates.clear(); StructureGrowEvent structureEvent = null; @@ -430,11 +467,11 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 @Override public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode) { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC 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(); @@ -442,11 +479,11 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 @Override public boolean canPlace(BlockData data) { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC 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(); @@ -454,53 +491,70 @@ index 5cb69d0b822e11a99a96aef4f59986d083b079f4..1bfcb513f2d9a9b86a3833a7f57700b3 @Override public void tick() { -+ // DivineMC start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && world instanceof ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking final ServerLevel level = this.world.getMinecraftWorld(); 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..762bb2827dc1c0c0649a4cb3d8b0c8c0c9ea95d1 100644 +index 768d3f93da2522d467183654260a8bd8653588b1..dd3c9e214a59d20c2b5e8556951687e2aba2d116 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -25,7 +25,7 @@ public abstract class CraftBlockEntityState extends Craft - private final T tileEntity; +@@ -26,6 +26,25 @@ 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 = ThreadLocal.withInitial(() -> Boolean.FALSE); // DivineMC - parallel world ticking + public static boolean DISABLE_SNAPSHOT = false; // Paper ++ // DivineMC start - Parallel world ticking ++ public static ThreadLocal DISABLE_SNAPSHOT_TL = ThreadLocal.withInitial(() -> Boolean.FALSE); ++ ++ public static boolean getDisableSnapshotTL() { ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && DISABLE_SNAPSHOT_TL.get()) return true; ++ ++ synchronized (CraftBlockEntityState.class) { ++ return DISABLE_SNAPSHOT; ++ } ++ } ++ ++ public static void setDisableSnapshotTL(boolean value) { ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) DISABLE_SNAPSHOT_TL.set(value); ++ ++ synchronized (CraftBlockEntityState.class) { ++ DISABLE_SNAPSHOT = value; ++ } ++ } ++ // DivineMC end - Parallel world ticking public CraftBlockEntityState(World world, T tileEntity) { super(world, tileEntity.getBlockPos(), tileEntity.getBlockState()); -@@ -34,8 +34,10 @@ public abstract class CraftBlockEntityState extends Craft +@@ -34,8 +53,10 @@ 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) { -+ // DivineMC start - parallel world ticking -+ this.snapshotDisabled = DISABLE_SNAPSHOT.get(); -+ if (DISABLE_SNAPSHOT.get()) { -+ // DivineMC end - parallel world ticking ++ // DivineMC start - Parallel world ticking ++ this.snapshotDisabled = getDisableSnapshotTL(); ++ if (snapshotDisabled) { ++ // DivineMC end - Parallel world ticking 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..951e47811e861dffd59cc39e2dcd6fd68900fc72 100644 +index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..cddb460892f1756faa4b58ae53406058acd9803d 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java @@ -215,6 +215,12 @@ public class CraftBlockState implements BlockState { LevelAccessor access = this.getWorldHandle(); CraftBlock block = this.getBlock(); -+ // DivineMC start - parallel world ticking -+ if (access instanceof net.minecraft.server.level.ServerLevel serverWorld) { ++ // DivineMC start - Parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && access instanceof net.minecraft.server.level.ServerLevel serverWorld) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } -+ // DivineMC end - parallel world ticking ++ // DivineMC end - Parallel world ticking + if (block.getType() != this.getType()) { if (!force) { @@ -509,12 +563,12 @@ index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..951e47811e861dffd59cc39e2dcd6fd6 @Override public java.util.Collection getDrops(org.bukkit.inventory.ItemStack item, org.bukkit.entity.Entity entity) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(world.getHandle(), position, "Cannot modify world asynchronously"); // DivineMC - parallel world ticking ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(world.getHandle(), position, "Cannot modify world asynchronously"); // DivineMC - 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 56453454cbd4b9e9270fc833f8ab38d5fa7a3763..a8e740b255336c2d611e44129418b5fb29792592 100644 +index 56453454cbd4b9e9270fc833f8ab38d5fa7a3763..c3cc5012cf460f57495d8867f198007676bae5bf 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java @@ -249,8 +249,10 @@ public final class CraftBlockStates { @@ -524,8 +578,8 @@ index 56453454cbd4b9e9270fc833f8ab38d5fa7a3763..a8e740b255336c2d611e44129418b5fb - boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; - CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; + // DivineMC start - Parallel world ticking -+ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT.get(); -+ CraftBlockEntityState.DISABLE_SNAPSHOT.set(!useSnapshot); ++ boolean prev = CraftBlockEntityState.getDisableSnapshotTL(); ++ CraftBlockEntityState.setDisableSnapshotTL(!useSnapshot); + // DivineMC end - Parallel world ticking try { // Paper end @@ -535,38 +589,59 @@ index 56453454cbd4b9e9270fc833f8ab38d5fa7a3763..a8e740b255336c2d611e44129418b5fb // Paper start } finally { - CraftBlockEntityState.DISABLE_SNAPSHOT = prev; -+ CraftBlockEntityState.DISABLE_SNAPSHOT.set(prev); // DivineMC - parallel world ticking ++ CraftBlockEntityState.setDisableSnapshotTL(prev); // DivineMC - Parallel world ticking } // 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 4df143dfa4c01dc70e496ec8dc44fdde00ab40c6..1a398376298fbc5a247d6645e733f7c543106fb1 100644 +index 4df143dfa4c01dc70e496ec8dc44fdde00ab40c6..59ee059f8d2d96b5e5ae507f209d267da24c9fa1 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -960,7 +960,7 @@ public class CraftEventFactory { - return CraftEventFactory.handleBlockSpreadEvent(world, source, target, block, 2); +@@ -961,6 +961,26 @@ 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<>(); // SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. // DivineMC - parallel world ticking (this is from Folia, fixes concurrency bugs with sculk catalysts) + 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. ++ // DivineMC start - Parallel world ticking ++ public static final ThreadLocal sourceBlockOverrideTL = new ThreadLocal<>(); ++ ++ public static BlockPos getSourceBlockOverrideTL() { ++ BlockPos sourceBlockOverrideRTCopy; ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && (sourceBlockOverrideRTCopy = sourceBlockOverrideTL.get()) != null) return sourceBlockOverrideRTCopy; ++ ++ synchronized (CraftEventFactory.class) { ++ return sourceBlockOverride; ++ } ++ } ++ ++ public static void setSourceBlockOverrideTL(BlockPos value) { ++ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking) sourceBlockOverrideTL.set(value); ++ ++ synchronized (CraftEventFactory.class) { ++ sourceBlockOverride = value; ++ } ++ } ++ // DivineMC end - Parallel world ticking public static boolean handleBlockSpreadEvent(LevelAccessor world, BlockPos source, BlockPos target, net.minecraft.world.level.block.state.BlockState block, int flag) { // Suppress during worldgen -@@ -972,7 +972,7 @@ public class CraftEventFactory { +@@ -972,7 +992,10 @@ public class CraftEventFactory { CraftBlockState state = CraftBlockStates.getBlockState(world, target, flag); 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.sourceBlockOverrideRT.get() != null ? CraftEventFactory.sourceBlockOverrideRT.get() : source), state); // DivineMC - parallel world ticking ++ // DivineMC start - Parallel world ticking ++ final BlockPos sourceBlockOverrideRTSnap = getSourceBlockOverrideTL(); ++ BlockSpreadEvent event = new BlockSpreadEvent(state.getBlock(), CraftBlock.at(world, sourceBlockOverrideRTSnap != null ? sourceBlockOverrideRTSnap : source), state); ++ // DivineMC end - Parallel world ticking Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { -@@ -2245,7 +2245,7 @@ public class CraftEventFactory { +@@ -2245,7 +2268,7 @@ public class CraftEventFactory { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemStack.copyWithCount(1)); 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.eventFired.get()) { // DivineMC - parallel world ticking ++ if (!net.minecraft.world.level.block.DispenserBlock.getEventFiredTL()) { // DivineMC - Parallel world ticking if (!event.callEvent()) { return itemStack; } diff --git a/divinemc-server/paper-patches/features/0011-Multithreaded-Tracker.patch b/divinemc-server/paper-patches/features/0011-Multithreaded-Tracker.patch index 620a8ce..075937c 100644 --- a/divinemc-server/paper-patches/features/0011-Multithreaded-Tracker.patch +++ b/divinemc-server/paper-patches/features/0011-Multithreaded-Tracker.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Multithreaded Tracker diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java -index d7398b1ecf2660c29fb7d106b48fe02d3736603e..a9ec83b5bcb329bf3d2f3fb0e502685a37f9dcbc 100644 +index 124715b53090085fc0a9f50bb2df196d31d89bed..adf526bcb5b4df3b798a8b80ad11b7b2c30775d7 100644 --- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java +++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java -@@ -42,6 +42,12 @@ class PaperEventManager { - if (event.isAsynchronous() && this.server.isPrimaryThread()) { +@@ -49,6 +49,12 @@ class PaperEventManager { + // DivineMC end - Parallel world ticking throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously."); } else if (!event.isAsynchronous() && !this.server.isPrimaryThread() && !this.server.isStopping()) { + // DivineMC start - Multithreaded Tracker @@ -22,10 +22,10 @@ index d7398b1ecf2660c29fb7d106b48fe02d3736603e..a9ec83b5bcb329bf3d2f3fb0e502685a } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 1a398376298fbc5a247d6645e733f7c543106fb1..b761e416d3844063efd66d7ec8519f548995aacd 100644 +index 59ee059f8d2d96b5e5ae507f209d267da24c9fa1..68c529473e9ce24cb6c6108cb65100757d1d8759 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1973,6 +1973,26 @@ public class CraftEventFactory { +@@ -1996,6 +1996,26 @@ public class CraftEventFactory { } public static boolean handleBlockFormEvent(Level world, BlockPos pos, net.minecraft.world.level.block.state.BlockState block, int flag, @Nullable Entity entity) { diff --git a/divinemc-server/paper-patches/features/0012-Paper-PR-Add-FillBottleEvents-for-player-and-dispens.patch b/divinemc-server/paper-patches/features/0012-Paper-PR-Add-FillBottleEvents-for-player-and-dispens.patch index f662895..59136d6 100644 --- a/divinemc-server/paper-patches/features/0012-Paper-PR-Add-FillBottleEvents-for-player-and-dispens.patch +++ b/divinemc-server/paper-patches/features/0012-Paper-PR-Add-FillBottleEvents-for-player-and-dispens.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Paper PR: Add FillBottleEvents for player and dispenser diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index b761e416d3844063efd66d7ec8519f548995aacd..036913b57313ac437115698282c6d76eb749cf52 100644 +index 68c529473e9ce24cb6c6108cb65100757d1d8759..ba5adea7a791a9539ae485ef1c1641a56ca19236 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -2307,4 +2307,18 @@ public class CraftEventFactory { +@@ -2330,4 +2330,18 @@ public class CraftEventFactory { return event; } // Paper end - add EntityFertilizeEggEvent diff --git a/divinemc-server/src/main/java/org/bxteam/divinemc/util/PWTTeleportState.java b/divinemc-server/src/main/java/org/bxteam/divinemc/util/PWTTeleportState.java new file mode 100644 index 0000000..21b3c37 --- /dev/null +++ b/divinemc-server/src/main/java/org/bxteam/divinemc/util/PWTTeleportState.java @@ -0,0 +1,7 @@ +package org.bxteam.divinemc.util; + +public enum PWTTeleportState { + INACTIVE, + PENDING, + CANCELLED +}