Restore SBB contraption rendering

This commit is contained in:
PepperCode1 2024-05-16 21:18:58 -07:00
parent 7d265eb2c1
commit 79e1c8c950
46 changed files with 493 additions and 764 deletions

View file

@ -1,8 +1,8 @@
package com.simibubi.create;
import com.simibubi.create.content.contraptions.glue.SuperGlueSelectionHandler;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.contraptions.render.SBBContraptionManager;
import com.simibubi.create.content.contraptions.render.ContraptionRenderInfo;
import com.simibubi.create.content.contraptions.render.ContraptionRenderInfoManager;
import com.simibubi.create.content.decoration.encasing.CasingConnectivity;
import com.simibubi.create.content.equipment.bell.SoulPulseEffectHandler;
import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonRenderHandler;
@ -80,7 +80,7 @@ public class CreateClient {
BUFFER_CACHE.registerCompartment(CachedBufferer.DIRECTIONAL_PARTIAL);
BUFFER_CACHE.registerCompartment(KineticBlockEntityRenderer.KINETIC_BLOCK);
BUFFER_CACHE.registerCompartment(WaterWheelRenderer.WATER_WHEEL);
BUFFER_CACHE.registerCompartment(SBBContraptionManager.CONTRAPTION, 20);
BUFFER_CACHE.registerCompartment(ContraptionRenderInfo.CONTRAPTION, 20);
BUFFER_CACHE.registerCompartment(WorldSectionElement.DOC_WORLD_SECTION, 20);
AllPartialModels.init();
@ -95,7 +95,7 @@ public class CreateClient {
BUFFER_CACHE.invalidate();
SCHEMATIC_HANDLER.updateRenderers();
ContraptionRenderDispatcher.reset();
ContraptionRenderInfoManager.resetAll();
}
public static void checkGraphicsFanciness() {

View file

@ -28,7 +28,7 @@ import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.elevator.ElevatorContraption;
import com.simibubi.create.content.contraptions.glue.SuperGlueEntity;
import com.simibubi.create.content.contraptions.mounted.MountedContraption;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.contraptions.render.ContraptionRenderInfo;
import com.simibubi.create.content.contraptions.sync.ContraptionSeatMappingPacket;
import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock;
import com.simibubi.create.content.trains.entity.CarriageContraption;
@ -379,7 +379,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
if (!contraption.deferInvalidate)
return;
contraption.deferInvalidate = false;
ContraptionRenderDispatcher.invalidate(contraption);
ContraptionRenderInfo.invalidate(contraption);
});
if (!(level() instanceof ServerLevelAccessor sl))

View file

@ -158,8 +158,7 @@ public abstract class Contraption {
// Client
public Map<BlockPos, ModelData> modelData;
public Map<BlockPos, BlockEntity> presentBlockEntities;
public List<BlockEntity> maybeInstancedBlockEntities;
public List<BlockEntity> specialRenderedBlockEntities;
public List<BlockEntity> renderedBlockEntities;
protected ContraptionWorld world;
public boolean deferInvalidate;
@ -176,8 +175,7 @@ public abstract class Contraption {
glueToRemove = new HashSet<>();
initialPassengers = new HashMap<>();
presentBlockEntities = new HashMap<>();
maybeInstancedBlockEntities = new ArrayList<>();
specialRenderedBlockEntities = new ArrayList<>();
renderedBlockEntities = new ArrayList<>();
pendingSubContraptions = new ArrayList<>();
stabilizedSubContraptions = new HashMap<>();
simplifiedEntityColliders = Optional.empty();
@ -688,7 +686,7 @@ public abstract class Contraption {
public void readNBT(Level world, CompoundTag nbt, boolean spawnData) {
blocks.clear();
presentBlockEntities.clear();
specialRenderedBlockEntities.clear();
renderedBlockEntities.clear();
Tag blocks = nbt.get("Blocks");
// used to differentiate between the 'old' and the paletted serialization
@ -893,20 +891,17 @@ public abstract class Contraption {
if (be == null)
return;
be.setLevel(world);
modelData.put(info.pos(), be.getModelData());
if (be instanceof KineticBlockEntity kbe)
kbe.setSpeed(0);
be.getBlockState();
MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(info.state());
if (movementBehaviour == null || !movementBehaviour.hasSpecialInstancedRendering())
maybeInstancedBlockEntities.add(be);
if (movementBehaviour != null && !movementBehaviour.renderAsNormalBlockEntity())
return;
presentBlockEntities.put(info.pos(), be);
specialRenderedBlockEntities.add(be);
modelData.put(info.pos(), be.getModelData());
MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(info.state());
if (movementBehaviour == null || !movementBehaviour.disableBlockEntityRendering()) {
renderedBlockEntities.add(be);
}
});
}
@ -1376,8 +1371,8 @@ public abstract class Contraption {
}, blocks.keySet());
}
public Collection<BlockEntity> getSpecialRenderedBEs() {
return specialRenderedBlockEntities;
public Collection<BlockEntity> getRenderedBEs() {
return renderedBlockEntities;
}
public boolean isHiddenInPortal(BlockPos localPos) {

View file

@ -11,32 +11,31 @@ import com.jozufozu.flywheel.lib.instance.AbstractInstance;
import net.minecraft.core.BlockPos;
public class ActorInstance extends AbstractInstance {
public float x;
public float y;
public float z;
public byte blockLight;
public byte skyLight;
public float rotationOffset;
public byte rotationAxisX;
public byte rotationAxisY;
public byte rotationAxisZ;
public Quaternionf rotation = new Quaternionf();
public byte rotationCenterX = 64;
public byte rotationCenterY = 64;
public byte rotationCenterZ = 64;
public float speed;
public float x;
public float y;
public float z;
public byte blockLight;
public byte skyLight;
public float rotationOffset;
public byte rotationAxisX;
public byte rotationAxisY;
public byte rotationAxisZ;
public Quaternionf rotation = new Quaternionf();
public byte rotationCenterX = 64;
public byte rotationCenterY = 64;
public byte rotationCenterZ = 64;
public float speed;
public ActorInstance(InstanceType<?> type, InstanceHandle handle) {
super(type, handle);
}
public ActorInstance setPosition(BlockPos pos) {
this.x = pos.getX();
this.y = pos.getY();
this.z = pos.getZ();
return this;
}
this.x = pos.getX();
this.y = pos.getY();
this.z = pos.getZ();
return this;
}
public ActorInstance setBlockLight(int blockLight) {
this.blockLight = (byte) blockLight;
@ -48,39 +47,39 @@ public class ActorInstance extends AbstractInstance {
return this;
}
public ActorInstance setRotationOffset(float rotationOffset) {
this.rotationOffset = rotationOffset;
return this;
}
public ActorInstance setRotationOffset(float rotationOffset) {
this.rotationOffset = rotationOffset;
return this;
}
public ActorInstance setSpeed(float speed) {
this.speed = speed;
return this;
}
public ActorInstance setSpeed(float speed) {
this.speed = speed;
return this;
}
public ActorInstance setRotationAxis(Vector3f axis) {
setRotationAxis(axis.x(), axis.y(), axis.z());
return this;
}
public ActorInstance setRotationAxis(Vector3f axis) {
setRotationAxis(axis.x(), axis.y(), axis.z());
return this;
}
public ActorInstance setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) {
this.rotationAxisX = (byte) (rotationAxisX * 127);
this.rotationAxisY = (byte) (rotationAxisY * 127);
this.rotationAxisZ = (byte) (rotationAxisZ * 127);
return this;
}
public ActorInstance setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) {
this.rotationAxisX = (byte) (rotationAxisX * 127);
this.rotationAxisY = (byte) (rotationAxisY * 127);
this.rotationAxisZ = (byte) (rotationAxisZ * 127);
return this;
}
public ActorInstance setRotationCenter(Vector3f axis) {
setRotationCenter(axis.x(), axis.y(), axis.z());
return this;
}
public ActorInstance setRotationCenter(Vector3f axis) {
setRotationCenter(axis.x(), axis.y(), axis.z());
return this;
}
public ActorInstance setRotationCenter(float rotationCenterX, float rotationCenterY, float rotationCenterZ) {
this.rotationCenterX = (byte) (rotationCenterX * 127);
this.rotationCenterY = (byte) (rotationCenterY * 127);
this.rotationCenterZ = (byte) (rotationCenterZ * 127);
return this;
}
public ActorInstance setRotationCenter(float rotationCenterX, float rotationCenterY, float rotationCenterZ) {
this.rotationCenterX = (byte) (rotationCenterX * 127);
this.rotationCenterY = (byte) (rotationCenterY * 127);
this.rotationCenterZ = (byte) (rotationCenterZ * 127);
return this;
}
public ActorInstance setLocalRotation(Quaternionfc q) {
this.rotation.set(q);

View file

@ -138,11 +138,6 @@ public class ContraptionControlsMovement implements MovementBehaviour {
.string();
}
@Override
public boolean renderAsNormalBlockEntity() {
return true;
}
@Override
@OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext ctx, VirtualRenderWorld renderWorld, ContraptionMatrices matrices,

View file

@ -5,11 +5,11 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableBoolean;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ActorVisual;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.VecHelper;
@ -45,25 +45,6 @@ public class HarvesterMovementBehaviour implements MovementBehaviour {
.getOpposite());
}
@Override
public boolean hasSpecialInstancedRendering() {
return true;
}
@Nullable
@Override
public ActorVisual createInstance(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
MovementContext movementContext) {
return new HarvesterActorVisual(visualizationContext, simulationWorld, movementContext);
}
@Override
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffers) {
if (!ContraptionRenderDispatcher.canInstance())
HarvesterRenderer.renderInContraption(context, renderWorld, matrices, buffers);
}
@Override
public Vec3 getActiveAreaOffset(MovementContext context) {
return Vec3.atLowerCornerOf(context.state.getValue(HarvesterBlock.FACING)
@ -218,4 +199,23 @@ public class HarvesterMovementBehaviour implements MovementBehaviour {
.createLegacyBlock();
}
@Override
public boolean disableBlockEntityRendering() {
return true;
}
@Override
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffers) {
if (!VisualizationManager.supportsVisualization(context.world))
HarvesterRenderer.renderInContraption(context, renderWorld, matrices, buffers);
}
@Nullable
@Override
public ActorVisual createVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
MovementContext movementContext) {
return new HarvesterActorVisual(visualizationContext, simulationWorld, movementContext);
}
}

View file

@ -6,7 +6,6 @@ import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
@ -15,6 +14,7 @@ import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
@ -54,7 +54,7 @@ public class HarvesterRenderer extends SafeBlockEntityRenderer<HarvesterBlockEnt
transform(context.world, facing, superBuffer, speed, PIVOT);
superBuffer
.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.light(matrices.getWorld(), LevelRenderer.getLightColor(renderWorld, context.localPos))
.renderInto(matrices.getViewProjection(), buffers.getBuffer(RenderType.cutoutMipped()));
}

View file

@ -5,11 +5,11 @@ import java.util.Optional;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ActorVisual;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.trains.entity.CarriageContraption;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
@ -40,13 +40,13 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour {
}
@Override
public boolean hasSpecialInstancedRendering() {
public boolean disableBlockEntityRendering() {
return true;
}
@Nullable
@Override
public ActorVisual createInstance(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
public ActorVisual createVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
MovementContext movementContext) {
return new PSIActorVisual(visualizationContext, simulationWorld, movementContext);
}
@ -55,7 +55,7 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour {
@OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffer) {
if (!ContraptionRenderDispatcher.canInstance())
if (!VisualizationManager.supportsVisualization(context.world))
PortableStorageInterfaceRenderer.renderInContraption(context, renderWorld, matrices, buffer);
}

View file

@ -10,7 +10,6 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
@ -19,6 +18,7 @@ import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
@ -56,7 +56,7 @@ public class PortableStorageInterfaceRenderer extends SafeBlockEntityRenderer<Po
boolean lit = animation.settled();
render(blockState, lit, progress, matrices.getModel(),
sbb -> sbb
.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.light(matrices.getWorld(), LevelRenderer.getLightColor(renderWorld, context.localPos))
.renderInto(matrices.getViewProjection(), vb));
}

View file

@ -10,13 +10,13 @@ import java.util.function.BiConsumer;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.actors.roller.RollerBlockEntity.RollingMode;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.pulley.PulleyContraption;
import com.simibubi.create.content.contraptions.render.ActorVisual;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.trains.bogey.StandardBogeyBlock;
@ -70,13 +70,13 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
}
@Override
public boolean hasSpecialInstancedRendering() {
public boolean disableBlockEntityRendering() {
return true;
}
@Nullable
@Override
public ActorVisual createInstance(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
public ActorVisual createVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
MovementContext movementContext) {
return new RollerActorVisual(visualizationContext, simulationWorld, movementContext);
}
@ -84,7 +84,7 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffers) {
if (!ContraptionRenderDispatcher.canInstance())
if (!VisualizationManager.supportsVisualization(context.world))
RollerRenderer.renderInContraption(context, renderWorld, matrices, buffers);
}

View file

@ -7,7 +7,6 @@ import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.actors.harvester.HarvesterRenderer;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
@ -15,6 +14,7 @@ import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context;
@ -73,7 +73,7 @@ public class RollerRenderer extends SmartBlockEntityRenderer<RollerBlockEntity>
PoseStack viewProjection = matrices.getViewProjection();
viewProjection.pushPose();
viewProjection.translate(0, -.25, 0);
int contraptionWorldLight = ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld);
int contraptionWorldLight = LevelRenderer.getLightColor(renderWorld, context.localPos);
superBuffer.translate(0, -.5, .5)
.rotateYDegrees(90)
.light(matrices.getWorld(), contraptionWorldLight)

View file

@ -5,13 +5,13 @@ import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.Direction;
@ -32,7 +32,7 @@ public class ControlsRenderer {
.center()
.rotateYDegrees(hAngle)
.uncenter()
.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.light(matrices.getWorld(), LevelRenderer.getLightColor(renderWorld, context.localPos))
.renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.cutoutMipped()));
double yOffset = Mth.lerp(equipAnimation * equipAnimation, -0.15f, 0.05f);
@ -52,7 +52,7 @@ public class ControlsRenderer {
.translate(0, -2 / 16f, -3 / 16f)
.translate(first ? 0 : 6 / 16f, 0, 0);
lever.transform(ms)
.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.light(matrices.getWorld(), LevelRenderer.getLightColor(renderWorld, context.localPos))
.renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid()));
ms.popPose();
}

View file

@ -5,6 +5,7 @@ import javax.annotation.Nullable;
import org.joml.Quaternionf;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.jozufozu.flywheel.lib.model.baked.PartialModel;
import com.mojang.math.Axis;
import com.simibubi.create.AllPartialModels;
@ -15,12 +16,12 @@ import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ActorVisual;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.Direction;
@ -36,11 +37,16 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
return null;
}
@Override
public boolean disableBlockEntityRendering() {
return true;
}
@Override
@OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffer) {
if (ContraptionRenderDispatcher.canInstance())
if (!VisualizationManager.supportsVisualization(context.world))
return;
Direction facing = context.state.getValue(BlockStateProperties.FACING);
@ -67,18 +73,13 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour {
// render
superBuffer
.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.light(matrices.getWorld(), LevelRenderer.getLightColor(renderWorld, context.localPos))
.renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid()));
}
@Override
public boolean hasSpecialInstancedRendering() {
return true;
}
@Nullable
@Override
public ActorVisual createInstance(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
public ActorVisual createVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
MovementContext movementContext) {
return new StabilizedBearingVisual(visualizationContext, simulationWorld, movementContext);
}

View file

@ -11,12 +11,6 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.Vec3;
public class BellMovementBehaviour implements MovementBehaviour {
@Override
public boolean renderAsNormalBlockEntity() {
return true;
}
@Override
public boolean isActive(MovementContext context) {
return MovementBehaviour.super.isActive(context) && !(context.contraption instanceof CarriageContraption);

View file

@ -5,11 +5,6 @@ import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.CampfireBlock;
public class CampfireMovementBehaviour implements MovementBehaviour {
@Override
public boolean renderAsNormalBlockEntity() {
return true;
}
@Override
public void tick(MovementContext context) {
if (context.world == null || !context.world.isClientSide || context.position == null

View file

@ -80,11 +80,7 @@ public interface MovementBehaviour {
default void writeExtraData(MovementContext context) {}
default boolean renderAsNormalBlockEntity() {
return false;
}
default boolean hasSpecialInstancedRendering() {
default boolean disableBlockEntityRendering() {
return false;
}
@ -94,7 +90,7 @@ public interface MovementBehaviour {
@OnlyIn(Dist.CLIENT)
@Nullable
default ActorVisual createInstance(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
default ActorVisual createVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
MovementContext movementContext) {
return null;
}

View file

@ -1,16 +1,30 @@
package com.simibubi.create.content.contraptions.render;
import org.apache.commons.lang3.tuple.Pair;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.jozufozu.flywheel.lib.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.content.contraptions.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.Contraption;
import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.foundation.render.BlockEntityRenderHelper;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
public class ContraptionEntityRenderer<C extends AbstractContraptionEntity> extends EntityRenderer<C> {
public ContraptionEntityRenderer(EntityRendererProvider.Context context) {
super(context);
}
@ -21,7 +35,7 @@ public class ContraptionEntityRenderer<C extends AbstractContraptionEntity> exte
}
@Override
public boolean shouldRender(C entity, Frustum clippingHelper, double cameraX, double cameraY,
public boolean shouldRender(C entity, Frustum frustum, double cameraX, double cameraY,
double cameraZ) {
if (entity.getContraption() == null)
return false;
@ -30,18 +44,72 @@ public class ContraptionEntityRenderer<C extends AbstractContraptionEntity> exte
if (!entity.isReadyForRender())
return false;
return super.shouldRender(entity, clippingHelper, cameraX, cameraY, cameraZ);
return super.shouldRender(entity, frustum, cameraX, cameraY, cameraZ);
}
@Override
public void render(C entity, float yaw, float partialTicks, PoseStack ms, MultiBufferSource buffers,
public void render(C entity, float yaw, float partialTicks, PoseStack poseStack, MultiBufferSource buffers,
int overlay) {
super.render(entity, yaw, partialTicks, ms, buffers, overlay);
super.render(entity, yaw, partialTicks, poseStack, buffers, overlay);
// Contraption contraption = entity.getContraption();
// if (contraption != null) {
// ContraptionRenderDispatcher.renderFromEntity(entity, contraption, buffers);
// }
Contraption contraption = entity.getContraption();
if (contraption == null) {
return;
}
Level level = entity.level();
ContraptionRenderInfo renderInfo = ContraptionRenderInfo.get(contraption);
VirtualRenderWorld renderWorld = renderInfo.getRenderWorld();
ContraptionMatrices matrices = renderInfo.getMatrices();
matrices.setup(poseStack, entity);
if (!VisualizationManager.supportsVisualization(level)) {
for (RenderType renderType : RenderType.chunkBufferLayers()) {
SuperByteBuffer sbb = renderInfo.getBuffer(renderType);
if (!sbb.isEmpty()) {
VertexConsumer vc = buffers.getBuffer(renderType);
sbb.transform(matrices.getModel())
.light(matrices.getWorld())
.hybridLight()
.renderInto(poseStack, vc);
}
}
}
renderBlockEntities(level, renderWorld, contraption, matrices, buffers);
renderActors(level, renderWorld, contraption, matrices, buffers);
matrices.clear();
}
private static void renderBlockEntities(Level level, VirtualRenderWorld renderWorld, Contraption c,
ContraptionMatrices matrices, MultiBufferSource buffer) {
BlockEntityRenderHelper.renderBlockEntities(level, renderWorld, c.getRenderedBEs(),
matrices.getModelViewProjection(), matrices.getLight(), buffer);
}
private static void renderActors(Level level, VirtualRenderWorld renderWorld, Contraption c,
ContraptionMatrices matrices, MultiBufferSource buffer) {
PoseStack m = matrices.getModel();
for (Pair<StructureTemplate.StructureBlockInfo, MovementContext> actor : c.getActors()) {
MovementContext context = actor.getRight();
if (context == null)
continue;
if (context.world == null)
context.world = level;
StructureTemplate.StructureBlockInfo blockInfo = actor.getLeft();
MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(blockInfo.state());
if (movementBehaviour != null) {
if (c.isHiddenInPortal(blockInfo.pos()))
continue;
m.pushPose();
TransformStack.of(m)
.translate(blockInfo.pos());
movementBehaviour.renderInContraption(context, renderWorld, matrices, buffer);
m.popPose();
}
}
}
}

View file

@ -22,9 +22,7 @@ public class ContraptionMatrices {
private final Matrix4f world = new Matrix4f();
private final Matrix4f light = new Matrix4f();
private boolean ready;
public void setup(PoseStack viewProjection, AbstractContraptionEntity entity) {
void setup(PoseStack viewProjection, AbstractContraptionEntity entity) {
float partialTicks = AnimationTickHolder.getPartialTicks();
this.viewProjection.pushPose();
@ -41,17 +39,14 @@ public class ContraptionMatrices {
light.set(world);
light.mul(model.last()
.pose());
ready = true;
}
public void clear() {
void clear() {
clearStack(modelViewProjection);
clearStack(viewProjection);
clearStack(model);
world.identity();
light.identity();
ready = false;
}
public PoseStack getModelViewProjection() {
@ -74,10 +69,6 @@ public class ContraptionMatrices {
return light;
}
public boolean isReady() {
return ready;
}
public static void transform(PoseStack ms, PoseStack transform) {
ms.last()
.pose()

View file

@ -1,31 +0,0 @@
package com.simibubi.create.content.contraptions.render;
public class ContraptionProgram {
// protected final int uLightBoxSize;
// protected final int uLightBoxMin;
// protected final int uModel;
//
// protected int uLightVolume;
//
// public ContraptionProgram(ResourceLocation name, int handle) {
// super(handle);
// uLightBoxSize = getUniformLocation("uLightBoxSize");
// uLightBoxMin = getUniformLocation("uLightBoxMin");
// uModel = getUniformLocation("uModel");
// }
//
// @Override
// protected void registerSamplers() {
// super.registerSamplers();
// uLightVolume = setSamplerBinding("uLightVolume", 4);
// }
//
// public void bind(Matrix4f model, AABB lightVolume) {
// double sizeX = lightVolume.maxX - lightVolume.minX;
// double sizeY = lightVolume.maxY - lightVolume.minY;
// double sizeZ = lightVolume.maxZ - lightVolume.minZ;
// GL20.glUniform3f(uLightBoxSize, (float) sizeX, (float) sizeY, (float) sizeZ);
// GL20.glUniform3f(uLightBoxMin, (float) lightVolume.minX, (float) lightVolume.minY, (float) lightVolume.minZ);
// // uploadMatrixUniform(uModel, model);
// }
}

View file

@ -1,182 +0,0 @@
package com.simibubi.create.content.contraptions.render;
import org.apache.commons.lang3.tuple.Pair;
import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
import com.jozufozu.flywheel.api.event.RenderStageEvent;
import com.jozufozu.flywheel.backend.gl.error.GlError;
import com.jozufozu.flywheel.lib.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.content.contraptions.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.Contraption;
import com.simibubi.create.content.contraptions.ContraptionWorld;
import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.foundation.render.BlockEntityRenderHelper;
import com.simibubi.create.foundation.utility.WorldAttached;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.common.Mod;
@OnlyIn(Dist.CLIENT)
@Mod.EventBusSubscriber(Dist.CLIENT)
public class ContraptionRenderDispatcher {
private static WorldAttached<ContraptionRenderingWorld<?>> WORLDS = new WorldAttached<>(SBBContraptionManager::new);
/**
* Reset a contraption's renderer.
*
* @param contraption The contraption to invalidate.
* @return true if there was a renderer associated with the given contraption.
*/
public static boolean invalidate(Contraption contraption) {
Level level = contraption.entity.level();
return WORLDS.get(level)
.invalidate(contraption);
}
public static void tick(Level world) {
if (Minecraft.getInstance()
.isPaused())
return;
WORLDS.get(world)
.tick();
}
public static void beginFrame(BeginFrameEvent event) {
WORLDS.get(event.getContext()
.level())
.beginFrame(event);
}
public static void renderLayer(RenderStageEvent event) {
WORLDS.get(event.getLevel())
.renderLayer(event);
GlError.pollAndThrow(() -> "contraption layer: " + event.getStage());
}
public static void onRendererReload(ReloadLevelRendererEvent event) {
reset();
}
public static void renderFromEntity(AbstractContraptionEntity entity, Contraption contraption,
MultiBufferSource buffers) {
Level world = entity.level();
ContraptionRenderInfo renderInfo = WORLDS.get(world)
.getRenderInfo(contraption);
ContraptionMatrices matrices = renderInfo.getMatrices();
// something went wrong with the other rendering
if (!matrices.isReady())
return;
VirtualRenderWorld renderWorld = renderInfo.renderWorld;
renderBlockEntities(world, renderWorld, contraption, matrices, buffers);
if (buffers instanceof MultiBufferSource.BufferSource)
((MultiBufferSource.BufferSource) buffers).endBatch();
renderActors(world, renderWorld, contraption, matrices, buffers);
}
public static VirtualRenderWorld setupRenderWorld(Level world, Contraption c) {
ContraptionWorld contraptionWorld = c.getContraptionWorld();
BlockPos origin = c.anchor;
int minBuildHeight = contraptionWorld.getMinBuildHeight();
int height = contraptionWorld.getHeight();
VirtualRenderWorld renderWorld = new VirtualRenderWorld(world, minBuildHeight, height, origin) {
@Override
public boolean supportsVisualization() {
return canInstance();
}
};
renderWorld.setBlockEntities(c.presentBlockEntities.values());
for (StructureTemplate.StructureBlockInfo info : c.getBlocks()
.values())
// Skip individual lighting updates to prevent lag with large contraptions
// FIXME 1.20 this '0' used to be Block.UPDATE_SUPPRESS_LIGHT, yet VirtualRenderWorld didn't actually parse the flags at all
renderWorld.setBlock(info.pos(), info.state(), 0);
renderWorld.runLightEngine();
return renderWorld;
}
public static void renderBlockEntities(Level world, VirtualRenderWorld renderWorld, Contraption c,
ContraptionMatrices matrices, MultiBufferSource buffer) {
BlockEntityRenderHelper.renderBlockEntities(world, renderWorld, c.getSpecialRenderedBEs(),
matrices.getModelViewProjection(), matrices.getLight(), buffer);
}
protected static void renderActors(Level world, VirtualRenderWorld renderWorld, Contraption c,
ContraptionMatrices matrices, MultiBufferSource buffer) {
PoseStack m = matrices.getModel();
for (Pair<StructureTemplate.StructureBlockInfo, MovementContext> actor : c.getActors()) {
MovementContext context = actor.getRight();
if (context == null)
continue;
if (context.world == null)
context.world = world;
StructureTemplate.StructureBlockInfo blockInfo = actor.getLeft();
MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(blockInfo.state());
if (movementBehaviour != null) {
if (c.isHiddenInPortal(blockInfo.pos()))
continue;
m.pushPose();
TransformStack.of(m)
.translate(blockInfo.pos());
movementBehaviour.renderInContraption(context, renderWorld, matrices, buffer);
m.popPose();
}
}
}
public static int getLight(Level world, float lx, float ly, float lz) {
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
float block = 0, sky = 0;
float offset = 1 / 8f;
for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset)
for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset)
for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) {
pos.set(lx + xOffset, ly + yOffset, lz + zOffset);
block += world.getBrightness(LightLayer.BLOCK, pos) / 8f;
sky += world.getBrightness(LightLayer.SKY, pos) / 8f;
}
return LightTexture.pack((int) block, (int) sky);
}
public static int getContraptionWorldLight(MovementContext context, VirtualRenderWorld renderWorld) {
return LevelRenderer.getLightColor(renderWorld, context.localPos);
}
public static void reset() {
}
public static boolean canInstance() {
return false;
}
}

View file

@ -1,78 +1,156 @@
package com.simibubi.create.content.contraptions.render;
import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import org.apache.commons.lang3.tuple.Pair;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.jozufozu.flywheel.lib.model.ModelUtil;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.content.contraptions.AbstractContraptionEntity;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.Contraption;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.content.contraptions.Contraption.RenderedBlocks;
import com.simibubi.create.content.contraptions.ContraptionWorld;
import com.simibubi.create.foundation.render.ShadeSeparatingVertexConsumer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.SuperByteBufferCache;
import com.simibubi.create.foundation.render.VirtualRenderHelper;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.util.Mth;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraftforge.client.model.data.ModelData;
public class ContraptionRenderInfo {
public final Contraption contraption;
public final VirtualRenderWorld renderWorld;
public static final SuperByteBufferCache.Compartment<Pair<Contraption, RenderType>> CONTRAPTION = new SuperByteBufferCache.Compartment<>();
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
private final Contraption contraption;
private final VirtualRenderWorld renderWorld;
private final ContraptionMatrices matrices = new ContraptionMatrices();
private boolean visible;
public ContraptionRenderInfo(Contraption contraption, VirtualRenderWorld renderWorld) {
ContraptionRenderInfo(Level level, Contraption contraption) {
this.contraption = contraption;
this.renderWorld = renderWorld;
this.renderWorld = setupRenderWorld(level, contraption);
}
public int getEntityId() {
return contraption.entity.getId();
public static ContraptionRenderInfo get(Contraption contraption) {
return ContraptionRenderInfoManager.MANAGERS.get(contraption.entity.level()).getRenderInfo(contraption);
}
/**
* Reset a contraption's renderer.
*
* @param contraption The contraption to invalidate.
* @return true if there was a renderer associated with the given contraption.
*/
public static boolean invalidate(Contraption contraption) {
return ContraptionRenderInfoManager.MANAGERS.get(contraption.entity.level()).invalidate(contraption);
}
public boolean isDead() {
return !contraption.entity.isAliveOrStale();
}
public void beginFrame(BeginFrameEvent event) {
matrices.clear();
AbstractContraptionEntity entity = contraption.entity;
visible = false;
// visible = event.getFrustum()
// .isVisible(entity.getBoundingBoxForCulling()
// .inflate(2));
public Contraption getContraption() {
return contraption;
}
public boolean isVisible() {
return visible && contraption.entity.isAliveOrStale() && contraption.entity.isReadyForRender();
public VirtualRenderWorld getRenderWorld() {
return renderWorld;
}
/**
* Need to call this during RenderLayerEvent.
*/
public void setupMatrices(PoseStack viewProjection, double camX, double camY, double camZ) {
if (!matrices.isReady()) {
AbstractContraptionEntity entity = contraption.entity;
viewProjection.pushPose();
double x = Mth.lerp(AnimationTickHolder.getPartialTicks(), entity.xOld, entity.getX()) - camX;
double y = Mth.lerp(AnimationTickHolder.getPartialTicks(), entity.yOld, entity.getY()) - camY;
double z = Mth.lerp(AnimationTickHolder.getPartialTicks(), entity.zOld, entity.getZ()) - camZ;
viewProjection.translate(x, y, z);
matrices.setup(viewProjection, entity);
viewProjection.popPose();
}
}
/**
* If #setupMatrices is called correctly, the returned matrices will be ready
*/
public ContraptionMatrices getMatrices() {
return matrices;
}
public void invalidate() {
public SuperByteBuffer getBuffer(RenderType renderType) {
return CreateClient.BUFFER_CACHE.get(CONTRAPTION, Pair.of(contraption, renderType), () -> buildStructureBuffer(renderType));
}
public void invalidate() {
for (RenderType renderType : RenderType.chunkBufferLayers()) {
CreateClient.BUFFER_CACHE.invalidate(CONTRAPTION, Pair.of(contraption, renderType));
}
}
public static VirtualRenderWorld setupRenderWorld(Level level, Contraption c) {
ContraptionWorld contraptionWorld = c.getContraptionWorld();
BlockPos origin = c.anchor;
int minBuildHeight = contraptionWorld.getMinBuildHeight();
int height = contraptionWorld.getHeight();
VirtualRenderWorld renderWorld = new VirtualRenderWorld(level, minBuildHeight, height, origin) {
@Override
public boolean supportsVisualization() {
return VisualizationManager.supportsVisualization(level);
}
};
renderWorld.setBlockEntities(c.presentBlockEntities.values());
for (StructureTemplate.StructureBlockInfo info : c.getBlocks()
.values())
renderWorld.setBlock(info.pos(), info.state(), 0);
renderWorld.runLightEngine();
return renderWorld;
}
private SuperByteBuffer buildStructureBuffer(RenderType layer) {
BlockRenderDispatcher dispatcher = ModelUtil.VANILLA_RENDERER;
ModelBlockRenderer renderer = dispatcher.getModelRenderer();
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
PoseStack poseStack = objects.poseStack;
RandomSource random = objects.random;
RenderedBlocks blocks = contraption.getRenderedBlocks();
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
BufferBuilder shadedBuilder = objects.shadedBuilder;
BufferBuilder unshadedBuilder = objects.unshadedBuilder;
shadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
shadeSeparatingWrapper.prepare(shadedBuilder, unshadedBuilder);
ModelBlockRenderer.enableCaching();
for (BlockPos pos : blocks.positions()) {
BlockState state = blocks.lookup().apply(pos);
if (state.getRenderShape() == RenderShape.MODEL) {
BakedModel model = dispatcher.getBlockModel(state);
ModelData modelData = contraption.modelData.getOrDefault(pos, ModelData.EMPTY);
modelData = model.getModelData(renderWorld, pos, state, modelData);
long randomSeed = state.getSeed(pos);
random.setSeed(randomSeed);
if (model.getRenderTypes(state, random, modelData).contains(layer)) {
poseStack.pushPose();
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
renderer.tesselateBlock(renderWorld, model, state, pos, poseStack, shadeSeparatingWrapper, true, random, randomSeed, OverlayTexture.NO_OVERLAY, modelData, layer);
poseStack.popPose();
}
}
}
ModelBlockRenderer.clearCache();
shadeSeparatingWrapper.clear();
return VirtualRenderHelper.endAndCombine(shadedBuilder, unshadedBuilder);
}
private static class ThreadLocalObjects {
public final PoseStack poseStack = new PoseStack();
public final RandomSource random = RandomSource.createNewThreadLocalInstance();
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
public final BufferBuilder shadedBuilder = new BufferBuilder(512);
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
}
}

View file

@ -0,0 +1,84 @@
package com.simibubi.create.content.contraptions.render;
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
import com.simibubi.create.content.contraptions.Contraption;
import com.simibubi.create.foundation.utility.WorldAttached;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(Dist.CLIENT)
public class ContraptionRenderInfoManager {
static final WorldAttached<ContraptionRenderInfoManager> MANAGERS = new WorldAttached<>(ContraptionRenderInfoManager::new);
private final Level level;
private final Int2ObjectMap<ContraptionRenderInfo> renderInfos = new Int2ObjectOpenHashMap<>();
private int removalTimer;
private ContraptionRenderInfoManager(LevelAccessor level) {
this.level = (Level) level;
}
public static void tickFor(Level level) {
if (Minecraft.getInstance()
.isPaused())
return;
MANAGERS.get(level)
.tick();
}
public static void resetAll() {
MANAGERS.empty(ContraptionRenderInfoManager::delete);
}
@SubscribeEvent
public static void onReloadLevelRenderer(ReloadLevelRendererEvent event) {
resetAll();
}
ContraptionRenderInfo getRenderInfo(Contraption contraption) {
int entityId = contraption.entity.getId();
ContraptionRenderInfo renderInfo = renderInfos.get(entityId);
if (renderInfo == null) {
renderInfo = new ContraptionRenderInfo(level, contraption);
renderInfos.put(entityId, renderInfo);
}
return renderInfo;
}
boolean invalidate(Contraption contraption) {
int entityId = contraption.entity.getId();
ContraptionRenderInfo renderInfo = renderInfos.remove(entityId);
if (renderInfo != null) {
renderInfo.invalidate();
return true;
}
return false;
}
private void tick() {
if (removalTimer >= 20) {
renderInfos.values().removeIf(ContraptionRenderInfo::isDead);
removalTimer = 0;
}
removalTimer++;
}
private void delete() {
for (ContraptionRenderInfo renderer : renderInfos.values()) {
renderer.invalidate();
}
renderInfos.clear();
}
}

View file

@ -1,118 +0,0 @@
package com.simibubi.create.content.contraptions.render;
import java.lang.ref.Reference;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.RenderStageEvent;
import com.simibubi.create.content.contraptions.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.Contraption;
import com.simibubi.create.content.contraptions.ContraptionHandler;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
public abstract class ContraptionRenderingWorld<C extends ContraptionRenderInfo> {
protected final Level world;
private int removalTimer;
protected final Int2ObjectMap<C> renderInfos = new Int2ObjectOpenHashMap<>();
protected final List<C> visible = new ObjectArrayList<>();
public ContraptionRenderingWorld(LevelAccessor world) {
this.world = (Level) world;
}
public boolean invalidate(Contraption contraption) {
int entityId = contraption.entity.getId();
C removed = renderInfos.remove(entityId);
if (removed != null) {
removed.invalidate();
visible.remove(removed);
return true;
}
return false;
}
public void renderLayer(RenderStageEvent event) {
var position = event.getCamera()
.getPosition();
for (C c : visible) {
c.setupMatrices(event.getStack(), position.x, position.y, position.z);
}
}
protected abstract C create(Contraption c);
public void tick() {
removalTimer++;
if (removalTimer >= 20) {
removeDeadRenderers();
removalTimer = 0;
}
ContraptionHandler.loadedContraptions.get(world)
.values()
.stream()
.map(Reference::get)
.filter(Objects::nonNull)
.map(AbstractContraptionEntity::getContraption)
.filter(Objects::nonNull) // contraptions that are too large will not be synced, and un-synced contraptions will be null
.forEach(this::getRenderInfo);
}
public void beginFrame(BeginFrameEvent event) {
renderInfos.int2ObjectEntrySet()
.stream()
.map(Map.Entry::getValue)
.forEach(renderInfo -> renderInfo.beginFrame(event));
collectVisible();
}
protected void collectVisible() {
visible.clear();
renderInfos.int2ObjectEntrySet()
.stream()
.map(Map.Entry::getValue)
.filter(ContraptionRenderInfo::isVisible)
.forEach(visible::add);
}
public C getRenderInfo(Contraption c) {
int entityId = c.entity.getId();
C renderInfo = renderInfos.get(entityId);
if (renderInfo == null) {
renderInfo = create(c);
renderInfos.put(entityId, renderInfo);
}
return renderInfo;
}
public void delete() {
for (C renderer : renderInfos.values()) {
renderer.invalidate();
}
renderInfos.clear();
}
/**
* Remove all render infos associated with dead/removed contraptions.
*/
public void removeDeadRenderers() {
renderInfos.values().removeIf(ContraptionRenderInfo::isDead);
}
}

View file

@ -73,7 +73,7 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
setEmbeddingMatrices(partialTick);
Contraption contraption = entity.getContraption();
virtualRenderWorld = ContraptionRenderDispatcher.setupRenderWorld(level, contraption);
virtualRenderWorld = ContraptionRenderInfo.setupRenderWorld(level, contraption);
RenderedBlocks blocks = contraption.getRenderedBlocks();
BlockAndTintGetter modelWorld = new WrappedBlockAndTintGetter(virtualRenderWorld) {
@ -91,7 +91,7 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
.instancer(InstanceTypes.TRANSFORMED, model)
.createInstance();
for (BlockEntity be : contraption.maybeInstancedBlockEntities) {
for (BlockEntity be : contraption.getRenderedBEs()) {
setupVisualizer(be, partialTick);
}
@ -102,32 +102,6 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
updateLight();
}
private void setupActor(MutablePair<StructureTemplate.StructureBlockInfo, MovementContext> actor, float partialTick) {
MovementContext context = actor.getRight();
if (context == null) {
return;
}
if (context.world == null) {
context.world = level;
}
StructureTemplate.StructureBlockInfo blockInfo = actor.getLeft();
MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(blockInfo.state());
if (movementBehaviour == null) {
return;
}
var instance = movementBehaviour.createInstance(this.embedding, virtualRenderWorld, context);
if (instance == null) {
return;
}
instance.init(partialTick);
actors.add(instance);
}
@SuppressWarnings("unchecked")
protected <T extends BlockEntity> void setupVisualizer(T be, float partialTicks) {
BlockEntityVisualizer<? super T> visualizer = (BlockEntityVisualizer<? super T>) VisualizerRegistry.getVisualizer(be.getType());
@ -154,6 +128,32 @@ public class ContraptionVisual<E extends AbstractContraptionEntity> extends Abst
be.setLevel(world);
}
private void setupActor(MutablePair<StructureTemplate.StructureBlockInfo, MovementContext> actor, float partialTick) {
MovementContext context = actor.getRight();
if (context == null) {
return;
}
if (context.world == null) {
context.world = level;
}
StructureTemplate.StructureBlockInfo blockInfo = actor.getLeft();
MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(blockInfo.state());
if (movementBehaviour == null) {
return;
}
var visual = movementBehaviour.createVisual(this.embedding, virtualRenderWorld, context);
if (visual == null) {
return;
}
visual.init(partialTick);
actors.add(visual);
}
@Override
public Plan<VisualTickContext> planTick() {
return NestedPlan.of(

View file

@ -7,20 +7,18 @@ import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
public class OrientedContraptionEntityRenderer extends ContraptionEntityRenderer<OrientedContraptionEntity> {
public OrientedContraptionEntityRenderer(EntityRendererProvider.Context context) {
super(context);
}
@Override
public boolean shouldRender(OrientedContraptionEntity entity, Frustum p_225626_2_, double p_225626_3_,
double p_225626_5_, double p_225626_7_) {
if (!super.shouldRender(entity, p_225626_2_, p_225626_3_, p_225626_5_, p_225626_7_))
public boolean shouldRender(OrientedContraptionEntity entity, Frustum frustum, double cameraX, double cameraY,
double cameraZ) {
if (!super.shouldRender(entity, frustum, cameraX, cameraY, cameraZ))
return false;
if (entity.getContraption()
.getType() == ContraptionType.MOUNTED && entity.getVehicle() == null)
return false;
return true;
}
}

View file

@ -1,127 +0,0 @@
package com.simibubi.create.content.contraptions.render;
import com.jozufozu.flywheel.api.event.RenderStageEvent;
import com.jozufozu.flywheel.lib.model.ModelUtil;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.Contraption;
import com.simibubi.create.content.contraptions.Contraption.RenderedBlocks;
import com.simibubi.create.foundation.render.ShadeSeparatingVertexConsumer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.SuperByteBufferCache;
import com.simibubi.create.foundation.render.VirtualRenderHelper;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.data.ModelData;
public class SBBContraptionManager extends ContraptionRenderingWorld<ContraptionRenderInfo> {
public static final SuperByteBufferCache.Compartment<Pair<Contraption, RenderType>> CONTRAPTION = new SuperByteBufferCache.Compartment<>();
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
public SBBContraptionManager(LevelAccessor world) {
super(world);
}
@Override
public void renderLayer(RenderStageEvent event) {
super.renderLayer(event);
// RenderType type = event.getType();
// VertexConsumer consumer = event.buffers.bufferSource()
// .getBuffer(type);
// visible.forEach(info -> renderContraptionLayerSBB(info, type, consumer));
//
// event.buffers.bufferSource().endBatch(type);
}
@Override
public boolean invalidate(Contraption contraption) {
for (RenderType chunkBufferLayer : RenderType.chunkBufferLayers()) {
CreateClient.BUFFER_CACHE.invalidate(CONTRAPTION, Pair.of(contraption, chunkBufferLayer));
}
return super.invalidate(contraption);
}
@Override
protected ContraptionRenderInfo create(Contraption c) {
VirtualRenderWorld renderWorld = ContraptionRenderDispatcher.setupRenderWorld(world, c);
return new ContraptionRenderInfo(c, renderWorld);
}
private void renderContraptionLayerSBB(ContraptionRenderInfo renderInfo, RenderType layer, VertexConsumer consumer) {
if (!renderInfo.isVisible()) return;
SuperByteBuffer contraptionBuffer = CreateClient.BUFFER_CACHE.get(CONTRAPTION, Pair.of(renderInfo.contraption, layer), () -> buildStructureBuffer(renderInfo.renderWorld, renderInfo.contraption, layer));
if (!contraptionBuffer.isEmpty()) {
ContraptionMatrices matrices = renderInfo.getMatrices();
contraptionBuffer.transform(matrices.getModel())
.light(matrices.getWorld())
.hybridLight()
.renderInto(matrices.getViewProjection(), consumer);
}
}
private static SuperByteBuffer buildStructureBuffer(VirtualRenderWorld renderWorld, Contraption contraption, RenderType layer) {
BlockRenderDispatcher dispatcher = ModelUtil.VANILLA_RENDERER;
ModelBlockRenderer renderer = dispatcher.getModelRenderer();
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
PoseStack poseStack = objects.poseStack;
RandomSource random = objects.random;
RenderedBlocks blocks = contraption.getRenderedBlocks();
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
BufferBuilder shadedBuilder = objects.shadedBuilder;
BufferBuilder unshadedBuilder = objects.unshadedBuilder;
shadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
shadeSeparatingWrapper.prepare(shadedBuilder, unshadedBuilder);
ModelBlockRenderer.enableCaching();
for (BlockPos pos : blocks.positions()) {
BlockState state = blocks.lookup().apply(pos);
if (state.getRenderShape() == RenderShape.MODEL) {
BakedModel model = dispatcher.getBlockModel(state);
ModelData modelData = contraption.modelData.getOrDefault(pos, ModelData.EMPTY);
modelData = model.getModelData(renderWorld, pos, state, modelData);
long randomSeed = state.getSeed(pos);
random.setSeed(randomSeed);
if (model.getRenderTypes(state, random, modelData).contains(layer)) {
poseStack.pushPose();
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
renderer.tesselateBlock(renderWorld, model, state, pos, poseStack, shadeSeparatingWrapper, true, random, randomSeed, OverlayTexture.NO_OVERLAY, modelData, layer);
poseStack.popPose();
}
}
}
ModelBlockRenderer.clearCache();
shadeSeparatingWrapper.clear();
return VirtualRenderHelper.endAndCombine(shadedBuilder, unshadedBuilder);
}
private static class ThreadLocalObjects {
public final PoseStack poseStack = new PoseStack();
public final RandomSource random = RandomSource.createNewThreadLocalInstance();
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
public final BufferBuilder shadedBuilder = new BufferBuilder(512);
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
}
}

View file

@ -32,12 +32,6 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
import net.minecraft.world.phys.Vec3;
public class SlidingDoorMovementBehaviour implements MovementBehaviour {
@Override
public boolean renderAsNormalBlockEntity() {
return true;
}
@Override
public boolean mustTickWhileDisabled() {
return true;

View file

@ -64,7 +64,7 @@ public class BeltVisual extends KineticBlockEntityVisual<BeltBlockEntity> {
PartialModel beltPartial = BeltRenderer.getBeltPartial(diagonal, start, end, bottom);
SpriteShiftEntry spriteShift = BeltRenderer.getSpriteShiftEntry(color, diagonal, bottom);
Instancer<BeltInstance> beltModel = instancerProvider.instancer(AllInstanceTypes.BELTS, Models.partial(beltPartial));
Instancer<BeltInstance> beltModel = instancerProvider.instancer(AllInstanceTypes.BELT, Models.partial(beltPartial));
keys.add(setup(beltModel.createInstance(), bottom, spriteShift));

View file

@ -9,6 +9,7 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.Pair;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.contraptions.AbstractContraptionEntity;
@ -18,7 +19,6 @@ import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.mounted.MountedContraption;
import com.simibubi.create.content.contraptions.render.ActorVisual;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.schematics.SchematicInstances;
@ -282,20 +282,20 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
}
@Override
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffers) {
if (!ContraptionRenderDispatcher.canInstance())
DeployerRenderer.renderInContraption(context, renderWorld, matrices, buffers);
public boolean disableBlockEntityRendering() {
return true;
}
@Override
public boolean hasSpecialInstancedRendering() {
return true;
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffers) {
if (!VisualizationManager.supportsVisualization(context.world))
DeployerRenderer.renderInContraption(context, renderWorld, matrices, buffers);
}
@Nullable
@Override
public ActorVisual createInstance(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
public ActorVisual createVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld,
MovementContext movementContext) {
return new DeployerActorVisual(visualizationContext, simulationWorld, movementContext);
}

View file

@ -13,7 +13,6 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.kinetics.base.IRotate;
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer;
@ -29,6 +28,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
@ -213,11 +213,11 @@ public class DeployerRenderer extends SafeBlockEntityRenderer<DeployerBlockEntit
transform(pole, blockState, true);
transform(hand, blockState, false);
shaft.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
shaft.light(matrices.getWorld(), LevelRenderer.getLightColor(renderWorld, context.localPos))
.renderInto(matrices.getViewProjection(), builder);
pole.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
pole.light(matrices.getWorld(), LevelRenderer.getLightColor(renderWorld, context.localPos))
.renderInto(matrices.getViewProjection(), builder);
hand.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
hand.light(matrices.getWorld(), LevelRenderer.getLightColor(renderWorld, context.localPos))
.renderInto(matrices.getViewProjection(), builder);
m.popPose();

View file

@ -38,7 +38,7 @@ public class DrillActorVisual extends ActorVisual {
else
eulerY = facing.toYRot() + ((axis == Direction.Axis.X) ? 180 : 0);
drillHead = instancerProvider.instancer(AllInstanceTypes.ACTORS, Models.partial(AllPartialModels.DRILL_HEAD))
drillHead = instancerProvider.instancer(AllInstanceTypes.ACTOR, Models.partial(AllPartialModels.DRILL_HEAD))
.createInstance();
drillHead.setPosition(context.localPos)
@ -46,12 +46,14 @@ public class DrillActorVisual extends ActorVisual {
.setRotationOffset(0)
.setRotationAxis(0, 0, 1)
.setLocalRotation(new Quaternionf().rotationXYZ(eulerX * Mth.DEG_TO_RAD, eulerY * Mth.DEG_TO_RAD, 0))
.setSpeed(getSpeed(facing));
.setSpeed(getSpeed(facing))
.setChanged();
}
@Override
public void beginFrame() {
drillHead.setSpeed(getSpeed(facing));
drillHead.setSpeed(getSpeed(facing))
.setChanged();
}
protected float getSpeed(Direction facing) {

View file

@ -3,11 +3,11 @@ package com.simibubi.create.content.kinetics.drill;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.simibubi.create.AllTags;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ActorVisual;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour;
import com.simibubi.create.foundation.damageTypes.CreateDamageSources;
import com.simibubi.create.foundation.utility.VecHelper;
@ -38,21 +38,21 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
}
@Override
@OnlyIn(value = Dist.CLIENT)
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffer) {
if (!ContraptionRenderDispatcher.canInstance())
DrillRenderer.renderInContraption(context, renderWorld, matrices, buffer);
public boolean disableBlockEntityRendering() {
return true;
}
@Override
public boolean hasSpecialInstancedRendering() {
return true;
@OnlyIn(value = Dist.CLIENT)
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
ContraptionMatrices matrices, MultiBufferSource buffer) {
if (!VisualizationManager.supportsVisualization(context.world))
DrillRenderer.renderInContraption(context, renderWorld, matrices, buffer);
}
@Nullable
@Override
public ActorVisual createInstance(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld, MovementContext movementContext) {
public ActorVisual createVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld, MovementContext movementContext) {
return new DrillActorVisual(visualizationContext, simulationWorld, movementContext);
}

View file

@ -3,7 +3,6 @@ package com.simibubi.create.content.kinetics.drill;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
@ -12,6 +11,7 @@ import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
@ -49,7 +49,7 @@ public class DrillRenderer extends KineticBlockEntityRenderer<DrillBlockEntity>
.rotateZDegrees(angle)
.uncenter()
.light(matrices.getWorld(),
ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
LevelRenderer.getLightColor(renderWorld, context.localPos))
.renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid()));
}

View file

@ -90,6 +90,11 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
world.addFreshEntity(entity);
}
@Override
public boolean disableBlockEntityRendering() {
return true;
}
@Override
@OnlyIn(value = Dist.CLIENT)
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,

View file

@ -9,7 +9,6 @@ import com.mojang.math.Axis;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.kinetics.base.KineticBlockEntity;
import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer;
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringRenderer;
@ -21,6 +20,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
@ -198,7 +198,7 @@ public class SawRenderer extends SafeBlockEntityRenderer<SawBlockEntity> {
}
superBuffer.uncenter()
.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld))
.light(matrices.getWorld(), LevelRenderer.getLightColor(renderWorld, context.localPos))
.renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.cutoutMipped()));
}

View file

@ -119,9 +119,4 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
}
}
@Override
public boolean renderAsNormalBlockEntity() {
return true;
}
}

View file

@ -33,7 +33,7 @@ public class FunnelVisual extends AbstractBlockEntityVisual<FunnelBlockEntity> i
PartialModel flapPartial = (blockState.getBlock() instanceof FunnelBlock ? AllPartialModels.FUNNEL_FLAP
: AllPartialModels.BELT_FUNNEL_FLAP);
Instancer<FlapInstance> model = instancerProvider.instancer(AllInstanceTypes.FLAPS, Models.partial(flapPartial));
Instancer<FlapInstance> model = instancerProvider.instancer(AllInstanceTypes.FLAP, Models.partial(flapPartial));
int blockLight = level.getBrightness(LightLayer.BLOCK, pos);
int skyLight = level.getBrightness(LightLayer.SKY, pos);

View file

@ -31,7 +31,7 @@ public class BeltTunnelVisual extends AbstractBlockEntityVisual<BeltTunnelBlockE
}
private void setupFlaps(float partialTick) {
Instancer<FlapInstance> model = instancerProvider.instancer(AllInstanceTypes.FLAPS, Models.partial(AllPartialModels.BELT_TUNNEL_FLAP));
Instancer<FlapInstance> model = instancerProvider.instancer(AllInstanceTypes.FLAP, Models.partial(AllPartialModels.BELT_TUNNEL_FLAP));
int blockLight = level.getBrightness(LightLayer.BLOCK, pos);
int skyLight = level.getBrightness(LightLayer.SKY, pos);

View file

@ -22,11 +22,6 @@ public class BasinMovementBehaviour implements MovementBehaviour {
return map;
}
@Override
public boolean renderAsNormalBlockEntity() {
return true;
}
@Override
public void tick(MovementContext context) {
MovementBehaviour.super.tick(context);

View file

@ -30,11 +30,6 @@ import net.minecraftforge.api.distmarker.OnlyIn;
public class BlazeBurnerMovementBehaviour implements MovementBehaviour {
@Override
public boolean renderAsNormalBlockEntity() {
return false;
}
@Override
public ItemStack canBeDisabledVia(MovementContext context) {
return null;
@ -117,6 +112,11 @@ public class BlazeBurnerMovementBehaviour implements MovementBehaviour {
return false;
}
@Override
public boolean disableBlockEntityRendering() {
return true;
}
@Override
@OnlyIn(Dist.CLIENT)
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,

View file

@ -254,17 +254,17 @@ public class CarriageContraption extends Contraption {
return secondBogeyPos;
}
private Collection<BlockEntity> specialRenderedBEsOutsidePortal = new ArrayList<>();
private Collection<BlockEntity> renderedBEsOutsidePortal = new ArrayList<>();
@Override
public RenderedBlocks getRenderedBlocks() {
if (notInPortal())
return super.getRenderedBlocks();
specialRenderedBEsOutsidePortal = new ArrayList<>();
specialRenderedBlockEntities.stream()
renderedBEsOutsidePortal = new ArrayList<>();
renderedBlockEntities.stream()
.filter(be -> !isHiddenInPortal(be.getBlockPos()))
.forEach(specialRenderedBEsOutsidePortal::add);
.forEach(renderedBEsOutsidePortal::add);
Map<BlockPos, BlockState> values = new HashMap<>();
blocks.forEach((pos, info) -> {
@ -278,10 +278,10 @@ public class CarriageContraption extends Contraption {
}
@Override
public Collection<BlockEntity> getSpecialRenderedBEs() {
public Collection<BlockEntity> getRenderedBEs() {
if (notInPortal())
return super.getSpecialRenderedBEs();
return specialRenderedBEsOutsidePortal;
return super.getRenderedBEs();
return renderedBEsOutsidePortal;
}
@Override

View file

@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.minecart.CouplingHandlerClient;
import com.simibubi.create.content.contraptions.minecart.CouplingPhysics;
import com.simibubi.create.content.contraptions.minecart.CouplingRenderer;
import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController;
import com.simibubi.create.content.contraptions.render.ContraptionRenderInfoManager;
import com.simibubi.create.content.decoration.girder.GirderWrenchBehavior;
import com.simibubi.create.content.equipment.armor.BacktankArmorLayer;
import com.simibubi.create.content.equipment.armor.DivingHelmetItem;
@ -155,6 +156,7 @@ public class ClientEvents {
PlacementHelpers.tick();
CreateClient.OUTLINER.tickOutlines();
CreateClient.GHOST_BLOCKS.tickGhosts();
ContraptionRenderInfoManager.tickFor(world);
BlueprintOverlayRenderer.tick();
ToolboxHandlerClient.clientTick();
TrackTargetingClient.clientTick();

View file

@ -19,8 +19,6 @@ import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class AllInstanceTypes {
// FIXME: optimize layouts/pack fields together if possible
public static final InstanceType<RotatingInstance> ROTATING = SimpleInstanceType.builder(RotatingInstance::new)
.cullShader(asResource("instance/cull/rotating.glsl"))
.vertexShader(asResource("instance/rotating.vert"))
@ -51,7 +49,8 @@ public class AllInstanceTypes {
MemoryUtil.memPutByte(ptr + 34, instance.rotationAxisZ);
})
.register();
public static final InstanceType<BeltInstance> BELTS = SimpleInstanceType.builder(BeltInstance::new)
public static final InstanceType<BeltInstance> BELT = SimpleInstanceType.builder(BeltInstance::new)
.cullShader(asResource("instance/cull/belt.glsl"))
.vertexShader(asResource("instance/belt.vert"))
.layout(LayoutBuilder.create()
@ -92,9 +91,10 @@ public class AllInstanceTypes {
MemoryUtil.memPutFloat(ptr + 72, instance.scrollMult);
})
.register();
public static final InstanceType<ActorInstance> ACTORS = SimpleInstanceType.builder(ActorInstance::new)
.cullShader(asResource("instance/cull/contraption_actor.glsl"))
.vertexShader(asResource("instance/contraption_actor.vert"))
public static final InstanceType<ActorInstance> ACTOR = SimpleInstanceType.builder(ActorInstance::new)
.cullShader(asResource("instance/cull/actor.glsl"))
.vertexShader(asResource("instance/actor.vert"))
.layout(LayoutBuilder.create()
.vector("pos", FloatRepr.FLOAT, 3)
.vector("light", IntegerRepr.SHORT, 2)
@ -126,7 +126,7 @@ public class AllInstanceTypes {
.register();
// TODO: remove
public static final InstanceType<FlapInstance> FLAPS = SimpleInstanceType.builder(FlapInstance::new)
public static final InstanceType<FlapInstance> FLAP = SimpleInstanceType.builder(FlapInstance::new)
.cullShader(asResource("instance/cull/flap.glsl"))
.vertexShader(asResource("instance/flap.vert"))
.layout(LayoutBuilder.create()

View file

@ -7,7 +7,7 @@ import javax.annotation.Nullable;
import org.joml.Matrix4f;
import org.joml.Vector4f;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.jozufozu.flywheel.impl.visualization.VisualizationHelper;
import com.jozufozu.flywheel.lib.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
@ -50,7 +50,7 @@ public class BlockEntityRenderHelper {
Iterator<BlockEntity> iterator = customRenderBEs.iterator();
while (iterator.hasNext()) {
BlockEntity blockEntity = iterator.next();
if (BackendManager.isBackendOn() && VisualizationHelper.shouldSkipRender(blockEntity))
if (VisualizationManager.supportsVisualization(world) && VisualizationHelper.shouldSkipRender(blockEntity))
continue;
BlockEntityRenderer<BlockEntity> renderer = Minecraft.getInstance().getBlockEntityRenderDispatcher().getRenderer(blockEntity);