mirror of
https://github.com/BX-Team/DivineMC.git
synced 2025-12-19 14:59:25 +00:00
1421 lines
91 KiB
Diff
1421 lines
91 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
|
Date: Wed, 29 Jan 2025 00:59:03 +0300
|
|
Subject: [PATCH] SparklyPaper: Parallel world ticking
|
|
|
|
Original project: https://github.com/SparklyPower/SparklyPaper
|
|
|
|
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
|
index 6ce4a98e4d3b633e3c87944c23b6b3f0ff58f159..57fec1f9a210d2ecb74ff7b05cec790ae77f9178 100644
|
|
--- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
|
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
|
@@ -1142,7 +1142,7 @@ public final class ChunkHolderManager {
|
|
if (changedFullStatus.isEmpty()) {
|
|
return;
|
|
}
|
|
- if (!TickThread.isTickThread()) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking && !TickThread.isTickThreadFor(world) || !TickThread.isTickThread()) { // DivineMC - Parallel world ticking
|
|
// These will be handled on the next ServerChunkCache$MainThreadExecutor#pollTask, as it runs the distance manager update
|
|
// which will invoke processTicketUpdates
|
|
this.offThreadPendingFullLoadUpdate.addAll(changedFullStatus);
|
|
@@ -1163,7 +1163,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");
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.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");
|
|
@@ -1429,7 +1435,7 @@ public final class ChunkHolderManager {
|
|
if (BLOCK_TICKET_UPDATES.get() == Boolean.TRUE) {
|
|
throw new IllegalStateException("Cannot update ticket level while unloading chunks or updating entity manager");
|
|
}
|
|
- final boolean isTickThread = TickThread.isTickThread();
|
|
+ final boolean isTickThread = org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking && TickThread.isTickThreadFor(world) || TickThread.isTickThread(); // DivineMC - Parallel world ticking
|
|
|
|
if (!PlatformHooks.get().allowAsyncTicketUpdates() && isTickThread) {
|
|
TickThread.ensureTickThread("Cannot asynchronously process ticket updates");
|
|
diff --git a/io/papermc/paper/redstone/RedstoneWireTurbo.java b/io/papermc/paper/redstone/RedstoneWireTurbo.java
|
|
index ff747a1ecdf3c888bca0d69de4f85dcd810b6139..544c05c94b535174d97675ea3c21706dfe305438 100644
|
|
--- a/io/papermc/paper/redstone/RedstoneWireTurbo.java
|
|
+++ b/io/papermc/paper/redstone/RedstoneWireTurbo.java
|
|
@@ -829,14 +829,9 @@ public final class RedstoneWireTurbo {
|
|
j = getMaxCurrentStrength(upd, j);
|
|
int l = 0;
|
|
|
|
- wire.shouldSignal = false;
|
|
- // Unfortunately, World.isBlockIndirectlyGettingPowered is complicated,
|
|
- // and I'm not ready to try to replicate even more functionality from
|
|
- // elsewhere in Minecraft into this accelerator. So sadly, we must
|
|
- // suffer the performance hit of this very expensive call. If there
|
|
- // is consistency to what this call returns, we may be able to cache it.
|
|
- final int k = worldIn.getBestNeighborSignal(upd.self);
|
|
- wire.shouldSignal = true;
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ final int k = wire.getBlockSignal(worldIn, upd.self);
|
|
+ // DivineMC end - Parallel world ticking
|
|
|
|
// The variable 'k' holds the maximum redstone power value of any adjacent blocks.
|
|
// If 'k' has the highest level of all neighbors, then the power level of this
|
|
diff --git a/net/minecraft/core/dispenser/DispenseItemBehavior.java b/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
|
index ac27ff24f018d8798921c5152e679ceed1e88d8d..ec7d1353b19e55b00c558df8981323efb9b88bdf 100644
|
|
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
|
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
|
@@ -401,8 +401,10 @@ public interface DispenseItemBehavior {
|
|
// CraftBukkit start
|
|
level.captureTreeGeneration = false;
|
|
if (!level.capturedBlockStates.isEmpty()) {
|
|
- 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.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<org.bukkit.block.BlockState> states = new java.util.ArrayList<>(level.capturedBlockStates.values());
|
|
level.capturedBlockStates.clear();
|
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
|
index a0cad0bdb8245b19f4ff983245d61d7b237a4042..c56fa00f9443b6a3a44f0b89da9dcfb6a4faf1c8 100644
|
|
--- a/net/minecraft/server/MinecraftServer.java
|
|
+++ b/net/minecraft/server/MinecraftServer.java
|
|
@@ -290,6 +290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
protected boolean upnp = false; // Purpur - UPnP Port Forwarding
|
|
public final org.bxteam.divinemc.util.tps.TPSCalculator tpsCalculator = new org.bxteam.divinemc.util.tps.TPSCalculator(); // DivineMC - Lag compensation
|
|
public gg.pufferfish.pufferfish.util.AsyncExecutor mobSpawnExecutor = new gg.pufferfish.pufferfish.util.AsyncExecutor("Mob Spawning"); // DivineMC - Pufferfish: Optimize mob spawning
|
|
+ public java.util.concurrent.Semaphore serverLevelTickingSemaphore = null; // DivineMC - Parallel world ticking
|
|
|
|
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
|
|
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
|
|
@@ -322,24 +323,36 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
private long lastMidTickExecute;
|
|
private long lastMidTickExecuteFailure;
|
|
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ private boolean tickLevelMidTickTasks(ServerLevel world) {
|
|
+ long currTime = System.nanoTime();
|
|
+ if (currTime - ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)world).moonrise$getLastMidTickFailure() <= TASK_EXECUTION_FAILURE_BACKOFF) {
|
|
+ return false;
|
|
+ }
|
|
+ if (!world.getChunkSource().pollTask()) {
|
|
+ // we need to back off if this fails
|
|
+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)world).moonrise$setLastMidTickFailure(currTime);
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
+
|
|
private boolean tickMidTickTasks() {
|
|
// give all worlds a fair chance at by targeting them all.
|
|
// if we execute too many tasks, that's fine - we have logic to correctly handle overuse of allocated time.
|
|
- boolean executed = false;
|
|
- for (final ServerLevel world : this.getAllLevels()) {
|
|
- long currTime = System.nanoTime();
|
|
- if (currTime - ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)world).moonrise$getLastMidTickFailure() <= TASK_EXECUTION_FAILURE_BACKOFF) {
|
|
- continue;
|
|
- }
|
|
- if (!world.getChunkSource().pollTask()) {
|
|
- // we need to back off if this fails
|
|
- ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)world).moonrise$setLastMidTickFailure(currTime);
|
|
- } else {
|
|
- executed = true;
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking && Thread.currentThread() instanceof ca.spottedleaf.moonrise.common.util.TickThread.ServerLevelTickThread levelThread) {
|
|
+ return this.tickLevelMidTickTasks(levelThread.currentlyTickingServerLevel);
|
|
+ } else {
|
|
+ boolean executed = false;
|
|
+ for (final ServerLevel world : this.getAllLevels()) {
|
|
+ executed = executed || this.tickLevelMidTickTasks(world);
|
|
}
|
|
- }
|
|
|
|
- return executed;
|
|
+ return executed;
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
}
|
|
|
|
@Override
|
|
@@ -1661,6 +1674,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
|
|
public final io.papermc.paper.threadedregions.EntityScheduler.EntitySchedulerTickList entitySchedulerTickList = new io.papermc.paper.threadedregions.EntityScheduler.EntitySchedulerTickList(); // Paper - optimise Folia entity scheduler
|
|
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ private void tickLevel(ServerLevel serverLevel, BooleanSupplier hasTimeLeft) {
|
|
+ try {
|
|
+ serverLevel.tick(hasTimeLeft);
|
|
+ } catch (Throwable levelTickingException) {
|
|
+ CrashReport crashReport = CrashReport.forThrowable(levelTickingException, "Exception ticking world");
|
|
+ serverLevel.fillReportDetails(crashReport);
|
|
+ throw new ReportedException(crashReport);
|
|
+ }
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
+
|
|
protected void tickChildren(BooleanSupplier hasTimeLeft) {
|
|
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
|
|
this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit
|
|
@@ -1706,28 +1731,43 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
}
|
|
|
|
this.isIteratingOverLevels = true; // Paper - Throw exception on world create while being ticked
|
|
- for (ServerLevel serverLevel : this.getAllLevels()) {
|
|
- serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
|
- serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
|
- serverLevel.updateLagCompensationTick(); // Paper - lag compensation
|
|
- net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = serverLevel.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers
|
|
- serverLevel.hasRidableMoveEvent = org.purpurmc.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur - Ridables
|
|
- /* Drop global time updates
|
|
- if (this.tickCount % 20 == 0) {
|
|
- this.synchronizeTime(serverLevel);
|
|
- }
|
|
- // CraftBukkit end */
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ java.util.ArrayDeque<java.util.concurrent.Future<ServerLevel>> tasks = new java.util.ArrayDeque<>();
|
|
+ try {
|
|
+ for (ServerLevel serverLevel : this.getAllLevels()) {
|
|
+ serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
|
+ serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
|
+ serverLevel.updateLagCompensationTick(); // Paper - lag compensation
|
|
+ net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = serverLevel.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers
|
|
+ serverLevel.hasRidableMoveEvent = org.purpurmc.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur - Ridables
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ serverLevelTickingSemaphore.acquire();
|
|
+ tasks.add(
|
|
+ serverLevel.tickExecutor.submit(() -> {
|
|
+ ca.spottedleaf.moonrise.common.util.TickThread.ServerLevelTickThread currentThread = (ca.spottedleaf.moonrise.common.util.TickThread.ServerLevelTickThread) Thread.currentThread();
|
|
+ currentThread.currentlyTickingServerLevel = serverLevel;
|
|
|
|
- try {
|
|
- serverLevel.tick(hasTimeLeft);
|
|
- } catch (Throwable var7) {
|
|
- CrashReport crashReport = CrashReport.forThrowable(var7, "Exception ticking world");
|
|
- serverLevel.fillReportDetails(crashReport);
|
|
- throw new ReportedException(crashReport);
|
|
+ try {
|
|
+ tickLevel(serverLevel, hasTimeLeft);
|
|
+ } finally {
|
|
+ serverLevelTickingSemaphore.release();
|
|
+ }
|
|
+ }, serverLevel)
|
|
+ );
|
|
+ } else {
|
|
+ tickLevel(serverLevel, hasTimeLeft);
|
|
+ }
|
|
+
|
|
+ serverLevel.explosionDensityCache.clear(); // Paper - Optimize explosions
|
|
}
|
|
|
|
- serverLevel.explosionDensityCache.clear(); // Paper - Optimize explosions
|
|
+ while (!tasks.isEmpty()) {
|
|
+ tasks.pop().get();
|
|
+ }
|
|
+ } catch (java.lang.InterruptedException | java.util.concurrent.ExecutionException e) {
|
|
+ throw new RuntimeException(e);
|
|
}
|
|
+ // DivineMC end - Parallel world ticking
|
|
this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked
|
|
|
|
this.tickConnection();
|
|
@@ -1805,6 +1845,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
Map<ResourceKey<Level>, ServerLevel> oldLevels = this.levels;
|
|
Map<ResourceKey<Level>, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels);
|
|
newLevels.remove(level.dimension());
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) level.tickExecutor.shutdown(); // DivineMC - Parallel world ticking
|
|
this.levels = Collections.unmodifiableMap(newLevels);
|
|
}
|
|
// CraftBukkit end
|
|
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
|
|
index 3836d60ce84fb26f30a609486a5755d3fd1c94f1..1aab02441e4dfa7703963855d77bb918dee7a6fc 100644
|
|
--- a/net/minecraft/server/PlayerAdvancements.java
|
|
+++ b/net/minecraft/server/PlayerAdvancements.java
|
|
@@ -54,6 +54,7 @@ public class PlayerAdvancements {
|
|
private final Map<AdvancementHolder, AdvancementProgress> progress = new LinkedHashMap<>();
|
|
private final Set<AdvancementHolder> visible = new HashSet<>();
|
|
private final Set<AdvancementHolder> progressChanged = new HashSet<>();
|
|
+ private final Set<AdvancementHolder> progressChangedConcurrent = java.util.concurrent.ConcurrentHashMap.newKeySet(); // DivineMC - Parallel world ticking
|
|
private final Set<AdvancementNode> rootsToUpdate = new HashSet<>();
|
|
private ServerPlayer player;
|
|
@Nullable
|
|
@@ -88,6 +89,7 @@ public class PlayerAdvancements {
|
|
this.visible.clear();
|
|
this.rootsToUpdate.clear();
|
|
this.progressChanged.clear();
|
|
+ this.progressChangedConcurrent.clear(); // DivineMC - Parallel world ticking
|
|
this.isFirstPacket = true;
|
|
this.lastSelectedTab = null;
|
|
this.tree = manager.tree();
|
|
@@ -178,10 +180,12 @@ public class PlayerAdvancements {
|
|
return false;
|
|
}
|
|
// Paper end - Add PlayerAdvancementCriterionGrantEvent
|
|
- this.unregisterListeners(advancement);
|
|
- this.progressChanged.add(advancement);
|
|
- flag = true;
|
|
- if (!isDone && orStartProgress.isDone()) {
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ this.unregisterListeners(advancement); // Must unregister criteria listeners
|
|
+ (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking ? this.progressChangedConcurrent : this.progressChanged).add(advancement);
|
|
+ flag = true; // Mark progress changed
|
|
+ if (!isDone && orStartProgress.isDone()) { // If the advancement was just completed
|
|
+ // DivineMC end - Parallel world ticking
|
|
// Paper start - Add Adventure message to PlayerAdvancementDoneEvent
|
|
final net.kyori.adventure.text.Component message = advancement.value().display().flatMap(info -> {
|
|
return java.util.Optional.ofNullable(
|
|
@@ -215,8 +219,10 @@ public class PlayerAdvancements {
|
|
AdvancementProgress orStartProgress = this.getOrStartProgress(advancement);
|
|
boolean isDone = orStartProgress.isDone();
|
|
if (orStartProgress.revokeProgress(criterionKey)) {
|
|
+ // DivineMC start - Parallel world ticking
|
|
this.registerListeners(advancement);
|
|
- this.progressChanged.add(advancement);
|
|
+ (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking ? this.progressChangedConcurrent : this.progressChanged).add(advancement);
|
|
+ // DivineMC end - Parallel world ticking
|
|
flag = true;
|
|
}
|
|
|
|
@@ -266,7 +272,11 @@ public class PlayerAdvancements {
|
|
}
|
|
|
|
public void flushDirty(ServerPlayer player, boolean showAdvancements) {
|
|
- if (this.isFirstPacket || !this.rootsToUpdate.isEmpty() || !this.progressChanged.isEmpty()) {
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ final boolean useConcurrent = org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking;
|
|
+ final Set<AdvancementHolder> relevantProgressSet = useConcurrent ? this.progressChangedConcurrent : this.progressChanged;
|
|
+ if (this.isFirstPacket || !this.rootsToUpdate.isEmpty() || !relevantProgressSet.isEmpty()) {
|
|
+ // DivineMC end - Parallel world ticking
|
|
Map<ResourceLocation, AdvancementProgress> map = new HashMap<>();
|
|
Set<AdvancementHolder> set = new java.util.TreeSet<>(java.util.Comparator.comparing(adv -> adv.id().toString())); // Paper - Changed from HashSet to TreeSet ordered alphabetically.
|
|
Set<ResourceLocation> set1 = new HashSet<>();
|
|
@@ -277,13 +287,23 @@ public class PlayerAdvancements {
|
|
|
|
this.rootsToUpdate.clear();
|
|
|
|
- for (AdvancementHolder advancementHolder : this.progressChanged) {
|
|
- if (this.visible.contains(advancementHolder)) {
|
|
- map.put(advancementHolder.id(), this.progress.get(advancementHolder));
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (!relevantProgressSet.isEmpty()) {
|
|
+ Set<AdvancementHolder> toProcess = useConcurrent ? new HashSet<>(relevantProgressSet) : relevantProgressSet;
|
|
+
|
|
+ for (AdvancementHolder advancementHolder : toProcess) {
|
|
+ if (this.visible.contains(advancementHolder)) {
|
|
+ map.put(advancementHolder.id(), this.progress.get(advancementHolder));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (useConcurrent) {
|
|
+ this.progressChangedConcurrent.removeAll(toProcess);
|
|
+ } else {
|
|
+ this.progressChanged.clear();
|
|
}
|
|
}
|
|
-
|
|
- this.progressChanged.clear();
|
|
+ // DivineMC end - Parallel world ticking
|
|
if (!map.isEmpty() || !set.isEmpty() || !set1.isEmpty()) {
|
|
player.connection.send(new ClientboundUpdateAdvancementsPacket(this.isFirstPacket, set, set1, map, showAdvancements));
|
|
}
|
|
@@ -328,7 +348,7 @@ public class PlayerAdvancements {
|
|
if (this.visible.add(advancementHolder)) {
|
|
advancementOutput.add(advancementHolder);
|
|
if (this.progress.containsKey(advancementHolder)) {
|
|
- this.progressChanged.add(advancementHolder);
|
|
+ (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking ? this.progressChangedConcurrent : this.progressChanged).add(advancementHolder); // DivineMC - Parallel world ticking
|
|
}
|
|
}
|
|
} else if (this.visible.remove(advancementHolder)) {
|
|
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
|
index 46adbe6ccf1e4291e33a52a6612f624558c18f96..374abd7e1502edefb78cd6451a36c3b8ad6d8f8f 100644
|
|
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
|
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
|
@@ -218,6 +218,13 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
|
}
|
|
// DivineMC end - Pufferfish: SIMD Support
|
|
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ serverLevelTickingSemaphore = new java.util.concurrent.Semaphore(org.bxteam.divinemc.config.DivineConfig.AsyncCategory.parallelThreadCount);
|
|
+ DedicatedServer.LOGGER.info("Using {} permits for Parallel world ticking", serverLevelTickingSemaphore.availablePermits());
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
+
|
|
this.setPvpAllowed(properties.pvp);
|
|
this.setFlightAllowed(properties.allowFlight);
|
|
this.setMotd(properties.motd);
|
|
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
|
index bf680624bc6c618dfa0eeeb74c103ff6716fd27e..654d03368f06ab9870c11745b0994ea6722fa7bf 100644
|
|
--- a/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -175,7 +175,6 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
|
|
// call mid-tick tasks for chunk system
|
|
if ((i & 7) == 0) {
|
|
- ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.level.getServer()).moonrise$executeMidTickTasks();
|
|
continue;
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
|
index 3c1795eb56900cd80cfec38bd1d922d566463ecb..b752bcc03b558a26f9c592c829efb44a299be8de 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
|
|
private final MinecraftServer server;
|
|
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
|
|
private final ServerWaypointManager waypointManager;
|
|
// Paper - rewrite chunk system
|
|
private final GameEventDispatcher gameEventDispatcher;
|
|
@@ -217,6 +217,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
public boolean hasRidableMoveEvent = false; // Purpur - Ridables
|
|
public net.minecraft.world.item.ItemStack ominousBanner; // DivineMC - Optimize Raids
|
|
public org.bxteam.divinemc.util.tps.TPSCalculator tpsCalculator = new org.bxteam.divinemc.util.tps.TPSCalculator(); // DivineMC - Lag Compensation
|
|
+ public java.util.concurrent.ExecutorService tickExecutor; // DivineMC - Parallel world ticking
|
|
|
|
@Override
|
|
public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
|
|
@@ -680,7 +681,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
this.sleepStatus = new SleepStatus();
|
|
this.gameEventDispatcher = new GameEventDispatcher(this);
|
|
this.randomSequences = Objects.requireNonNullElseGet(randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.TYPE));
|
|
- this.waypointManager = new ServerWaypointManager();
|
|
+ this.waypointManager = new ServerWaypointManager(this); // DivineMC - Parallel world ticking
|
|
// Paper start - rewrite chunk system
|
|
this.moonrise$setEntityLookup(new ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup((ServerLevel)(Object)this, ((ServerLevel)(Object)this).new EntityCallbacks()));
|
|
this.chunkTaskScheduler = new ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler((ServerLevel)(Object)this);
|
|
@@ -698,6 +699,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
|
this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle
|
|
this.ominousBanner = Objects.requireNonNullElse(this.registryAccess(), net.minecraft.core.RegistryAccess.EMPTY).lookup(Registries.BANNER_PATTERN).map(Raid::getOminousBannerInstance).orElse(null); // DivineMC - Optimize Raids
|
|
+ this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new org.bxteam.divinemc.async.world.ServerLevelTickThreadFactory(getWorld().getName())); // DivineMC - Parallel world ticking
|
|
}
|
|
|
|
// Paper start
|
|
@@ -1300,12 +1302,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
if (fluidState.is(fluid)) {
|
|
fluidState.tick(this, pos, blockState);
|
|
}
|
|
- // 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.config.DivineConfig.AsyncCategory.enableParallelWorldTicking && (this.tickedBlocksOrFluids & 7L) != 0L) {
|
|
+ this.server.moonrise$executeMidTickTasks();
|
|
}
|
|
- // Paper end - rewrite chunk system
|
|
-
|
|
+ // DivineMC end - Parallel world ticking
|
|
}
|
|
|
|
private void tickBlock(BlockPos pos, Block block) {
|
|
@@ -1313,12 +1315,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
if (blockState.is(block)) {
|
|
blockState.tick(this, pos, this.random);
|
|
}
|
|
- // 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.config.DivineConfig.AsyncCategory.enableParallelWorldTicking && (this.tickedBlocksOrFluids & 7L) != 0L) {
|
|
+ this.server.moonrise$executeMidTickTasks();
|
|
}
|
|
- // Paper end - rewrite chunk system
|
|
-
|
|
+ // DivineMC end - Parallel world ticking
|
|
}
|
|
|
|
// Paper start - log detailed entity tick information
|
|
@@ -1581,6 +1583,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
}
|
|
|
|
private void addPlayer(ServerPlayer player) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add player off-main"); // DivineMC - Parallel world ticking
|
|
Entity entity = this.getEntity(player.getUUID());
|
|
if (entity != null) {
|
|
LOGGER.warn("Force-added player with duplicate UUID {}", player.getUUID());
|
|
@@ -1593,7 +1596,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
|
|
// CraftBukkit start
|
|
private boolean addEntity(Entity entity, @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
|
- org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.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 1431a2e386bee22ec10365a38ead349a398d551f..77d1cab278a13e08ba8096af2c683b5042cc1574 100644
|
|
--- a/net/minecraft/server/level/ServerPlayer.java
|
|
+++ b/net/minecraft/server/level/ServerPlayer.java
|
|
@@ -431,6 +431,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
|
private boolean compassBar = false; // Purpur - Add compass command
|
|
private boolean ramBar = false; // Purpur - Implement rambar commands
|
|
public boolean smoothWorldTeleport; // DivineMC - Smooth teleport API
|
|
+ public boolean hasTickedAtLeastOnceInNewWorld = false; // DivineMC - Parallel world ticking
|
|
|
|
// Paper start - rewrite chunk system
|
|
private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
|
|
@@ -748,6 +749,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
|
|
|
@Override
|
|
public void tick() {
|
|
+ hasTickedAtLeastOnceInNewWorld = true; // DivineMC - Parallel world ticking
|
|
// CraftBukkit start
|
|
if (this.joining) {
|
|
this.joining = false;
|
|
@@ -1434,6 +1436,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
|
return this;
|
|
} else {
|
|
// CraftBukkit start
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot change dimension of a player off-main, from world " + level().getWorld().getName() + " to world " + level.getWorld().getName()); // DivineMC - Parallel world ticking (additional concurrency issues logs)
|
|
/*
|
|
this.isChangingDimension = true;
|
|
LevelData levelData = level.getLevelData();
|
|
@@ -1779,6 +1782,12 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
|
return OptionalInt.empty();
|
|
} else {
|
|
// CraftBukkit start
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.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
|
|
this.containerMenu = abstractContainerMenu; // Moved up
|
|
if (!this.isImmobile())
|
|
this.connection
|
|
@@ -1843,6 +1852,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
|
}
|
|
@Override
|
|
public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
|
|
+ // DivineMC start - Parallel world ticking (debugging)
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.logContainerCreationStacktraces) {
|
|
+ MinecraftServer.LOGGER.warn("Closing {} inventory that was created at", this.getBukkitEntity().getName(), this.containerMenu.containerCreationStacktrace);
|
|
+ }
|
|
+ // 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 84250c9786f4886fe4ab2e42808f8162da3f45d8..cfe2bbc46046f144044d8cba67cda978f231d354 100644
|
|
--- a/net/minecraft/server/players/PlayerList.java
|
|
+++ b/net/minecraft/server/players/PlayerList.java
|
|
@@ -149,6 +149,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) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.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();
|
|
@@ -685,6 +686,14 @@ public abstract class PlayerList {
|
|
}
|
|
|
|
public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, @Nullable org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason, @Nullable org.bukkit.Location location) {
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ if (location != null)
|
|
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot respawn player off-main, from world " + player.level().getWorld().getName() + " to world " + location.getWorld().getName());
|
|
+ else
|
|
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot respawn player off-main, respawning in world " + player.level().getWorld().getName());
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
player.stopRiding(); // CraftBukkit
|
|
this.players.remove(player);
|
|
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
|
|
@@ -695,6 +704,7 @@ public abstract class PlayerList {
|
|
ServerPlayer serverPlayer = player;
|
|
Level fromWorld = player.level();
|
|
player.wonGame = false;
|
|
+ serverPlayer.hasTickedAtLeastOnceInNewWorld = false; // DivineMC - Parallel world ticking
|
|
// CraftBukkit end
|
|
serverPlayer.connection = player.connection;
|
|
serverPlayer.restoreFrom(player, keepInventory);
|
|
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
|
index f9e7532f86122a379692561a639a209a126e8bba..839f6b7696ef85314da185bedba7cfc5870c314a 100644
|
|
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
|
|
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
|
@@ -19,9 +19,17 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
|
private final Set<WaypointTransmitter> waypoints = new HashSet<>();
|
|
private final Set<ServerPlayer> players = new HashSet<>();
|
|
private final Table<ServerPlayer, WaypointTransmitter, WaypointTransmitter.Connection> connections = HashBasedTable.create();
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ private final net.minecraft.server.level.ServerLevel level;
|
|
+
|
|
+ public ServerWaypointManager(net.minecraft.server.level.ServerLevel level) {
|
|
+ this.level = level;
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
|
|
@Override
|
|
public void trackWaypoint(WaypointTransmitter waypoint) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, "Cannot track waypoints off-main"); // DivineMC - Parallel world ticking
|
|
this.waypoints.add(waypoint);
|
|
|
|
for (ServerPlayer serverPlayer : this.players) {
|
|
@@ -31,6 +39,7 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
|
|
|
@Override
|
|
public void updateWaypoint(WaypointTransmitter waypoint) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, "Cannot update waypoints off-main"); // DivineMC - Parallel world ticking
|
|
if (this.waypoints.contains(waypoint)) {
|
|
Map<ServerPlayer, WaypointTransmitter.Connection> map = Tables.transpose(this.connections).row(waypoint);
|
|
SetView<ServerPlayer> set = Sets.difference(this.players, map.keySet());
|
|
@@ -47,12 +56,14 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
|
|
|
@Override
|
|
public void untrackWaypoint(WaypointTransmitter waypoint) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, "Cannot untrack waypoints off-main"); // DivineMC - Parallel world ticking
|
|
this.connections.column(waypoint).forEach((serverPlayer, connection) -> connection.disconnect());
|
|
Tables.transpose(this.connections).row(waypoint).clear();
|
|
this.waypoints.remove(waypoint);
|
|
}
|
|
|
|
public void addPlayer(ServerPlayer player) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, "Cannot add player to waypoints off-main"); // DivineMC - Parallel world ticking
|
|
this.players.add(player);
|
|
|
|
for (WaypointTransmitter waypointTransmitter : this.waypoints) {
|
|
@@ -65,6 +76,7 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
|
}
|
|
|
|
public void updatePlayer(ServerPlayer player) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, "Cannot update player for waypoints off-main"); // DivineMC - Parallel world ticking
|
|
Map<WaypointTransmitter, WaypointTransmitter.Connection> map = this.connections.row(player);
|
|
SetView<WaypointTransmitter> set = Sets.difference(this.waypoints, map.keySet());
|
|
|
|
@@ -78,6 +90,7 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
|
}
|
|
|
|
public void removePlayer(ServerPlayer player) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, "Cannot remove player from waypoints off-main"); // DivineMC - Parallel world ticking
|
|
this.connections.row(player).values().removeIf(connection -> {
|
|
connection.disconnect();
|
|
return true;
|
|
@@ -87,6 +100,7 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
|
}
|
|
|
|
public void breakAllConnections() {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, "Cannot break all waypoint connections off-main"); // DivineMC - Parallel world ticking
|
|
this.connections.values().forEach(WaypointTransmitter.Connection::disconnect);
|
|
this.connections.clear();
|
|
}
|
|
@@ -106,6 +120,7 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
|
}
|
|
|
|
private void createConnection(ServerPlayer player, WaypointTransmitter waypoint) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, "Cannot create waypoint connections off-main"); // DivineMC - Parallel world ticking
|
|
if (player != waypoint) {
|
|
if (isLocatorBarEnabledFor(player)) {
|
|
waypoint.makeWaypointConnectionWith(player).ifPresentOrElse(connection -> {
|
|
@@ -122,6 +137,7 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
|
}
|
|
|
|
private void updateConnection(ServerPlayer player, WaypointTransmitter waypoint, WaypointTransmitter.Connection connection) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, "Cannot update waypoint connection off-main"); // DivineMC - Parallel world ticking
|
|
if (player != waypoint) {
|
|
if (isLocatorBarEnabledFor(player)) {
|
|
if (!connection.isBroken()) {
|
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
|
index 88855cb5d55f1bf6c711e441b037a44f61b8ab27..0915a08bc8d2dd38ade01e31c34abd69e1abd365 100644
|
|
--- a/net/minecraft/world/entity/Entity.java
|
|
+++ b/net/minecraft/world/entity/Entity.java
|
|
@@ -3461,14 +3461,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<Entity> 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.config.DivineConfig.AsyncCategory.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;
|
|
}
|
|
@@ -4045,6 +4065,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
|
}
|
|
|
|
private Entity teleportCrossDimension(ServerLevel oldLevel, ServerLevel newLevel, TeleportTransition teleportTransition) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(newLevel, "Cannot teleport entity to another world off-main, from world " + oldLevel.getWorld().getName() + " to world " + newLevel.getWorld().getName()); // DivineMC - Parallel world ticking
|
|
List<Entity> passengers = this.getPassengers();
|
|
List<Entity> list = new ArrayList<>(passengers.size());
|
|
this.ejectPassengers();
|
|
diff --git a/net/minecraft/world/entity/PortalProcessor.java b/net/minecraft/world/entity/PortalProcessor.java
|
|
index 91f6d43b3785ddad7db8eb529ba3293c45f3588d..7fd5f40ee928330769bbe0c5e8da17fa65b30db6 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.async.world.TeleportState teleportState = org.bxteam.divinemc.async.world.TeleportState.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;
|
|
@@ -52,7 +54,7 @@ public class PortalProcessor {
|
|
}
|
|
|
|
public boolean hasExpired() {
|
|
- return this.portalTime <= 0;
|
|
+ return !this.isParallelTeleportScheduled() && this.portalTime <= 0; // DivineMC - Parallel world ticking
|
|
}
|
|
|
|
public BlockPos getEntryPosition() {
|
|
@@ -78,4 +80,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.async.world.TeleportState.PENDING;
|
|
+ }
|
|
+
|
|
+ public boolean isParallelTeleportScheduled() {
|
|
+ return this.teleportState != org.bxteam.divinemc.async.world.TeleportState.INACTIVE;
|
|
+ }
|
|
+
|
|
+ public boolean isParallelCancelledByPlugin() {
|
|
+ return this.teleportState == org.bxteam.divinemc.async.world.TeleportState.CANCELLED;
|
|
+ }
|
|
+
|
|
+ public void setParallelAsScheduled() {
|
|
+ this.teleportState = org.bxteam.divinemc.async.world.TeleportState.PENDING;
|
|
+ }
|
|
+
|
|
+ public void confirmParallelAsHandled() {
|
|
+ this.teleportState = org.bxteam.divinemc.async.world.TeleportState.INACTIVE;
|
|
+ }
|
|
+
|
|
+ public void setParallelAsCancelled() {
|
|
+ this.teleportState = org.bxteam.divinemc.async.world.TeleportState.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..d972bcdba9c26cb66fedae58ca9658bb465e3af2 100644
|
|
--- a/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java
|
|
+++ b/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java
|
|
@@ -44,15 +44,31 @@ public class GoToPotentialJobSite extends Behavior<Villager> {
|
|
Optional<GlobalPos> memory = entity.getBrain().getMemory(MemoryModuleType.POTENTIAL_JOB_SITE);
|
|
memory.ifPresent(globalPos -> {
|
|
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
|
|
+ ServerLevel entityLevel = level;
|
|
+ ServerLevel poiLevel = entityLevel.getServer().getLevel(globalPos.dimension());
|
|
+
|
|
+ if (poiLevel != null) {
|
|
+ Runnable poiOperationsTask = () -> {
|
|
+ PoiManager poiManager = poiLevel.getPoiManager();
|
|
+ if (poiManager.exists(blockPos, holder -> true)) {
|
|
+ poiManager.release(blockPos);
|
|
+ }
|
|
+ };
|
|
|
|
- DebugPackets.sendPoiTicketCountPacket(level, blockPos);
|
|
+ Runnable debugPacketTask = () -> {
|
|
+ DebugPackets.sendPoiTicketCountPacket(entityLevel, blockPos);
|
|
+ };
|
|
+
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ poiLevel.moonrise$getChunkTaskScheduler().scheduleChunkTask(blockPos.getX() >> 4, blockPos.getZ() >> 4, poiOperationsTask, ca.spottedleaf.concurrentutil.util.Priority.BLOCKING);
|
|
+ entityLevel.moonrise$getChunkTaskScheduler().scheduleChunkTask(entity.chunkPosition().x, entity.chunkPosition().z, debugPacketTask, ca.spottedleaf.concurrentutil.util.Priority.BLOCKING);
|
|
+ } else {
|
|
+ poiOperationsTask.run();
|
|
+ debugPacketTask.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 8eb4a35b08f0d0325608f782ac617bc6b01787a0..00cd08ebbb2cc8b258e0e2b68db1728a9b4335a9 100644
|
|
--- a/net/minecraft/world/entity/npc/Villager.java
|
|
+++ b/net/minecraft/world/entity/npc/Villager.java
|
|
@@ -795,13 +795,24 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
|
this.brain.getMemory(moduleType).ifPresent(pos -> {
|
|
ServerLevel level = server.getLevel(pos.dimension());
|
|
if (level != null) {
|
|
- PoiManager poiManager = level.getPoiManager();
|
|
- Optional<Holder<PoiType>> type = poiManager.getType(pos.pos());
|
|
- BiPredicate<Villager, Holder<PoiType>> biPredicate = POI_MEMORIES.get(moduleType);
|
|
- if (type.isPresent() && biPredicate.test(this, type.get())) {
|
|
- poiManager.release(pos.pos());
|
|
- DebugPackets.sendPoiTicketCountPacket(level, pos.pos());
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ Runnable releasePoiTask = () -> {
|
|
+ PoiManager poiManager = level.getPoiManager();
|
|
+ Optional<Holder<PoiType>> type = poiManager.getType(pos.pos());
|
|
+ BiPredicate<Villager, Holder<PoiType>> biPredicate = POI_MEMORIES.get(moduleType);
|
|
+ if (type.isPresent() && biPredicate.test(this, type.get())) {
|
|
+ poiManager.release(pos.pos());
|
|
+ DebugPackets.sendPoiTicketCountPacket(level, pos.pos());
|
|
+ }
|
|
+ };
|
|
+
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.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 2258736e6f9f52efe5bd353b8949a7a0b9a4fdb8..440fbe301782e81cec679a27a876dd3c0bf8615e 100644
|
|
--- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
|
|
+++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
|
|
@@ -119,40 +119,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.snapTo(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<ServerPlayer> 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.snapTo(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.level(), 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.level(), 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.config.DivineConfig.AsyncCategory.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 2305a3ef6bbb21ab77cb261f20c08ac8ce1bf9ed..b313f6a4e27f6918d174dacba37479a93936668f 100644
|
|
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
|
|
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
|
@@ -96,8 +96,14 @@ public abstract class AbstractContainerMenu {
|
|
|
|
public void startOpen() {}
|
|
// CraftBukkit end
|
|
+ public Throwable containerCreationStacktrace; // DivineMC - Parallel world ticking
|
|
|
|
protected AbstractContainerMenu(@Nullable MenuType<?> menuType, int containerId) {
|
|
+ // DivineMC start - Parallel world ticking (debugging)
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.logContainerCreationStacktraces) {
|
|
+ this.containerCreationStacktrace = new Throwable();
|
|
+ }
|
|
+ // 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 d3892cc9ef3ab66a45fe3ab72e8a5ef8b904b7c0..6b5b6d73897ded23dd2fbf17abb1b5c1ee5b1082 100644
|
|
--- a/net/minecraft/world/item/ItemStack.java
|
|
+++ b/net/minecraft/world/item/ItemStack.java
|
|
@@ -398,8 +398,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;
|
|
+ // 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<org.bukkit.craftbukkit.block.CraftBlockState> 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 bf38e3bfcb0b96c4529d5e535893043512f52b02..dc82e12783989c307be2ac709a21321dac25f217 100644
|
|
--- a/net/minecraft/world/level/Level.java
|
|
+++ b/net/minecraft/world/level/Level.java
|
|
@@ -160,6 +160,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
|
|
|
|
public final org.purpurmc.purpur.PurpurWorldConfig purpurConfig; // Purpur - Purpur config files
|
|
public final org.bxteam.divinemc.config.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 static @Nullable BlockPos lastPhysicsProblem; // Spigot
|
|
private int tileTickPosition;
|
|
public final Map<ServerExplosion.CacheKey, Float> explosionDensityCache = new java.util.HashMap<>(); // Paper - Optimize explosions
|
|
@@ -1134,6 +1135,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
|
|
|
|
@Override
|
|
public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.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
|
|
@@ -1517,11 +1519,12 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
|
|
this.blockEntityTickers.markAsRemoved(this.tileTickPosition); // DivineMC - optimize block entity removals - Fix MC-117075
|
|
} else if (runsNormally && this.shouldTickBlocksAt(tickingBlockEntity.getPos())) {
|
|
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.config.DivineConfig.AsyncCategory.enableParallelWorldTicking && (tickedEntities & 7) == 0) {
|
|
+ this.moonrise$midTickTasks();
|
|
}
|
|
- // Paper end - rewrite chunk system
|
|
+ // DivineMC end - Parallel world ticking
|
|
}
|
|
}
|
|
this.blockEntityTickers.removeMarkedEntries(); // DivineMC - optimize block entity removals - Fix MC-117075
|
|
@@ -1541,7 +1544,11 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
|
|
entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
|
// Paper end - Prevent block entity and entity crashes
|
|
}
|
|
- this.moonrise$midTickTasks(); // Paper - rewrite chunk system
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (!org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ this.moonrise$midTickTasks(); // Paper - rewrite chunk system
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
}
|
|
|
|
// Paper start - Option to prevent armor stands from doing entity lookups
|
|
@@ -1678,6 +1685,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
|
|
@Nullable
|
|
@Override
|
|
public BlockEntity getBlockEntity(BlockPos pos) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.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) {
|
|
@@ -1694,6 +1702,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
|
|
}
|
|
|
|
public void setBlockEntity(BlockEntity blockEntity) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.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
|
|
@@ -1778,6 +1787,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
|
|
|
|
@Override
|
|
public List<Entity> getEntities(@Nullable Entity entity, AABB boundingBox, Predicate<? super Entity> predicate) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, boundingBox, "Cannot getEntities asynchronously"); // DivineMC - Parallel world ticking (additional concurrency issues logs)
|
|
List<Entity> list = Lists.newArrayList();
|
|
|
|
// Paper start - rewrite chunk system
|
|
@@ -2100,8 +2110,15 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
|
|
public abstract RecipeAccess recipeAccess();
|
|
|
|
public BlockPos getBlockRandomPos(int x, int y, int z, int yMask) {
|
|
- this.randValue = this.randValue * 3 + 1013904223;
|
|
- int i = this.randValue >> 2;
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ int i;
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ i = this.random.nextInt() >> 2;
|
|
+ } else {
|
|
+ this.randValue = this.randValue * 3 + 1013904223;
|
|
+ i = this.randValue >> 2;
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
return new BlockPos(x + (i & 15), y + (i >> 16 & yMask), z + (i >> 8 & 15));
|
|
}
|
|
|
|
diff --git a/net/minecraft/world/level/block/FungusBlock.java b/net/minecraft/world/level/block/FungusBlock.java
|
|
index 9711efb088bd0da9168e9bcd0496bd7caddd2974..ea310d53f728aaf5de3284b372ed393e4225a52f 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 VegetationBlock implements BonemealableBlock {
|
|
// CraftBukkit start
|
|
.map((value) -> {
|
|
if (this == Blocks.WARPED_FUNGUS) {
|
|
- SaplingBlock.treeType = org.bukkit.TreeType.WARPED_FUNGUS;
|
|
+ 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.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 d306f5f524dc64618df94c9783c2168dc561a5e3..6a0c4dc2ff5e3d82e811db63dc9da7b93e6f2cc9 100644
|
|
--- a/net/minecraft/world/level/block/MushroomBlock.java
|
|
+++ b/net/minecraft/world/level/block/MushroomBlock.java
|
|
@@ -93,7 +93,7 @@ public class MushroomBlock extends VegetationBlock implements BonemealableBlock
|
|
return false;
|
|
} else {
|
|
level.removeBlock(pos, false);
|
|
- SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? org.bukkit.TreeType.BROWN_MUSHROOM : org.bukkit.TreeType.RED_MUSHROOM; // CraftBukkit
|
|
+ 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 {
|
|
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
|
index 1943a6aad888647953e2d9dbbeedb0bd81c6f9df..48c5c13f993f5c30912833a99c82071942c83401 100644
|
|
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
|
|
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
|
@@ -66,6 +66,7 @@ public class RedStoneWireBlock extends Block {
|
|
private final BlockState crossState;
|
|
private final RedstoneWireEvaluator evaluator = new DefaultRedstoneWireEvaluator(this);
|
|
public boolean shouldSignal = true;
|
|
+ private final ThreadLocal<Boolean> shouldSignalTL = ThreadLocal.withInitial(() -> true); // DivineMC - Parallel world ticking
|
|
|
|
@Override
|
|
public MapCodec<RedStoneWireBlock> codec() {
|
|
@@ -283,7 +284,13 @@ public class RedStoneWireBlock extends Block {
|
|
if (orientation != null) {
|
|
source = pos.relative(orientation.getFront().getOpposite());
|
|
}
|
|
- turbo.updateSurroundingRedstone(worldIn, pos, state, source);
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ worldIn.turbo.updateSurroundingRedstone(worldIn, pos, state, source);
|
|
+ } else {
|
|
+ turbo.updateSurroundingRedstone(worldIn, pos, state, source);
|
|
+ }
|
|
+ // DivineMC end
|
|
return;
|
|
}
|
|
updatePowerStrength(worldIn, pos, state, orientation, blockAdded);
|
|
@@ -311,7 +318,13 @@ public class RedStoneWireBlock extends Block {
|
|
// [Space Walker] suppress shape updates and emit those manually to
|
|
// bypass the new neighbor update stack.
|
|
if (level.setBlock(pos, state, Block.UPDATE_KNOWN_SHAPE | Block.UPDATE_CLIENTS)) {
|
|
- turbo.updateNeighborShapes(level, pos, state);
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ level.turbo.updateNeighborShapes(level, pos, state);
|
|
+ } else {
|
|
+ turbo.updateNeighborShapes(level, pos, state);
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
}
|
|
}
|
|
}
|
|
@@ -328,10 +341,19 @@ public class RedStoneWireBlock extends Block {
|
|
}
|
|
|
|
public int getBlockSignal(Level level, BlockPos pos) {
|
|
- this.shouldSignal = false;
|
|
- int bestNeighborSignal = level.getBestNeighborSignal(pos);
|
|
- this.shouldSignal = true;
|
|
- return bestNeighborSignal;
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ this.shouldSignalTL.set(false);
|
|
+ int bestNeighborSignal = level.getBestNeighborSignal(pos);
|
|
+ this.shouldSignalTL.set(true);
|
|
+ return bestNeighborSignal;
|
|
+ } else {
|
|
+ this.shouldSignal = false;
|
|
+ int bestNeighborSignal = level.getBestNeighborSignal(pos);
|
|
+ this.shouldSignal = true;
|
|
+ return bestNeighborSignal;
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
}
|
|
|
|
private void checkCornerChangeAt(Level level, BlockPos pos) {
|
|
@@ -422,12 +444,23 @@ public class RedStoneWireBlock extends Block {
|
|
|
|
@Override
|
|
protected int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) {
|
|
- return !this.shouldSignal ? 0 : blockState.getSignal(blockAccess, pos, side);
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ boolean signal = org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking ? this.shouldSignalTL.get() : this.shouldSignal;
|
|
+ return !signal ? 0 : blockState.getSignal(blockAccess, pos, side);
|
|
+ // DivineMC end - Parallel world ticking
|
|
}
|
|
|
|
@Override
|
|
protected int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) {
|
|
- if (this.shouldSignal && side != Direction.DOWN) {
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ boolean signal;
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ signal = this.shouldSignalTL.get();
|
|
+ } else {
|
|
+ signal = this.shouldSignal;
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
+ if (signal && side != Direction.DOWN) { // DivineMC - Parallel world ticking
|
|
int powerValue = blockState.getValue(POWER);
|
|
if (powerValue == 0) {
|
|
return 0;
|
|
@@ -459,7 +492,13 @@ public class RedStoneWireBlock extends Block {
|
|
|
|
@Override
|
|
protected boolean isSignalSource(BlockState state) {
|
|
- return this.shouldSignal;
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) {
|
|
+ return this.shouldSignalTL.get();
|
|
+ } else {
|
|
+ return this.shouldSignal;
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
}
|
|
|
|
public static int getColorForPower(int power) {
|
|
diff --git a/net/minecraft/world/level/block/SaplingBlock.java b/net/minecraft/world/level/block/SaplingBlock.java
|
|
index a22cb810622e0ae97bc2a0d6390d026d9482b783..5856178e41523700ca7ed9a46c1c802c33903b53 100644
|
|
--- a/net/minecraft/world/level/block/SaplingBlock.java
|
|
+++ b/net/minecraft/world/level/block/SaplingBlock.java
|
|
@@ -26,6 +26,26 @@ public class SaplingBlock extends VegetationBlock implements BonemealableBlock {
|
|
private static final VoxelShape SHAPE = Block.column(12.0, 0.0, 12.0);
|
|
protected final TreeGrower treeGrower;
|
|
public static @javax.annotation.Nullable org.bukkit.TreeType treeType; // CraftBukkit
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ public static final ThreadLocal<org.bukkit.TreeType> treeTypeTL = new ThreadLocal<>();
|
|
+
|
|
+ public static org.bukkit.TreeType getTreeTypeTL() {
|
|
+ org.bukkit.TreeType treeTypeRTCopy;
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking && (treeTypeRTCopy = treeTypeTL.get()) != null) return treeTypeRTCopy;
|
|
+
|
|
+ synchronized (SaplingBlock.class) {
|
|
+ return treeType;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void setTreeTypeTL(org.bukkit.TreeType value) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) treeTypeTL.set(value);
|
|
+
|
|
+ synchronized (SaplingBlock.class) {
|
|
+ treeType = value;
|
|
+ }
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
|
|
@Override
|
|
public MapCodec<? extends SaplingBlock> codec() {
|
|
@@ -62,14 +82,16 @@ public class SaplingBlock extends VegetationBlock 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 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<org.bukkit.block.BlockState> 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 5a094257a31f0500278a706a418e1697f8810ffb..3df0633fe4e632f7d42289facf4ad79978d50c40 100644
|
|
--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
|
@@ -76,6 +76,12 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
|
|
}
|
|
|
|
public static boolean canUnlock(Player player, LockCode code, Component displayName, @Nullable BlockEntity blockEntity) {
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking && player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != serverPlayer.level()) {
|
|
+ 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
|
|
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 0a94670dc20bb9c521b0395633eb100393895f6a..4ad9c47862a9791f72a18835a343bf0e962c14c8 100644
|
|
--- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
|
|
@@ -43,9 +43,7 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi
|
|
// Paper end - Fix NPE in SculkBloomEvent world access
|
|
|
|
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.
|
|
sculkCatalyst.catalystListener.getSculkSpreader().updateCursors(level, pos, level.getRandom(), true);
|
|
- org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit
|
|
}
|
|
|
|
@Override
|
|
diff --git a/net/minecraft/world/level/block/grower/TreeGrower.java b/net/minecraft/world/level/block/grower/TreeGrower.java
|
|
index d23f255de9208f42125fa358a9e8194c984fe4d3..92e9bc9ba577474ca1108b8d0615739502ca5e57 100644
|
|
--- a/net/minecraft/world/level/block/grower/TreeGrower.java
|
|
+++ b/net/minecraft/world/level/block/grower/TreeGrower.java
|
|
@@ -203,55 +203,59 @@ public final class TreeGrower {
|
|
|
|
// CraftBukkit start
|
|
private void setTreeType(Holder<ConfiguredFeature<?, ?>> feature) {
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ org.bukkit.TreeType treeType;
|
|
if (feature.is(TreeFeatures.OAK) || feature.is(TreeFeatures.OAK_BEES_005)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.TREE;
|
|
+ treeType = org.bukkit.TreeType.TREE;
|
|
} else if (feature.is(TreeFeatures.HUGE_RED_MUSHROOM)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.RED_MUSHROOM;
|
|
+ treeType = org.bukkit.TreeType.RED_MUSHROOM;
|
|
} else if (feature.is(TreeFeatures.HUGE_BROWN_MUSHROOM)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.BROWN_MUSHROOM;
|
|
+ treeType = org.bukkit.TreeType.BROWN_MUSHROOM;
|
|
} else if (feature.is(TreeFeatures.JUNGLE_TREE)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.COCOA_TREE;
|
|
+ treeType = org.bukkit.TreeType.COCOA_TREE;
|
|
} else if (feature.is(TreeFeatures.JUNGLE_TREE_NO_VINE)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.SMALL_JUNGLE;
|
|
+ treeType = org.bukkit.TreeType.SMALL_JUNGLE;
|
|
} else if (feature.is(TreeFeatures.PINE)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.TALL_REDWOOD;
|
|
+ treeType = org.bukkit.TreeType.TALL_REDWOOD;
|
|
} else if (feature.is(TreeFeatures.SPRUCE)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.REDWOOD;
|
|
+ treeType = org.bukkit.TreeType.REDWOOD;
|
|
} else if (feature.is(TreeFeatures.ACACIA)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.ACACIA;
|
|
+ treeType = org.bukkit.TreeType.ACACIA;
|
|
} else if (feature.is(TreeFeatures.BIRCH) || feature.is(TreeFeatures.BIRCH_BEES_005)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.BIRCH;
|
|
+ treeType = org.bukkit.TreeType.BIRCH;
|
|
} else if (feature.is(TreeFeatures.SUPER_BIRCH_BEES_0002)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.TALL_BIRCH;
|
|
+ treeType = org.bukkit.TreeType.TALL_BIRCH;
|
|
} else if (feature.is(TreeFeatures.SWAMP_OAK)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.SWAMP;
|
|
+ treeType = org.bukkit.TreeType.SWAMP;
|
|
} else if (feature.is(TreeFeatures.FANCY_OAK) || feature.is(TreeFeatures.FANCY_OAK_BEES_005)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.BIG_TREE;
|
|
+ treeType = org.bukkit.TreeType.BIG_TREE;
|
|
} else if (feature.is(TreeFeatures.JUNGLE_BUSH)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.JUNGLE_BUSH;
|
|
+ treeType = org.bukkit.TreeType.JUNGLE_BUSH;
|
|
} else if (feature.is(TreeFeatures.DARK_OAK)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.DARK_OAK;
|
|
+ treeType = org.bukkit.TreeType.DARK_OAK;
|
|
} else if (feature.is(TreeFeatures.MEGA_SPRUCE)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.MEGA_REDWOOD;
|
|
+ treeType = org.bukkit.TreeType.MEGA_REDWOOD;
|
|
} else if (feature.is(TreeFeatures.MEGA_PINE)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.MEGA_PINE;
|
|
+ treeType = org.bukkit.TreeType.MEGA_PINE;
|
|
} else if (feature.is(TreeFeatures.MEGA_JUNGLE_TREE)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.JUNGLE;
|
|
+ treeType = org.bukkit.TreeType.JUNGLE;
|
|
} else if (feature.is(TreeFeatures.AZALEA_TREE)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.AZALEA;
|
|
+ treeType = org.bukkit.TreeType.AZALEA;
|
|
} else if (feature.is(TreeFeatures.MANGROVE)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.MANGROVE;
|
|
+ treeType = org.bukkit.TreeType.MANGROVE;
|
|
} else if (feature.is(TreeFeatures.TALL_MANGROVE)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.TALL_MANGROVE;
|
|
+ treeType = org.bukkit.TreeType.TALL_MANGROVE;
|
|
} else if (feature.is(TreeFeatures.CHERRY) || feature.is(TreeFeatures.CHERRY_BEES_005)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.CHERRY;
|
|
+ treeType = org.bukkit.TreeType.CHERRY;
|
|
} else if (feature.is(TreeFeatures.PALE_OAK) || feature.is(TreeFeatures.PALE_OAK_BONEMEAL)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.PALE_OAK;
|
|
+ treeType = org.bukkit.TreeType.PALE_OAK;
|
|
} else if (feature.is(TreeFeatures.PALE_OAK_CREAKING)) {
|
|
- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.PALE_OAK_CREAKING;
|
|
+ treeType = org.bukkit.TreeType.PALE_OAK_CREAKING;
|
|
} else {
|
|
throw new IllegalArgumentException("Unknown tree generator " + feature);
|
|
}
|
|
+ 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 6f25be39103cd0bb26bc365d9599b9846c6fe133..24f13e2b0b694ff4dd01aeea876ef874f1828304 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
|
|
@Override
|
|
public BlockState setBlockState(BlockPos pos, BlockState state, int flags) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, pos, "Updating block asynchronously"); // DivineMC - Parallel world ticking
|
|
int y = pos.getY();
|
|
LevelChunkSection section = this.getSection(this.getSectionIndex(y));
|
|
boolean hasOnlyAir = section.hasOnlyAir();
|
|
diff --git a/net/minecraft/world/level/entity/EntityTickList.java b/net/minecraft/world/level/entity/EntityTickList.java
|
|
index c89701d7bdc9b889038d3c52f2232fb17624b113..f2ba43b92b0d0356a97069fd427f9fa446d6c007 100644
|
|
--- a/net/minecraft/world/level/entity/EntityTickList.java
|
|
+++ b/net/minecraft/world/level/entity/EntityTickList.java
|
|
@@ -11,16 +11,31 @@ import net.minecraft.world.entity.Entity;
|
|
public class EntityTickList {
|
|
public final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<net.minecraft.world.entity.Entity> entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system
|
|
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ @Nullable
|
|
+ private final net.minecraft.server.level.ServerLevel serverLevel;
|
|
+
|
|
+ public EntityTickList() {
|
|
+ this(null);
|
|
+ }
|
|
+
|
|
+ public EntityTickList(@Nullable net.minecraft.server.level.ServerLevel serverLevel) {
|
|
+ this.serverLevel = serverLevel;
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
+
|
|
private void ensureActiveIsNotIterated() {
|
|
// Paper - rewrite chunk system
|
|
}
|
|
|
|
public void add(Entity entity) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(entity, "Asynchronous entity ticklist addition"); // DivineMC - Parallel world ticking
|
|
this.ensureActiveIsNotIterated();
|
|
this.entities.add(entity); // Paper - rewrite chunk system
|
|
}
|
|
|
|
public void remove(Entity entity) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(entity, "Asynchronous entity ticklist removal"); // DivineMC - Parallel world ticking
|
|
this.ensureActiveIsNotIterated();
|
|
this.entities.remove(entity); // Paper - rewrite chunk system
|
|
}
|
|
@@ -30,6 +45,7 @@ public class EntityTickList {
|
|
}
|
|
|
|
public void forEach(Consumer<Entity> entity) {
|
|
+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.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/net/minecraft/world/level/saveddata/maps/MapIndex.java b/net/minecraft/world/level/saveddata/maps/MapIndex.java
|
|
index 06025d79cc2297119b22224d777aca79f9d3d9c1..53e6a478eafec512be42422898e7fb334015946b 100644
|
|
--- a/net/minecraft/world/level/saveddata/maps/MapIndex.java
|
|
+++ b/net/minecraft/world/level/saveddata/maps/MapIndex.java
|
|
@@ -23,8 +23,12 @@ public class MapIndex extends SavedData {
|
|
}
|
|
|
|
public MapId getNextMapId() {
|
|
- MapId mapId = new MapId(++this.lastMapId);
|
|
- this.setDirty();
|
|
- return mapId;
|
|
+ // DivineMC start - Parallel world ticking
|
|
+ synchronized (TYPE) {
|
|
+ MapId mapId = new MapId(++this.lastMapId);
|
|
+ this.setDirty();
|
|
+ return mapId;
|
|
+ }
|
|
+ // DivineMC end - Parallel world ticking
|
|
}
|
|
}
|