|
|
|
|
@@ -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<net.minecraft.world.level.ServerExplosion> 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<net.minecraft.world.level.biome.Biome> 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<BlockState> 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<T extends BlockEntity> extends Craft
|
|
|
|
|
private final T tileEntity;
|
|
|
|
|
@@ -26,6 +26,25 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
|
|
|
|
|
private final T snapshot;
|
|
|
|
|
public boolean snapshotDisabled; // Paper
|
|
|
|
|
- public static boolean DISABLE_SNAPSHOT = false; // Paper
|
|
|
|
|
+ public static ThreadLocal<Boolean> 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<Boolean> 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<T extends BlockEntity> extends Craft
|
|
|
|
|
@@ -34,8 +53,10 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> 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<org.bukkit.inventory.ItemStack> 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<BlockPos> 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<BlockPos> 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;
|
|
|
|
|
}
|
|
|
|
|
|