minecraft-src/net/minecraft/client/renderer/blockentity/BannerRenderer.java
2025-07-04 03:45:38 +03:00

144 lines
6.1 KiB
Java

package net.minecraft.client.renderer.blockentity;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.model.BannerFlagModel;
import net.minecraft.client.model.BannerModel;
import net.minecraft.client.model.geom.EntityModelSet;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.client.model.geom.ModelPart;
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.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.state.BlockState;
import net.minecraft.world.level.block.state.properties.RotationSegment;
import net.minecraft.world.phys.Vec3;
@Environment(EnvType.CLIENT)
public class BannerRenderer implements BlockEntityRenderer<BannerBlockEntity> {
private static final int MAX_PATTERNS = 16;
private static final float SIZE = 0.6666667F;
private final BannerModel standingModel;
private final BannerModel wallModel;
private final BannerFlagModel standingFlagModel;
private final BannerFlagModel wallFlagModel;
public BannerRenderer(Context context) {
this(context.getModelSet());
}
public BannerRenderer(EntityModelSet modelSet) {
this.standingModel = new BannerModel(modelSet.bakeLayer(ModelLayers.STANDING_BANNER));
this.wallModel = new BannerModel(modelSet.bakeLayer(ModelLayers.WALL_BANNER));
this.standingFlagModel = new BannerFlagModel(modelSet.bakeLayer(ModelLayers.STANDING_BANNER_FLAG));
this.wallFlagModel = new BannerFlagModel(modelSet.bakeLayer(ModelLayers.WALL_BANNER_FLAG));
}
public void render(BannerBlockEntity bannerBlockEntity, float f, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, int j, Vec3 vec3) {
BlockState blockState = bannerBlockEntity.getBlockState();
BannerModel bannerModel;
BannerFlagModel bannerFlagModel;
float g;
if (blockState.getBlock() instanceof BannerBlock) {
g = -RotationSegment.convertToDegrees((Integer)blockState.getValue(BannerBlock.ROTATION));
bannerModel = this.standingModel;
bannerFlagModel = this.standingFlagModel;
} else {
g = -((Direction)blockState.getValue(WallBannerBlock.FACING)).toYRot();
bannerModel = this.wallModel;
bannerFlagModel = this.wallFlagModel;
}
long l = bannerBlockEntity.getLevel().getGameTime();
BlockPos blockPos = bannerBlockEntity.getBlockPos();
float h = ((float)Math.floorMod(blockPos.getX() * 7 + blockPos.getY() * 9 + blockPos.getZ() * 13 + l, 100L) + f) / 100.0F;
renderBanner(poseStack, multiBufferSource, i, j, g, bannerModel, bannerFlagModel, h, bannerBlockEntity.getBaseColor(), bannerBlockEntity.getPatterns());
}
public void renderInHand(
PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay, DyeColor baseColor, BannerPatternLayers patterns
) {
renderBanner(poseStack, bufferSource, packedLight, packedOverlay, 0.0F, this.standingModel, this.standingFlagModel, 0.0F, baseColor, patterns);
}
private static void renderBanner(
PoseStack poseStack,
MultiBufferSource bufferSource,
int packedLight,
int packedOverlay,
float rotation,
BannerModel standingModel,
BannerFlagModel standingFlagModel,
float angle,
DyeColor baseColor,
BannerPatternLayers patterns
) {
poseStack.pushPose();
poseStack.translate(0.5F, 0.0F, 0.5F);
poseStack.mulPose(Axis.YP.rotationDegrees(rotation));
poseStack.scale(0.6666667F, -0.6666667F, -0.6666667F);
standingModel.renderToBuffer(poseStack, ModelBakery.BANNER_BASE.buffer(bufferSource, RenderType::entitySolid), packedLight, packedOverlay);
standingFlagModel.setupAnim(angle);
renderPatterns(poseStack, bufferSource, packedLight, packedOverlay, standingFlagModel.root(), ModelBakery.BANNER_BASE, true, baseColor, patterns);
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++) {
BannerPatternLayers.Layer layer = (BannerPatternLayers.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);
}
}