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) {