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

181 lines
6.3 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 java.util.List;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.Font.DisplayMode;
import net.minecraft.client.model.Model;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context;
import net.minecraft.client.resources.model.Material;
import net.minecraft.core.BlockPos;
import net.minecraft.util.ARGB;
import net.minecraft.util.FormattedCharSequence;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.level.block.SignBlock;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.level.block.entity.SignText;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.WoodType;
import net.minecraft.world.phys.Vec3;
@Environment(EnvType.CLIENT)
public abstract class AbstractSignRenderer implements BlockEntityRenderer<SignBlockEntity> {
private static final int BLACK_TEXT_OUTLINE_COLOR = -988212;
private static final int OUTLINE_RENDER_DISTANCE = Mth.square(16);
private final Font font;
public AbstractSignRenderer(Context context) {
this.font = context.getFont();
}
protected abstract Model getSignModel(BlockState state, WoodType woodType);
protected abstract Material getSignMaterial(WoodType woodType);
protected abstract float getSignModelRenderScale();
protected abstract float getSignTextRenderScale();
protected abstract Vec3 getTextOffset();
protected abstract void translateSign(PoseStack poseStack, float yRot, BlockState state);
public void render(SignBlockEntity signBlockEntity, float f, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, int j, Vec3 vec3) {
BlockState blockState = signBlockEntity.getBlockState();
SignBlock signBlock = (SignBlock)blockState.getBlock();
Model model = this.getSignModel(blockState, signBlock.type());
this.renderSignWithText(signBlockEntity, poseStack, multiBufferSource, i, j, blockState, signBlock, signBlock.type(), model);
}
private void renderSignWithText(
SignBlockEntity blockEntity,
PoseStack poseStack,
MultiBufferSource bufferSource,
int packedLight,
int packedOverlay,
BlockState state,
SignBlock sign,
WoodType woodType,
Model model
) {
poseStack.pushPose();
this.translateSign(poseStack, -sign.getYRotationDegrees(state), state);
this.renderSign(poseStack, bufferSource, packedLight, packedOverlay, woodType, model);
this.renderSignText(
blockEntity.getBlockPos(),
blockEntity.getFrontText(),
poseStack,
bufferSource,
packedLight,
blockEntity.getTextLineHeight(),
blockEntity.getMaxTextLineWidth(),
true
);
this.renderSignText(
blockEntity.getBlockPos(),
blockEntity.getBackText(),
poseStack,
bufferSource,
packedLight,
blockEntity.getTextLineHeight(),
blockEntity.getMaxTextLineWidth(),
false
);
poseStack.popPose();
}
protected void renderSign(PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay, WoodType woodType, Model model) {
poseStack.pushPose();
float f = this.getSignModelRenderScale();
poseStack.scale(f, -f, -f);
Material material = this.getSignMaterial(woodType);
VertexConsumer vertexConsumer = material.buffer(bufferSource, model::renderType);
model.renderToBuffer(poseStack, vertexConsumer, packedLight, packedOverlay);
poseStack.popPose();
}
private void renderSignText(
BlockPos pos, SignText text, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int lineHeight, int maxLineWidth, boolean isFront
) {
poseStack.pushPose();
this.translateSignText(poseStack, isFront, this.getTextOffset());
int i = getDarkColor(text);
int j = 4 * lineHeight / 2;
FormattedCharSequence[] formattedCharSequences = text.getRenderMessages(Minecraft.getInstance().isTextFilteringEnabled(), component -> {
List<FormattedCharSequence> list = this.font.split(component, maxLineWidth);
return list.isEmpty() ? FormattedCharSequence.EMPTY : (FormattedCharSequence)list.get(0);
});
int k;
boolean bl;
int l;
if (text.hasGlowingText()) {
k = text.getColor().getTextColor();
bl = isOutlineVisible(pos, k);
l = 15728880;
} else {
k = i;
bl = false;
l = packedLight;
}
for (int m = 0; m < 4; m++) {
FormattedCharSequence formattedCharSequence = formattedCharSequences[m];
float f = -this.font.width(formattedCharSequence) / 2;
if (bl) {
this.font.drawInBatch8xOutline(formattedCharSequence, f, m * lineHeight - j, k, i, poseStack.last().pose(), bufferSource, l);
} else {
this.font
.drawInBatch(formattedCharSequence, f, (float)(m * lineHeight - j), k, false, poseStack.last().pose(), bufferSource, DisplayMode.POLYGON_OFFSET, 0, l);
}
}
poseStack.popPose();
}
private void translateSignText(PoseStack poseStack, boolean isFront, Vec3 offset) {
if (!isFront) {
poseStack.mulPose(Axis.YP.rotationDegrees(180.0F));
}
float f = 0.015625F * this.getSignTextRenderScale();
poseStack.translate(offset);
poseStack.scale(f, -f, f);
}
private static boolean isOutlineVisible(BlockPos pos, int color) {
if (color == DyeColor.BLACK.getTextColor()) {
return true;
} else {
Minecraft minecraft = Minecraft.getInstance();
LocalPlayer localPlayer = minecraft.player;
if (localPlayer != null && minecraft.options.getCameraType().isFirstPerson() && localPlayer.isScoping()) {
return true;
} else {
Entity entity = minecraft.getCameraEntity();
return entity != null && entity.distanceToSqr(Vec3.atCenterOf(pos)) < OUTLINE_RENDER_DISTANCE;
}
}
}
public static int getDarkColor(SignText text) {
int i = text.getColor().getTextColor();
if (i == DyeColor.BLACK.getTextColor() && text.hasGlowingText()) {
return -988212;
} else {
double d = 0.4;
int j = (int)(ARGB.red(i) * 0.4);
int k = (int)(ARGB.green(i) * 0.4);
int l = (int)(ARGB.blue(i) * 0.4);
return ARGB.color(0, j, k, l);
}
}
}