package net.minecraft.client.renderer.blockentity; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import java.util.List; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.MultiBufferSource; 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.block.model.BlockModelPart; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.piston.PistonBaseBlock; import net.minecraft.world.level.block.piston.PistonHeadBlock; import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.PistonType; import net.minecraft.world.phys.Vec3; @Environment(EnvType.CLIENT) public class PistonHeadRenderer implements BlockEntityRenderer { private final BlockRenderDispatcher blockRenderer; public PistonHeadRenderer(Context context) { this.blockRenderer = context.getBlockRenderDispatcher(); } public void render(PistonMovingBlockEntity pistonMovingBlockEntity, float f, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, int j, Vec3 vec3) { Level level = pistonMovingBlockEntity.getLevel(); if (level != null) { BlockPos blockPos = pistonMovingBlockEntity.getBlockPos().relative(pistonMovingBlockEntity.getMovementDirection().getOpposite()); BlockState blockState = pistonMovingBlockEntity.getMovedState(); if (!blockState.isAir()) { ModelBlockRenderer.enableCaching(); poseStack.pushPose(); poseStack.translate(pistonMovingBlockEntity.getXOff(f), pistonMovingBlockEntity.getYOff(f), pistonMovingBlockEntity.getZOff(f)); if (blockState.is(Blocks.PISTON_HEAD) && pistonMovingBlockEntity.getProgress(f) <= 4.0F) { blockState = blockState.setValue(PistonHeadBlock.SHORT, pistonMovingBlockEntity.getProgress(f) <= 0.5F); this.renderBlock(blockPos, blockState, poseStack, multiBufferSource, level, false, j); } else if (pistonMovingBlockEntity.isSourcePiston() && !pistonMovingBlockEntity.isExtending()) { PistonType pistonType = blockState.is(Blocks.STICKY_PISTON) ? PistonType.STICKY : PistonType.DEFAULT; BlockState blockState2 = Blocks.PISTON_HEAD .defaultBlockState() .setValue(PistonHeadBlock.TYPE, pistonType) .setValue(PistonHeadBlock.FACING, (Direction)blockState.getValue(PistonBaseBlock.FACING)); blockState2 = blockState2.setValue(PistonHeadBlock.SHORT, pistonMovingBlockEntity.getProgress(f) >= 0.5F); this.renderBlock(blockPos, blockState2, poseStack, multiBufferSource, level, false, j); BlockPos blockPos2 = blockPos.relative(pistonMovingBlockEntity.getMovementDirection()); poseStack.popPose(); poseStack.pushPose(); blockState = blockState.setValue(PistonBaseBlock.EXTENDED, true); this.renderBlock(blockPos2, blockState, poseStack, multiBufferSource, level, true, j); } else { this.renderBlock(blockPos, blockState, poseStack, multiBufferSource, level, false, j); } poseStack.popPose(); ModelBlockRenderer.clearCache(); } } } /** * @param extended if {@code true}, checks all sides before rendering via {@link net.minecraft.world.level.block.Block#shouldRenderFace(net.minecraft.world.level.block.state.BlockState, net.minecraft.world.level.BlockGetter, net.minecraft.core.BlockPos, net.minecraft.core.Direction, net.minecraft.core.BlockPos)} */ private void renderBlock(BlockPos pos, BlockState state, PoseStack poseStack, MultiBufferSource bufferSource, Level level, boolean extended, int packedOverlay) { RenderType renderType = ItemBlockRenderTypes.getMovingBlockRenderType(state); VertexConsumer vertexConsumer = bufferSource.getBuffer(renderType); List list = this.blockRenderer.getBlockModel(state).collectParts(RandomSource.create(state.getSeed(pos))); this.blockRenderer.getModelRenderer().tesselateBlock(level, list, state, pos, poseStack, vertexConsumer, extended, packedOverlay); } @Override public int getViewDistance() { return 68; } }