Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.21.1] Add a hook for blocks to suppress a neighboring fluid overlay #1701

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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());
}
}