From db8621dcde7d5a8c65900259c41169d8a612cf95 Mon Sep 17 00:00:00 2001 From: Martijn Muijsers Date: Wed, 1 Feb 2023 00:18:03 +0100 Subject: [PATCH] Add multithreaded ticking configuration --- patches/server/0157-Split-tick-steps.patch | 26 +- ...58-Define-server-children-tick-steps.patch | 199 ----------- .../server/0158-Multithreaded-ticking.patch | 308 ++++++++++++++++++ 3 files changed, 317 insertions(+), 216 deletions(-) delete mode 100644 patches/server/0158-Define-server-children-tick-steps.patch create mode 100644 patches/server/0158-Multithreaded-ticking.patch diff --git a/patches/server/0157-Split-tick-steps.patch b/patches/server/0157-Split-tick-steps.patch index bc49e8c..d3fc169 100644 --- a/patches/server/0157-Split-tick-steps.patch +++ b/patches/server/0157-Split-tick-steps.patch @@ -7,18 +7,10 @@ License: AGPL-3.0 (https://www.gnu.org/licenses/agpl-3.0.html) Gale - https://galemc.org diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 7ed820d2483bf6741a355b062f062a04866ba938..d39b432ed49257901e0432c73ecd1a84f404a8d2 100644 +index 7ed820d2483bf6741a355b062f062a04866ba938..575f8ba79cf3547b837abb5957fed0aa29e1d0cf 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -42,6 +42,7 @@ import java.util.concurrent.CompletableFuture; - import java.util.concurrent.Executor; - import java.util.concurrent.atomic.AtomicReference; - import java.util.function.BooleanSupplier; -+import java.util.function.Consumer; - import java.util.function.Function; - import java.util.stream.Collectors; - import java.util.stream.Stream; -@@ -154,7 +155,6 @@ import org.galemc.gale.executor.annotation.thread.OriginalServerThreadOnly; +@@ -154,7 +154,6 @@ import org.galemc.gale.executor.annotation.thread.OriginalServerThreadOnly; import org.galemc.gale.executor.queue.BaseTaskQueues; import org.galemc.gale.executor.queue.ScheduledServerThreadTaskQueues; import org.galemc.gale.executor.thread.OriginalServerThread; @@ -26,7 +18,7 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..d39b432ed49257901e0432c73ecd1a84 import org.galemc.gale.executor.thread.pool.BaseThreadActivation; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; -@@ -1576,15 +1576,53 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop +@@ -1576,15 +1575,53 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop co.aikar.timings.TimingsManager.FULL_SERVER_TICK.stopTimingFullServerTick(); // Paper // Gale - final timings calls } @@ -50,7 +42,7 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..d39b432ed49257901e0432c73ecd1a84 + this.tickStep_updateEvents(worldserver); + this.tickStep_tickWorld(worldserver); + this.tickStep_recalculateRegions(worldserver); -+ this.tickStep_clearExplosionDensity(worldserver); ++ this.tickStep_clearExplosionDensityCache(worldserver); + } + this.tickStep_stopIteratingOverLevels(); + this.tickStep_tickConnection(); @@ -81,7 +73,7 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..d39b432ed49257901e0432c73ecd1a84 // CraftBukkit start // Run tasks that are waiting on processing MinecraftTimings.processQueueTimer.startTiming(); // Spigot -@@ -1592,11 +1630,14 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop +@@ -1592,11 +1629,14 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop this.processQueue.remove().run(); } MinecraftTimings.processQueueTimer.stopTiming(); // Spigot @@ -97,7 +89,7 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..d39b432ed49257901e0432c73ecd1a84 final boolean doDaylight = world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT); final long dayTime = world.getDayTime(); long worldTime = world.getGameTime(); -@@ -1611,15 +1652,23 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop +@@ -1611,15 +1651,23 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop new ClientboundSetTimePacket(worldTime, playerTime, doDaylight); entityplayer.connection.send(packet); // Add support for per player time } @@ -123,7 +115,7 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..d39b432ed49257901e0432c73ecd1a84 /* Drop global time updates if (this.tickCount % 20 == 0) { -@@ -1629,16 +1678,28 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop +@@ -1629,16 +1677,28 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop } // CraftBukkit end */ @@ -157,7 +149,7 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..d39b432ed49257901e0432c73ecd1a84 // Spigot Start CrashReport crashreport; try { -@@ -1651,22 +1712,47 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop +@@ -1651,22 +1711,47 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop worldserver.fillReportDetails(crashreport); throw new ReportedException(crashreport); @@ -165,7 +157,7 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..d39b432ed49257901e0432c73ecd1a84 + // Gale start - split tick steps + } -+ public final void tickStep_clearExplosionDensity(ServerLevel worldserver) { ++ public final void tickStep_clearExplosionDensityCache(ServerLevel worldserver) { + // Gale end - split tick steps worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions - } diff --git a/patches/server/0158-Define-server-children-tick-steps.patch b/patches/server/0158-Define-server-children-tick-steps.patch deleted file mode 100644 index 2a47cef..0000000 --- a/patches/server/0158-Define-server-children-tick-steps.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martijn Muijsers -Date: Tue, 31 Jan 2023 22:39:10 +0100 -Subject: [PATCH] Define server children tick steps - -License: AGPL-3.0 (https://www.gnu.org/licenses/agpl-3.0.html) -Gale - https://galemc.org - -diff --git a/src/main/java/org/galemc/gale/tick/step/ServerChildrenTickSteps.java b/src/main/java/org/galemc/gale/tick/step/ServerChildrenTickSteps.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0e438fd13ef36bb7fd572286768ca231a2ef5039 ---- /dev/null -+++ b/src/main/java/org/galemc/gale/tick/step/ServerChildrenTickSteps.java -@@ -0,0 +1,107 @@ -+// Gale - multithreaded ticking -+ -+package org.galemc.gale.tick.step; -+ -+import net.minecraft.server.MinecraftServer; -+ -+/** -+ * A utility class defining the tick steps in {@link MinecraftServer#tickChildren} in a way -+ * that they can be executed both in the default order, or submitted as tasks that may run in parallel. -+ * -+ * @author Martijn Muijsers under AGPL-3.0 -+ */ -+public final class ServerChildrenTickSteps { -+ -+ private ServerChildrenTickSteps() {} -+ -+ public static final ServerTickStep doSchedulerHeartbeat = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_doSchedulerHeartbeat()); -+ public static final ServerTickStep tickFunctions = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_tickFunctions()); -+ public static final ServerTickStep runProcessQueueTasks = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_runProcessQueueTasks()); -+ public static final WorldTickStep sendTimeUpdates = new WorldTickStep(world -> MinecraftServer.SERVER.tickStep_sendTimeUpdates(world)); -+ public static final ServerTickStep startIteratingOverLevels = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_startIteratingOverLevels()); -+ public static final WorldTickStep updateEvents = new WorldTickStep(world -> MinecraftServer.SERVER.tickStep_updateEvents(world)); -+ -+ public static final WorldTickStep updatePlayersAffectingSpawning = new WorldTickStep(world -> world.tickStep_updatePlayersAffectingSpawning.run()); -+ public static final WorldTickStep startHandlingTick = new WorldTickStep(world -> world.tickStep_startHandlingTick.run()); -+ public static final WorldTickStep tickWorldBorder = new WorldTickStep(world -> world.tickStep_tickWorldBorder.run()); -+ public static final WorldTickStep advanceWeatherCycle = new WorldTickStep(world -> world.tickStep_advanceWeatherCycle.run()); -+ public static final WorldTickStep applySleep = new WorldTickStep(world -> world.tickStep_applySleep.run()); -+ public static final WorldTickStep updateSkyBrightness = new WorldTickStep(world -> world.tickStep_updateSkyBrightness.run()); -+ public static final WorldTickStep tickTime = new WorldTickStep(world -> world.tickStep_tickTime.run()); -+ public static final WorldTickStep setScheduledBlocksGameTime = new WorldTickStep(world -> world.tickStep_setScheduledBlocksGameTime.run()); -+ public static final WorldTickStep setIsDebug = new WorldTickStep(world -> world.tickStep_setIsDebug.run()); -+ public static final WorldTickStep tickBlocks = new WorldTickStep(world -> world.tickStep_tickBlocks.run()); -+ public static final WorldTickStep tickFluids = new WorldTickStep(world -> world.tickStep_tickFluids.run()); -+ public static final WorldTickStep tickRaids = new WorldTickStep(world -> world.tickStep_tickRaids.run()); -+ -+ public static final WorldTickStep purgeStaleTickets = new WorldTickStep(world -> world.getChunkSource().tickStep_purgeStaleTickets.run()); -+ public static final WorldTickStep runDistanceManagerUpdates = new WorldTickStep(world -> world.getChunkSource().tickStep_runDistanceManagerUpdates.run()); -+ public static final WorldTickStep tickChunks = new WorldTickStep(world -> world.getChunkSource().tickStep_tickChunks.run()); -+ public static final WorldTickStep tickChunkMap = new WorldTickStep(world -> world.getChunkSource().tickStep_tickChunkMap.run()); -+ public static final WorldTickStep clearCache = new WorldTickStep(world -> world.getChunkSource().tickStep_clearCache.run()); -+ -+ public static final WorldTickStep doRunBlockEvents = new WorldTickStep(world -> world.tickStep_doRunBlockEvents.run()); -+ public static final WorldTickStep stopHandlingTick = new WorldTickStep(world -> world.tickStep_stopHandlingTick.run()); -+ public static final WorldTickStep setDoEntityAndBlockEntityTick = new WorldTickStep(world -> world.tickStep_setDoEntityAndBlockEntityTick.run()); -+ public static final WorldTickStep tickDragonFight = new WorldTickStep(world -> world.tickStep_tickDragonFight.run()); -+ public static final WorldTickStep activateEntities = new WorldTickStep(world -> world.tickStep_activateEntities.run()); -+ public static final WorldTickStep tickEntityList = new WorldTickStep(world -> world.tickStep_tickEntityList.run()); -+ public static final WorldTickStep tickBlockEntities = new WorldTickStep(world -> world.tickStep_tickBlockEntities.run()); -+ -+ public static final WorldTickStep recalculateRegions = new WorldTickStep(world -> MinecraftServer.SERVER.tickStep_recalculateRegions(world)); -+ public static final WorldTickStep clearExplosionDensity = new WorldTickStep(world -> MinecraftServer.SERVER.tickStep_clearExplosionDensity(world)); -+ public static final ServerTickStep stopIteratingOverLevels = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_stopIteratingOverLevels()); -+ public static final ServerTickStep tickConnection = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_tickConnection()); -+ public static final ServerTickStep tickPlayerList = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_tickPlayerList()); -+ public static final ServerTickStep tickGameTestTicker = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_tickGameTestTicker()); -+ public static final ServerTickStep runTickables = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_runTickables()); -+ -+ /** -+ * The {@linkplain TickStep tick steps} that occur in {@link MinecraftServer#tickChildren}, -+ * in the same order. -+ */ -+ public static final TickStep[] values = { -+ doSchedulerHeartbeat, -+ tickFunctions, -+ runProcessQueueTasks, -+ sendTimeUpdates, -+ startIteratingOverLevels, -+ updateEvents, -+ -+ updatePlayersAffectingSpawning, -+ startHandlingTick, -+ tickWorldBorder, -+ advanceWeatherCycle, -+ applySleep, -+ updateSkyBrightness, -+ tickTime, -+ setScheduledBlocksGameTime, -+ setIsDebug, -+ tickBlocks, -+ tickFluids, -+ tickRaids, -+ -+ purgeStaleTickets, -+ runDistanceManagerUpdates, -+ tickChunks, -+ tickChunkMap, -+ clearCache, -+ -+ doRunBlockEvents, -+ stopHandlingTick, -+ setDoEntityAndBlockEntityTick, -+ tickDragonFight, -+ activateEntities, -+ tickEntityList, -+ tickBlockEntities, -+ -+ recalculateRegions, -+ clearExplosionDensity, -+ stopIteratingOverLevels, -+ tickConnection, -+ tickPlayerList, -+ tickGameTestTicker, -+ runTickables -+ }; -+ -+} -diff --git a/src/main/java/org/galemc/gale/tick/step/ServerTickStep.java b/src/main/java/org/galemc/gale/tick/step/ServerTickStep.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8530b7c5cf64572440c05a5539532e245333746f ---- /dev/null -+++ b/src/main/java/org/galemc/gale/tick/step/ServerTickStep.java -@@ -0,0 +1,23 @@ -+// Gale - multithreaded ticking -+ -+package org.galemc.gale.tick.step; -+ -+import net.minecraft.server.level.ServerLevel; -+ -+import java.util.function.Consumer; -+ -+/** -+ * A {@link TickStep} that applies to the whole server (i.e. is run once per tick). -+ * -+ * @author Martijn Muijsers under AGPL-3.0 -+ */ -+public class ServerTickStep extends TickStep { -+ -+ public final Runnable action; -+ -+ ServerTickStep(Runnable action) { -+ super(); -+ this.action = action; -+ } -+ -+} -diff --git a/src/main/java/org/galemc/gale/tick/step/TickStep.java b/src/main/java/org/galemc/gale/tick/step/TickStep.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e07883e4121e3241657f1e60ba46540ab0dd6f08 ---- /dev/null -+++ b/src/main/java/org/galemc/gale/tick/step/TickStep.java -@@ -0,0 +1,14 @@ -+// Gale - multithreaded ticking -+ -+package org.galemc.gale.tick.step; -+ -+/** -+ * An abstract step of ticking, as used in {@link ServerChildrenTickSteps}. -+ * -+ * @author Martijn Muijsers under AGPL-3.0 -+ */ -+public abstract class TickStep { -+ -+ protected TickStep() {} -+ -+} -diff --git a/src/main/java/org/galemc/gale/tick/step/WorldTickStep.java b/src/main/java/org/galemc/gale/tick/step/WorldTickStep.java -new file mode 100644 -index 0000000000000000000000000000000000000000..9c2dddae5f26c4e8db4c7490c23afaf3acb06f2b ---- /dev/null -+++ b/src/main/java/org/galemc/gale/tick/step/WorldTickStep.java -@@ -0,0 +1,23 @@ -+// Gale - multithreaded ticking -+ -+package org.galemc.gale.tick.step; -+ -+import net.minecraft.server.level.ServerLevel; -+ -+import java.util.function.Consumer; -+ -+/** -+ * A {@link TickStep} that applies to each individual world separately. -+ * -+ * @author Martijn Muijsers under AGPL-3.0 -+ */ -+public class WorldTickStep extends TickStep { -+ -+ public final Consumer action; -+ -+ WorldTickStep(Consumer action) { -+ super(); -+ this.action = action; -+ } -+ -+} diff --git a/patches/server/0158-Multithreaded-ticking.patch b/patches/server/0158-Multithreaded-ticking.patch new file mode 100644 index 0000000..d2a52f5 --- /dev/null +++ b/patches/server/0158-Multithreaded-ticking.patch @@ -0,0 +1,308 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martijn Muijsers +Date: Tue, 31 Jan 2023 22:39:10 +0100 +Subject: [PATCH] Multithreaded ticking + +License: AGPL-3.0 (https://www.gnu.org/licenses/agpl-3.0.html) +Gale - https://galemc.org + +diff --git a/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java b/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java +index 39c4fe8fdd806b4b5bc3cb2dfdde9a29b11b386e..6188bfcffeded21563aa8eae0e3d135cc497e386 100644 +--- a/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java ++++ b/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java +@@ -432,4 +432,20 @@ public class GaleGlobalConfiguration extends ConfigurationPart { + + } + ++ // Gale start - multithreading ++ public Multithreading multithreading; ++ public class Multithreading extends ConfigurationPart { ++ ++ // Gale start - multithreaded ticking ++ public Ticking ticking; ++ public class Ticking extends ConfigurationPart { ++ ++ public boolean clearExplosionDensityCache = true; ++ ++ } ++ // Gale end - multithreaded ticking ++ ++ } ++ // Gale end - multithreading ++ + } +diff --git a/src/main/java/org/galemc/gale/tick/step/ServerChildrenTickSteps.java b/src/main/java/org/galemc/gale/tick/step/ServerChildrenTickSteps.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9408c7c6e6b60bd9d5153912a2d85585bc7744d1 +--- /dev/null ++++ b/src/main/java/org/galemc/gale/tick/step/ServerChildrenTickSteps.java +@@ -0,0 +1,146 @@ ++// Gale - multithreaded ticking ++ ++package org.galemc.gale.tick.step; ++ ++import net.minecraft.server.MinecraftServer; ++import org.galemc.gale.configuration.GaleGlobalConfiguration; ++ ++/** ++ * A utility class defining the tick steps in {@link MinecraftServer#tickChildren} in a way ++ * that they can be executed both in the default order, or submitted as tasks that may run in parallel. ++ * ++ * @author Martijn Muijsers under AGPL-3.0 ++ */ ++public final class ServerChildrenTickSteps { ++ ++ private ServerChildrenTickSteps() {} ++ ++ public static final ServerTickStep doSchedulerHeartbeat = ++ new ServerTickStep("doSchedulerHeartbeat", () -> MinecraftServer.SERVER.tickStep_doSchedulerHeartbeat()); ++ public static final ServerTickStep tickFunctions = ++ new ServerTickStep("tickFunctions", () -> MinecraftServer.SERVER.tickStep_tickFunctions()); ++ public static final ServerTickStep runProcessQueueTasks = ++ new ServerTickStep("runProcessQueueTasks", () -> MinecraftServer.SERVER.tickStep_runProcessQueueTasks()); ++ public static final WorldTickStep sendTimeUpdates = ++ new WorldTickStep("sendTimeUpdates", world -> MinecraftServer.SERVER.tickStep_sendTimeUpdates(world)); ++ public static final ServerTickStep startIteratingOverLevels = ++ new ServerTickStep("startIteratingOverLevels", () -> MinecraftServer.SERVER.tickStep_startIteratingOverLevels()); ++ public static final WorldTickStep updateEvents = ++ new WorldTickStep("updateEvents", world -> MinecraftServer.SERVER.tickStep_updateEvents(world)); ++ ++ public static final WorldTickStep updatePlayersAffectingSpawning = ++ new WorldTickStep("updatePlayersAffectingSpawning", world -> world.tickStep_updatePlayersAffectingSpawning.run()); ++ public static final WorldTickStep startHandlingTick = ++ new WorldTickStep("startHandlingTick", world -> world.tickStep_startHandlingTick.run()); ++ public static final WorldTickStep tickWorldBorder = ++ new WorldTickStep("tickWorldBorder", world -> world.tickStep_tickWorldBorder.run()); ++ public static final WorldTickStep advanceWeatherCycle = ++ new WorldTickStep("advanceWeatherCycle", world -> world.tickStep_advanceWeatherCycle.run()); ++ public static final WorldTickStep applySleep = ++ new WorldTickStep("applySleep", world -> world.tickStep_applySleep.run()); ++ public static final WorldTickStep updateSkyBrightness = ++ new WorldTickStep("updateSkyBrightness", world -> world.tickStep_updateSkyBrightness.run()); ++ public static final WorldTickStep tickTime = ++ new WorldTickStep("tickTime", world -> world.tickStep_tickTime.run()); ++ public static final WorldTickStep setScheduledBlocksGameTime = ++ new WorldTickStep("setScheduledBlocksGameTime", world -> world.tickStep_setScheduledBlocksGameTime.run()); ++ public static final WorldTickStep setIsDebug = ++ new WorldTickStep("setIsDebug", world -> world.tickStep_setIsDebug.run()); ++ public static final WorldTickStep tickBlocks = ++ new WorldTickStep("tickBlocks", world -> world.tickStep_tickBlocks.run()); ++ public static final WorldTickStep tickFluids = ++ new WorldTickStep("tickFluids", world -> world.tickStep_tickFluids.run()); ++ public static final WorldTickStep tickRaids = ++ new WorldTickStep("tickRaids", world -> world.tickStep_tickRaids.run()); ++ ++ public static final WorldTickStep purgeStaleTickets = ++ new WorldTickStep("purgeStaleTickets", world -> world.getChunkSource().tickStep_purgeStaleTickets.run()); ++ public static final WorldTickStep runDistanceManagerUpdates = ++ new WorldTickStep("runDistanceManagerUpdates", world -> world.getChunkSource().tickStep_runDistanceManagerUpdates.run()); ++ public static final WorldTickStep tickChunks = ++ new WorldTickStep("tickChunks", world -> world.getChunkSource().tickStep_tickChunks.run()); ++ public static final WorldTickStep tickChunkMap = ++ new WorldTickStep("tickChunkMap", world -> world.getChunkSource().tickStep_tickChunkMap.run()); ++ public static final WorldTickStep clearCache = ++ new WorldTickStep("clearCache", world -> world.getChunkSource().tickStep_clearCache.run()); ++ ++ public static final WorldTickStep doRunBlockEvents = ++ new WorldTickStep("doRunBlockEvents", world -> world.tickStep_doRunBlockEvents.run()); ++ public static final WorldTickStep stopHandlingTick = ++ new WorldTickStep("stopHandlingTick", world -> world.tickStep_stopHandlingTick.run()); ++ public static final WorldTickStep setDoEntityAndBlockEntityTick = ++ new WorldTickStep("setDoEntityAndBlockEntityTick", world -> world.tickStep_setDoEntityAndBlockEntityTick.run()); ++ public static final WorldTickStep tickDragonFight = ++ new WorldTickStep("tickDragonFight", world -> world.tickStep_tickDragonFight.run()); ++ public static final WorldTickStep activateEntities = ++ new WorldTickStep("activateEntities", world -> world.tickStep_activateEntities.run()); ++ public static final WorldTickStep tickEntityList = ++ new WorldTickStep("tickEntityList", world -> world.tickStep_tickEntityList.run()); ++ public static final WorldTickStep tickBlockEntities = ++ new WorldTickStep("tickBlockEntities", world -> world.tickStep_tickBlockEntities.run()); ++ ++ public static final WorldTickStep recalculateRegions = ++ new WorldTickStep("recalculateRegions", world -> MinecraftServer.SERVER.tickStep_recalculateRegions(world)); ++ public static final WorldTickStep clearExplosionDensityCache = (WorldTickStep) ++ new WorldTickStep("clearExplosionDensityCache", world -> MinecraftServer.SERVER.tickStep_clearExplosionDensityCache(world)) ++ .withGetDoMultithreaded(() -> GaleGlobalConfiguration.get().multithreading.ticking.clearExplosionDensityCache); ++ public static final ServerTickStep stopIteratingOverLevels = ++ new ServerTickStep("stopIteratingOverLevels", () -> MinecraftServer.SERVER.tickStep_stopIteratingOverLevels()); ++ public static final ServerTickStep tickConnection = ++ new ServerTickStep("tickConnection", () -> MinecraftServer.SERVER.tickStep_tickConnection()); ++ public static final ServerTickStep tickPlayerList = ++ new ServerTickStep("tickPlayerList", () -> MinecraftServer.SERVER.tickStep_tickPlayerList()); ++ public static final ServerTickStep tickGameTestTicker = ++ new ServerTickStep("tickGameTestTicker", () -> MinecraftServer.SERVER.tickStep_tickGameTestTicker()); ++ public static final ServerTickStep runTickables = ++ new ServerTickStep("runTickables", () -> MinecraftServer.SERVER.tickStep_runTickables()); ++ ++ /** ++ * The {@linkplain TickStep tick steps} that occur in {@link MinecraftServer#tickChildren}, ++ * in the same order. ++ */ ++ public static final TickStep[] values = { ++ doSchedulerHeartbeat, ++ tickFunctions, ++ runProcessQueueTasks, ++ sendTimeUpdates, ++ startIteratingOverLevels, ++ updateEvents, ++ ++ updatePlayersAffectingSpawning, ++ startHandlingTick, ++ tickWorldBorder, ++ advanceWeatherCycle, ++ applySleep, ++ updateSkyBrightness, ++ tickTime, ++ setScheduledBlocksGameTime, ++ setIsDebug, ++ tickBlocks, ++ tickFluids, ++ tickRaids, ++ ++ purgeStaleTickets, ++ runDistanceManagerUpdates, ++ tickChunks, ++ tickChunkMap, ++ clearCache, ++ ++ doRunBlockEvents, ++ stopHandlingTick, ++ setDoEntityAndBlockEntityTick, ++ tickDragonFight, ++ activateEntities, ++ tickEntityList, ++ tickBlockEntities, ++ ++ recalculateRegions, ++ clearExplosionDensityCache, ++ stopIteratingOverLevels, ++ tickConnection, ++ tickPlayerList, ++ tickGameTestTicker, ++ runTickables ++ }; ++ ++} +diff --git a/src/main/java/org/galemc/gale/tick/step/ServerTickStep.java b/src/main/java/org/galemc/gale/tick/step/ServerTickStep.java +new file mode 100644 +index 0000000000000000000000000000000000000000..538dad9bfa0eb982ef0d0ffb96bb8a6ef7d4ca38 +--- /dev/null ++++ b/src/main/java/org/galemc/gale/tick/step/ServerTickStep.java +@@ -0,0 +1,26 @@ ++// Gale - multithreaded ticking ++ ++package org.galemc.gale.tick.step; ++ ++import net.minecraft.server.level.ServerLevel; ++ ++import java.util.function.Consumer; ++ ++/** ++ * A {@link TickStep} that applies to the whole server (i.e. is run once per tick). ++ * ++ * @author Martijn Muijsers under AGPL-3.0 ++ */ ++public class ServerTickStep extends TickStep { ++ ++ /** ++ * A {@link Runnable} that performs this tick step. ++ */ ++ public final Runnable action; ++ ++ ServerTickStep(String name, Runnable action) { ++ super(name); ++ this.action = action; ++ } ++ ++} +diff --git a/src/main/java/org/galemc/gale/tick/step/TickStep.java b/src/main/java/org/galemc/gale/tick/step/TickStep.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d34aa02b1164f96bf614381aca756faba0f044b4 +--- /dev/null ++++ b/src/main/java/org/galemc/gale/tick/step/TickStep.java +@@ -0,0 +1,53 @@ ++// Gale - multithreaded ticking ++ ++package org.galemc.gale.tick.step; ++ ++import java.util.function.Supplier; ++ ++/** ++ * An abstract step of ticking, as used in {@link ServerChildrenTickSteps}. ++ * ++ * @author Martijn Muijsers under AGPL-3.0 ++ */ ++public abstract class TickStep { ++ ++ /** ++ * A human-readable name for this tick step, for use in debugging. ++ */ ++ public final String name; ++ ++ /** ++ * Whether to execute this tick step over multiple threads, as far as possible. ++ *
++ * This value is set by using {@link #updateDoMultithreaded()}. ++ */ ++ public boolean doMultithreaded; ++ ++ /** ++ * The supplier for updating {@link #doMultithreaded} via {@link #updateDoMultithreaded()}. ++ *
++ * This can be set via {@link #withGetDoMultithreaded} ++ */ ++ private Supplier getDoMultiThreaded = () -> false; ++ ++ protected TickStep(String name) { ++ this.name = name; ++ } ++ ++ /** ++ * @param getDoMultithreaded The new value for {@link #getDoMultiThreaded}. ++ * @return This instance. ++ */ ++ TickStep withGetDoMultithreaded(Supplier getDoMultithreaded) { ++ this.getDoMultiThreaded = getDoMultithreaded; ++ return this; ++ } ++ ++ /** ++ * Updates {@link #doMultithreaded} according to {@link #getDoMultiThreaded}. ++ */ ++ public void updateDoMultithreaded() { ++ this.doMultithreaded = this.getDoMultiThreaded.get(); ++ } ++ ++} +diff --git a/src/main/java/org/galemc/gale/tick/step/WorldTickStep.java b/src/main/java/org/galemc/gale/tick/step/WorldTickStep.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2c07a88ffb341ce57a030c5d72b55debbd34fec6 +--- /dev/null ++++ b/src/main/java/org/galemc/gale/tick/step/WorldTickStep.java +@@ -0,0 +1,26 @@ ++// Gale - multithreaded ticking ++ ++package org.galemc.gale.tick.step; ++ ++import net.minecraft.server.level.ServerLevel; ++ ++import java.util.function.Consumer; ++ ++/** ++ * A {@link TickStep} that applies to each individual world separately. ++ * ++ * @author Martijn Muijsers under AGPL-3.0 ++ */ ++public class WorldTickStep extends TickStep { ++ ++ /** ++ * A {@link Consumer} that performs this tick step for a given {@link ServerLevel}. ++ */ ++ public final Consumer action; ++ ++ WorldTickStep(String name, Consumer action) { ++ super(name); ++ this.action = action; ++ } ++ ++}