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; }