diff --git a/src/main/java/com/jozufozu/flywheel/api/visual/DynamicVisual.java b/src/main/java/com/jozufozu/flywheel/api/visual/DynamicVisual.java
index 426fa419c..d246974fc 100644
--- a/src/main/java/com/jozufozu/flywheel/api/visual/DynamicVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/api/visual/DynamicVisual.java
@@ -1,7 +1,6 @@
package com.jozufozu.flywheel.api.visual;
-import com.jozufozu.flywheel.api.instance.Instance;
-import com.jozufozu.flywheel.api.instance.Instancer;
+import com.jozufozu.flywheel.api.task.Plan;
/**
* An interface giving {@link Visual}s a hook to have a function called at
@@ -13,15 +12,5 @@ import com.jozufozu.flywheel.api.instance.Instancer;
* to parameterize the instances, you're encouraged to implement this for prototyping.
*/
public interface DynamicVisual extends Visual {
- /**
- * Called every frame.
- *
- * The implementation is free to parallelize calls to this method.
- * You must ensure proper synchronization if you need to mutate anything outside this visual.
- *
- * This method and {@link TickableVisual#tick} will never be called simultaneously.
- *
- * {@link Instancer}/{@link Instance} creation/acquisition is safe here.
- */
- void beginFrame(VisualFrameContext ctx);
+ Plan planFrame();
}
diff --git a/src/main/java/com/jozufozu/flywheel/api/visual/PlannedVisual.java b/src/main/java/com/jozufozu/flywheel/api/visual/PlannedVisual.java
deleted file mode 100644
index c9c44fffc..000000000
--- a/src/main/java/com/jozufozu/flywheel/api/visual/PlannedVisual.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.jozufozu.flywheel.api.visual;
-
-import com.jozufozu.flywheel.api.task.Plan;
-import com.jozufozu.flywheel.lib.task.UnitPlan;
-
-/**
- * An interface giving {@link Visual}s a way to define complex, parallelized update plans.
- */
-public interface PlannedVisual extends Visual {
- default Plan planFrame() {
- return UnitPlan.of();
- }
-
- default Plan planTick() {
- return UnitPlan.of();
- }
-}
diff --git a/src/main/java/com/jozufozu/flywheel/api/visual/TickableVisual.java b/src/main/java/com/jozufozu/flywheel/api/visual/TickableVisual.java
index 1d4f3056b..e9e3c0087 100644
--- a/src/main/java/com/jozufozu/flywheel/api/visual/TickableVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/api/visual/TickableVisual.java
@@ -1,7 +1,6 @@
package com.jozufozu.flywheel.api.visual;
-import com.jozufozu.flywheel.api.instance.Instance;
-import com.jozufozu.flywheel.api.instance.Instancer;
+import com.jozufozu.flywheel.api.task.Plan;
/**
* An interface giving {@link Visual}s a hook to have a function called at
@@ -20,15 +19,5 @@ import com.jozufozu.flywheel.api.instance.Instancer;
*
*/
public interface TickableVisual extends Visual {
- /**
- * Called every tick.
- *
- * The implementation is free to parallelize calls to this method.
- * You must ensure proper synchronization if you need to mutate anything outside this visual.
- *
- * This method and {@link DynamicVisual#beginFrame} will never be called simultaneously.
- *
- * {@link Instancer}/{@link Instance} creation/acquisition is safe here.
- */
- void tick(VisualTickContext ctx);
+ Plan planTick();
}
diff --git a/src/main/java/com/jozufozu/flywheel/api/visual/Visual.java b/src/main/java/com/jozufozu/flywheel/api/visual/Visual.java
index 7dac8dbf3..481b0352f 100644
--- a/src/main/java/com/jozufozu/flywheel/api/visual/Visual.java
+++ b/src/main/java/com/jozufozu/flywheel/api/visual/Visual.java
@@ -5,7 +5,6 @@ package com.jozufozu.flywheel.api.visual;
*
* @see DynamicVisual
* @see TickableVisual
- * @see PlannedVisual
* @see LitVisual
*/
public interface Visual {
diff --git a/src/main/java/com/jozufozu/flywheel/impl/visualization/manager/VisualManagerImpl.java b/src/main/java/com/jozufozu/flywheel/impl/visualization/manager/VisualManagerImpl.java
index d18b81f5d..8351eaac0 100644
--- a/src/main/java/com/jozufozu/flywheel/impl/visualization/manager/VisualManagerImpl.java
+++ b/src/main/java/com/jozufozu/flywheel/impl/visualization/manager/VisualManagerImpl.java
@@ -66,11 +66,11 @@ public class VisualManagerImpl> implements VisualManager
public Plan framePlan() {
return SimplePlan.of(context -> processQueue(context.partialTick()))
- .then(storage.getFramePlan());
+ .then(storage.framePlan());
}
public Plan tickPlan() {
return SimplePlan.of(context -> processQueue(0))
- .then(storage.getTickPlan());
+ .then(storage.tickPlan());
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/FastPlanStorage.java b/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/FastPlanStorage.java
new file mode 100644
index 000000000..69ddcc029
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/FastPlanStorage.java
@@ -0,0 +1,35 @@
+package com.jozufozu.flywheel.impl.visualization.storage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jozufozu.flywheel.api.task.TaskExecutor;
+import com.jozufozu.flywheel.lib.task.PlanUtil;
+import com.jozufozu.flywheel.lib.task.SimplyComposedPlan;
+import com.jozufozu.flywheel.lib.task.functional.ConsumerWithContext;
+
+public class FastPlanStorage implements SimplyComposedPlan {
+ private final List objects = new ArrayList<>();
+ private final ConsumerWithContext consumer;
+
+ public FastPlanStorage(ConsumerWithContext consumer) {
+ this.consumer = consumer;
+ }
+
+ public void add(T object) {
+ objects.add(object);
+ }
+
+ public void remove(T object) {
+ objects.remove(object);
+ }
+
+ public void clear() {
+ objects.clear();
+ }
+
+ @Override
+ public void execute(TaskExecutor taskExecutor, C context, Runnable onCompletion) {
+ PlanUtil.distribute(taskExecutor, context, onCompletion, objects, consumer);
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/PlanStorage.java b/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/PlanStorage.java
new file mode 100644
index 000000000..ace588c1a
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/PlanStorage.java
@@ -0,0 +1,72 @@
+package com.jozufozu.flywheel.impl.visualization.storage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jozufozu.flywheel.api.task.Plan;
+import com.jozufozu.flywheel.api.task.TaskExecutor;
+import com.jozufozu.flywheel.lib.task.PlanUtil;
+import com.jozufozu.flywheel.lib.task.SimplyComposedPlan;
+import com.jozufozu.flywheel.lib.task.Synchronizer;
+
+public class PlanStorage implements SimplyComposedPlan {
+ private final List objects = new ArrayList<>();
+ private final List> plans = new ArrayList<>();
+
+ public void add(T object, Plan plan) {
+ objects.add(object);
+ plans.add(plan);
+ }
+
+ public void remove(T object) {
+ int index = objects.indexOf(object);
+
+ if (index != -1) {
+ objects.remove(index);
+ plans.remove(index);
+ }
+ }
+
+ public void clear() {
+ objects.clear();
+ plans.clear();
+ }
+
+ @Override
+ public void execute(TaskExecutor taskExecutor, C context, Runnable onCompletion) {
+ final int size = plans.size();
+
+ if (size == 0) {
+ onCompletion.run();
+ return;
+ }
+
+ var synchronizer = new Synchronizer(size, onCompletion);
+ final int sliceSize = PlanUtil.sliceSize(taskExecutor, size, 8);
+
+ if (size <= sliceSize) {
+ for (var t : plans) {
+ t.execute(taskExecutor, context, synchronizer);
+ }
+ } else if (sliceSize == 1) {
+ for (var t : plans) {
+ taskExecutor.execute(() -> t.execute(taskExecutor, context, synchronizer));
+ }
+ } else {
+ int remaining = size;
+
+ while (remaining > 0) {
+ int end = remaining;
+ remaining -= sliceSize;
+ int start = Math.max(remaining, 0);
+
+ var subList = plans.subList(start, end);
+ taskExecutor.execute(() -> {
+ for (var t : subList) {
+ t.execute(taskExecutor, context, synchronizer);
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/Storage.java b/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/Storage.java
index 8f9875144..c2d104724 100644
--- a/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/Storage.java
+++ b/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/Storage.java
@@ -1,8 +1,6 @@
package com.jozufozu.flywheel.impl.visualization.storage;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
@@ -11,29 +9,25 @@ import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.task.Plan;
import com.jozufozu.flywheel.api.visual.DynamicVisual;
import com.jozufozu.flywheel.api.visual.LitVisual;
-import com.jozufozu.flywheel.api.visual.PlannedVisual;
import com.jozufozu.flywheel.api.visual.TickableVisual;
import com.jozufozu.flywheel.api.visual.Visual;
import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import com.jozufozu.flywheel.api.visual.VisualTickContext;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
-import com.jozufozu.flywheel.lib.task.ForEachPlan;
+import com.jozufozu.flywheel.lib.task.NestedPlan;
+import com.jozufozu.flywheel.lib.visual.SimpleDynamicVisual;
+import com.jozufozu.flywheel.lib.visual.SimpleTickableVisual;
import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
public abstract class Storage {
protected final Supplier visualizationContextSupplier;
- protected final List tickableVisuals = new ArrayList<>();
- protected final List dynamicVisuals = new ArrayList<>();
- protected final List plannedVisuals = new ArrayList<>();
+ protected final PlanStorage dynamicVisuals = new PlanStorage<>();
+ protected final FastPlanStorage fastDynamicVisuals = new FastPlanStorage<>(SimpleDynamicVisual::beginFrame);
+ protected final PlanStorage tickableVisuals = new PlanStorage<>();
+ protected final FastPlanStorage fastTickableVisuals = new FastPlanStorage<>(SimpleTickableVisual::tick);
protected final LitVisualStorage litVisuals = new LitVisualStorage();
- protected final VisualUpdatePlan framePlan = new VisualUpdatePlan<>(() -> plannedVisuals.stream()
- .map(PlannedVisual::planFrame)
- .toList());
- protected final VisualUpdatePlan tickPlan = new VisualUpdatePlan<>(() -> plannedVisuals.stream()
- .map(PlannedVisual::planTick)
- .toList());
private final Map visuals = new Reference2ObjectOpenHashMap<>();
@@ -61,15 +55,17 @@ public abstract class Storage {
}
if (visual instanceof TickableVisual tickable) {
- tickableVisuals.remove(tickable);
+ if (visual instanceof SimpleTickableVisual simpleTickable) {
+ fastTickableVisuals.remove(simpleTickable);
+ } else {
+ tickableVisuals.remove(tickable);
+ }
}
if (visual instanceof DynamicVisual dynamic) {
- dynamicVisuals.remove(dynamic);
- }
- if (visual instanceof PlannedVisual planned) {
- if (plannedVisuals.remove(planned)) {
- framePlan.triggerReInitialize();
- tickPlan.triggerReInitialize();
+ if (visual instanceof SimpleDynamicVisual simpleDynamic) {
+ fastDynamicVisuals.remove(simpleDynamic);
+ } else {
+ dynamicVisuals.remove(dynamic);
}
}
if (visual instanceof LitVisual lit) {
@@ -98,8 +94,9 @@ public abstract class Storage {
public void recreateAll(float partialTick) {
tickableVisuals.clear();
+ fastTickableVisuals.clear();
dynamicVisuals.clear();
- plannedVisuals.clear();
+ fastDynamicVisuals.clear();
litVisuals.clear();
visuals.replaceAll((obj, visual) -> {
visual.delete();
@@ -117,10 +114,7 @@ public abstract class Storage {
public void invalidate() {
tickableVisuals.clear();
dynamicVisuals.clear();
- plannedVisuals.clear();
litVisuals.clear();
- framePlan.triggerReInitialize();
- tickPlan.triggerReInitialize();
visuals.values()
.forEach(Visual::delete);
visuals.clear();
@@ -138,13 +132,12 @@ public abstract class Storage {
@Nullable
protected abstract Visual createRaw(T obj);
- public Plan getFramePlan() {
- return framePlan.and(ForEachPlan.of(() -> dynamicVisuals, DynamicVisual::beginFrame))
- .and(litVisuals.plan());
+ public Plan framePlan() {
+ return NestedPlan.of(dynamicVisuals, fastDynamicVisuals, litVisuals.plan());
}
- public Plan getTickPlan() {
- return tickPlan.and(ForEachPlan.of(() -> tickableVisuals, TickableVisual::tick));
+ public Plan tickPlan() {
+ return NestedPlan.of(tickableVisuals, fastTickableVisuals);
}
public void enqueueLightUpdateSections(LongSet sections) {
@@ -155,17 +148,19 @@ public abstract class Storage {
visual.init(partialTick);
if (visual instanceof TickableVisual tickable) {
- tickableVisuals.add(tickable);
+ if (visual instanceof SimpleTickableVisual simpleTickable) {
+ fastTickableVisuals.add(simpleTickable);
+ } else {
+ tickableVisuals.add(tickable, tickable.planTick());
+ }
}
if (visual instanceof DynamicVisual dynamic) {
- dynamicVisuals.add(dynamic);
- }
-
- if (visual instanceof PlannedVisual planned) {
- plannedVisuals.add(planned);
- framePlan.add(planned.planFrame());
- tickPlan.add(planned.planTick());
+ if (visual instanceof SimpleDynamicVisual simpleDynamic) {
+ fastDynamicVisuals.add(simpleDynamic);
+ } else {
+ dynamicVisuals.add(dynamic, dynamic.planFrame());
+ }
}
if (visual instanceof LitVisual lit) {
diff --git a/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/VisualUpdatePlan.java b/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/VisualUpdatePlan.java
deleted file mode 100644
index 3fe67ae97..000000000
--- a/src/main/java/com/jozufozu/flywheel/impl/visualization/storage/VisualUpdatePlan.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.jozufozu.flywheel.impl.visualization.storage;
-
-import java.util.List;
-import java.util.function.Supplier;
-
-import com.jozufozu.flywheel.api.task.Plan;
-import com.jozufozu.flywheel.api.task.TaskExecutor;
-import com.jozufozu.flywheel.lib.task.NestedPlan;
-import com.jozufozu.flywheel.lib.task.SimplyComposedPlan;
-import com.jozufozu.flywheel.lib.task.UnitPlan;
-
-public class VisualUpdatePlan implements SimplyComposedPlan {
- private final Supplier>> initializer;
- private Plan plan = UnitPlan.of();
- private boolean initialized = false;
- private boolean needsSimplify = true;
-
- public VisualUpdatePlan(Supplier>> initializer) {
- this.initializer = initializer;
- }
-
- @Override
- public void execute(TaskExecutor taskExecutor, C context, Runnable onCompletion) {
- updatePlans().execute(taskExecutor, context, onCompletion);
- }
-
- public void add(Plan plan) {
- this.plan = this.plan.and(plan);
-
- needsSimplify = true;
- }
-
- private Plan updatePlans() {
- if (!initialized) {
- Plan mainPlan = new NestedPlan<>(initializer.get());
- plan = mainPlan.and(plan);
- plan = plan.simplify();
- initialized = true;
- } else if (needsSimplify) {
- plan = plan.simplify();
- }
-
- needsSimplify = false;
- return plan;
- }
-
- public void triggerReInitialize() {
- plan = UnitPlan.of();
- initialized = false;
- }
-}
diff --git a/src/main/java/com/jozufozu/flywheel/lib/task/PlanUtil.java b/src/main/java/com/jozufozu/flywheel/lib/task/PlanUtil.java
index 5cda49541..b3ff709e3 100644
--- a/src/main/java/com/jozufozu/flywheel/lib/task/PlanUtil.java
+++ b/src/main/java/com/jozufozu/flywheel/lib/task/PlanUtil.java
@@ -91,7 +91,11 @@ public final class PlanUtil {
}
public static int sliceSize(TaskExecutor taskExecutor, int totalSize) {
- return MoreMath.ceilingDiv(totalSize, taskExecutor.getThreadCount() * 32);
+ return sliceSize(taskExecutor, totalSize, 32);
+ }
+
+ public static int sliceSize(TaskExecutor taskExecutor, int totalSize, int denominator) {
+ return MoreMath.ceilingDiv(totalSize, taskExecutor.getThreadCount() * denominator);
}
private PlanUtil() {
diff --git a/src/main/java/com/jozufozu/flywheel/lib/task/RunnablePlan.java b/src/main/java/com/jozufozu/flywheel/lib/task/RunnablePlan.java
new file mode 100644
index 000000000..1be7ae18f
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/lib/task/RunnablePlan.java
@@ -0,0 +1,20 @@
+package com.jozufozu.flywheel.lib.task;
+
+import com.jozufozu.flywheel.api.task.TaskExecutor;
+import com.jozufozu.flywheel.lib.task.functional.RunnableWithContext;
+
+public record RunnablePlan(RunnableWithContext runnable) implements SimplyComposedPlan {
+ public static RunnablePlan of(RunnableWithContext runnable) {
+ return new RunnablePlan<>(runnable);
+ }
+
+ public static RunnablePlan of(RunnableWithContext.Ignored runnable) {
+ return new RunnablePlan<>(runnable);
+ }
+
+ @Override
+ public void execute(TaskExecutor taskExecutor, C context, Runnable onCompletion) {
+ runnable.accept(context);
+ onCompletion.run();
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractBlockEntityVisual.java b/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractBlockEntityVisual.java
index 9eefda60b..68df9cca8 100644
--- a/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractBlockEntityVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractBlockEntityVisual.java
@@ -8,7 +8,6 @@ import org.joml.FrustumIntersection;
import com.jozufozu.flywheel.api.visual.BlockEntityVisual;
import com.jozufozu.flywheel.api.visual.DynamicVisual;
import com.jozufozu.flywheel.api.visual.LitVisual;
-import com.jozufozu.flywheel.api.visual.PlannedVisual;
import com.jozufozu.flywheel.api.visual.TickableVisual;
import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import com.jozufozu.flywheel.api.visualization.VisualManager;
@@ -27,7 +26,6 @@ import net.minecraft.world.level.block.state.BlockState;
*
* - {@link DynamicVisual}
* - {@link TickableVisual}
- * - {@link PlannedVisual}
*
* See the interfaces' documentation for more information about each one.
*
diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java b/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java
index ebba08ccb..9cec1d4df 100644
--- a/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java
@@ -5,7 +5,6 @@ import org.joml.Vector3f;
import com.jozufozu.flywheel.api.visual.DynamicVisual;
import com.jozufozu.flywheel.api.visual.EntityVisual;
-import com.jozufozu.flywheel.api.visual.PlannedVisual;
import com.jozufozu.flywheel.api.visual.TickableVisual;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
@@ -21,7 +20,6 @@ import net.minecraft.world.phys.Vec3;
*
* - {@link DynamicVisual}
* - {@link TickableVisual}
- * - {@link PlannedVisual}
*
* See the interfaces' documentation for more information about each one.
*
diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleDynamicVisual.java b/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleDynamicVisual.java
new file mode 100644
index 000000000..36c2436ee
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleDynamicVisual.java
@@ -0,0 +1,28 @@
+package com.jozufozu.flywheel.lib.visual;
+
+import com.jozufozu.flywheel.api.instance.Instance;
+import com.jozufozu.flywheel.api.instance.Instancer;
+import com.jozufozu.flywheel.api.task.Plan;
+import com.jozufozu.flywheel.api.visual.DynamicVisual;
+import com.jozufozu.flywheel.api.visual.TickableVisual;
+import com.jozufozu.flywheel.api.visual.VisualFrameContext;
+import com.jozufozu.flywheel.lib.task.RunnablePlan;
+
+public interface SimpleDynamicVisual extends DynamicVisual {
+ /**
+ * Called every frame.
+ *
+ * The implementation is free to parallelize calls to this method.
+ * You must ensure proper synchronization if you need to mutate anything outside this visual.
+ *
+ * This method and {@link TickableVisual#tick} will never be called simultaneously.
+ *
+ * {@link Instancer}/{@link Instance} creation/acquisition is safe here.
+ */
+ void beginFrame(VisualFrameContext ctx);
+
+ @Override
+ default Plan planFrame() {
+ return RunnablePlan.of(this::beginFrame);
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleEntityVisual.java b/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleEntityVisual.java
index 5b810787b..9654e2adc 100644
--- a/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleEntityVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleEntityVisual.java
@@ -3,13 +3,12 @@ package com.jozufozu.flywheel.lib.visual;
import java.util.ArrayList;
import java.util.List;
-import com.jozufozu.flywheel.api.visual.DynamicVisual;
import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import net.minecraft.world.entity.Entity;
-public class SimpleEntityVisual extends AbstractEntityVisual implements DynamicVisual {
+public class SimpleEntityVisual extends AbstractEntityVisual implements SimpleDynamicVisual {
protected final List components = new ArrayList<>();
public SimpleEntityVisual(VisualizationContext ctx, T entity) {
diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleTickableVisual.java b/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleTickableVisual.java
new file mode 100644
index 000000000..11a6b2f40
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleTickableVisual.java
@@ -0,0 +1,29 @@
+package com.jozufozu.flywheel.lib.visual;
+
+import com.jozufozu.flywheel.api.instance.Instance;
+import com.jozufozu.flywheel.api.instance.Instancer;
+import com.jozufozu.flywheel.api.task.Plan;
+import com.jozufozu.flywheel.api.visual.DynamicVisual;
+import com.jozufozu.flywheel.api.visual.TickableVisual;
+import com.jozufozu.flywheel.api.visual.VisualTickContext;
+import com.jozufozu.flywheel.lib.task.RunnablePlan;
+
+public interface SimpleTickableVisual extends TickableVisual {
+
+ /**
+ * Called every tick.
+ *
+ * The implementation is free to parallelize calls to this method.
+ * You must ensure proper synchronization if you need to mutate anything outside this visual.
+ *
+ * This method and {@link DynamicVisual#beginFrame} will never be called simultaneously.
+ *
+ * {@link Instancer}/{@link Instance} creation/acquisition is safe here.
+ */
+ void tick(VisualTickContext ctx);
+
+ @Override
+ default Plan planTick() {
+ return RunnablePlan.of(this::tick);
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/BellVisual.java b/src/main/java/com/jozufozu/flywheel/vanilla/BellVisual.java
index 32c12ba07..29e21cda3 100644
--- a/src/main/java/com/jozufozu/flywheel/vanilla/BellVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/vanilla/BellVisual.java
@@ -7,7 +7,6 @@ import org.joml.Quaternionf;
import org.joml.Vector3f;
import com.jozufozu.flywheel.api.instance.Instance;
-import com.jozufozu.flywheel.api.visual.DynamicVisual;
import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.lib.instance.InstanceTypes;
@@ -17,13 +16,14 @@ import com.jozufozu.flywheel.lib.model.ModelHolder;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
import com.jozufozu.flywheel.lib.model.part.ModelPartConverter;
import com.jozufozu.flywheel.lib.visual.AbstractBlockEntityVisual;
+import com.jozufozu.flywheel.lib.visual.SimpleDynamicVisual;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.client.renderer.blockentity.BellRenderer;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.entity.BellBlockEntity;
-public class BellVisual extends AbstractBlockEntityVisual implements DynamicVisual {
+public class BellVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual {
private static final ModelHolder BELL_MODEL = new ModelHolder(() -> {
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.BELL, BellRenderer.BELL_RESOURCE_LOCATION.sprite(), "bell_body"), Materials.BELL);
});
diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ChestVisual.java b/src/main/java/com/jozufozu/flywheel/vanilla/ChestVisual.java
index ccabc2e10..6fdf12a83 100644
--- a/src/main/java/com/jozufozu/flywheel/vanilla/ChestVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/vanilla/ChestVisual.java
@@ -8,7 +8,6 @@ import java.util.function.Consumer;
import org.joml.Quaternionf;
import com.jozufozu.flywheel.api.instance.Instance;
-import com.jozufozu.flywheel.api.visual.DynamicVisual;
import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.lib.instance.InstanceTypes;
@@ -20,6 +19,7 @@ import com.jozufozu.flywheel.lib.model.SingleMeshModel;
import com.jozufozu.flywheel.lib.model.part.ModelPartConverter;
import com.jozufozu.flywheel.lib.util.Pair;
import com.jozufozu.flywheel.lib.visual.AbstractBlockEntityVisual;
+import com.jozufozu.flywheel.lib.visual.SimpleDynamicVisual;
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
import net.minecraft.client.model.geom.ModelLayerLocation;
@@ -35,7 +35,7 @@ import net.minecraft.world.level.block.entity.ChestBlockEntity;
import net.minecraft.world.level.block.entity.LidBlockEntity;
import net.minecraft.world.level.block.state.properties.ChestType;
-public class ChestVisual extends AbstractBlockEntityVisual implements DynamicVisual {
+public class ChestVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual {
private static final Map LAYER_LOCATIONS = new EnumMap<>(ChestType.class);
static {
LAYER_LOCATIONS.put(ChestType.SINGLE, ModelLayers.CHEST);
diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java
index 28e02ede4..c27a5f817 100644
--- a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java
@@ -2,8 +2,6 @@ package com.jozufozu.flywheel.vanilla;
import org.jetbrains.annotations.Nullable;
-import com.jozufozu.flywheel.api.visual.DynamicVisual;
-import com.jozufozu.flywheel.api.visual.TickableVisual;
import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import com.jozufozu.flywheel.api.visual.VisualTickContext;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
@@ -14,7 +12,9 @@ import com.jozufozu.flywheel.lib.model.ModelHolder;
import com.jozufozu.flywheel.lib.model.Models;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
import com.jozufozu.flywheel.lib.model.part.ModelPartConverter;
+import com.jozufozu.flywheel.lib.visual.SimpleDynamicVisual;
import com.jozufozu.flywheel.lib.visual.SimpleEntityVisual;
+import com.jozufozu.flywheel.lib.visual.SimpleTickableVisual;
import com.jozufozu.flywheel.lib.visual.components.FireComponent;
import com.jozufozu.flywheel.lib.visual.components.HitboxComponent;
import com.jozufozu.flywheel.lib.visual.components.ShadowComponent;
@@ -29,7 +29,7 @@ import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
-public class MinecartVisual extends SimpleEntityVisual implements TickableVisual, DynamicVisual {
+public class MinecartVisual extends SimpleEntityVisual implements SimpleTickableVisual, SimpleDynamicVisual {
public static final ModelHolder CHEST_BODY_MODEL = createBodyModelHolder(ModelLayers.CHEST_MINECART);
public static final ModelHolder COMMAND_BLOCK_BODY_MODEL = createBodyModelHolder(ModelLayers.COMMAND_BLOCK_MINECART);
public static final ModelHolder FURNACE_BODY_MODEL = createBodyModelHolder(ModelLayers.FURNACE_MINECART);
diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxVisual.java b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxVisual.java
index c302045a8..8f205bc26 100644
--- a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxVisual.java
@@ -5,7 +5,6 @@ import java.util.function.Consumer;
import org.joml.Quaternionf;
import com.jozufozu.flywheel.api.instance.Instance;
-import com.jozufozu.flywheel.api.visual.DynamicVisual;
import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.lib.instance.InstanceTypes;
@@ -16,6 +15,7 @@ import com.jozufozu.flywheel.lib.model.SingleMeshModel;
import com.jozufozu.flywheel.lib.model.part.ModelPartConverter;
import com.jozufozu.flywheel.lib.transform.TransformStack;
import com.jozufozu.flywheel.lib.visual.AbstractBlockEntityVisual;
+import com.jozufozu.flywheel.lib.visual.SimpleDynamicVisual;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
@@ -27,7 +27,7 @@ import net.minecraft.world.item.DyeColor;
import net.minecraft.world.level.block.ShulkerBoxBlock;
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
-public class ShulkerBoxVisual extends AbstractBlockEntityVisual implements DynamicVisual {
+public class ShulkerBoxVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual {
private static final ModelCache BASE_MODELS = new ModelCache<>(texture -> {
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "base"), Materials.SHULKER);
});
diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java b/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java
index dd947fc95..d4c8784b6 100644
--- a/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java
+++ b/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java
@@ -7,9 +7,10 @@ import org.joml.Vector3f;
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
import com.jozufozu.flywheel.api.task.Plan;
+import com.jozufozu.flywheel.api.visual.DynamicVisual;
import com.jozufozu.flywheel.api.visual.Effect;
import com.jozufozu.flywheel.api.visual.EffectVisual;
-import com.jozufozu.flywheel.api.visual.PlannedVisual;
+import com.jozufozu.flywheel.api.visual.TickableVisual;
import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import com.jozufozu.flywheel.api.visual.VisualTickContext;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
@@ -101,7 +102,7 @@ public class ExampleEffect implements Effect {
return new ExampleVisual(ctx);
}
- public class ExampleVisual implements EffectVisual, PlannedVisual {
+ public class ExampleVisual implements EffectVisual, TickableVisual, DynamicVisual {
private final List effects;
private final List boids;