diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/BackendDebugFlags.java b/common/src/backend/java/dev/engine_room/flywheel/backend/BackendDebugFlags.java
new file mode 100644
index 000000000..66704fecc
--- /dev/null
+++ b/common/src/backend/java/dev/engine_room/flywheel/backend/BackendDebugFlags.java
@@ -0,0 +1,5 @@
+package dev.engine_room.flywheel.backend;
+
+public class BackendDebugFlags {
+ public static boolean LIGHT_STORAGE_VIEW = false;
+}
diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java
index 060cf6f7d..c9539ca95 100644
--- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java
+++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java
@@ -10,6 +10,7 @@ import dev.engine_room.flywheel.api.visual.Effect;
import dev.engine_room.flywheel.api.visual.EffectVisual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.api.visualization.VisualizationManager;
+import dev.engine_room.flywheel.backend.BackendDebugFlags;
import dev.engine_room.flywheel.backend.SkyLightSectionStorageExtension;
import dev.engine_room.flywheel.backend.engine.indirect.StagingBuffer;
import dev.engine_room.flywheel.backend.gl.buffer.GlBuffer;
@@ -49,8 +50,6 @@ import net.minecraft.world.level.chunk.DataLayer;
*
Thus, each section occupies 5832 bytes.
*/
public class LightStorage implements Effect {
- public static boolean DEBUG = false;
-
public static final int BLOCKS_PER_SECTION = 18 * 18 * 18;
public static final int LIGHT_SIZE_BYTES = BLOCKS_PER_SECTION;
public static final int SOLID_SIZE_BYTES = MoreMath.ceilingDiv(BLOCKS_PER_SECTION, Integer.SIZE) * Integer.BYTES;
@@ -108,12 +107,12 @@ public class LightStorage implements Effect {
public Plan createFramePlan() {
return SimplePlan.of(() -> {
- if (DEBUG != isDebugOn) {
+ if (BackendDebugFlags.LIGHT_STORAGE_VIEW != isDebugOn) {
var visualizationManager = VisualizationManager.get(level);
// Really should be non-null, but just in case.
if (visualizationManager != null) {
- if (DEBUG) {
+ if (BackendDebugFlags.LIGHT_STORAGE_VIEW) {
visualizationManager.effects()
.queueAdd(this);
} else {
@@ -121,7 +120,7 @@ public class LightStorage implements Effect {
.queueRemove(this);
}
}
- isDebugOn = DEBUG;
+ isDebugOn = BackendDebugFlags.LIGHT_STORAGE_VIEW;
}
if (updatedSections.isEmpty() && requestedSections == null) {
diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/ConditionalPlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/ConditionalPlan.java
new file mode 100644
index 000000000..143bf3939
--- /dev/null
+++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/ConditionalPlan.java
@@ -0,0 +1,44 @@
+package dev.engine_room.flywheel.lib.task;
+
+import dev.engine_room.flywheel.api.task.Plan;
+import dev.engine_room.flywheel.api.task.TaskExecutor;
+import dev.engine_room.flywheel.lib.task.functional.BooleanSupplierWithContext;
+
+/**
+ * Executes one plan or another, depending on a dynamically evaluated condition.
+ *
+ * @param condition The condition to branch on.
+ * @param onTrue The plan to execute if the condition is true.
+ * @param The type of the context object.
+ */
+public record ConditionalPlan(BooleanSupplierWithContext condition,
+ Plan onTrue) implements SimplyComposedPlan {
+ public static Builder on(BooleanSupplierWithContext condition) {
+ return new Builder<>(condition);
+ }
+
+ public static Builder on(BooleanSupplierWithContext.Ignored condition) {
+ return new Builder<>(condition);
+ }
+
+ @Override
+ public void execute(TaskExecutor taskExecutor, C context, Runnable onCompletion) {
+ if (condition.getAsBoolean(context)) {
+ onTrue.execute(taskExecutor, context, onCompletion);
+ } else {
+ onCompletion.run();
+ }
+ }
+
+ public static final class Builder {
+ private final BooleanSupplierWithContext condition;
+
+ public Builder(BooleanSupplierWithContext condition) {
+ this.condition = condition;
+ }
+
+ public ConditionalPlan then(Plan onTrue) {
+ return new ConditionalPlan<>(condition, onTrue);
+ }
+ }
+}
diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/ImplDebugFlags.java b/common/src/main/java/dev/engine_room/flywheel/impl/ImplDebugFlags.java
new file mode 100644
index 000000000..4072110ae
--- /dev/null
+++ b/common/src/main/java/dev/engine_room/flywheel/impl/ImplDebugFlags.java
@@ -0,0 +1,8 @@
+package dev.engine_room.flywheel.impl;
+
+public class ImplDebugFlags {
+ /**
+ * Debug flag to globally turn beginFrame/tick off.
+ */
+ public static boolean PAUSE_UPDATES = false;
+}
diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java
index 1cc6667a7..0bef0fd10 100644
--- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java
+++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java
@@ -15,6 +15,8 @@ import dev.engine_room.flywheel.api.visual.ShaderLightVisual;
import dev.engine_room.flywheel.api.visual.TickableVisual;
import dev.engine_room.flywheel.api.visual.Visual;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
+import dev.engine_room.flywheel.impl.ImplDebugFlags;
+import dev.engine_room.flywheel.lib.task.ConditionalPlan;
import dev.engine_room.flywheel.lib.task.ForEachPlan;
import dev.engine_room.flywheel.lib.task.NestedPlan;
import dev.engine_room.flywheel.lib.task.PlanMap;
@@ -42,11 +44,16 @@ public abstract class Storage {
}
public Plan framePlan() {
- return NestedPlan.of(dynamicVisuals, lightUpdatedVisuals.plan(), ForEachPlan.of(() -> simpleDynamicVisuals, SimpleDynamicVisual::beginFrame));
+ var update = ConditionalPlan.on(() -> !ImplDebugFlags.PAUSE_UPDATES)
+ .then(NestedPlan.of(dynamicVisuals, ForEachPlan.of(() -> simpleDynamicVisuals, SimpleDynamicVisual::beginFrame)));
+
+ // Do light updates regardless.
+ return NestedPlan.of(lightUpdatedVisuals.plan(), update);
}
public Plan tickPlan() {
- return NestedPlan.of(tickableVisuals, ForEachPlan.of(() -> simpleTickableVisuals, SimpleTickableVisual::tick));
+ return ConditionalPlan.on(() -> !ImplDebugFlags.PAUSE_UPDATES)
+ .then(NestedPlan.of(tickableVisuals, ForEachPlan.of(() -> simpleTickableVisuals, SimpleTickableVisual::tick)));
}
public LightUpdatedVisualStorage lightUpdatedVisuals() {
diff --git a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java
index 45e0703d6..f6fa12545 100644
--- a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java
+++ b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java
@@ -8,9 +8,9 @@ import com.mojang.brigadier.context.CommandContext;
import dev.engine_room.flywheel.api.backend.Backend;
import dev.engine_room.flywheel.api.backend.BackendManager;
+import dev.engine_room.flywheel.backend.BackendDebugFlags;
import dev.engine_room.flywheel.backend.compile.LightSmoothness;
import dev.engine_room.flywheel.backend.compile.PipelineCompiler;
-import dev.engine_room.flywheel.backend.engine.LightStorage;
import dev.engine_room.flywheel.backend.engine.uniform.DebugMode;
import dev.engine_room.flywheel.backend.engine.uniform.FrameUniforms;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
@@ -179,12 +179,24 @@ public final class FlwCommands {
debug.then(ClientCommandManager.literal("lightSections")
.then(ClientCommandManager.literal("on")
.executes(context -> {
- LightStorage.DEBUG = true;
+ BackendDebugFlags.LIGHT_STORAGE_VIEW = true;
return Command.SINGLE_SUCCESS;
}))
.then(ClientCommandManager.literal("off")
.executes(context -> {
- LightStorage.DEBUG = false;
+ BackendDebugFlags.LIGHT_STORAGE_VIEW = false;
+ return Command.SINGLE_SUCCESS;
+ })));
+
+ debug.then(ClientCommandManager.literal("pauseUpdates")
+ .then(ClientCommandManager.literal("on")
+ .executes(context -> {
+ ImplDebugFlags.PAUSE_UPDATES = true;
+ return Command.SINGLE_SUCCESS;
+ }))
+ .then(ClientCommandManager.literal("off")
+ .executes(context -> {
+ ImplDebugFlags.PAUSE_UPDATES = false;
return Command.SINGLE_SUCCESS;
})));
diff --git a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java
index 0fcb96d35..8aeb9e45f 100644
--- a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java
+++ b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java
@@ -6,9 +6,9 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import dev.engine_room.flywheel.api.backend.Backend;
import dev.engine_room.flywheel.api.backend.BackendManager;
+import dev.engine_room.flywheel.backend.BackendDebugFlags;
import dev.engine_room.flywheel.backend.compile.LightSmoothness;
import dev.engine_room.flywheel.backend.compile.PipelineCompiler;
-import dev.engine_room.flywheel.backend.engine.LightStorage;
import dev.engine_room.flywheel.backend.engine.uniform.DebugMode;
import dev.engine_room.flywheel.backend.engine.uniform.FrameUniforms;
import net.minecraft.client.Minecraft;
@@ -172,14 +172,27 @@ public final class FlwCommands {
debug.then(Commands.literal("lightSections")
.then(Commands.literal("on")
.executes(context -> {
- LightStorage.DEBUG = true;
+ BackendDebugFlags.LIGHT_STORAGE_VIEW = true;
return Command.SINGLE_SUCCESS;
}))
.then(Commands.literal("off")
.executes(context -> {
- LightStorage.DEBUG = false;
+ BackendDebugFlags.LIGHT_STORAGE_VIEW = false;
return Command.SINGLE_SUCCESS;
})));
+
+ debug.then(Commands.literal("pauseUpdates")
+ .then(Commands.literal("on")
+ .executes(context -> {
+ ImplDebugFlags.PAUSE_UPDATES = true;
+ return Command.SINGLE_SUCCESS;
+ }))
+ .then(Commands.literal("off")
+ .executes(context -> {
+ ImplDebugFlags.PAUSE_UPDATES = false;
+ return Command.SINGLE_SUCCESS;
+ })));
+
return debug;
}