Explosive changes

- Fix TNT minecarts' contents not receiving overlay and scaling
- Fix all types of minecarts using the body model of the standard
minecart
- Add overlay to ColoredLitInstance
- Make default chunk materials not disable overlay
- Rename *Visualizer.shouldSkipRender -> skipVanillaRender
- Rename Simple*Visualizer.configure -> builder
- Rename Simple*Visualizer.*Config -> Builder
- Make Simple*Visualizer.Builder always skip vanilla render by default
- Remove DiffuseLightCalculator and associated methods in RenderMath
- Add BackendImplemented annotation to Backend
- Mark PoseTransformStack as Internal at the class level
This commit is contained in:
PepperCode1 2024-01-25 13:14:39 -08:00
parent 7cfaf06f36
commit 72c755ae13
18 changed files with 284 additions and 226 deletions

View file

@ -1,11 +1,13 @@
package com.jozufozu.flywheel.api.backend;
import com.jozufozu.flywheel.api.BackendImplemented;
import com.jozufozu.flywheel.api.registry.IdRegistry;
import com.jozufozu.flywheel.impl.IdRegistryImpl;
import net.minecraft.network.chat.Component;
import net.minecraft.world.level.LevelAccessor;
@BackendImplemented
public interface Backend {
static IdRegistry<Backend> REGISTRY = IdRegistryImpl.create();

View file

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.api.visualization;
import com.jozufozu.flywheel.api.visual.BlockEntityVisual;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.world.level.block.entity.BlockEntity;
/**
@ -19,9 +20,9 @@ public interface BlockEntityVisualizer<T extends BlockEntity> {
BlockEntityVisual<? super T> createVisual(VisualizationContext ctx, T blockEntity);
/**
* Checks if the given block entity should not be rendered normally.
* Checks if the given block entity should not be rendered with the vanilla {@link BlockEntityRenderer}.
* @param blockEntity The block entity to check.
* @return {@code true} if the block entity should not be rendered normally, {@code false} if it should.
* @return {@code true} if the block entity should not be rendered with the vanilla {@link BlockEntityRenderer}, {@code false} if it should.
*/
boolean shouldSkipRender(T blockEntity);
boolean skipVanillaRender(T blockEntity);
}

View file

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.api.visualization;
import com.jozufozu.flywheel.api.visual.EntityVisual;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.world.entity.Entity;
/**
@ -19,9 +20,9 @@ public interface EntityVisualizer<T extends Entity> {
EntityVisual<? super T> createVisual(VisualizationContext ctx, T entity);
/**
* Checks if the given entity should not render normally.
* Checks if the given entity should not render with the vanilla {@link EntityRenderer}.
* @param entity The entity to check.
* @return {@code true} if the entity should not render normally, {@code false} if it should.
* @return {@code true} if the entity should not render with the vanilla {@link EntityRenderer}, {@code false} if it should.
*/
boolean shouldSkipRender(T entity);
boolean skipVanillaRender(T entity);
}

View file

@ -60,7 +60,7 @@ public final class VisualizationHelper {
if (visualizer == null) {
return false;
}
return visualizer.shouldSkipRender(blockEntity);
return visualizer.skipVanillaRender(blockEntity);
}
/**
@ -74,7 +74,7 @@ public final class VisualizationHelper {
if (visualizer == null) {
return false;
}
return visualizer.shouldSkipRender(entity);
return visualizer.skipVanillaRender(entity);
}
public static <T extends BlockEntity> boolean tryAddBlockEntity(T blockEntity) {
@ -91,6 +91,6 @@ public final class VisualizationHelper {
manager.getBlockEntities().queueAdd(blockEntity);
return visualizer.shouldSkipRender(blockEntity);
return visualizer.skipVanillaRender(blockEntity);
}
}

View file

@ -4,37 +4,23 @@ import com.jozufozu.flywheel.api.instance.InstanceHandle;
import com.jozufozu.flywheel.api.instance.InstanceType;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.texture.OverlayTexture;
public abstract class ColoredLitInstance extends AbstractInstance implements FlatLit {
public byte blockLight;
public byte skyLight;
public byte r = (byte) 0xFF;
public byte g = (byte) 0xFF;
public byte b = (byte) 0xFF;
public byte a = (byte) 0xFF;
public byte blockLight;
public byte skyLight;
public int overlay = OverlayTexture.NO_OVERLAY;
public ColoredLitInstance(InstanceType<? extends ColoredLitInstance> type, InstanceHandle handle) {
super(type, handle);
}
@Override
public ColoredLitInstance setBlockLight(int blockLight) {
this.blockLight = (byte) blockLight;
return this;
}
@Override
public ColoredLitInstance setSkyLight(int skyLight) {
this.skyLight = (byte) skyLight;
return this;
}
@Override
public int getPackedLight() {
return LightTexture.pack(blockLight, skyLight);
}
public ColoredLitInstance setColor(int color) {
return setColor(color, false);
}
@ -70,4 +56,26 @@ public abstract class ColoredLitInstance extends AbstractInstance implements Fla
this.a = a;
return this;
}
@Override
public ColoredLitInstance setBlockLight(int blockLight) {
this.blockLight = (byte) blockLight;
return this;
}
@Override
public ColoredLitInstance setSkyLight(int skyLight) {
this.skyLight = (byte) skyLight;
return this;
}
@Override
public int getPackedLight() {
return LightTexture.pack(blockLight, skyLight);
}
public ColoredLitInstance setOverlay(int overlay) {
this.overlay = overlay;
return this;
}
}

View file

@ -13,20 +13,22 @@ import com.jozufozu.flywheel.lib.math.MatrixMath;
public final class InstanceTypes {
public static final InstanceType<TransformedInstance> TRANSFORMED = SimpleInstanceType.builder(TransformedInstance::new)
.layout(LayoutBuilder.create()
.vector("light", IntegerRepr.SHORT, 2)
.vector("color", FloatRepr.NORMALIZED_UNSIGNED_BYTE, 4)
.vector("light", IntegerRepr.SHORT, 2)
.vector("overlay", IntegerRepr.SHORT, 2)
.matrix("pose", FloatRepr.FLOAT, 4)
.matrix("normal", FloatRepr.FLOAT, 3)
.build())
.writer((ptr, instance) -> {
MemoryUtil.memPutShort(ptr, instance.blockLight);
MemoryUtil.memPutShort(ptr + 2, instance.skyLight);
MemoryUtil.memPutByte(ptr + 4, instance.r);
MemoryUtil.memPutByte(ptr + 5, instance.g);
MemoryUtil.memPutByte(ptr + 6, instance.b);
MemoryUtil.memPutByte(ptr + 7, instance.a);
MatrixMath.writeUnsafe(instance.model, ptr + 8);
MatrixMath.writeUnsafe(instance.normal, ptr + 72);
MemoryUtil.memPutByte(ptr, instance.r);
MemoryUtil.memPutByte(ptr + 1, instance.g);
MemoryUtil.memPutByte(ptr + 2, instance.b);
MemoryUtil.memPutByte(ptr + 3, instance.a);
MemoryUtil.memPutShort(ptr + 4, instance.blockLight);
MemoryUtil.memPutShort(ptr + 6, instance.skyLight);
MemoryUtil.memPutInt(ptr + 8, instance.overlay);
MatrixMath.writeUnsafe(instance.model, ptr + 12);
MatrixMath.writeUnsafe(instance.normal, ptr + 76);
})
.vertexShader(Flywheel.rl("instance/transformed.vert"))
.cullShader(Flywheel.rl("instance/cull/transformed.glsl"))
@ -34,29 +36,31 @@ public final class InstanceTypes {
public static final InstanceType<OrientedInstance> ORIENTED = SimpleInstanceType.builder(OrientedInstance::new)
.layout(LayoutBuilder.create()
.vector("light", IntegerRepr.SHORT, 2)
.vector("color", FloatRepr.NORMALIZED_UNSIGNED_BYTE, 4)
.vector("light", IntegerRepr.SHORT, 2)
.vector("overlay", IntegerRepr.SHORT, 2)
.vector("position", FloatRepr.FLOAT, 3)
.vector("pivot", FloatRepr.FLOAT, 3)
.vector("rotation", FloatRepr.FLOAT, 4)
.build())
.writer((ptr, instance) -> {
MemoryUtil.memPutShort(ptr, instance.blockLight);
MemoryUtil.memPutShort(ptr + 2, instance.skyLight);
MemoryUtil.memPutByte(ptr + 4, instance.r);
MemoryUtil.memPutByte(ptr + 5, instance.g);
MemoryUtil.memPutByte(ptr + 6, instance.b);
MemoryUtil.memPutByte(ptr + 7, instance.a);
MemoryUtil.memPutFloat(ptr + 8, instance.posX);
MemoryUtil.memPutFloat(ptr + 12, instance.posY);
MemoryUtil.memPutFloat(ptr + 16, instance.posZ);
MemoryUtil.memPutFloat(ptr + 20, instance.pivotX);
MemoryUtil.memPutFloat(ptr + 24, instance.pivotY);
MemoryUtil.memPutFloat(ptr + 28, instance.pivotZ);
MemoryUtil.memPutFloat(ptr + 32, instance.rotation.x);
MemoryUtil.memPutFloat(ptr + 36, instance.rotation.y);
MemoryUtil.memPutFloat(ptr + 40, instance.rotation.z);
MemoryUtil.memPutFloat(ptr + 44, instance.rotation.w);
MemoryUtil.memPutByte(ptr, instance.r);
MemoryUtil.memPutByte(ptr + 1, instance.g);
MemoryUtil.memPutByte(ptr + 2, instance.b);
MemoryUtil.memPutByte(ptr + 3, instance.a);
MemoryUtil.memPutShort(ptr + 4, instance.blockLight);
MemoryUtil.memPutShort(ptr + 6, instance.skyLight);
MemoryUtil.memPutInt(ptr + 8, instance.overlay);
MemoryUtil.memPutFloat(ptr + 12, instance.posX);
MemoryUtil.memPutFloat(ptr + 16, instance.posY);
MemoryUtil.memPutFloat(ptr + 20, instance.posZ);
MemoryUtil.memPutFloat(ptr + 24, instance.pivotX);
MemoryUtil.memPutFloat(ptr + 28, instance.pivotY);
MemoryUtil.memPutFloat(ptr + 32, instance.pivotZ);
MemoryUtil.memPutFloat(ptr + 36, instance.rotation.x);
MemoryUtil.memPutFloat(ptr + 40, instance.rotation.y);
MemoryUtil.memPutFloat(ptr + 44, instance.rotation.z);
MemoryUtil.memPutFloat(ptr + 48, instance.rotation.w);
})
.vertexShader(Flywheel.rl("instance/oriented.vert"))
.cullShader(Flywheel.rl("instance/cull/oriented.glsl"))

View file

@ -11,61 +11,18 @@ import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.Vec3;
public class OrientedInstance extends ColoredLitInstance implements Rotate<OrientedInstance> {
public final Quaternionf rotation = new Quaternionf();
public float pivotX = 0.5f;
public float pivotY = 0.5f;
public float pivotZ = 0.5f;
public float posX;
public float posY;
public float posZ;
public float pivotX = 0.5f;
public float pivotY = 0.5f;
public float pivotZ = 0.5f;
public final Quaternionf rotation = new Quaternionf();
public OrientedInstance(InstanceType<? extends OrientedInstance> type, InstanceHandle handle) {
super(type, handle);
}
@Override
public OrientedInstance rotate(Quaternionf quaternion) {
rotation.mul(quaternion);
return this;
}
public OrientedInstance setRotation(Quaternionf q) {
rotation.set(q);
return this;
}
public OrientedInstance setRotation(float x, float y, float z, float w) {
rotation.set(x, y, z, w);
return this;
}
public OrientedInstance resetRotation() {
rotation.identity();
return this;
}
public OrientedInstance setPivot(float x, float y, float z) {
pivotX = x;
pivotY = y;
pivotZ = z;
return this;
}
public OrientedInstance setPivot(Vector3f pos) {
return setPivot(pos.x(), pos.y(), pos.z());
}
public OrientedInstance setPivot(Vec3 pos) {
return setPivot((float) pos.x(), (float) pos.y(), (float) pos.z());
}
public OrientedInstance nudgePosition(float x, float y, float z) {
posX += x;
posY += y;
posZ += z;
return this;
}
public OrientedInstance setPosition(float x, float y, float z) {
posX = x;
posY = y;
@ -81,7 +38,58 @@ public class OrientedInstance extends ColoredLitInstance implements Rotate<Orien
return setPosition(pos.getX(), pos.getY(), pos.getZ());
}
public OrientedInstance setPosition(Vec3 pos) {
return setPosition((float) pos.x(), (float) pos.y(), (float) pos.z());
}
public OrientedInstance resetPosition() {
return setPosition(0, 0, 0);
}
public OrientedInstance nudgePosition(float x, float y, float z) {
posX += x;
posY += y;
posZ += z;
return this;
}
public OrientedInstance setPivot(float x, float y, float z) {
pivotX = x;
pivotY = y;
pivotZ = z;
return this;
}
public OrientedInstance setPivot(Vector3f pos) {
return setPivot(pos.x(), pos.y(), pos.z());
}
public OrientedInstance setPivot(Vec3i pos) {
return setPivot(pos.getX(), pos.getY(), pos.getZ());
}
public OrientedInstance setPivot(Vec3 pos) {
return setPivot((float) pos.x(), (float) pos.y(), (float) pos.z());
}
public OrientedInstance setRotation(Quaternionf q) {
rotation.set(q);
return this;
}
public OrientedInstance setRotation(float x, float y, float z, float w) {
rotation.set(x, y, z, w);
return this;
}
public OrientedInstance resetRotation() {
rotation.identity();
return this;
}
@Override
public OrientedInstance rotate(Quaternionf quaternion) {
rotation.mul(quaternion);
return this;
}
}

View file

@ -10,54 +10,44 @@ public final class Materials {
private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png");
public static final Material CHUNK_SOLID_SHADED = SimpleMaterial.builder()
.useOverlay(false)
.build();
public static final Material CHUNK_SOLID_UNSHADED = SimpleMaterial.builder()
.useOverlay(false)
.diffuse(false)
.build();
public static final Material CHUNK_CUTOUT_MIPPED_SHADED = SimpleMaterial.builder()
.cutout(CutoutShaders.HALF)
.useOverlay(false)
.build();
public static final Material CHUNK_CUTOUT_MIPPED_UNSHADED = SimpleMaterial.builder()
.cutout(CutoutShaders.HALF)
.useOverlay(false)
.diffuse(false)
.build();
public static final Material CHUNK_CUTOUT_SHADED = SimpleMaterial.builder()
.cutout(CutoutShaders.ONE_TENTH)
.mipmap(false)
.useOverlay(false)
.build();
public static final Material CHUNK_CUTOUT_UNSHADED = SimpleMaterial.builder()
.cutout(CutoutShaders.ONE_TENTH)
.mipmap(false)
.useOverlay(false)
.diffuse(false)
.build();
public static final Material CHUNK_TRANSLUCENT_SHADED = SimpleMaterial.builder()
.transparency(Transparency.TRANSLUCENT)
.useOverlay(false)
.build();
public static final Material CHUNK_TRANSLUCENT_UNSHADED = SimpleMaterial.builder()
.transparency(Transparency.TRANSLUCENT)
.useOverlay(false)
.diffuse(false)
.build();
public static final Material CHUNK_TRIPWIRE_SHADED = SimpleMaterial.builder()
.cutout(CutoutShaders.ONE_TENTH)
.transparency(Transparency.TRANSLUCENT)
.useOverlay(false)
.build();
public static final Material CHUNK_TRIPWIRE_UNSHADED = SimpleMaterial.builder()
.cutout(CutoutShaders.ONE_TENTH)
.transparency(Transparency.TRANSLUCENT)
.useOverlay(false)
.diffuse(false)
.build();

View file

@ -1,14 +0,0 @@
package com.jozufozu.flywheel.lib.math;
import net.minecraft.client.multiplayer.ClientLevel;
public interface DiffuseLightCalculator {
DiffuseLightCalculator DEFAULT = RenderMath::diffuseLight;
DiffuseLightCalculator NETHER = RenderMath::diffuseLightNether;
static DiffuseLightCalculator forLevel(ClientLevel level) {
return level.effects().constantAmbientLight() ? NETHER : DEFAULT;
}
float getDiffuse(float normalX, float normalY, float normalZ, boolean shaded);
}

View file

@ -1,7 +1,5 @@
package com.jozufozu.flywheel.lib.math;
import net.minecraftforge.client.model.lighting.QuadLighter;
public final class RenderMath {
private RenderMath() {
}
@ -33,18 +31,4 @@ public final class RenderMath {
public static byte unb(float f) {
return (byte) (int) (f * 255);
}
public static float diffuseLight(float x, float y, float z, boolean shaded) {
if (!shaded) {
return 1f;
}
return QuadLighter.calculateShade(x, y, z, false);
}
public static float diffuseLightNether(float x, float y, float z, boolean shaded) {
if (!shaded) {
return 0.9f;
}
return QuadLighter.calculateShade(x, y, z, true);
}
}

View file

@ -12,10 +12,10 @@ import com.mojang.blaze3d.vertex.PoseStack;
* <br>
* Only one instance of this class should exist per {@link PoseStack}.
*/
@ApiStatus.Internal
public class PoseTransformStack implements TransformStack<PoseTransformStack> {
private final PoseStack stack;
@ApiStatus.Internal
public PoseTransformStack(PoseStack stack) {
this.stack = stack;
}

View file

@ -8,16 +8,17 @@ import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.api.visualization.VisualizerRegistry;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
public class SimpleBlockEntityVisualizer<T extends BlockEntity> implements BlockEntityVisualizer<T> {
protected Factory<T> visualFactory;
protected Predicate<T> skipRender;
protected Predicate<T> skipVanillaRender;
public SimpleBlockEntityVisualizer(Factory<T> visualFactory, Predicate<T> skipRender) {
public SimpleBlockEntityVisualizer(Factory<T> visualFactory, Predicate<T> skipVanillaRender) {
this.visualFactory = visualFactory;
this.skipRender = skipRender;
this.skipVanillaRender = skipVanillaRender;
}
@Override
@ -26,8 +27,8 @@ public class SimpleBlockEntityVisualizer<T extends BlockEntity> implements Block
}
@Override
public boolean shouldSkipRender(T blockEntity) {
return skipRender.test(blockEntity);
public boolean skipVanillaRender(T blockEntity) {
return skipVanillaRender.test(blockEntity);
}
/**
@ -37,8 +38,8 @@ public class SimpleBlockEntityVisualizer<T extends BlockEntity> implements Block
* @param <T> The type of the block entity.
* @return The configuration object.
*/
public static <T extends BlockEntity> BlockEntityConfig<T> configure(BlockEntityType<T> type) {
return new BlockEntityConfig<>(type);
public static <T extends BlockEntity> Builder<T> builder(BlockEntityType<T> type) {
return new Builder<>(type);
}
@FunctionalInterface
@ -51,12 +52,12 @@ public class SimpleBlockEntityVisualizer<T extends BlockEntity> implements Block
*
* @param <T> The type of the block entity.
*/
public static class BlockEntityConfig<T extends BlockEntity> {
public static class Builder<T extends BlockEntity> {
protected BlockEntityType<T> type;
protected Factory<T> visualFactory;
protected Predicate<T> skipRender;
protected Predicate<T> skipVanillaRender;
public BlockEntityConfig(BlockEntityType<T> type) {
public Builder(BlockEntityType<T> type) {
this.type = type;
}
@ -66,40 +67,44 @@ public class SimpleBlockEntityVisualizer<T extends BlockEntity> implements Block
* @param visualFactory The visual factory.
* @return {@code this}
*/
public BlockEntityConfig<T> factory(Factory<T> visualFactory) {
public Builder<T> factory(Factory<T> visualFactory) {
this.visualFactory = visualFactory;
return this;
}
/**
* Sets a predicate to determine whether to skip rendering a block entity.
* @param skipRender The predicate.
* Sets a predicate to determine whether to skip rendering with the vanilla {@link BlockEntityRenderer}.
*
* @param skipVanillaRender The predicate.
* @return {@code this}
*/
public BlockEntityConfig<T> skipRender(Predicate<T> skipRender) {
this.skipRender = skipRender;
public Builder<T> skipVanillaRender(Predicate<T> skipVanillaRender) {
this.skipVanillaRender = skipVanillaRender;
return this;
}
/**
* Sets a predicate to always skip rendering for block entities of this type.
* Sets a predicate to never skip rendering with the vanilla {@link BlockEntityRenderer}.
*
* @return {@code this}
*/
public BlockEntityConfig<T> alwaysSkipRender() {
this.skipRender = be -> true;
public Builder<T> neverSkipVanillaRender() {
this.skipVanillaRender = blockEntity -> false;
return this;
}
/**
* Constructs the block entity visualizer, and sets it for the block entity type.
* Constructs the block entity visualizer and sets it for the block entity type.
*
* @return The block entity visualizer.
*/
public SimpleBlockEntityVisualizer<T> apply() {
Objects.requireNonNull(visualFactory, "Visual factory cannot be null!");
if (skipRender == null) {
skipRender = be -> false;
if (skipVanillaRender == null) {
skipVanillaRender = blockEntity -> true;
}
SimpleBlockEntityVisualizer<T> visualizer = new SimpleBlockEntityVisualizer<>(visualFactory, skipRender);
SimpleBlockEntityVisualizer<T> visualizer = new SimpleBlockEntityVisualizer<>(visualFactory, skipVanillaRender);
VisualizerRegistry.setVisualizer(type, visualizer);
return visualizer;
}

View file

@ -8,16 +8,17 @@ import com.jozufozu.flywheel.api.visualization.EntityVisualizer;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.api.visualization.VisualizerRegistry;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
public class SimpleEntityVisualizer<T extends Entity> implements EntityVisualizer<T> {
protected Factory<T> visualFactory;
protected Predicate<T> skipRender;
protected Predicate<T> skipVanillaRender;
public SimpleEntityVisualizer(Factory<T> visualFactory, Predicate<T> skipRender) {
public SimpleEntityVisualizer(Factory<T> visualFactory, Predicate<T> skipVanillaRender) {
this.visualFactory = visualFactory;
this.skipRender = skipRender;
this.skipVanillaRender = skipVanillaRender;
}
@Override
@ -26,8 +27,8 @@ public class SimpleEntityVisualizer<T extends Entity> implements EntityVisualize
}
@Override
public boolean shouldSkipRender(T entity) {
return skipRender.test(entity);
public boolean skipVanillaRender(T entity) {
return skipVanillaRender.test(entity);
}
/**
@ -37,8 +38,8 @@ public class SimpleEntityVisualizer<T extends Entity> implements EntityVisualize
* @param <T> The type of the entity.
* @return The configuration object.
*/
public static <T extends Entity> EntityConfig<T> configure(EntityType<T> type) {
return new EntityConfig<>(type);
public static <T extends Entity> Builder<T> builder(EntityType<T> type) {
return new Builder<>(type);
}
@FunctionalInterface
@ -51,12 +52,12 @@ public class SimpleEntityVisualizer<T extends Entity> implements EntityVisualize
*
* @param <T> The type of the entity.
*/
public static class EntityConfig<T extends Entity> {
public static class Builder<T extends Entity> {
protected EntityType<T> type;
protected Factory<T> visualFactory;
protected Predicate<T> skipRender;
protected Predicate<T> skipVanillaRender;
public EntityConfig(EntityType<T> type) {
public Builder(EntityType<T> type) {
this.type = type;
}
@ -66,40 +67,44 @@ public class SimpleEntityVisualizer<T extends Entity> implements EntityVisualize
* @param visualFactory The visual factory.
* @return {@code this}
*/
public EntityConfig<T> factory(Factory<T> visualFactory) {
public Builder<T> factory(Factory<T> visualFactory) {
this.visualFactory = visualFactory;
return this;
}
/**
* Sets a predicate to determine whether to skip rendering an entity.
* @param skipRender The predicate.
* Sets a predicate to determine whether to skip rendering with the vanilla {@link EntityRenderer}.
*
* @param skipVanillaRender The predicate.
* @return {@code this}
*/
public EntityConfig<T> skipRender(Predicate<T> skipRender) {
this.skipRender = skipRender;
public Builder<T> skipVanillaRender(Predicate<T> skipVanillaRender) {
this.skipVanillaRender = skipVanillaRender;
return this;
}
/**
* Sets a predicate to always skip rendering for entities of this type.
* Sets a predicate to always skip rendering with the vanilla {@link EntityRenderer}.
*
* @return {@code this}
*/
public EntityConfig<T> alwaysSkipRender() {
this.skipRender = entity -> true;
public Builder<T> neverSkipVanillaRender() {
this.skipVanillaRender = entity -> false;
return this;
}
/**
* Constructs the entity visualizer, and sets it for the entity type.
* Constructs the entity visualizer and sets it for the entity type.
*
* @return The entity visualizer.
*/
public SimpleEntityVisualizer<T> apply() {
Objects.requireNonNull(visualFactory, "Visual factory cannot be null!");
if (skipRender == null) {
skipRender = entity -> false;
if (skipVanillaRender == null) {
skipVanillaRender = entity -> true;
}
SimpleEntityVisualizer<T> visualizer = new SimpleEntityVisualizer<>(visualFactory, skipRender);
SimpleEntityVisualizer<T> visualizer = new SimpleEntityVisualizer<>(visualFactory, skipVanillaRender);
VisualizerRegistry.setVisualizer(type, visualizer);
return visualizer;
}

View file

@ -17,6 +17,7 @@ import com.jozufozu.flywheel.lib.visual.AbstractEntityVisual;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
@ -25,9 +26,15 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
public class MinecartVisual<T extends AbstractMinecart> extends AbstractEntityVisual<T> implements TickableVisual, DynamicVisual {
private static final ModelHolder BODY_MODEL = new ModelHolder(() -> {
return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.MINECART), Materials.MINECART);
});
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);
public static final ModelHolder HOPPER_BODY_MODEL = createBodyModelHolder(ModelLayers.HOPPER_MINECART);
public static final ModelHolder STANDARD_BODY_MODEL = createBodyModelHolder(ModelLayers.MINECART);
public static final ModelHolder SPAWNER_BODY_MODEL = createBodyModelHolder(ModelLayers.SPAWNER_MINECART);
public static final ModelHolder TNT_BODY_MODEL = createBodyModelHolder(ModelLayers.TNT_MINECART);
private final ModelHolder bodyModel;
private TransformedInstance body;
private TransformedInstance contents;
@ -36,8 +43,15 @@ public class MinecartVisual<T extends AbstractMinecart> extends AbstractEntityVi
private final PoseStack stack = new PoseStack();
public MinecartVisual(VisualizationContext ctx, T entity) {
public MinecartVisual(VisualizationContext ctx, T entity, ModelHolder bodyModel) {
super(ctx, entity);
this.bodyModel = bodyModel;
}
private static ModelHolder createBodyModelHolder(ModelLayerLocation layer) {
return new ModelHolder(() -> {
return new SingleMeshModel(ModelPartConverter.convert(layer), Materials.MINECART);
});
}
@Override
@ -46,13 +60,13 @@ public class MinecartVisual<T extends AbstractMinecart> extends AbstractEntityVi
blockState = entity.getDisplayBlockState();
contents = createContentsInstance();
updatePosition(partialTick);
updateInstances(partialTick);
super.init(partialTick);
}
private TransformedInstance createBodyInstance() {
return instancerProvider.instancer(InstanceTypes.TRANSFORMED, BODY_MODEL.get(), RenderStage.AFTER_ENTITIES)
return instancerProvider.instancer(InstanceTypes.TRANSFORMED, bodyModel.get(), RenderStage.AFTER_ENTITIES)
.createInstance();
}
@ -75,7 +89,7 @@ public class MinecartVisual<T extends AbstractMinecart> extends AbstractEntityVi
}
@Override
public void tick(VisualTickContext c) {
public void tick(VisualTickContext context) {
BlockState displayBlockState = entity.getDisplayBlockState();
if (displayBlockState != blockState) {
@ -98,10 +112,10 @@ public class MinecartVisual<T extends AbstractMinecart> extends AbstractEntityVi
return;
}
updatePosition(context.partialTick());
updateInstances(context.partialTick());
}
private void updatePosition(float partialTick) {
private void updateInstances(float partialTick) {
stack.setIdentity();
double posX = Mth.lerp(partialTick, entity.xOld, entity.getX());
@ -160,10 +174,9 @@ public class MinecartVisual<T extends AbstractMinecart> extends AbstractEntityVi
if (contents != null) {
stack.pushPose();
stack.scale(0.75F, 0.75F, 0.75F);
stack.translate(-0.5D, (float) (displayOffset - 8) / 16, 0.5D);
stack.translate(-0.5F, (float) (displayOffset - 8) / 16, 0.5F);
stack.mulPose(Axis.YP.rotationDegrees(90));
contents.setTransform(stack)
.setChanged();
updateContents(contents, stack, partialTick);
stack.popPose();
}
@ -172,6 +185,11 @@ public class MinecartVisual<T extends AbstractMinecart> extends AbstractEntityVi
.setChanged();
}
protected void updateContents(TransformedInstance contents, PoseStack stack, float partialTick) {
contents.setTransform(stack)
.setChanged();
}
public void updateLight() {
relight(entity.blockPosition(), body, contents);
}

View file

@ -0,0 +1,41 @@
package com.jozufozu.flywheel.vanilla;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.lib.instance.TransformedInstance;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.vehicle.MinecartTNT;
public class TntMinecartVisual<T extends MinecartTNT> extends MinecartVisual<T> {
private static final int WHITE_OVERLAY = OverlayTexture.pack(OverlayTexture.u(1.0F), 10);
public TntMinecartVisual(VisualizationContext ctx, T entity) {
super(ctx, entity, TNT_BODY_MODEL);
}
@Override
protected void updateContents(TransformedInstance contents, PoseStack stack, float partialTick) {
int fuseTime = entity.getFuse();
if (fuseTime > -1 && (float) fuseTime - partialTick + 1.0F < 10.0F) {
float f = 1.0F - ((float) fuseTime - partialTick + 1.0F) / 10.0F;
f = Mth.clamp(f, 0.0F, 1.0F);
f *= f;
f *= f;
float scale = 1.0F + f * 0.3F;
stack.scale(scale, scale, scale);
}
int overlay;
if (fuseTime > -1 && fuseTime / 5 % 2 == 0) {
overlay = WHITE_OVERLAY;
} else {
overlay = OverlayTexture.NO_OVERLAY;
}
contents.setTransform(stack)
.setOverlay(overlay)
.setChanged();
}
}

View file

@ -1,7 +1,7 @@
package com.jozufozu.flywheel.vanilla;
import static com.jozufozu.flywheel.lib.visual.SimpleBlockEntityVisualizer.configure;
import static com.jozufozu.flywheel.lib.visual.SimpleEntityVisualizer.configure;
import static com.jozufozu.flywheel.lib.visual.SimpleBlockEntityVisualizer.builder;
import static com.jozufozu.flywheel.lib.visual.SimpleEntityVisualizer.builder;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.block.entity.BlockEntityType;
@ -28,48 +28,51 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
*/
public class VanillaVisuals {
public static void init() {
configure(BlockEntityType.CHEST)
.alwaysSkipRender()
builder(BlockEntityType.CHEST)
.factory(ChestVisual::new)
.apply();
configure(BlockEntityType.ENDER_CHEST)
.alwaysSkipRender()
builder(BlockEntityType.ENDER_CHEST)
.factory(ChestVisual::new)
.apply();
configure(BlockEntityType.TRAPPED_CHEST)
.alwaysSkipRender()
builder(BlockEntityType.TRAPPED_CHEST)
.factory(ChestVisual::new)
.apply();
configure(BlockEntityType.BELL)
.alwaysSkipRender()
builder(BlockEntityType.BELL)
.factory(BellVisual::new)
.apply();
configure(BlockEntityType.SHULKER_BOX)
.alwaysSkipRender()
builder(BlockEntityType.SHULKER_BOX)
.factory(ShulkerBoxVisual::new)
.apply();
configure(EntityType.MINECART)
.skipRender(MinecartVisual::shouldSkipRender)
.factory(MinecartVisual::new)
builder(EntityType.CHEST_MINECART)
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.CHEST_BODY_MODEL))
.skipVanillaRender(MinecartVisual::shouldSkipRender)
.apply();
configure(EntityType.COMMAND_BLOCK_MINECART)
.skipRender(MinecartVisual::shouldSkipRender)
.factory(MinecartVisual::new)
builder(EntityType.COMMAND_BLOCK_MINECART)
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.COMMAND_BLOCK_BODY_MODEL))
.skipVanillaRender(MinecartVisual::shouldSkipRender)
.apply();
configure(EntityType.FURNACE_MINECART)
.skipRender(MinecartVisual::shouldSkipRender)
.factory(MinecartVisual::new)
builder(EntityType.FURNACE_MINECART)
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.FURNACE_BODY_MODEL))
.skipVanillaRender(MinecartVisual::shouldSkipRender)
.apply();
configure(EntityType.HOPPER_MINECART)
.skipRender(MinecartVisual::shouldSkipRender)
.factory(MinecartVisual::new)
builder(EntityType.HOPPER_MINECART)
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.HOPPER_BODY_MODEL))
.skipVanillaRender(MinecartVisual::shouldSkipRender)
.apply();
configure(EntityType.TNT_MINECART)
.skipRender(MinecartVisual::shouldSkipRender)
.factory(MinecartVisual::new)
builder(EntityType.MINECART)
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.STANDARD_BODY_MODEL))
.skipVanillaRender(MinecartVisual::shouldSkipRender)
.apply();
builder(EntityType.SPAWNER_MINECART)
.factory((ctx, entity) -> new MinecartVisual<>(ctx, entity, MinecartVisual.SPAWNER_BODY_MODEL))
.skipVanillaRender(MinecartVisual::shouldSkipRender)
.apply();
builder(EntityType.TNT_MINECART)
.factory(TntMinecartVisual::new)
.skipVanillaRender(MinecartVisual::shouldSkipRender)
.apply();
}
}

View file

@ -4,5 +4,6 @@ void flw_instanceVertex(in FlwInstance i) {
flw_vertexPos = vec4(rotateByQuaternion(flw_vertexPos.xyz - i.pivot, i.rotation) + i.pivot + i.position, 1.0);
flw_vertexNormal = rotateByQuaternion(flw_vertexNormal, i.rotation);
flw_vertexColor = i.color;
flw_vertexOverlay = i.overlay;
flw_vertexLight = i.light / 15.0;
}

View file

@ -2,5 +2,6 @@ void flw_instanceVertex(in FlwInstance i) {
flw_vertexPos = i.pose * flw_vertexPos;
flw_vertexNormal = i.normal * flw_vertexNormal;
flw_vertexColor = i.color;
flw_vertexOverlay = i.overlay;
flw_vertexLight = i.light / 15.0;
}