minecraft-src/net/minecraft/client/renderer/blockentity/BannerRenderer.java
2025-07-04 02:49:36 +03:00

150 lines
6.5 KiB
Java

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.geom.ModelLayers;
import net.minecraft.client.model.geom.ModelPart;
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.client.resources.model.ModelBakery;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.Mth;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.level.block.BannerBlock;
import net.minecraft.world.level.block.WallBannerBlock;
import net.minecraft.world.level.block.entity.BannerBlockEntity;
import net.minecraft.world.level.block.entity.BannerPatternLayers;
import net.minecraft.world.level.block.entity.BannerPatternLayers.Layer;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.RotationSegment;
@Environment(EnvType.CLIENT)
public class BannerRenderer implements BlockEntityRenderer<BannerBlockEntity> {
private static final int BANNER_WIDTH = 20;
private static final int BANNER_HEIGHT = 40;
private static final int MAX_PATTERNS = 16;
public static final String FLAG = "flag";
private static final String POLE = "pole";
private static final String BAR = "bar";
private final ModelPart flag;
private final ModelPart pole;
private final ModelPart bar;
public BannerRenderer(Context context) {
ModelPart modelPart = context.bakeLayer(ModelLayers.BANNER);
this.flag = modelPart.getChild("flag");
this.pole = modelPart.getChild("pole");
this.bar = modelPart.getChild("bar");
}
public static LayerDefinition createBodyLayer() {
MeshDefinition meshDefinition = new MeshDefinition();
PartDefinition partDefinition = meshDefinition.getRoot();
partDefinition.addOrReplaceChild(
"flag", CubeListBuilder.create().texOffs(0, 0).addBox(-10.0F, 0.0F, -2.0F, 20.0F, 40.0F, 1.0F), PartPose.offset(0.0F, -32.0F, 0.0F)
);
partDefinition.addOrReplaceChild("pole", CubeListBuilder.create().texOffs(44, 0).addBox(-1.0F, -30.0F, -1.0F, 2.0F, 42.0F, 2.0F), PartPose.ZERO);
partDefinition.addOrReplaceChild("bar", CubeListBuilder.create().texOffs(0, 42).addBox(-10.0F, -32.0F, -1.0F, 20.0F, 2.0F, 2.0F), PartPose.ZERO);
return LayerDefinition.create(meshDefinition, 64, 64);
}
public void render(BannerBlockEntity blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
float f = 0.6666667F;
boolean bl = blockEntity.getLevel() == null;
poseStack.pushPose();
long l;
if (bl) {
l = 0L;
poseStack.translate(0.5F, 0.5F, 0.5F);
this.pole.visible = true;
} else {
l = blockEntity.getLevel().getGameTime();
BlockState blockState = blockEntity.getBlockState();
if (blockState.getBlock() instanceof BannerBlock) {
poseStack.translate(0.5F, 0.5F, 0.5F);
float g = -RotationSegment.convertToDegrees((Integer)blockState.getValue(BannerBlock.ROTATION));
poseStack.mulPose(Axis.YP.rotationDegrees(g));
this.pole.visible = true;
} else {
poseStack.translate(0.5F, -0.16666667F, 0.5F);
float g = -((Direction)blockState.getValue(WallBannerBlock.FACING)).toYRot();
poseStack.mulPose(Axis.YP.rotationDegrees(g));
poseStack.translate(0.0F, -0.3125F, -0.4375F);
this.pole.visible = false;
}
}
poseStack.pushPose();
poseStack.scale(0.6666667F, -0.6666667F, -0.6666667F);
VertexConsumer vertexConsumer = ModelBakery.BANNER_BASE.buffer(bufferSource, RenderType::entitySolid);
this.pole.render(poseStack, vertexConsumer, packedLight, packedOverlay);
this.bar.render(poseStack, vertexConsumer, packedLight, packedOverlay);
BlockPos blockPos = blockEntity.getBlockPos();
float h = ((float)Math.floorMod(blockPos.getX() * 7 + blockPos.getY() * 9 + blockPos.getZ() * 13 + l, 100L) + partialTick) / 100.0F;
this.flag.xRot = (-0.0125F + 0.01F * Mth.cos((float) (Math.PI * 2) * h)) * (float) Math.PI;
renderPatterns(
poseStack, bufferSource, packedLight, packedOverlay, this.flag, ModelBakery.BANNER_BASE, true, blockEntity.getBaseColor(), blockEntity.getPatterns()
);
poseStack.popPose();
poseStack.popPose();
}
/**
* @param banner if {@code true}, uses banner material; otherwise if {@code false} uses shield material
*/
public static void renderPatterns(
PoseStack poseStack,
MultiBufferSource bufferSource,
int packedLight,
int packedOverlay,
ModelPart flagPart,
Material flagMaterial,
boolean banner,
DyeColor baseColor,
BannerPatternLayers patterns
) {
renderPatterns(poseStack, bufferSource, packedLight, packedOverlay, flagPart, flagMaterial, banner, baseColor, patterns, false, true);
}
public static void renderPatterns(
PoseStack poseStack,
MultiBufferSource bufferSource,
int packedLight,
int packedOverlay,
ModelPart flagPart,
Material flagMaterial,
boolean banner,
DyeColor baseColor,
BannerPatternLayers patterns,
boolean withGlint,
boolean noEntity
) {
flagPart.render(poseStack, flagMaterial.buffer(bufferSource, RenderType::entitySolid, noEntity, withGlint), packedLight, packedOverlay);
renderPatternLayer(poseStack, bufferSource, packedLight, packedOverlay, flagPart, banner ? Sheets.BANNER_BASE : Sheets.SHIELD_BASE, baseColor);
for (int i = 0; i < 16 && i < patterns.layers().size(); i++) {
Layer layer = (Layer)patterns.layers().get(i);
Material material = banner ? Sheets.getBannerMaterial(layer.pattern()) : Sheets.getShieldMaterial(layer.pattern());
renderPatternLayer(poseStack, bufferSource, packedLight, packedOverlay, flagPart, material, layer.color());
}
}
private static void renderPatternLayer(
PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay, ModelPart flagPart, Material material, DyeColor color
) {
int i = color.getTextureDiffuseColor();
flagPart.render(poseStack, material.buffer(buffer, RenderType::entityNoOutline), packedLight, packedOverlay, i);
}
}