diff --git a/leaf-server/minecraft-patches/features/0200-SparklyPaper-Parallel-world-ticking.patch b/leaf-server/minecraft-patches/features/0200-SparklyPaper-Parallel-world-ticking.patch index 8ca3a82e..900cb2a1 100644 --- a/leaf-server/minecraft-patches/features/0200-SparklyPaper-Parallel-world-ticking.patch +++ b/leaf-server/minecraft-patches/features/0200-SparklyPaper-Parallel-world-ticking.patch @@ -423,7 +423,7 @@ index eaaa66c4d86d4ebda0acf8f1dbe8ecb55aa28285..3a6c894178829cec8daa08ea9f0294f7 continue; } diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 30bb5b9d021d01dea272313763b0748856ce28a6..bfb4ea9d597b5f480ca0b7c095edf5090b84211c 100644 +index 06294e4036991a803deefc20e35160c5ff76a81b..8f93d8887d1e0ee8d27d0ead8e733cf7fa5d719d 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -180,7 +180,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -523,7 +523,7 @@ index 30bb5b9d021d01dea272313763b0748856ce28a6..bfb4ea9d597b5f480ca0b7c095edf509 + } + + // Executes the actual read operation based on the request type -+ private Object executeReadRequest(org.dreeam.leaf.async.world.WorldReadRequest request) { ++ public Object executeReadRequest(org.dreeam.leaf.async.world.WorldReadRequest request) { + Object[] params = request.params(); + BlockPos pos; // Declare pos outside the switch + @@ -858,7 +858,7 @@ index f9e7532f86122a379692561a639a209a126e8bba..fab317d6c9a1c914f19bae11846cb576 if (isLocatorBarEnabledFor(player)) { if (!connection.isBroken()) { diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 67556752551e1d30519e2533543de9b04342420b..45bc4aa35fda48c816e08ec8bacfb11a5c792b27 100644 +index c18f6f3f8307ae1d221a38cd1dc2191cdc4e767a..1bb78f90f9bfc58f39f21605d1e4e45680fdd41b 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -3476,15 +3476,40 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess diff --git a/leaf-server/paper-patches/features/0046-SparklyPaper-Parallel-world-ticking.patch b/leaf-server/paper-patches/features/0046-SparklyPaper-Parallel-world-ticking.patch index b15cd38b..9e0159c7 100644 --- a/leaf-server/paper-patches/features/0046-SparklyPaper-Parallel-world-ticking.patch +++ b/leaf-server/paper-patches/features/0046-SparklyPaper-Parallel-world-ticking.patch @@ -5,6 +5,8 @@ Subject: [PATCH] SparklyPaper: Parallel world ticking Original project: https://github.com/SparklyPower/SparklyPaper +Co-authored-by: MrlingXD <90316914+wling-art@users.noreply.github.com> + diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java index 69cdd304d255d52c9b7dc9b6a33ffdb630b79abe..09dfab1ace05ee62df5cf6e292f8be0146e85a36 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java @@ -337,10 +339,10 @@ index 61121d2efd0df2fcafdc4c272e1cd1b986f42e24..ee5f342995a335593932a497c2bafd36 } // 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 dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee2596d89bcd1 100644 +index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d447b4180f8db81dd28a34cd60cec2ad36c6b641 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -74,12 +74,97 @@ public class CraftBlock implements Block { +@@ -74,12 +74,109 @@ public class CraftBlock implements Block { return new CraftBlock(world, position); } @@ -367,6 +369,18 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 + return defaultValue; + } + ++ // Leaf start - SparklyPaper - parallel world ticking - Deadlock prevention ++ if (Thread.currentThread() instanceof ca.spottedleaf.moonrise.common.util.TickThread.ServerLevelTickThread) { ++ try { ++ org.dreeam.leaf.async.world.WorldReadRequest request = new org.dreeam.leaf.async.world.WorldReadRequest(type, params, null); ++ Object result = level.executeReadRequest(request); ++ return (T) result; ++ } catch (Exception e) { ++ return defaultValue; ++ } ++ } ++ // Leaf end - SparklyPaper - parallel world ticking - Deadlock prevention ++ + java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); + + // Leaf start - SparklyPaper - parallel world ticking - Shutdown handling for async reads @@ -440,7 +454,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 } public BlockPos getPosition() { -@@ -142,10 +227,12 @@ public class CraftBlock implements Block { +@@ -142,10 +239,12 @@ public class CraftBlock implements Block { return this.getWorld().getChunkAt(this); } @@ -453,7 +467,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 public void setData(final byte data, boolean applyPhysics) { if (applyPhysics) { this.setData(data, net.minecraft.world.level.block.Block.UPDATE_ALL); -@@ -155,12 +242,18 @@ public class CraftBlock implements Block { +@@ -155,12 +254,18 @@ public class CraftBlock implements Block { } private void setData(final byte data, int flags) { @@ -473,7 +487,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 return CraftMagicNumbers.toLegacyData(state); } -@@ -177,6 +270,7 @@ public class CraftBlock implements Block { +@@ -177,6 +282,7 @@ public class CraftBlock implements Block { @Override public void setType(Material type, boolean applyPhysics) { Preconditions.checkArgument(type != null, "Material cannot be null"); @@ -481,7 +495,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 this.setBlockData(type.createBlockData(), applyPhysics); } -@@ -196,6 +290,11 @@ public class CraftBlock implements Block { +@@ -196,6 +302,11 @@ public class CraftBlock implements Block { } public static boolean setBlockState(LevelAccessor world, BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState, boolean applyPhysics) { @@ -493,7 +507,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 // SPIGOT-611: need to do this to prevent glitchiness. Easier to handle this here (like /setblock) than to fix weirdness in block entity cleanup if (oldState.hasBlockEntity() && newState.getBlock() != oldState.getBlock()) { // SPIGOT-3725 remove old block entity if block changes // SPIGOT-4612: faster - just clear tile -@@ -227,22 +326,62 @@ public class CraftBlock implements Block { +@@ -227,22 +338,62 @@ public class CraftBlock implements Block { @Override public Material getType() { @@ -560,7 +574,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 } public Block getFace(final BlockFace face) { -@@ -287,47 +426,32 @@ public class CraftBlock implements Block { +@@ -287,47 +438,32 @@ public class CraftBlock implements Block { } public static BlockFace notchToBlockFace(Direction notch) { @@ -631,7 +645,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 } @Override -@@ -344,18 +468,65 @@ public class CraftBlock implements Block { +@@ -344,18 +480,65 @@ public class CraftBlock implements Block { @Override public Biome getBiome() { @@ -699,7 +713,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 this.getWorld().setBiome(this.getX(), this.getY(), this.getZ(), bio); } -@@ -371,12 +542,50 @@ public class CraftBlock implements Block { +@@ -371,12 +554,50 @@ public class CraftBlock implements Block { @Override public boolean isBlockPowered() { @@ -752,7 +766,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 } @Override -@@ -398,44 +607,103 @@ public class CraftBlock implements Block { +@@ -398,45 +619,104 @@ public class CraftBlock implements Block { @Override public boolean isBlockFacePowered(BlockFace face) { @@ -835,7 +849,8 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 + if (needsBuffering(level, handlingMode)) { + // Buffered path + return executeBufferedRead(level, org.dreeam.leaf.async.world.ReadOperationType.BLOCK_GET_BLOCK_POWER, new Object[]{this.position, face}, 0, "getBlockPower"); -+ } else { + } else { +- return Math.max(state.getValue(RedStoneWireBlock.POWER), power); + // Strict/Disabled/Non-ServerLevel path + checkStrictMode(level, handlingMode, "getBlockPower"); + try { @@ -863,24 +878,24 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 + org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "PWT: Direct access failed for getBlockPower" + (level == null ? " (Not a ServerLevel)" : ""), e); + return 0; + } -+ } -+ } -+ + } + } + + // Static helper, safe + public static int getPower(int currentMax, net.minecraft.world.level.block.state.BlockState neighborState) { + if (!neighborState.is(Blocks.REDSTONE_WIRE)) { + return currentMax; - } else { -- return Math.max(state.getValue(RedStoneWireBlock.POWER), power); ++ } else { + int neighborPower = neighborState.getValue(RedStoneWireBlock.POWER); + return Math.max(neighborPower, currentMax); - } - } ++ } ++ } + // Leaf end - SparklyPaper - parallel world ticking - ++ @Override public int getBlockPower() { -@@ -478,23 +746,35 @@ public class CraftBlock implements Block { + return this.getBlockPower(BlockFace.SELF); +@@ -478,23 +758,35 @@ public class CraftBlock implements Block { @Override public PistonMoveReaction getPistonMoveReaction() { @@ -919,7 +934,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 } @Override -@@ -506,84 +786,147 @@ public class CraftBlock implements Block { +@@ -506,84 +798,147 @@ public class CraftBlock implements Block { public boolean breakNaturally(ItemStack item, boolean triggerEffect, boolean dropExperience, boolean forceEffect) { // Paper end // Order matters here, need to drop before setting to air so skulls can get their data @@ -978,7 +993,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 + // Log if we couldn't drop XP because it wasn't a ServerLevel + if (dropExperience && !state.isAir()) { // Only warn if XP was requested and block wasn't air + org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.WARNING, "PWT: Cannot drop experience for breakNaturally: Not a ServerLevel."); - } ++ } + // Still trigger effects if requested and possible with LevelAccessor + if (triggerEffect && !state.isAir()) { + int eventId = (state.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) @@ -987,9 +1002,11 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 + int eventData = (eventId == net.minecraft.world.level.block.LevelEvent.PARTICLES_DESTROY_BLOCK) + ? net.minecraft.world.level.block.Block.getId(state) : 0; + this.world.levelEvent(eventId, this.position, eventData); -+ } -+ } -+ + } + } + +- // SPIGOT-6778: Directly call setBlock instead of setBlockState, so that the block entity is not removed and custom remove logic is run. +- // Paper start - improve breakNaturally + // Trigger effect using LevelAccessor (safe) + if ((droppedItems && triggerEffect) || (forceEffect && block != Blocks.AIR)) { + int eventId = (state.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) @@ -998,10 +1015,8 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 + int eventData = (eventId == net.minecraft.world.level.block.LevelEvent.PARTICLES_DESTROY_BLOCK) + ? net.minecraft.world.level.block.Block.getId(state) : 0; + this.world.levelEvent(eventId, this.position, eventData); - } - -- // SPIGOT-6778: Directly call setBlock instead of setBlockState, so that the block entity is not removed and custom remove logic is run. -- // Paper start - improve breakNaturally ++ } ++ + // Remove the block using LevelAccessor (safe) boolean destroyed = this.world.removeBlock(this.position, false); if (destroyed) { @@ -1104,7 +1119,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 } @Override -@@ -598,20 +941,45 @@ public class CraftBlock implements Block { +@@ -598,20 +953,45 @@ public class CraftBlock implements Block { @Override public Collection getDrops(ItemStack item, Entity entity) { @@ -1157,7 +1172,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 net.minecraft.world.level.block.state.BlockState state = this.getNMS(); net.minecraft.world.item.ItemStack nms = CraftItemStack.asNMSCopy(item); return CraftBlockData.isPreferredTool(state, nms); -@@ -620,9 +988,23 @@ public class CraftBlock implements Block { +@@ -620,9 +1000,23 @@ public class CraftBlock implements Block { @Override public float getBreakSpeed(Player player) { Preconditions.checkArgument(player != null, "player cannot be null"); @@ -1182,7 +1197,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 @Override public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { this.getCraftWorld().getBlockMetadata().setMetadata(this, metadataKey, newMetadataValue); -@@ -645,57 +1027,148 @@ public class CraftBlock implements Block { +@@ -645,57 +1039,148 @@ public class CraftBlock implements Block { @Override public boolean isPassable() { @@ -1354,7 +1369,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 } @Override -@@ -711,7 +1184,10 @@ public class CraftBlock implements Block { +@@ -711,7 +1196,10 @@ public class CraftBlock implements Block { // Paper start @Override public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { @@ -1366,7 +1381,7 @@ index dd122bbbe2c33183017dbde6997d3f1cd08479b5..d164d50bcee7281283c6d9a7b85ee259 } @Override -@@ -724,26 +1200,76 @@ public class CraftBlock implements Block { +@@ -724,26 +1212,76 @@ public class CraftBlock implements Block { return this.getNMS().getBlock().getDescriptionId(); }