diff --git a/patches/net/minecraft/client/renderer/block/BlockRenderDispatcher.java.patch b/patches/net/minecraft/client/renderer/block/BlockRenderDispatcher.java.patch index c8be1c70b3..c2045b7daa 100644 --- a/patches/net/minecraft/client/renderer/block/BlockRenderDispatcher.java.patch +++ b/patches/net/minecraft/client/renderer/block/BlockRenderDispatcher.java.patch @@ -59,6 +59,14 @@ ); } } catch (Throwable throwable) { +@@ -90,6 +_,7 @@ + + public void renderLiquid(BlockPos p_234364_, BlockAndTintGetter p_234365_, VertexConsumer p_234366_, BlockState p_234367_, FluidState p_234368_) { + try { ++ if (net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions.of(p_234368_).renderFluid(p_234368_, p_234365_, p_234364_, p_234366_, p_234367_)) return; + this.liquidBlockRenderer.tesselate(p_234365_, p_234364_, p_234366_, p_234367_, p_234368_); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Tesselating liquid in world"); @@ -107,7 +_,11 @@ return this.blockModelShaper.getBlockModel(p_110911_); } @@ -101,3 +109,13 @@ } } } +@@ -140,5 +_,9 @@ + @Override + public void onResourceManagerReload(ResourceManager p_110909_) { + this.liquidBlockRenderer.setupSprites(); ++ } ++ ++ public LiquidBlockRenderer getLiquidBlockRenderer() { ++ return this.liquidBlockRenderer; + } + } diff --git a/src/main/java/net/neoforged/neoforge/client/extensions/common/IClientFluidTypeExtensions.java b/src/main/java/net/neoforged/neoforge/client/extensions/common/IClientFluidTypeExtensions.java index 592c23ea92..2b1af23c53 100644 --- a/src/main/java/net/neoforged/neoforge/client/extensions/common/IClientFluidTypeExtensions.java +++ b/src/main/java/net/neoforged/neoforge/client/extensions/common/IClientFluidTypeExtensions.java @@ -7,6 +7,7 @@ import com.mojang.blaze3d.shaders.FogShape; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; import java.util.function.Consumer; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; @@ -16,6 +17,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.BlockAndTintGetter; +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.level.material.Fluids; @@ -329,4 +331,22 @@ default ResourceLocation getFlowingTexture(FluidStack stack) { default ResourceLocation getOverlayTexture(FluidStack stack) { return this.getOverlayTexture(); } + + /** + * Called to allow rendering custom quads for a fluid during chunk meshing. You may replace the fluid + * rendering entirely, or return false to allow vanilla's fluid rendering to also run. + * + *
Note: this method will be called once for every fluid block during chunk meshing, so any logic + * here needs to be performant. + * + * @param fluidState the state of the fluid + * @param getter the getter the fluid can be obtained from + * @param pos the position of the fluid + * @param vertexConsumer the vertex consumer to emit quads to + * @param blockState the blockstate at the position of the fluid + * @return true if vanilla fluid rendering should be skipped + */ + default boolean renderFluid(FluidState fluidState, BlockAndTintGetter getter, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState) { + return false; + } } diff --git a/tests/src/main/java/net/neoforged/neoforge/oldtest/fluid/FluidTypeTest.java b/tests/src/main/java/net/neoforged/neoforge/oldtest/fluid/FluidTypeTest.java index 9543aea2bd..df6edfcff9 100644 --- a/tests/src/main/java/net/neoforged/neoforge/oldtest/fluid/FluidTypeTest.java +++ b/tests/src/main/java/net/neoforged/neoforge/oldtest/fluid/FluidTypeTest.java @@ -7,6 +7,7 @@ import com.mojang.blaze3d.shaders.FogShape; import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.VertexConsumer; import java.util.function.Consumer; import java.util.stream.Stream; import net.minecraft.client.Camera; @@ -15,6 +16,7 @@ import net.minecraft.client.renderer.FogRenderer; import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.registries.BuiltInRegistries; @@ -24,9 +26,11 @@ import net.minecraft.world.item.CreativeModeTabs; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; +import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.FlowingFluid; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; @@ -37,6 +41,7 @@ import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.neoforge.client.event.RegisterColorHandlersEvent; import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.client.model.pipeline.VertexConsumerWrapper; import net.neoforged.neoforge.common.NeoForgeMod; import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; import net.neoforged.neoforge.fluids.BaseFlowingFluid; @@ -137,6 +142,22 @@ public void modifyFogRender(Camera camera, FogRenderer.FogMode mode, float rende RenderSystem.setShaderFogEnd(farDistance); RenderSystem.setShaderFogShape(shape); } + + @Override + public boolean renderFluid(FluidState fluidState, BlockAndTintGetter getter, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState) { + // Flip RGB to BGR *only* for fluid blocks rendered at Y 100 + if (pos.getY() == 100) { + vertexConsumer = new VertexConsumerWrapper(vertexConsumer) { + @Override + public VertexConsumer color(int r, int g, int b, int a) { + return super.color(b, g, r, a); + } + }; + } + // Replace vanilla fluid rendering + Minecraft.getInstance().getBlockRenderer().getLiquidBlockRenderer().tesselate(getter, pos, vertexConsumer, blockState, fluidState); + return true; + } }); } });