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

206 lines
5.9 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.player.LocalPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ARGB;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.entity.BeaconBeamOwner;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec3;
@Environment(EnvType.CLIENT)
public class BeaconRenderer<T extends BlockEntity & BeaconBeamOwner> implements BlockEntityRenderer<T> {
public static final ResourceLocation BEAM_LOCATION = ResourceLocation.withDefaultNamespace("textures/entity/beacon_beam.png");
public static final int MAX_RENDER_Y = 2048;
private static final float BEAM_SCALE_THRESHOLD = 96.0F;
public static final float SOLID_BEAM_RADIUS = 0.2F;
public static final float BEAM_GLOW_RADIUS = 0.25F;
public BeaconRenderer(Context context) {
}
@Override
public void render(T blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay, Vec3 cameraPos) {
long l = blockEntity.getLevel().getGameTime();
float f = (float)cameraPos.subtract(blockEntity.getBlockPos().getCenter()).horizontalDistance();
LocalPlayer localPlayer = Minecraft.getInstance().player;
float g = localPlayer != null && localPlayer.isScoping() ? 1.0F : Math.max(1.0F, f / 96.0F);
List<BeaconBeamOwner.Section> list = blockEntity.getBeamSections();
int i = 0;
for (int j = 0; j < list.size(); j++) {
BeaconBeamOwner.Section section = (BeaconBeamOwner.Section)list.get(j);
renderBeaconBeam(poseStack, bufferSource, partialTick, g, l, i, j == list.size() - 1 ? 2048 : section.getHeight(), section.getColor());
i += section.getHeight();
}
}
private static void renderBeaconBeam(
PoseStack poseStack, MultiBufferSource bufferSource, float partialTick, float radius, long gameTime, int yOffset, int height, int color
) {
renderBeaconBeam(poseStack, bufferSource, BEAM_LOCATION, partialTick, 1.0F, gameTime, yOffset, height, color, 0.2F * radius, 0.25F * radius);
}
public static void renderBeaconBeam(
PoseStack poseStack,
MultiBufferSource bufferSource,
ResourceLocation beamLocation,
float partialTick,
float textureScale,
long gameTime,
int yOffset,
int height,
int color,
float beamRadius,
float glowRadius
) {
int i = yOffset + height;
poseStack.pushPose();
poseStack.translate(0.5, 0.0, 0.5);
float f = Math.floorMod(gameTime, 40) + partialTick;
float g = height < 0 ? f : -f;
float h = Mth.frac(g * 0.2F - Mth.floor(g * 0.1F));
poseStack.pushPose();
poseStack.mulPose(Axis.YP.rotationDegrees(f * 2.25F - 45.0F));
float j = 0.0F;
float m = 0.0F;
float n = -beamRadius;
float o = 0.0F;
float p = 0.0F;
float q = -beamRadius;
float r = 0.0F;
float s = 1.0F;
float t = -1.0F + h;
float u = height * textureScale * (0.5F / beamRadius) + t;
renderPart(
poseStack,
bufferSource.getBuffer(RenderType.beaconBeam(beamLocation, false)),
color,
yOffset,
i,
0.0F,
beamRadius,
beamRadius,
0.0F,
n,
0.0F,
0.0F,
q,
0.0F,
1.0F,
u,
t
);
poseStack.popPose();
j = -glowRadius;
float k = -glowRadius;
m = -glowRadius;
n = -glowRadius;
r = 0.0F;
s = 1.0F;
t = -1.0F + h;
u = height * textureScale + t;
renderPart(
poseStack,
bufferSource.getBuffer(RenderType.beaconBeam(beamLocation, true)),
ARGB.color(32, color),
yOffset,
i,
j,
k,
glowRadius,
m,
n,
glowRadius,
glowRadius,
glowRadius,
0.0F,
1.0F,
u,
t
);
poseStack.popPose();
}
private static void renderPart(
PoseStack poseStack,
VertexConsumer consumer,
int color,
int minY,
int maxY,
float x1,
float z1,
float x2,
float z2,
float x3,
float z3,
float x4,
float z4,
float minU,
float maxU,
float minV,
float maxV
) {
PoseStack.Pose pose = poseStack.last();
renderQuad(pose, consumer, color, minY, maxY, x1, z1, x2, z2, minU, maxU, minV, maxV);
renderQuad(pose, consumer, color, minY, maxY, x4, z4, x3, z3, minU, maxU, minV, maxV);
renderQuad(pose, consumer, color, minY, maxY, x2, z2, x4, z4, minU, maxU, minV, maxV);
renderQuad(pose, consumer, color, minY, maxY, x3, z3, x1, z1, minU, maxU, minV, maxV);
}
private static void renderQuad(
PoseStack.Pose pose,
VertexConsumer consumer,
int color,
int minY,
int maxY,
float minX,
float minZ,
float maxX,
float maxZ,
float minU,
float maxU,
float minV,
float maxV
) {
addVertex(pose, consumer, color, maxY, minX, minZ, maxU, minV);
addVertex(pose, consumer, color, minY, minX, minZ, maxU, maxV);
addVertex(pose, consumer, color, minY, maxX, maxZ, minU, maxV);
addVertex(pose, consumer, color, maxY, maxX, maxZ, minU, minV);
}
private static void addVertex(PoseStack.Pose pose, VertexConsumer consumer, int color, int y, float x, float z, float u, float v) {
consumer.addVertex(pose, x, (float)y, z)
.setColor(color)
.setUv(u, v)
.setOverlay(OverlayTexture.NO_OVERLAY)
.setLight(15728880)
.setNormal(pose, 0.0F, 1.0F, 0.0F);
}
@Override
public boolean shouldRenderOffScreen(T blockEntity) {
return true;
}
@Override
public int getViewDistance() {
return Minecraft.getInstance().options.getEffectiveRenderDistance() * 16;
}
@Override
public boolean shouldRender(T blockEntity, Vec3 cameraPos) {
return Vec3.atCenterOf(blockEntity.getBlockPos()).multiply(1.0, 0.0, 1.0).closerThan(cameraPos.multiply(1.0, 0.0, 1.0), this.getViewDistance());
}
}