Skip to content

Commit

Permalink
[1.21.1] Add a hook for blocks to suppress a neighboring fluid overlay (
Browse files Browse the repository at this point in the history
#1701)

Co-authored-by: Marc Hermans <[email protected]>
  • Loading branch information
embeddedt and marchermans authored Nov 27, 2024
1 parent e44f7ae commit d1afc78
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,42 @@
--- a/net/minecraft/client/renderer/block/LiquidBlockRenderer.java
+++ b/net/minecraft/client/renderer/block/LiquidBlockRenderer.java
@@ -38,6 +_,7 @@
@@ -38,12 +_,17 @@
this.waterIcons[0] = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(Blocks.WATER.defaultBlockState()).getParticleIcon();
this.waterIcons[1] = ModelBakery.WATER_FLOW.sprite();
this.waterOverlay = ModelBakery.WATER_OVERLAY.sprite();
+ net.neoforged.neoforge.client.textures.FluidSpriteCache.reload();
}

private static boolean isNeighborSameFluid(FluidState p_203186_, FluidState p_203187_) {
@@ -70,8 +_,9 @@
return p_203187_.getType().isSame(p_203186_.getType());
}

+ private static boolean isNeighborStateHidingOverlay(FluidState selfState, BlockState otherState, Direction neighborFace) {
+ return otherState.shouldHideAdjacentFluidFace(neighborFace, selfState);
+ }
+
private static boolean isFaceOccludedByState(BlockGetter p_110979_, Direction p_110980_, float p_110981_, BlockPos p_110982_, BlockState p_110983_) {
if (p_110983_.canOcclude()) {
VoxelShape voxelshape = Shapes.box(0.0, 0.0, 0.0, 1.0, (double)p_110981_, 1.0);
@@ -62,16 +_,26 @@
return isFaceOccludedByState(p_110960_, p_110963_.getOpposite(), 1.0F, p_110961_, p_110962_);
}

+ /** @deprecated Neo: use overload that accepts BlockState */
public static boolean shouldRenderFace(
BlockAndTintGetter p_203167_, BlockPos p_203168_, FluidState p_203169_, BlockState p_203170_, Direction p_203171_, FluidState p_203172_
) {
return !isFaceOccludedBySelf(p_203167_, p_203168_, p_203170_, p_203171_) && !isNeighborSameFluid(p_203169_, p_203172_);
}

+ public static boolean shouldRenderFace(
+ BlockAndTintGetter level, BlockPos pos, FluidState fluidState, BlockState selfState, Direction direction, BlockState otherState
+ ) {
+ return !isFaceOccludedBySelf(level, pos, selfState, direction) && !isNeighborStateHidingOverlay(fluidState, otherState, direction.getOpposite());
+ }
+
+
+
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;
Expand All @@ -20,6 +47,26 @@
float f = (float)(i >> 16 & 0xFF) / 255.0F;
float f1 = (float)(i >> 8 & 0xFF) / 255.0F;
float f2 = (float)(i & 0xFF) / 255.0F;
@@ -87,13 +_,13 @@
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_234370_, p_234371_, p_234374_, p_234373_, Direction.DOWN, fluidstate)
+ boolean flag1 = !isNeighborStateHidingOverlay(p_234374_, blockstate1, Direction.DOWN);
+ boolean flag2 = shouldRenderFace(p_234370_, p_234371_, p_234374_, p_234373_, Direction.DOWN, blockstate)
&& !isFaceOccludedByNeighbor(p_234370_, p_234371_, Direction.DOWN, 0.8888889F, blockstate);
- boolean flag3 = shouldRenderFace(p_234370_, p_234371_, p_234374_, p_234373_, Direction.NORTH, fluidstate2);
- boolean flag4 = shouldRenderFace(p_234370_, p_234371_, p_234374_, p_234373_, Direction.SOUTH, fluidstate3);
- boolean flag5 = shouldRenderFace(p_234370_, p_234371_, p_234374_, p_234373_, Direction.WEST, fluidstate4);
- boolean flag6 = shouldRenderFace(p_234370_, p_234371_, p_234374_, p_234373_, Direction.EAST, fluidstate5);
+ boolean flag3 = shouldRenderFace(p_234370_, p_234371_, p_234374_, p_234373_, Direction.NORTH, blockstate2);
+ boolean flag4 = shouldRenderFace(p_234370_, p_234371_, p_234374_, p_234373_, Direction.SOUTH, blockstate3);
+ boolean flag5 = shouldRenderFace(p_234370_, p_234371_, p_234374_, p_234373_, Direction.WEST, blockstate4);
+ boolean flag6 = shouldRenderFace(p_234370_, p_234371_, p_234374_, p_234373_, Direction.EAST, blockstate5);
if (flag1 || flag2 || flag6 || flag5 || flag3 || flag4) {
float f3 = p_234370_.getShade(Direction.DOWN, true);
float f4 = p_234370_.getShade(Direction.UP, true);
@@ -181,15 +_,15 @@
float f57 = f4 * f;
float f29 = f4 * f1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1019,4 +1019,16 @@ default BubbleColumnDirection getBubbleColumnDirection(BlockState state) {
return BubbleColumnDirection.NONE;
}
}

/**
* Determines if a fluid adjacent to the block on the given side should not be rendered.
*
* @param state the block state of the block
* @param selfFace the face of this block that the fluid is adjacent to
* @param adjacentFluid the fluid that is touching that face
* @return true if this block should cause the fluid's face to not render
*/
default boolean shouldHideAdjacentFluidFace(BlockState state, Direction selfFace, FluidState adjacentFluid) {
return state.getFluidState().getType().isSame(adjacentFluid.getType());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -755,4 +755,15 @@ default boolean isEmpty() {
default BubbleColumnDirection getBubbleColumnDirection() {
return self().getBlock().getBubbleColumnDirection(self());
}

/**
* Determines if a fluid adjacent to the block on the given side should not be rendered.
*
* @param selfFace the face of this block that the fluid is adjacent to
* @param adjacentFluid the fluid that is touching that face
* @return true if this block should cause the fluid's face to not render
*/
default boolean shouldHideAdjacentFluidFace(Direction selfFace, FluidState adjacentFluid) {
return self().getBlock().shouldHideAdjacentFluidFace(self(), selfFace, adjacentFluid);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "neotests_test_water_glass_face_removal:block/water_glass"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"block.neotests_test_water_glass_face_removal.water_glass": "Water Glass"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cube_all",
"render_type": "minecraft:cutout",
"textures": {
"all": "minecraft:block/glass"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.neoforge.debug.fluid;

import net.minecraft.client.renderer.block.LiquidBlockRenderer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.gametest.framework.GameTest;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.TransparentBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.neoforge.client.model.generators.BlockStateProvider;
import net.neoforged.testframework.DynamicTest;
import net.neoforged.testframework.annotation.ForEachTest;
import net.neoforged.testframework.annotation.TestHolder;
import net.neoforged.testframework.gametest.EmptyTemplate;
import net.neoforged.testframework.registration.RegistrationHelper;

@ForEachTest(groups = ClientFluidTests.GROUP, side = Dist.CLIENT)
public class ClientFluidTests {
public static final String GROUP = "level.fluid.client";

static class WaterGlassBlock extends TransparentBlock {
private static final Direction HIDE_DIRECTION = Direction.NORTH;

public WaterGlassBlock(Properties p_309186_) {
super(p_309186_);
}

@Override
public boolean shouldHideAdjacentFluidFace(BlockState state, Direction selfFace, FluidState adjacentFluid) {
if (selfFace == HIDE_DIRECTION) {
return adjacentFluid.getFluidType() == Fluids.WATER.getFluidType();
} else {
return super.shouldHideAdjacentFluidFace(state, selfFace, adjacentFluid);
}
}
}

@GameTest
@EmptyTemplate
@TestHolder(description = "Tests if blocks can prevent neighboring fluids from rendering against them")
static void testWaterGlassFaceRemoval(final DynamicTest test, final RegistrationHelper reg) {
final var glass = reg.blocks().registerBlock("water_glass", WaterGlassBlock::new, BlockBehaviour.Properties.ofFullCopy(Blocks.GLASS)).withLang("Water Glass").withBlockItem();
reg.provider(BlockStateProvider.class, prov -> prov.simpleBlock(glass.get(), prov.models()
.cubeAll("water_glass", ResourceLocation.withDefaultNamespace("block/glass"))
.renderType("cutout")));
final var waterPosition = new BlockPos(1, 1, 2);
final var glassDirection = WaterGlassBlock.HIDE_DIRECTION.getOpposite();
final var glassPosition = waterPosition.relative(glassDirection);
test.onGameTest(helper -> helper.startSequence()
.thenExecute(() -> helper.setBlock(glassPosition, glass.get().defaultBlockState()))
.thenExecute(() -> helper.setBlock(waterPosition, Blocks.WATER.defaultBlockState()))
// Check that the north side of the water is not rendered
.thenExecute(() -> helper.assertFalse(
LiquidBlockRenderer.shouldRenderFace(helper.getLevel(), helper.absolutePos(waterPosition),
helper.getBlockState(waterPosition).getFluidState(),
helper.getBlockState(waterPosition),
glassDirection,
helper.getBlockState(glassPosition)),
"Fluid face rendering is not skipped"))
.thenSucceed());
}
}

0 comments on commit d1afc78

Please sign in to comment.