diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 256d46aa9..88b073b28 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.components.crank.HandCrankRender import com.simibubi.create.content.contraptions.components.crank.HandCrankTileEntity; import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerTileEntity; import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelTileEntity; +import com.simibubi.create.content.contraptions.components.deployer.DeployerInstance; import com.simibubi.create.content.contraptions.components.deployer.DeployerRenderer; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity; import com.simibubi.create.content.contraptions.components.fan.EncasedFanRenderer; @@ -476,7 +477,7 @@ public class AllTileEntities { public static final TileEntityEntry DEPLOYER = Create.registrate() .tileEntity("deployer", DeployerTileEntity::new) - .instance(() -> ShaftInstance::new) + .instance(() -> DeployerInstance::new) .validBlocks(AllBlocks.DEPLOYER) .renderer(() -> DeployerRenderer::new) .register(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java index f707b0532..a118962b4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java @@ -12,6 +12,7 @@ public enum ActorVertexAttributes implements IVertexAttrib { AXIS("aAxis", CommonAttributes.NORMAL), INSTANCE_ROTATION("aInstanceRot", CommonAttributes.VEC3), ROTATION_CENTER("aRotationCenter", CommonAttributes.NORMAL), + SPEED("aSpeed", CommonAttributes.FLOAT), ; private final String name; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java index 56853e9d1..6e41d205c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java @@ -30,6 +30,8 @@ public class ContraptionActorData extends InstanceData { private byte rotationCenterY = 64; private byte rotationCenterZ = 64; + private float speed; + protected ContraptionActorData(InstancedModel owner) { super(owner); } @@ -57,6 +59,11 @@ public class ContraptionActorData extends InstanceData { return this; } + public ContraptionActorData setSpeed(float speed) { + this.speed = speed; + return this; + } + public ContraptionActorData setRotationAxis(Vector3f axis) { setRotationAxis(axis.getX(), axis.getY(), axis.getZ()); return this; @@ -101,6 +108,7 @@ public class ContraptionActorData extends InstanceData { putVec3(buf, rotationAxisX, rotationAxisY, rotationAxisZ); putVec3(buf, localRotationX, localRotationY, localRotationZ); putVec3(buf, rotationCenterX, rotationCenterY, rotationCenterZ); + put(buf, speed); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java new file mode 100644 index 000000000..958670ede --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.contraptions.components.actors; + +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.block.BlockState; +import net.minecraft.util.Direction; + +public class DrillActorInstance extends ActorInstance { + + InstanceKey drillHead; + private Direction facing; + + public DrillActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { + super(modelManager, context); + + RenderMaterial> renderMaterial = modelManager.getActorMaterial(); + + BlockState state = context.state; + + facing = state.get(DrillBlock.FACING); + float eulerX = AngleHelper.verticalAngle(facing) + ((facing.getAxis() == Direction.Axis.Y) ? 180 : 0); + float eulerY = facing.getHorizontalAngle(); + + drillHead = renderMaterial.getModel(AllBlockPartials.DRILL_HEAD, state).createInstance(); + + drillHead.getInstance() + .setPosition(context.localPos) + .setBlockLight(localBlockLight()) + .setRotationOffset(0) + .setRotationAxis(0, 0, 1) + .setLocalRotation(eulerX, eulerY, 0) + .setSpeed(getSpeed(facing)); + } + + @Override + protected void tick() { + drillHead.getInstance().setSpeed(getSpeed(facing)); + } + + @Override + protected float getSpeed(Direction facing) { + if (context.contraption.stalled || !VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite())) + return context.getAnimationSpeed(); + return 0; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillInstance.java index 72b85d279..cb9a66d2d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillInstance.java @@ -22,23 +22,6 @@ public class DrillInstance extends SingleRotatingInstance { super(modelManager, tile); } - public static void addInstanceForContraption(RenderedContraption contraption, MovementContext context) { - RenderMaterial> renderMaterial = contraption.getActorMaterial(); - - BlockState state = context.state; - InstancedModel model = renderMaterial.getModel(AllBlockPartials.DRILL_HEAD, state); - - Direction facing = state.get(DrillBlock.FACING); - float eulerX = AngleHelper.verticalAngle(facing) + ((facing.getAxis() == Direction.Axis.Y) ? 180 : 0); - float eulerY = facing.getHorizontalAngle(); - model.getInstance(model.createInstance()) - .setPosition(context.localPos) - .setBlockLight(contraption.renderWorld.getLightLevel(LightType.BLOCK, context.localPos)) - .setRotationOffset(0) - .setRotationAxis(0, 0, 1) - .setLocalRotation(eulerX, eulerY, 0); - } - @Override protected InstancedModel getModel() { return AllBlockPartials.DRILL_HEAD.renderOnDirectionalSouthRotating(modelManager, tile.getBlockState()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java index 965d6c3c0..fd9a3959a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java @@ -2,6 +2,8 @@ package com.simibubi.create.content.contraptions.components.actors; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.VecHelper; @@ -15,6 +17,8 @@ import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import javax.annotation.Nullable; + public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { @Override @@ -42,9 +46,10 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { return true; } + @Nullable @Override - public void addInstance(RenderedContraption contraption, MovementContext context) { - DrillInstance.addInstanceForContraption(contraption, context); + public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) { + return new DrillActorInstance(kr, context); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java index ad434c4eb..825ba510e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java @@ -42,7 +42,7 @@ public class DrillRenderer extends KineticTileEntityRenderer { Direction facing = state.get(DrillBlock.FACING); float speed = (float) (context.contraption.stalled - || !VecHelper.isVecPointingTowards(context.relativeMotion, state.get(FACING) + || !VecHelper.isVecPointingTowards(context.relativeMotion, facing .getOpposite()) ? context.getAnimationSpeed() : 0); float time = AnimationTickHolder.getRenderTime() / 20; float angle = (float) (((time * speed) % 360)); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java new file mode 100644 index 000000000..f0431d63a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java @@ -0,0 +1,49 @@ +package com.simibubi.create.content.contraptions.components.actors; + +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; +import net.minecraft.block.BlockState; +import net.minecraft.client.renderer.Vector3f; +import net.minecraft.util.Direction; +import net.minecraft.world.LightType; + +import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING; + +public class HarvesterActorInstance extends ActorInstance { + + InstanceKey harvester; + private Direction facing; + + public HarvesterActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { + super(modelManager, context); + + RenderMaterial> renderMaterial = modelManager.getActorMaterial(); + + BlockState state = context.state; + + facing = state.get(HORIZONTAL_FACING); + float originOffset = 1 / 16f; + Vector3f rotOffset = new Vector3f(0.5f, -2 * originOffset + 0.5f, originOffset + 0.5f); + + harvester = renderMaterial.getModel(AllBlockPartials.HARVESTER_BLADE, state).createInstance(); + + harvester.getInstance() + .setPosition(context.localPos) + .setBlockLight(localBlockLight()) + .setRotationOffset(0) + .setRotationCenter(rotOffset) + .setRotationAxis(-1, 0, 0) + .setLocalRotation(0, facing.getHorizontalAngle(), 0) + .setSpeed(getSpeed(facing)); + } + + @Override + protected void tick() { + harvester.getInstance().setSpeed(getSpeed(facing)); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java index ea53b2b2c..2878d19da 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java @@ -2,6 +2,8 @@ package com.simibubi.create.content.contraptions.components.actors; import static net.minecraft.block.HorizontalBlock.HORIZONTAL_FACING; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import org.apache.commons.lang3.mutable.MutableBoolean; import com.mojang.blaze3d.matrix.MatrixStack; @@ -29,6 +31,8 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.common.IPlantable; +import javax.annotation.Nullable; + public class HarvesterMovementBehaviour extends MovementBehaviour { @Override @@ -42,9 +46,10 @@ public class HarvesterMovementBehaviour extends MovementBehaviour { return true; } + @Nullable @Override - public void addInstance(RenderedContraption contraption, MovementContext context) { - HarvesterRenderer.addInstanceForContraption(contraption, context); + public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) { + return new HarvesterActorInstance(kr, context); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java index cd130936c..b22a1ba12 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java @@ -43,24 +43,6 @@ public class HarvesterRenderer extends SafeTileEntityRenderer> renderMaterial = contraption.getActorMaterial(); - - BlockState state = context.state; - InstancedModel model = renderMaterial.getModel(AllBlockPartials.HARVESTER_BLADE, state); - - Direction facing = state.get(HORIZONTAL_FACING); - float originOffset = 1 / 16f; - Vector3f rotOffset = new Vector3f(0.5f, -2 * originOffset + 0.5f, originOffset + 0.5f); - model.getInstance(model.createInstance()) - .setPosition(context.localPos) - .setBlockLight(contraption.renderWorld.getLightLevel(LightType.BLOCK, context.localPos)) - .setRotationOffset(0) - .setRotationCenter(rotOffset) - .setRotationAxis(-1, 0, 0) - .setLocalRotation(0, facing.getHorizontalAngle(), 0); - } - public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffers) { BlockState blockState = context.state; @@ -90,7 +72,4 @@ public class HarvesterRenderer extends SafeTileEntityRenderer pole; + InstanceKey hand; + InstanceKey shaft; + + public DeployerActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { + super(modelManager, context); + + RenderMaterial> mat = modelManager.basicMaterial(); + + BlockState state = context.state; + DeployerTileEntity.Mode mode = NBTHelper.readEnum(context.tileData, "Mode", DeployerTileEntity.Mode.class); + AllBlockPartials handPose = DeployerRenderer.getHandPose(mode); + + stationaryTimer = context.data.contains("StationaryTimer"); + facing = state.get(FACING); + + boolean rotatePole = state.get(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; + yRot = AngleHelper.horizontalAngle(facing); + zRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; + zRotPole = rotatePole ? 90 : 0; + + pole = mat.getModel(AllBlockPartials.DEPLOYER_POLE, state).createInstance(); + hand = mat.getModel(handPose, state).createInstance(); + + Direction.Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); + shaft = modelManager.getMaterial(KineticRenderMaterials.ROTATING) + .getModel(KineticTileEntityRenderer.KINETIC_TILE, KineticTileInstance.shaft(axis)) + .createInstance(); + + int blockLight = localBlockLight(); + + shaft.getInstance() + .setBlockLight(blockLight) + .setRotationAxis(axis) + .setPosition(context.localPos); + + pole.getInstance().setBlockLight(blockLight); + hand.getInstance().setBlockLight(blockLight); + } + + @Override + protected void tick() { + double factor; + if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { + factor = MathHelper.sin(AnimationTickHolder.getRenderTime() * .5f) * .25f + .25f; + } else { + Vec3d center = VecHelper.getCenterOf(new BlockPos(context.position)); + double distance = context.position.distanceTo(center); + double nextDistance = context.position.add(context.motion) + .distanceTo(center); + factor = .5f - MathHelper.clamp(MathHelper.lerp(AnimationTickHolder.getPartialTicks(), distance, nextDistance), 0, 1); + } + + Vec3d offset = new Vec3d(facing.getDirectionVec()).scale(factor); + + MatrixStack ms = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(ms); + + msr.translate(context.localPos) + .translate(offset); + + DeployerInstance.transformModel(msr, pole, hand, yRot, zRot, zRotPole); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java new file mode 100644 index 000000000..8ac245d1c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java @@ -0,0 +1,132 @@ +package com.simibubi.create.content.contraptions.components.deployer; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; +import com.simibubi.create.foundation.render.backend.instancing.*; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.MatrixStacker; +import net.minecraft.util.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +import static com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; +import static com.simibubi.create.content.contraptions.base.DirectionalKineticBlock.FACING; + +public class DeployerInstance extends ShaftInstance implements ITickableInstance { + + DeployerTileEntity tile; + + Direction facing; + + InstanceKey pole; + + AllBlockPartials currentHand; + InstanceKey hand; + + float yRot; + float zRot; + float zRotPole; + + public DeployerInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + super(dispatcher, tile); + } + + @Override + protected void init() { + super.init(); + + this.tile = (DeployerTileEntity) super.tile; + facing = lastState.get(FACING); + + boolean rotatePole = lastState.get(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; + + yRot = AngleHelper.horizontalAngle(facing); + zRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; + zRotPole = rotatePole ? 90 : 0; + + pole = modelManager.basicMaterial().getModel(AllBlockPartials.DEPLOYER_POLE, lastState).createInstance(); + + updateHandPose(); + relight(pos, pole.getInstance()); + } + + @Override + public void tick() { + + updateHandPose(); + + MatrixStack ms = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(ms); + + msr.translate(getFloatingPos()) + .translate(getHandOffset(AnimationTickHolder.getPartialTicks())); + + transformModel(msr, pole, hand, yRot, zRot, zRotPole); + + } + + @Override + public void updateLight() { + super.updateLight(); + relight(pos, hand.getInstance(), pole.getInstance()); + } + + @Override + public void remove() { + super.remove(); + hand.delete(); + pole.delete(); + currentHand = null; // updateHandPose() uses an invalid key after a block update otherwise. + hand = null; + } + + private boolean updateHandPose() { + AllBlockPartials handPose = tile.getHandPose(); + + if (currentHand == handPose) return false; + currentHand = handPose; + + if (hand != null) hand.delete(); + + hand = modelManager.basicMaterial().getModel(currentHand, lastState).createInstance(); + + relight(pos, hand.getInstance()); + + return true; + } + + protected Vec3d getHandOffset(float partialTicks) { + float progress = 0; + if (tile.state == DeployerTileEntity.State.EXPANDING) + progress = 1 - (tile.timer - partialTicks * tile.getTimerSpeed()) / 1000f; + if (tile.state == DeployerTileEntity.State.RETRACTING) + progress = (tile.timer - partialTicks * tile.getTimerSpeed()) / 1000f; + + float handLength = tile.getHandPose() == AllBlockPartials.DEPLOYER_HAND_POINTING ? 0 + : tile.getHandPose() == AllBlockPartials.DEPLOYER_HAND_HOLDING ? 4 / 16f : 3 / 16f; + float distance = Math.min(MathHelper.clamp(progress, 0, 1) * (tile.reach + handLength), 21 / 16f); + Vec3d offset = new Vec3d(facing.getDirectionVec()).scale(distance); + return offset; + } + + static void transformModel(MatrixStacker msr, InstanceKey pole, InstanceKey hand, float yRot, float zRot, float zRotPole) { + + msr.centre(); + msr.rotate(Direction.SOUTH, (float) ((zRot) / 180 * Math.PI)); + msr.rotate(Direction.UP, (float) ((yRot) / 180 * Math.PI)); + + msr.push(); + msr.rotate(Direction.SOUTH, (float) ((zRotPole) / 180 * Math.PI)); + msr.unCentre(); + pole.getInstance().setTransform(msr.unwrap()); + msr.pop(); + + msr.unCentre(); + + hand.getInstance().setTransform(msr.unwrap()); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java index aa8f4240e..83738f6dd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java @@ -3,6 +3,9 @@ package com.simibubi.create.content.contraptions.components.deployer; import java.util.Arrays; import java.util.List; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import org.apache.commons.lang3.tuple.Pair; import com.mojang.blaze3d.matrix.MatrixStack; @@ -24,6 +27,8 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.server.ServerWorld; import net.minecraftforge.common.util.Constants.NBT; +import javax.annotation.Nullable; + public class DeployerMovementBehaviour extends MovementBehaviour { @Override @@ -167,7 +172,18 @@ public class DeployerMovementBehaviour extends MovementBehaviour { @Override public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffers) { - DeployerRenderer.renderInContraption(context, ms, msLocal, buffers); + if (!FastRenderDispatcher.available()) + DeployerRenderer.renderInContraption(context, ms, msLocal, buffers); } + @Override + public boolean hasSpecialInstancedRendering() { + return true; + } + + @Nullable + @Override + public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) { + return new DeployerActorInstance(kr, context); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java index 17aca279a..5438be5ac 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java @@ -49,11 +49,17 @@ public class DeployerRenderer extends SafeTileEntityRenderer int light, int overlay) { renderItem(te, partialTicks, ms, buffer, light, overlay); FilteringRenderer.renderOnTileEntity(te, partialTicks, ms, buffer, light, overlay); + + if (FastRenderDispatcher.available(te.getWorld())) return; + renderComponents(te, partialTicks, ms, buffer, light, overlay); } protected void renderItem(DeployerTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + + if (te.heldItem.isEmpty()) return; + BlockState deployerState = te.getBlockState(); Vec3d offset = getHandOffset(te, partialTicks, deployerState).add(VecHelper.getCenterOf(BlockPos.ZERO)); ms.push(); @@ -157,8 +163,7 @@ public class DeployerRenderer extends SafeTileEntityRenderer BlockPos pos = BlockPos.ZERO; Mode mode = NBTHelper.readEnum(context.tileData, "Mode", Mode.class); World world = context.world; - AllBlockPartials handPose = - mode == Mode.PUNCH ? AllBlockPartials.DEPLOYER_HAND_PUNCHING : AllBlockPartials.DEPLOYER_HAND_POINTING; + AllBlockPartials handPose = getHandPose(mode); SuperByteBuffer pole = AllBlockPartials.DEPLOYER_POLE.renderOn(blockState); SuperByteBuffer hand = handPose.renderOn(blockState); @@ -189,4 +194,8 @@ public class DeployerRenderer extends SafeTileEntityRenderer .renderInto(ms, builder); } + static AllBlockPartials getHandPose(DeployerTileEntity.Mode mode) { + return mode == DeployerTileEntity.Mode.PUNCH ? AllBlockPartials.DEPLOYER_HAND_PUNCHING : AllBlockPartials.DEPLOYER_HAND_POINTING; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java index 062a1601a..17a7c0af2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java @@ -1,6 +1,8 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -8,10 +10,13 @@ import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.gen.feature.template.Template; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.items.ItemHandlerHelper; +import javax.annotation.Nullable; + public abstract class MovementBehaviour { public boolean isActive(MovementContext context) { @@ -61,7 +66,10 @@ public abstract class MovementBehaviour { IRenderTypeBuffer buffer) {} @OnlyIn(Dist.CLIENT) - public void addInstance(RenderedContraption contraption, MovementContext context) {} + @Nullable + public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) { + return null; + } public void onSpeedChanged(MovementContext context, Vec3d oldMotion, Vec3d motion) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java new file mode 100644 index 000000000..97d7ecc34 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java @@ -0,0 +1,29 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.util.Direction; +import net.minecraft.world.LightType; + +public abstract class ActorInstance { + protected final ContraptionKineticRenderer modelManager; + protected final MovementContext context; + + public ActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { + this.modelManager = modelManager; + this.context = context; + } + + protected void tick() { } + + protected float getSpeed(Direction facing) { + if (context.contraption.stalled) + return 0; + + return !VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite()) ? context.getAnimationSpeed() : 0; + } + + protected int localBlockLight() { + return modelManager.contraption.renderWorld.getLightLevel(LightType.BLOCK, context.localPos); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java index 8413118f7..56d968c93 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java @@ -1,20 +1,41 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; +import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; import com.simibubi.create.content.contraptions.base.RotatingInstancedModel; +import com.simibubi.create.content.contraptions.components.actors.ContraptionActorData; import com.simibubi.create.content.contraptions.components.actors.RotatingActorModel; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.relays.belt.BeltInstancedModel; import com.simibubi.create.content.logistics.block.FlapInstancedModel; import com.simibubi.create.foundation.render.AllProgramSpecs; +import com.simibubi.create.foundation.render.backend.Backend; import com.simibubi.create.foundation.render.backend.RenderMaterials; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; +import com.simibubi.create.foundation.render.backend.instancing.*; import com.simibubi.create.foundation.render.backend.instancing.impl.BasicInstancedModel; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.feature.template.Template; +import org.apache.commons.lang3.tuple.MutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; public class ContraptionKineticRenderer extends InstancedTileRenderer { + protected ArrayList actors = new ArrayList<>(); + + public final RenderedContraption contraption; + + ContraptionKineticRenderer(RenderedContraption contraption) { + this.contraption = contraption; + } + @Override public void registerMaterials() { materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.C_MODEL, BasicInstancedModel::new)); @@ -25,6 +46,36 @@ public class ContraptionKineticRenderer extends InstancedTileRenderer(this, AllProgramSpecs.C_ACTOR, RotatingActorModel::new)); } + + @Override + public void beginFrame(double cameraX, double cameraY, double cameraZ) { + super.beginFrame(cameraX, cameraY, cameraZ); + + actors.forEach(ActorInstance::tick); + } + + @Nullable + public ActorInstance createActor(Pair actor) { + Template.BlockInfo blockInfo = actor.getLeft(); + MovementContext context = actor.getRight(); + + MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); + + if (movementBehaviour != null && movementBehaviour.hasSpecialInstancedRendering()) { + ActorInstance instance = movementBehaviour.createInstance(this, context); + + actors.add(instance); + + return instance; + } + + return null; + } + + public RenderMaterial> getActorMaterial() { + return getMaterial(KineticRenderMaterials.ACTORS); + } + @Override public BlockPos getOriginCoordinate() { return BlockPos.ZERO; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java index 23cdc0c55..9beb21f64 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java @@ -64,7 +64,7 @@ public class RenderedContraption { public RenderedContraption(World world, Contraption contraption) { this.contraption = contraption; this.lighter = contraption.makeLighter(); - this.kinetics = new ContraptionKineticRenderer(); + this.kinetics = new ContraptionKineticRenderer(this); this.renderWorld = setupRenderWorld(world, contraption); buildLayers(); @@ -86,10 +86,6 @@ public class RenderedContraption { return lighter; } - public RenderMaterial> getActorMaterial() { - return kinetics.getMaterial(KineticRenderMaterials.ACTORS); - } - public void doRenderLayer(RenderType layer, ContraptionProgram shader) { ContraptionModel structure = renderLayers.get(layer); if (structure != null) { @@ -172,18 +168,7 @@ public class RenderedContraption { } private void buildActors() { - List> actors = contraption.getActors(); - - for (MutablePair actor : actors) { - Template.BlockInfo blockInfo = actor.left; - MovementContext context = actor.right; - - MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); - - if (movementBehaviour != null) { - movementBehaviour.addInstance(this, context); - } - } + contraption.getActors().forEach(kinetics::createActor); } private static ContraptionModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java b/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java index 8ebc71b26..e9610c6fe 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java +++ b/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java @@ -109,4 +109,18 @@ public class MatrixStacker { return this; } + public MatrixStacker push() { + ms.push(); + return this; + } + + public MatrixStacker pop() { + ms.pop(); + return this; + } + + public MatrixStack unwrap() { + return ms; + } + } diff --git a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java index 7610ea984..611bbe2d0 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java @@ -60,7 +60,8 @@ public class VecHelper { } public static boolean isVecPointingTowards(Vec3d vec, Direction direction) { - return new Vec3d(direction.getDirectionVec()).distanceTo(vec.normalize()) < .75; + return new Vec3d(direction.getDirectionVec()).dotProduct(vec.normalize()) > 0; + //return new Vec3d(direction.getDirectionVec()).distanceTo(vec.normalize()) < .75; } public static Vec3d getCenterOf(Vec3i pos) { diff --git a/src/main/resources/assets/create/shader/contraption_actor.vert b/src/main/resources/assets/create/shader/contraption_actor.vert index cc31d18ed..31cdd6799 100644 --- a/src/main/resources/assets/create/shader/contraption_actor.vert +++ b/src/main/resources/assets/create/shader/contraption_actor.vert @@ -12,6 +12,7 @@ attribute float aOffset; attribute vec3 aAxis; attribute vec3 aInstanceRot; attribute vec3 aRotationCenter; +attribute float aSpeed; varying float Diffuse; @@ -57,11 +58,10 @@ mat4 rotation(vec3 rot) { } mat4 kineticRotation() { - const float speed = -20.; - float degrees = aOffset + uTime * speed * -3./10.; + float degrees = aOffset + uTime * aSpeed / 20.; float angle = fract(degrees / 360.) * PI * 2.; - return rotate(normalize(aAxis), angle); + return rotate(normalize(aAxis), -angle); } void main() {