181 lines
6.3 KiB
Java
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);
|
|
}
|
|
}
|
|
}
|