Code/net/minecraft/client/renderer/block/LiquidBlockRenderer.java

365 lines
18 KiB
Java
Raw Permalink Normal View History

2025-07-01 06:20:03 +00:00
package net.minecraft.client.renderer.block;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.Mth;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.HalfTransparentBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class LiquidBlockRenderer {
private static final float MAX_FLUID_HEIGHT = 0.8888889F;
private final TextureAtlasSprite[] lavaIcons = new TextureAtlasSprite[2];
private final TextureAtlasSprite[] waterIcons = new TextureAtlasSprite[2];
private TextureAtlasSprite waterOverlay;
protected void setupSprites() {
this.lavaIcons[0] = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(Blocks.LAVA.defaultBlockState()).particleIcon();
this.lavaIcons[1] = ModelBakery.LAVA_FLOW.sprite();
this.waterIcons[0] = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(Blocks.WATER.defaultBlockState()).particleIcon();
this.waterIcons[1] = ModelBakery.WATER_FLOW.sprite();
this.waterOverlay = ModelBakery.WATER_OVERLAY.sprite();
}
private static boolean isNeighborSameFluid(FluidState p_203186_, FluidState p_203187_) {
return p_203187_.getType().isSame(p_203186_.getType());
}
private static boolean isFaceOccludedByState(Direction p_110980_, float p_110981_, BlockState p_110983_) {
VoxelShape voxelshape = p_110983_.getFaceOcclusionShape(p_110980_.getOpposite());
if (voxelshape == Shapes.empty()) {
return false;
} else if (voxelshape == Shapes.block()) {
boolean flag = p_110981_ == 1.0F;
return p_110980_ != Direction.UP || flag;
} else {
VoxelShape voxelshape1 = Shapes.box(0.0, 0.0, 0.0, 1.0, p_110981_, 1.0);
return Shapes.blockOccludes(voxelshape1, voxelshape, p_110980_);
}
}
private static boolean isFaceOccludedByNeighbor(Direction p_203182_, float p_203183_, BlockState p_203184_) {
return isFaceOccludedByState(p_203182_, p_203183_, p_203184_);
}
private static boolean isFaceOccludedBySelf(BlockState p_110962_, Direction p_110963_) {
return isFaceOccludedByState(p_110963_.getOpposite(), 1.0F, p_110962_);
}
public static boolean shouldRenderFace(FluidState p_203169_, BlockState p_203170_, Direction p_203171_, FluidState p_203172_) {
return !isFaceOccludedBySelf(p_203170_, p_203171_) && !isNeighborSameFluid(p_203169_, p_203172_);
}
public void tesselate(BlockAndTintGetter p_234370_, BlockPos p_234371_, VertexConsumer p_234372_, BlockState p_234373_, FluidState p_234374_) {
boolean flag = p_234374_.is(FluidTags.LAVA);
TextureAtlasSprite[] atextureatlassprite = flag ? this.lavaIcons : this.waterIcons;
int i = flag ? 16777215 : BiomeColors.getAverageWaterColor(p_234370_, p_234371_);
float f = (i >> 16 & 0xFF) / 255.0F;
float f1 = (i >> 8 & 0xFF) / 255.0F;
float f2 = (i & 0xFF) / 255.0F;
BlockState blockstate = p_234370_.getBlockState(p_234371_.relative(Direction.DOWN));
FluidState fluidstate = blockstate.getFluidState();
BlockState blockstate1 = p_234370_.getBlockState(p_234371_.relative(Direction.UP));
FluidState fluidstate1 = blockstate1.getFluidState();
BlockState blockstate2 = p_234370_.getBlockState(p_234371_.relative(Direction.NORTH));
FluidState fluidstate2 = blockstate2.getFluidState();
BlockState blockstate3 = p_234370_.getBlockState(p_234371_.relative(Direction.SOUTH));
FluidState fluidstate3 = blockstate3.getFluidState();
BlockState blockstate4 = p_234370_.getBlockState(p_234371_.relative(Direction.WEST));
FluidState fluidstate4 = blockstate4.getFluidState();
BlockState blockstate5 = p_234370_.getBlockState(p_234371_.relative(Direction.EAST));
FluidState fluidstate5 = blockstate5.getFluidState();
boolean flag1 = !isNeighborSameFluid(p_234374_, fluidstate1);
boolean flag2 = shouldRenderFace(p_234374_, p_234373_, Direction.DOWN, fluidstate) && !isFaceOccludedByNeighbor(Direction.DOWN, 0.8888889F, blockstate);
boolean flag3 = shouldRenderFace(p_234374_, p_234373_, Direction.NORTH, fluidstate2);
boolean flag4 = shouldRenderFace(p_234374_, p_234373_, Direction.SOUTH, fluidstate3);
boolean flag5 = shouldRenderFace(p_234374_, p_234373_, Direction.WEST, fluidstate4);
boolean flag6 = shouldRenderFace(p_234374_, p_234373_, Direction.EAST, fluidstate5);
if (flag1 || flag2 || flag6 || flag5 || flag3 || flag4) {
float f3 = p_234370_.getShade(Direction.DOWN, true);
float f4 = p_234370_.getShade(Direction.UP, true);
float f5 = p_234370_.getShade(Direction.NORTH, true);
float f6 = p_234370_.getShade(Direction.WEST, true);
Fluid fluid = p_234374_.getType();
float f11 = this.getHeight(p_234370_, fluid, p_234371_, p_234373_, p_234374_);
float f7;
float f8;
float f9;
float f10;
if (f11 >= 1.0F) {
f7 = 1.0F;
f8 = 1.0F;
f9 = 1.0F;
f10 = 1.0F;
} else {
float f12 = this.getHeight(p_234370_, fluid, p_234371_.north(), blockstate2, fluidstate2);
float f13 = this.getHeight(p_234370_, fluid, p_234371_.south(), blockstate3, fluidstate3);
float f14 = this.getHeight(p_234370_, fluid, p_234371_.east(), blockstate5, fluidstate5);
float f15 = this.getHeight(p_234370_, fluid, p_234371_.west(), blockstate4, fluidstate4);
f7 = this.calculateAverageHeight(p_234370_, fluid, f11, f12, f14, p_234371_.relative(Direction.NORTH).relative(Direction.EAST));
f8 = this.calculateAverageHeight(p_234370_, fluid, f11, f12, f15, p_234371_.relative(Direction.NORTH).relative(Direction.WEST));
f9 = this.calculateAverageHeight(p_234370_, fluid, f11, f13, f14, p_234371_.relative(Direction.SOUTH).relative(Direction.EAST));
f10 = this.calculateAverageHeight(p_234370_, fluid, f11, f13, f15, p_234371_.relative(Direction.SOUTH).relative(Direction.WEST));
}
float f36 = p_234371_.getX() & 15;
float f37 = p_234371_.getY() & 15;
float f38 = p_234371_.getZ() & 15;
float f39 = 0.001F;
float f16 = flag2 ? 0.001F : 0.0F;
if (flag1 && !isFaceOccludedByNeighbor(Direction.UP, Math.min(Math.min(f8, f10), Math.min(f9, f7)), blockstate1)) {
f8 -= 0.001F;
f10 -= 0.001F;
f9 -= 0.001F;
f7 -= 0.001F;
Vec3 vec3 = p_234374_.getFlow(p_234370_, p_234371_);
float f17;
float f18;
float f19;
float f20;
float f21;
float f22;
float f23;
float f24;
if (vec3.x == 0.0 && vec3.z == 0.0) {
TextureAtlasSprite textureatlassprite1 = atextureatlassprite[0];
f17 = textureatlassprite1.getU(0.0F);
f21 = textureatlassprite1.getV(0.0F);
f18 = f17;
f22 = textureatlassprite1.getV(1.0F);
f19 = textureatlassprite1.getU(1.0F);
f23 = f22;
f20 = f19;
f24 = f21;
} else {
TextureAtlasSprite textureatlassprite = atextureatlassprite[1];
float f25 = (float)Mth.atan2(vec3.z, vec3.x) - (float) (Math.PI / 2);
float f26 = Mth.sin(f25) * 0.25F;
float f27 = Mth.cos(f25) * 0.25F;
float f28 = 0.5F;
f17 = textureatlassprite.getU(0.5F + (-f27 - f26));
f21 = textureatlassprite.getV(0.5F + (-f27 + f26));
f18 = textureatlassprite.getU(0.5F + (-f27 + f26));
f22 = textureatlassprite.getV(0.5F + (f27 + f26));
f19 = textureatlassprite.getU(0.5F + (f27 + f26));
f23 = textureatlassprite.getV(0.5F + (f27 - f26));
f20 = textureatlassprite.getU(0.5F + (f27 - f26));
f24 = textureatlassprite.getV(0.5F + (-f27 - f26));
}
float f53 = (f17 + f18 + f19 + f20) / 4.0F;
float f54 = (f21 + f22 + f23 + f24) / 4.0F;
float f55 = atextureatlassprite[0].uvShrinkRatio();
f17 = Mth.lerp(f55, f17, f53);
f18 = Mth.lerp(f55, f18, f53);
f19 = Mth.lerp(f55, f19, f53);
f20 = Mth.lerp(f55, f20, f53);
f21 = Mth.lerp(f55, f21, f54);
f22 = Mth.lerp(f55, f22, f54);
f23 = Mth.lerp(f55, f23, f54);
f24 = Mth.lerp(f55, f24, f54);
int l = this.getLightColor(p_234370_, p_234371_);
float f57 = f4 * f;
float f29 = f4 * f1;
float f30 = f4 * f2;
this.vertex(p_234372_, f36 + 0.0F, f37 + f8, f38 + 0.0F, f57, f29, f30, f17, f21, l);
this.vertex(p_234372_, f36 + 0.0F, f37 + f10, f38 + 1.0F, f57, f29, f30, f18, f22, l);
this.vertex(p_234372_, f36 + 1.0F, f37 + f9, f38 + 1.0F, f57, f29, f30, f19, f23, l);
this.vertex(p_234372_, f36 + 1.0F, f37 + f7, f38 + 0.0F, f57, f29, f30, f20, f24, l);
if (p_234374_.shouldRenderBackwardUpFace(p_234370_, p_234371_.above())) {
this.vertex(p_234372_, f36 + 0.0F, f37 + f8, f38 + 0.0F, f57, f29, f30, f17, f21, l);
this.vertex(p_234372_, f36 + 1.0F, f37 + f7, f38 + 0.0F, f57, f29, f30, f20, f24, l);
this.vertex(p_234372_, f36 + 1.0F, f37 + f9, f38 + 1.0F, f57, f29, f30, f19, f23, l);
this.vertex(p_234372_, f36 + 0.0F, f37 + f10, f38 + 1.0F, f57, f29, f30, f18, f22, l);
}
}
if (flag2) {
float f40 = atextureatlassprite[0].getU0();
float f41 = atextureatlassprite[0].getU1();
float f42 = atextureatlassprite[0].getV0();
float f43 = atextureatlassprite[0].getV1();
int k = this.getLightColor(p_234370_, p_234371_.below());
float f46 = f3 * f;
float f48 = f3 * f1;
float f50 = f3 * f2;
this.vertex(p_234372_, f36, f37 + f16, f38 + 1.0F, f46, f48, f50, f40, f43, k);
this.vertex(p_234372_, f36, f37 + f16, f38, f46, f48, f50, f40, f42, k);
this.vertex(p_234372_, f36 + 1.0F, f37 + f16, f38, f46, f48, f50, f41, f42, k);
this.vertex(p_234372_, f36 + 1.0F, f37 + f16, f38 + 1.0F, f46, f48, f50, f41, f43, k);
}
int j = this.getLightColor(p_234370_, p_234371_);
for (Direction direction : Direction.Plane.HORIZONTAL) {
float f44;
float f45;
float f47;
float f49;
float f51;
float f52;
boolean flag7;
switch (direction) {
case NORTH:
f44 = f8;
f45 = f7;
f47 = f36;
f51 = f36 + 1.0F;
f49 = f38 + 0.001F;
f52 = f38 + 0.001F;
flag7 = flag3;
break;
case SOUTH:
f44 = f9;
f45 = f10;
f47 = f36 + 1.0F;
f51 = f36;
f49 = f38 + 1.0F - 0.001F;
f52 = f38 + 1.0F - 0.001F;
flag7 = flag4;
break;
case WEST:
f44 = f10;
f45 = f8;
f47 = f36 + 0.001F;
f51 = f36 + 0.001F;
f49 = f38 + 1.0F;
f52 = f38;
flag7 = flag5;
break;
default:
f44 = f7;
f45 = f9;
f47 = f36 + 1.0F - 0.001F;
f51 = f36 + 1.0F - 0.001F;
f49 = f38;
f52 = f38 + 1.0F;
flag7 = flag6;
}
if (flag7 && !isFaceOccludedByNeighbor(direction, Math.max(f44, f45), p_234370_.getBlockState(p_234371_.relative(direction)))) {
BlockPos blockpos = p_234371_.relative(direction);
TextureAtlasSprite textureatlassprite2 = atextureatlassprite[1];
if (!flag) {
Block block = p_234370_.getBlockState(blockpos).getBlock();
if (block instanceof HalfTransparentBlock || block instanceof LeavesBlock) {
textureatlassprite2 = this.waterOverlay;
}
}
float f56 = textureatlassprite2.getU(0.0F);
float f58 = textureatlassprite2.getU(0.5F);
float f59 = textureatlassprite2.getV((1.0F - f44) * 0.5F);
float f60 = textureatlassprite2.getV((1.0F - f45) * 0.5F);
float f31 = textureatlassprite2.getV(0.5F);
float f32 = direction.getAxis() == Direction.Axis.Z ? f5 : f6;
float f33 = f4 * f32 * f;
float f34 = f4 * f32 * f1;
float f35 = f4 * f32 * f2;
this.vertex(p_234372_, f47, f37 + f44, f49, f33, f34, f35, f56, f59, j);
this.vertex(p_234372_, f51, f37 + f45, f52, f33, f34, f35, f58, f60, j);
this.vertex(p_234372_, f51, f37 + f16, f52, f33, f34, f35, f58, f31, j);
this.vertex(p_234372_, f47, f37 + f16, f49, f33, f34, f35, f56, f31, j);
if (textureatlassprite2 != this.waterOverlay) {
this.vertex(p_234372_, f47, f37 + f16, f49, f33, f34, f35, f56, f31, j);
this.vertex(p_234372_, f51, f37 + f16, f52, f33, f34, f35, f58, f31, j);
this.vertex(p_234372_, f51, f37 + f45, f52, f33, f34, f35, f58, f60, j);
this.vertex(p_234372_, f47, f37 + f44, f49, f33, f34, f35, f56, f59, j);
}
}
}
}
}
private float calculateAverageHeight(BlockAndTintGetter p_203150_, Fluid p_203151_, float p_203152_, float p_203153_, float p_203154_, BlockPos p_203155_) {
if (!(p_203154_ >= 1.0F) && !(p_203153_ >= 1.0F)) {
float[] afloat = new float[2];
if (p_203154_ > 0.0F || p_203153_ > 0.0F) {
float f = this.getHeight(p_203150_, p_203151_, p_203155_);
if (f >= 1.0F) {
return 1.0F;
}
this.addWeightedHeight(afloat, f);
}
this.addWeightedHeight(afloat, p_203152_);
this.addWeightedHeight(afloat, p_203154_);
this.addWeightedHeight(afloat, p_203153_);
return afloat[0] / afloat[1];
} else {
return 1.0F;
}
}
private void addWeightedHeight(float[] p_203189_, float p_203190_) {
if (p_203190_ >= 0.8F) {
p_203189_[0] += p_203190_ * 10.0F;
p_203189_[1] += 10.0F;
} else if (p_203190_ >= 0.0F) {
p_203189_[0] += p_203190_;
p_203189_[1]++;
}
}
private float getHeight(BlockAndTintGetter p_203157_, Fluid p_203158_, BlockPos p_203159_) {
BlockState blockstate = p_203157_.getBlockState(p_203159_);
return this.getHeight(p_203157_, p_203158_, p_203159_, blockstate, blockstate.getFluidState());
}
private float getHeight(BlockAndTintGetter p_203161_, Fluid p_203162_, BlockPos p_203163_, BlockState p_203164_, FluidState p_203165_) {
if (p_203162_.isSame(p_203165_.getType())) {
BlockState blockstate = p_203161_.getBlockState(p_203163_.above());
return p_203162_.isSame(blockstate.getFluidState().getType()) ? 1.0F : p_203165_.getOwnHeight();
} else {
return !p_203164_.isSolid() ? 0.0F : -1.0F;
}
}
private void vertex(
VertexConsumer p_110985_,
float p_110989_,
float p_110990_,
float p_110991_,
float p_110992_,
float p_110993_,
float p_343128_,
float p_344448_,
float p_344284_,
int p_110994_
) {
p_110985_.addVertex(p_110989_, p_110990_, p_110991_)
.setColor(p_110992_, p_110993_, p_343128_, 1.0F)
.setUv(p_344448_, p_344284_)
.setLight(p_110994_)
.setNormal(0.0F, 1.0F, 0.0F);
}
private int getLightColor(BlockAndTintGetter p_110946_, BlockPos p_110947_) {
int i = LevelRenderer.getLightColor(p_110946_, p_110947_);
int j = LevelRenderer.getLightColor(p_110946_, p_110947_.above());
int k = i & 0xFF;
int l = j & 0xFF;
int i1 = i >> 16 & 0xFF;
int j1 = j >> 16 & 0xFF;
return (k > l ? k : l) | (i1 > j1 ? i1 : j1) << 16;
}
}