From 881f71611561cda96e20930a7ff9a15ad5db1333 Mon Sep 17 00:00:00 2001 From: George Date: Sun, 7 Jun 2026 16:42:11 +0100 Subject: [PATCH] Fix two live simulation bugs: profiler crash + regions never updating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit forceUpdateRegion crashed with "no profiling cycle is active" because runModulesForRegion calls profiler.beginModule() which requires an active cycle. Wrapped the call in startCycle/endCycle in a try/finally. Regions showed tick=0 and no module data because SimulationScheduler's priority queue was never populated for normal rolling updates — only explicit queueRegion() calls worked. Fixed by auto-enqueueing all active regions in onMinecraftServerTick() just before each simulation cycle fires. Auto-enqueueing is placed there (not in runSimulationCycle()) so unit tests that drive cycles directly are unaffected. Co-Authored-By: Claude Sonnet 4.6 --- .../core/simulation/RegionManager.java | 8 +++++++- .../core/simulation/SimulationManager.java | 17 ++++++++++++++++- .../core/simulation/SimulationManagerTest.java | 5 +++++ .../testing/LongRunSimulationTest.java | 5 +++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/livingworld/core/simulation/RegionManager.java b/src/main/java/com/livingworld/core/simulation/RegionManager.java index 671d1b6..6952119 100644 --- a/src/main/java/com/livingworld/core/simulation/RegionManager.java +++ b/src/main/java/com/livingworld/core/simulation/RegionManager.java @@ -1,5 +1,6 @@ package com.livingworld.core.simulation; +import java.util.Collection; import java.util.List; import java.util.Optional; @@ -30,9 +31,14 @@ public interface RegionManager { */ List resolveAll(List coordinates); + /** + * Returns all currently active (cached/loaded) regions. + */ + Collection getActiveRegions(); + /** * Marks a region as dirty, indicating unsaved changes. - * + * * @param region the region to mark dirty (must not be null) */ void markDirty(Region region); diff --git a/src/main/java/com/livingworld/core/simulation/SimulationManager.java b/src/main/java/com/livingworld/core/simulation/SimulationManager.java index 24ad402..bbb9d09 100644 --- a/src/main/java/com/livingworld/core/simulation/SimulationManager.java +++ b/src/main/java/com/livingworld/core/simulation/SimulationManager.java @@ -1,5 +1,6 @@ package com.livingworld.core.simulation; +import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.Set; @@ -63,6 +64,11 @@ public final class SimulationManager { this.scheduler.onMinecraftTick(); if (this.scheduler.shouldRunSimulationCycle()) { + long tick = this.timeService.getSimulationTick(); + for (Region r : this.regionManager.getActiveRegions()) { + this.scheduler.queueRegion(new RegionUpdateJob( + r.getCoordinate(), 0, tick, null, UpdateReason.NORMAL_ROLLING_UPDATE)); + } runSimulationCycle(); } } @@ -209,7 +215,16 @@ public final class SimulationManager { long tick = getSimulationTickCounter(); RegionUpdateJob job = new RegionUpdateJob( coordinate, 100, tick, null, UpdateReason.FORCED_DEBUG_COMMAND); - runModulesForRegion(region.get(), job, tick); + if (this.profiler != null) { + this.profiler.startCycle(tick); + } + try { + runModulesForRegion(region.get(), job, tick); + } finally { + if (this.profiler != null) { + this.profiler.endCycle(0); + } + } } /** Returns a profile snapshot of the last completed simulation cycle. */ diff --git a/src/test/java/com/livingworld/core/simulation/SimulationManagerTest.java b/src/test/java/com/livingworld/core/simulation/SimulationManagerTest.java index 7a8502a..fbeea87 100644 --- a/src/test/java/com/livingworld/core/simulation/SimulationManagerTest.java +++ b/src/test/java/com/livingworld/core/simulation/SimulationManagerTest.java @@ -233,6 +233,11 @@ class SimulationManagerTest { return coordinates.stream().map(regions::get).filter(java.util.Objects::nonNull).toList(); } + @Override + public java.util.Collection getActiveRegions() { + return regions.values(); + } + @Override public void markDirty(Region region) { markDirtyCount++; diff --git a/src/test/java/com/livingworld/testing/LongRunSimulationTest.java b/src/test/java/com/livingworld/testing/LongRunSimulationTest.java index 948f19c..5a8c047 100644 --- a/src/test/java/com/livingworld/testing/LongRunSimulationTest.java +++ b/src/test/java/com/livingworld/testing/LongRunSimulationTest.java @@ -158,6 +158,11 @@ class LongRunSimulationTest { .toList(); } + @Override + public Collection getActiveRegions() { + return orderedRegions; + } + @Override public void markDirty(Region region) { region.markDirty();