diff --git a/src/main/java/com/jozufozu/flywheel/api/visual/LitVisual.java b/src/main/java/com/jozufozu/flywheel/api/visual/LitVisual.java
index 12c4d7212..b4f1b0a32 100644
--- a/src/main/java/com/jozufozu/flywheel/api/visual/LitVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/api/visual/LitVisual.java
@@ -5,28 +5,30 @@ import java.util.function.LongConsumer;
import net.minecraft.core.SectionPos;
/**
- * A non-moving visual that listens to light updates.
- *
- * If your visual moves around in the world at all, you should use {@link TickableVisual} or {@link DynamicVisual},
- * and poll for light yourself rather than listening for updates.
+ * A visual that listens to light updates.
+ *
+ *
If your visual moves around in the world at all, you should use {@link TickableVisual} or {@link DynamicVisual},
+ * and poll for light yourself along with listening for updates. When your visual moves to a different section, call
+ * {@link Notifier#notifySectionsChanged}.
*/
public interface LitVisual extends Visual {
/**
* Called when a section this visual is contained in receives a light update.
- *
- * Even if multiple sections are updated at the same time, this method will only be called once.
- *
- * The implementation is free to parallelize calls to this method, as well as call into
+ *
+ * Even if multiple sections are updated at the same time, this method will only be called once.
+ *
+ * The implementation is free to parallelize calls to this method, as well as call into
* {@link DynamicVisual#beginFrame} simultaneously. It is safe to query/update light here,
* but you must ensure proper synchronization if you want to mutate anything outside this
- * visual or anything that is also mutated by {@link DynamicVisual#beginFrame}.
+ * visual or anything that is also mutated by {@link DynamicVisual#beginFrame}.
*/
void updateLight();
/**
* Collect the sections that this visual is contained in.
- *
- * This method is called upon visual creation, and the frame after {@link Notifier#notifySectionsChanged} is called.
+ *
+ * This method is called upon visual creation, and the frame after
+ * {@link Notifier#notifySectionsChanged} is called.
*
* @param consumer The consumer to provide the sections to.
* @see SectionPos#asLong
@@ -35,9 +37,9 @@ public interface LitVisual extends Visual {
/**
* Set the notifier object.
- *
- * This method is only called once, upon visual creation,
- * after {@link #init} and before {@link #collectLightSections}.
+ *
+ * This method is only called once, upon visual creation,
+ * after {@link #init} and before {@link #collectLightSections}.
*
* @param notifier The notifier.
*/
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 5421d4397..7dac8dbf3 100644
--- a/src/main/java/com/jozufozu/flywheel/api/visual/Visual.java
+++ b/src/main/java/com/jozufozu/flywheel/api/visual/Visual.java
@@ -11,13 +11,17 @@ package com.jozufozu.flywheel.api.visual;
public interface Visual {
/**
* Initialize instances here.
+ *
+ * This method will be called exactly once upon visual creation.
*/
void init(float partialTick);
/**
- * Update instances here. Good for when instances don't change very often and when animations are GPU based.
- *
- *
If your animations are complex or more CPU driven, see {@link DynamicVisual} or {@link TickableVisual}.
+ * Update instances here.
+ *
+ * Good for when instances don't change very often and when animations are GPU based.
+ *
+ *
If your animations are complex or more CPU driven, see {@link DynamicVisual} or {@link TickableVisual}.
*/
void update(float partialTick);
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 957608290..ebba08ccb 100644
--- a/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java
@@ -33,17 +33,11 @@ import net.minecraft.world.phys.Vec3;
public abstract class AbstractEntityVisual extends AbstractVisual implements EntityVisual {
protected final T entity;
protected final EntityVisibilityTester visibilityTester;
- protected final ShadowComponent shadow;
- protected final FireComponent fire;
- protected final BoundingBoxComponent boundingBox;
public AbstractEntityVisual(VisualizationContext ctx, T entity) {
super(ctx, entity.level());
this.entity = entity;
visibilityTester = new EntityVisibilityTester(entity, ctx.renderOrigin(), 1.5f);
- shadow = new ShadowComponent(ctx, entity);
- fire = new FireComponent(ctx, entity);
- boundingBox = new BoundingBoxComponent(ctx, entity);
}
@Override
@@ -93,11 +87,4 @@ public abstract class AbstractEntityVisual extends AbstractVis
public boolean isVisible(FrustumIntersection frustum) {
return entity.noCulling || visibilityTester.check(frustum);
}
-
- @Override
- protected void _delete() {
- shadow.delete();
- fire.delete();
- boundingBox.delete();
- }
}
diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/EntityComponent.java b/src/main/java/com/jozufozu/flywheel/lib/visual/EntityComponent.java
new file mode 100644
index 000000000..d47ca3145
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/EntityComponent.java
@@ -0,0 +1,9 @@
+package com.jozufozu.flywheel.lib.visual;
+
+import com.jozufozu.flywheel.api.visual.VisualFrameContext;
+
+public interface EntityComponent {
+ void beginFrame(VisualFrameContext context);
+
+ void delete();
+}
diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleEntityVisual.java b/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleEntityVisual.java
new file mode 100644
index 000000000..5b810787b
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/SimpleEntityVisual.java
@@ -0,0 +1,36 @@
+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 {
+ protected final List components = new ArrayList<>();
+
+ public SimpleEntityVisual(VisualizationContext ctx, T entity) {
+ super(ctx, entity);
+ }
+
+ public void addComponent(EntityComponent component) {
+ components.add(component);
+ }
+
+ @Override
+ public void beginFrame(VisualFrameContext ctx) {
+ for (EntityComponent component : components) {
+ component.beginFrame(ctx);
+ }
+ }
+
+ @Override
+ protected void _delete() {
+ for (EntityComponent component : components) {
+ component.delete();
+ }
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/BoundingBoxComponent.java b/src/main/java/com/jozufozu/flywheel/lib/visual/components/BoundingBoxComponent.java
similarity index 94%
rename from src/main/java/com/jozufozu/flywheel/lib/visual/BoundingBoxComponent.java
rename to src/main/java/com/jozufozu/flywheel/lib/visual/components/BoundingBoxComponent.java
index d64b0b78c..72a61f0a6 100644
--- a/src/main/java/com/jozufozu/flywheel/lib/visual/BoundingBoxComponent.java
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/components/BoundingBoxComponent.java
@@ -1,4 +1,4 @@
-package com.jozufozu.flywheel.lib.visual;
+package com.jozufozu.flywheel.lib.visual.components;
import org.joml.Vector4f;
import org.joml.Vector4fc;
@@ -15,6 +15,8 @@ import com.jozufozu.flywheel.lib.material.StandardMaterialShaders;
import com.jozufozu.flywheel.lib.math.MoreMath;
import com.jozufozu.flywheel.lib.model.QuadMesh;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
+import com.jozufozu.flywheel.lib.visual.EntityComponent;
+import com.jozufozu.flywheel.lib.visual.InstanceRecycler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LightTexture;
@@ -22,7 +24,7 @@ import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
-public class BoundingBoxComponent {
+public class BoundingBoxComponent implements EntityComponent {
private static final Material MATERIAL = SimpleMaterial.builder()
.shaders(StandardMaterialShaders.WIREFRAME)
.backfaceCulling(false)
@@ -53,10 +55,12 @@ public class BoundingBoxComponent {
return instance;
}
- public void showEyeBox(boolean renderEyeBox) {
+ public BoundingBoxComponent showEyeBox(boolean renderEyeBox) {
this.showEyeBox = renderEyeBox;
+ return this;
}
+ @Override
public void beginFrame(VisualFrameContext context) {
recycler.resetCount();
@@ -93,6 +97,7 @@ public class BoundingBoxComponent {
recycler.discardExtra();
}
+ @Override
public void delete() {
recycler.delete();
}
diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/FireComponent.java b/src/main/java/com/jozufozu/flywheel/lib/visual/components/FireComponent.java
similarity index 95%
rename from src/main/java/com/jozufozu/flywheel/lib/visual/FireComponent.java
rename to src/main/java/com/jozufozu/flywheel/lib/visual/components/FireComponent.java
index 15ce01bdc..3b4a04bca 100644
--- a/src/main/java/com/jozufozu/flywheel/lib/visual/FireComponent.java
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/components/FireComponent.java
@@ -1,4 +1,4 @@
-package com.jozufozu.flywheel.lib.visual;
+package com.jozufozu.flywheel.lib.visual.components;
import org.joml.Vector4f;
import org.joml.Vector4fc;
@@ -14,6 +14,8 @@ import com.jozufozu.flywheel.lib.material.SimpleMaterial;
import com.jozufozu.flywheel.lib.model.ModelCache;
import com.jozufozu.flywheel.lib.model.QuadMesh;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
+import com.jozufozu.flywheel.lib.visual.EntityComponent;
+import com.jozufozu.flywheel.lib.visual.InstanceRecycler;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
@@ -26,7 +28,7 @@ import net.minecraft.world.entity.Entity;
/**
* A component that uses instances to render the fire animation on an entity.
*/
-public class FireComponent {
+public class FireComponent implements EntityComponent {
private static final Material FIRE_MATERIAL = SimpleMaterial.builderOf(Materials.CHUNK_CUTOUT_UNSHADED)
.backfaceCulling(false) // Disable backface because we want to be able to flip the model.
.build();
@@ -66,6 +68,7 @@ public class FireComponent {
*
* @param context The frame context.
*/
+ @Override
public void beginFrame(VisualFrameContext context) {
fire0.resetCount();
fire1.resetCount();
@@ -118,6 +121,7 @@ public class FireComponent {
}
}
+ @Override
public void delete() {
fire0.delete();
fire1.delete();
diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/ShadowComponent.java b/src/main/java/com/jozufozu/flywheel/lib/visual/components/ShadowComponent.java
similarity index 95%
rename from src/main/java/com/jozufozu/flywheel/lib/visual/ShadowComponent.java
rename to src/main/java/com/jozufozu/flywheel/lib/visual/components/ShadowComponent.java
index b4d8930c2..572b7e353 100644
--- a/src/main/java/com/jozufozu/flywheel/lib/visual/ShadowComponent.java
+++ b/src/main/java/com/jozufozu/flywheel/lib/visual/components/ShadowComponent.java
@@ -1,4 +1,4 @@
-package com.jozufozu.flywheel.lib.visual;
+package com.jozufozu.flywheel.lib.visual.components;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector4f;
@@ -16,6 +16,8 @@ import com.jozufozu.flywheel.lib.instance.ShadowInstance;
import com.jozufozu.flywheel.lib.material.SimpleMaterial;
import com.jozufozu.flywheel.lib.model.QuadMesh;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
+import com.jozufozu.flywheel.lib.visual.EntityComponent;
+import com.jozufozu.flywheel.lib.visual.InstanceRecycler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LightTexture;
@@ -40,7 +42,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
*
* The shadow will be cast on blocks at most {@code min(radius, 2 * strength)} blocks below the entity.
*/
-public class ShadowComponent {
+public class ShadowComponent implements EntityComponent {
private static final Material SHADOW_MATERIAL = SimpleMaterial.builder()
.texture(new ResourceLocation("textures/misc/shadow.png"))
.mipmap(false)
@@ -88,8 +90,9 @@ public class ShadowComponent {
*
* @param radius The radius of the shadow, in blocks.
*/
- public void radius(float radius) {
+ public ShadowComponent radius(float radius) {
this.radius = Math.min(radius, 32);
+ return this;
}
/**
@@ -97,8 +100,9 @@ public class ShadowComponent {
*
* @param strength The strength of the shadow.
*/
- public void strength(float strength) {
+ public ShadowComponent strength(float strength) {
this.strength = strength;
+ return this;
}
/**
@@ -107,6 +111,7 @@ public class ShadowComponent {
*
* @param context The frame context.
*/
+ @Override
public void beginFrame(VisualFrameContext context) {
instances.resetCount();
@@ -210,6 +215,7 @@ public class ShadowComponent {
return shape;
}
+ @Override
public void delete() {
instances.delete();
}
diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java
index 2fb19d7e5..5b3a64c95 100644
--- a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java
+++ b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartVisual.java
@@ -14,7 +14,10 @@ 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.AbstractEntityVisual;
+import com.jozufozu.flywheel.lib.visual.SimpleEntityVisual;
+import com.jozufozu.flywheel.lib.visual.components.BoundingBoxComponent;
+import com.jozufozu.flywheel.lib.visual.components.FireComponent;
+import com.jozufozu.flywheel.lib.visual.components.ShadowComponent;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
@@ -26,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 AbstractEntityVisual implements TickableVisual, DynamicVisual {
+public class MinecartVisual extends SimpleEntityVisual implements TickableVisual, DynamicVisual {
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);
@@ -48,7 +51,6 @@ public class MinecartVisual extends AbstractEntityVi
public MinecartVisual(VisualizationContext ctx, T entity, ModelHolder bodyModel) {
super(ctx, entity);
this.bodyModel = bodyModel;
- shadow.radius(0.7f);
}
private static ModelHolder createBodyModelHolder(ModelLayerLocation layer) {
@@ -59,6 +61,10 @@ public class MinecartVisual extends AbstractEntityVi
@Override
public void init(float partialTick) {
+ addComponent(new ShadowComponent(visualizationContext, entity).radius(0.7f));
+ addComponent(new FireComponent(visualizationContext, entity));
+ addComponent(new BoundingBoxComponent(visualizationContext, entity));
+
body = createBodyInstance();
blockState = entity.getDisplayBlockState();
contents = createContentsInstance();
@@ -109,9 +115,7 @@ public class MinecartVisual extends AbstractEntityVi
@Override
public void beginFrame(VisualFrameContext context) {
- shadow.beginFrame(context);
- fire.beginFrame(context);
- boundingBox.beginFrame(context);
+ super.beginFrame(context);
if (!isVisible(context.frustum())) {
return;
@@ -210,7 +214,6 @@ public class MinecartVisual extends AbstractEntityVi
if (contents != null) {
contents.delete();
}
- super._delete();
}
public static boolean shouldSkipRender(AbstractMinecart minecart) {