package net.minecraft.client.renderer.blockentity; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Axis; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.model.Model; import net.minecraft.client.model.Model.Simple; import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.model.geom.ModelLayers; import net.minecraft.client.model.geom.PartPose; import net.minecraft.client.model.geom.builders.CubeListBuilder; import net.minecraft.client.model.geom.builders.LayerDefinition; import net.minecraft.client.model.geom.builders.MeshDefinition; import net.minecraft.client.model.geom.builders.PartDefinition; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.Sheets; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; import net.minecraft.client.resources.model.Material; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.BedBlock; import net.minecraft.world.level.block.ChestBlock; import net.minecraft.world.level.block.DoubleBlockCombiner; import net.minecraft.world.level.block.DoubleBlockCombiner.NeighborCombineResult; import net.minecraft.world.level.block.entity.BedBlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BedPart; import net.minecraft.world.phys.Vec3; @Environment(EnvType.CLIENT) public class BedRenderer implements BlockEntityRenderer { private final Model headModel; private final Model footModel; public BedRenderer(Context context) { this(context.getModelSet()); } public BedRenderer(EntityModelSet modelSet) { this.headModel = new Simple(modelSet.bakeLayer(ModelLayers.BED_HEAD), RenderType::entitySolid); this.footModel = new Simple(modelSet.bakeLayer(ModelLayers.BED_FOOT), RenderType::entitySolid); } public static LayerDefinition createHeadLayer() { MeshDefinition meshDefinition = new MeshDefinition(); PartDefinition partDefinition = meshDefinition.getRoot(); partDefinition.addOrReplaceChild("main", CubeListBuilder.create().texOffs(0, 0).addBox(0.0F, 0.0F, 0.0F, 16.0F, 16.0F, 6.0F), PartPose.ZERO); partDefinition.addOrReplaceChild( "left_leg", CubeListBuilder.create().texOffs(50, 6).addBox(0.0F, 6.0F, 0.0F, 3.0F, 3.0F, 3.0F), PartPose.rotation((float) (Math.PI / 2), 0.0F, (float) (Math.PI / 2)) ); partDefinition.addOrReplaceChild( "right_leg", CubeListBuilder.create().texOffs(50, 18).addBox(-16.0F, 6.0F, 0.0F, 3.0F, 3.0F, 3.0F), PartPose.rotation((float) (Math.PI / 2), 0.0F, (float) Math.PI) ); return LayerDefinition.create(meshDefinition, 64, 64); } public static LayerDefinition createFootLayer() { MeshDefinition meshDefinition = new MeshDefinition(); PartDefinition partDefinition = meshDefinition.getRoot(); partDefinition.addOrReplaceChild("main", CubeListBuilder.create().texOffs(0, 22).addBox(0.0F, 0.0F, 0.0F, 16.0F, 16.0F, 6.0F), PartPose.ZERO); partDefinition.addOrReplaceChild( "left_leg", CubeListBuilder.create().texOffs(50, 0).addBox(0.0F, 6.0F, -16.0F, 3.0F, 3.0F, 3.0F), PartPose.rotation((float) (Math.PI / 2), 0.0F, 0.0F) ); partDefinition.addOrReplaceChild( "right_leg", CubeListBuilder.create().texOffs(50, 12).addBox(-16.0F, 6.0F, -16.0F, 3.0F, 3.0F, 3.0F), PartPose.rotation((float) (Math.PI / 2), 0.0F, (float) (Math.PI * 3.0 / 2.0)) ); return LayerDefinition.create(meshDefinition, 64, 64); } public void render(BedBlockEntity bedBlockEntity, float f, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, int j, Vec3 vec3) { Level level = bedBlockEntity.getLevel(); if (level != null) { Material material = Sheets.getBedMaterial(bedBlockEntity.getColor()); BlockState blockState = bedBlockEntity.getBlockState(); NeighborCombineResult neighborCombineResult = DoubleBlockCombiner.combineWithNeigbour( BlockEntityType.BED, BedBlock::getBlockType, BedBlock::getConnectedDirection, ChestBlock.FACING, blockState, level, bedBlockEntity.getBlockPos(), (levelAccessor, blockPos) -> false ); int k = neighborCombineResult.apply(new BrightnessCombiner<>()).get(i); this.renderPiece( poseStack, multiBufferSource, blockState.getValue(BedBlock.PART) == BedPart.HEAD ? this.headModel : this.footModel, blockState.getValue(BedBlock.FACING), material, k, j, false ); } } public void renderInHand(PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay, Material material) { this.renderPiece(poseStack, bufferSource, this.headModel, Direction.SOUTH, material, packedLight, packedOverlay, false); this.renderPiece(poseStack, bufferSource, this.footModel, Direction.SOUTH, material, packedLight, packedOverlay, true); } private void renderPiece( PoseStack poseStack, MultiBufferSource bufferSource, Model model, Direction direction, Material material, int packedLight, int packedOverlay, boolean isFeet ) { poseStack.pushPose(); poseStack.translate(0.0F, 0.5625F, isFeet ? -1.0F : 0.0F); poseStack.mulPose(Axis.XP.rotationDegrees(90.0F)); poseStack.translate(0.5F, 0.5F, 0.5F); poseStack.mulPose(Axis.ZP.rotationDegrees(180.0F + direction.toYRot())); poseStack.translate(-0.5F, -0.5F, -0.5F); VertexConsumer vertexConsumer = material.buffer(bufferSource, RenderType::entitySolid); model.renderToBuffer(poseStack, vertexConsumer, packedLight, packedOverlay); poseStack.popPose(); } }