filename:
common/src/main/java/rearth/oritech/client/renderers/MachineGantryRenderer.java
branch:
1.21
back to repo
package rearth.oritech.client.renderers;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayers;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
import org.joml.AxisAngle4f;
import org.joml.Quaternionf;
import rearth.oritech.block.base.block.FrameInteractionBlock;
import rearth.oritech.block.base.entity.FrameInteractionBlockEntity;
import rearth.oritech.block.entity.interaction.DestroyerBlockEntity;
import rearth.oritech.init.BlockContent;
public class MachineGantryRenderer implements BlockEntityRenderer<FrameInteractionBlockEntity> {
private static final BlockState renderedBeam = BlockContent.FRAME_GANTRY_ARM.getDefaultState();
private static final float BEAM_DEPTH = 3 / 16f;
private static final Random renderRandom = Random.create(100);
@Override
public int getRenderDistance() {
return 128;
}
@Override
public boolean rendersOutsideBoundingBox(FrameInteractionBlockEntity blockEntity) {
return true;
}
@Override
public void render(FrameInteractionBlockEntity entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
var state = entity.getCachedState();
if (!state.get(FrameInteractionBlock.HAS_FRAME) || entity.getAreaMin() == null || entity.getLastTarget() == null)
return;
var renderedPosition = Vec3d.of(entity.getCurrentTarget());
var movingOffset = new Vec3d(0, 0, 0);
var time = entity.getWorld().getTime() + tickDelta;
var passedTime = time - entity.getMoveStartedAt();
var random = entity.getWorld().random;
// check if currently moving, otherwise we can skip those calculations
if (time < entity.getMoveStartedAt() + entity.getMoveTime() && entity.getMoveStartedAt() > 1) {
var movementDoneAmount = passedTime / (float) entity.getMoveTime();
var offset = Vec3d.of(entity.getCurrentTarget().subtract(entity.getLastTarget())).multiply(movementDoneAmount);
renderedPosition = Vec3d.of(entity.getLastTarget()).add(offset);
} else {
// apply slight movement while working
var offsetY = renderRandom.nextFloat() * 0.009 - 0.004;
movingOffset = new Vec3d(0, offsetY, 0);
}
renderedPosition = LaserArmRenderer.lerp(entity.lastRenderedPosition, renderedPosition, 0.1f);
entity.lastRenderedPosition = renderedPosition;
var targetOffset = renderedPosition.subtract(Vec3d.of(entity.getPos())).add(movingOffset);
matrices.push();
matrices.translate(targetOffset.getX(), targetOffset.getY(), targetOffset.getZ());
var pos = entity.getCurrentTarget(); // relevant for correct lighting, actual rendered position is determined by matrix
MinecraftClient.getInstance().getBlockRenderManager().renderBlock(
entity.getMachineHead(),
pos,
entity.getWorld(),
matrices,
vertexConsumers.getBuffer(RenderLayers.getBlockLayer(entity.getMachineHead())),
true,
random);
matrices.pop();
matrices.push();
var length = entity.getAreaMax().getX() - entity.getAreaMin().getX() + 2 - BEAM_DEPTH * 2f;
var target = new Vec3d(entity.getAreaMin().getX() - 0.5 + BEAM_DEPTH, renderedPosition.y, renderedPosition.z).subtract(Vec3d.of(entity.getPos()));
matrices.translate(target.getX(), target.getY(), target.getZ());
matrices.scale(length, 1, 1);
MinecraftClient.getInstance().getBlockRenderManager().renderBlock(
renderedBeam,
pos,
entity.getWorld(),
matrices,
vertexConsumers.getBuffer(RenderLayers.getBlockLayer(renderedBeam)),
true,
random);
matrices.pop();
var renderedItem = entity.getToolheadAdditionalRender();
if (renderedItem != null) {
matrices.push();
matrices.translate(targetOffset.getX() + 0.4, targetOffset.getY(), targetOffset.getZ() + 0.4);
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(30));
// matrices.scale(0.3f, 0.3f, 0.3f);
MinecraftClient.getInstance().getItemRenderer().renderItem(
renderedItem,
ModelTransformationMode.FIRST_PERSON_RIGHT_HAND,
light,
OverlayTexture.DEFAULT_UV,
matrices,
vertexConsumers,
entity.getWorld(),
0
);
matrices.pop();
}
if (entity instanceof DestroyerBlockEntity destroyerBlock && destroyerBlock.range > 1) {
var beamHeight = pos.getY() - destroyerBlock.quarryTarget.getY() - 1.3f;
var beamInner = BlockContent.QUARRY_BEAM_INNER.getDefaultState();
var beamFrame = BlockContent.QUARRY_BEAM_TARGET.getDefaultState();
var beamRing = BlockContent.QUARRY_BEAM_RING.getDefaultState();
var offset = targetOffset.add(0, -1, 0);
matrices.push();
matrices.translate(offset.getX(), offset.getY() - beamHeight + 1, offset.getZ());
matrices.scale(1, beamHeight, 1);
// outer beam
// MinecraftClient.getInstance().getBlockRenderManager().renderBlock(
// beamFrame,
// pos,
// entity.getWorld(),
// matrices,
// vertexConsumers.getBuffer(RenderLayers.getBlockLayer(beamFrame)),
// true,
// random);
matrices.translate(0.5, 0, 0.5);
var rotation = new Quaternionf(new AxisAngle4f((entity.getWorld().getTime() / 3f) % 360, 0, 1, 0));
matrices.multiply(rotation);
matrices.translate(-0.5, 0, -0.5);
// inner beam
MinecraftClient.getInstance().getBlockRenderManager().renderBlock(
beamInner,
pos,
entity.getWorld(),
matrices,
vertexConsumers.getBuffer(RenderLayers.getBlockLayer(beamInner)),
true,
random);
matrices.pop();
// beam ring
matrices.push();
var ringHeight = Math.sin((entity.getWorld().getTime() + tickDelta) / 4f);
var heightOffset = beamHeight * 0.5 * ringHeight + beamHeight * 0.5;
matrices.translate(offset.getX(), offset.getY() - heightOffset + 1, offset.getZ());
// outer beam
MinecraftClient.getInstance().getBlockRenderManager().renderBlock(
beamRing,
pos,
entity.getWorld(),
matrices,
vertexConsumers.getBuffer(RenderLayers.getBlockLayer(beamRing)),
true,
random);
matrices.pop();
}
}
}