diff --git a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandler.java b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandler.java index 5997b2a19..14e6bebc4 100644 --- a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandler.java +++ b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandler.java @@ -20,13 +20,14 @@ import org.jetbrains.annotations.Nullable; import net.minecraft.block.BlockState; import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.block.FluidRenderer; import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.SpriteAtlasTexture; import net.minecraft.fluid.FluidState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.BlockRenderView; -import net.fabricmc.fabric.impl.client.rendering.fluid.FluidRenderHandlerRegistryImpl; +import net.fabricmc.fabric.impl.client.rendering.fluid.FluidRenderingImpl; /** * Interface for handling the rendering of a FluidState. @@ -67,14 +68,13 @@ public interface FluidRenderHandler { } /** - * Tessellate your fluid. This method will be invoked before the default - * fluid renderer. By default, it will call the default fluid renderer. Call - * {@code FluidRenderHandler.super.renderFluid} if you want to render over - * the default fluid renderer. - * - * <p>Note that this method must *only* return {@code true} if at least one - * face is tessellated. If no faces are tessellated this method must return - * {@code false}. + * Tessellate your fluid. By default, this method will call the default + * fluid renderer. Call {@code FluidRenderHandler.super.renderFluid} if + * you want to render over the default fluid renderer. This is the + * intended way to render default geometry; calling + * {@link FluidRenderer#render} is not supported. When rendering default + * geometry, the current handler will be used instead of looking up + * a new one for the passed fluid state. * * @param pos The position in the world, of the fluid to render. * @param world The world the fluid is in @@ -83,7 +83,7 @@ public interface FluidRenderHandler { * @param fluidState The fluid state being rendered. */ default void renderFluid(BlockPos pos, BlockRenderView world, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState) { - ((FluidRenderHandlerRegistryImpl) FluidRenderHandlerRegistry.INSTANCE).renderFluid(pos, world, vertexConsumer, blockState, fluidState); + FluidRenderingImpl.renderDefault(this, world, pos, vertexConsumer, blockState, fluidState); } /** diff --git a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRendering.java b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRendering.java new file mode 100644 index 000000000..eea7b3280 --- /dev/null +++ b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRendering.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.client.render.fluid.v1; + +import net.minecraft.block.BlockState; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.block.FluidRenderer; +import net.minecraft.fluid.FluidState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockRenderView; + +import net.fabricmc.fabric.impl.client.rendering.fluid.FluidRenderingImpl; + +/** + * A class containing some utilities for rendering fluids. + */ +public final class FluidRendering { + private FluidRendering() { + } + + /** + * Renders a fluid using the given handler, default renderer, and context. Internally, this just invokes + * {@link FluidRenderHandler#renderFluid}, but the passed default renderer is invoked instead of the vanilla + * renderer whenever the handler requests default geometry to be rendered. + * + * @param handler the render handler to invoke {@link FluidRenderHandler#renderFluid} on + * @param world the world + * @param pos the pos + * @param vertexConsumer the vertex consumer + * @param blockState the block state + * @param fluidState the fluid state + * @param defaultRenderer the renderer to use whenever the handler requests default geometry + */ + public static void render(FluidRenderHandler handler, BlockRenderView world, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState, DefaultRenderer defaultRenderer) { + FluidRenderingImpl.render(handler, world, pos, vertexConsumer, blockState, fluidState, defaultRenderer); + } + + public interface DefaultRenderer { + /** + * Render the default geometry when it is requested by {@link FluidRenderHandler#renderFluid}. The default + * implementation invokes the vanilla renderer. Calling {@link FluidRenderer#render} directly is not supported + * but using {@code DefaultRenderer.super.render} is supported. Note that the parameter values passed to this + * call are provided by the render handler, meaning they are not necessarily the same as those provided to the + * initial rendering call. As per the documentation of {@link FluidRenderHandler#renderFluid}, a new handler + * should not be retrieved and only the passed one should be used. + * + * @param handler the handler that {@link FluidRenderHandler#renderFluid} was invoked on + * @param world the world + * @param pos the pos + * @param vertexConsumer the vertex consumer + * @param blockState the block state + * @param fluidState the fluid state + */ + default void render(FluidRenderHandler handler, BlockRenderView world, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState) { + FluidRenderingImpl.renderVanillaDefault(handler, world, pos, vertexConsumer, blockState, fluidState); + } + } +} diff --git a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/SimpleFluidRenderHandler.java b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/SimpleFluidRenderHandler.java index 47d55e085..0f28042bc 100644 --- a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/SimpleFluidRenderHandler.java +++ b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/api/client/render/fluid/v1/SimpleFluidRenderHandler.java @@ -85,7 +85,7 @@ public class SimpleFluidRenderHandler implements FluidRenderHandler { */ public SimpleFluidRenderHandler(Identifier stillTexture, Identifier flowingTexture, @Nullable Identifier overlayTexture, int tint) { this.stillTexture = Objects.requireNonNull(stillTexture, "stillTexture"); - this.flowingTexture = Objects.requireNonNull(flowingTexture, "flowingTexture");; + this.flowingTexture = Objects.requireNonNull(flowingTexture, "flowingTexture"); this.overlayTexture = overlayTexture; this.sprites = new Sprite[overlayTexture == null ? 2 : 3]; this.tint = tint; diff --git a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRendererHookContainer.java b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRenderHandlerInfo.java similarity index 63% rename from fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRendererHookContainer.java rename to fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRenderHandlerInfo.java index 759dc7e3b..10e50df98 100644 --- a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRendererHookContainer.java +++ b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRenderHandlerInfo.java @@ -16,7 +16,8 @@ package net.fabricmc.fabric.impl.client.rendering.fluid; -import net.minecraft.block.BlockState; +import org.jetbrains.annotations.Nullable; + import net.minecraft.client.texture.Sprite; import net.minecraft.fluid.FluidState; import net.minecraft.util.math.BlockPos; @@ -24,41 +25,32 @@ import net.minecraft.world.BlockRenderView; import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler; -public class FluidRendererHookContainer { - public BlockRenderView view; - public BlockPos pos; - public BlockState blockState; - public FluidState fluidState; - public FluidRenderHandler handler; +public class FluidRenderHandlerInfo { public final Sprite[] sprites = new Sprite[2]; - public Sprite overlay; + @Nullable + public FluidRenderHandler handler; public boolean hasOverlay; + public Sprite overlaySprite; - public void getSprites(BlockRenderView world, BlockPos pos, FluidState fluidState) { - if (handler != null) { - Sprite[] sprites = handler.getFluidSprites(world, pos, fluidState); + public void setup(FluidRenderHandler handler, BlockRenderView world, BlockPos pos, FluidState fluidState) { + this.handler = handler; - this.sprites[0] = sprites[0]; - this.sprites[1] = sprites[1]; + Sprite[] sprites = handler.getFluidSprites(world, pos, fluidState); - if (sprites.length > 2) { - hasOverlay = true; - overlay = sprites[2]; - } - } else { - hasOverlay = false; + this.sprites[0] = sprites[0]; + this.sprites[1] = sprites[1]; + + if (sprites.length > 2) { + hasOverlay = true; + overlaySprite = sprites[2]; } } public void clear() { - view = null; - pos = null; - blockState = null; - fluidState = null; - handler = null; sprites[0] = null; sprites[1] = null; - overlay = null; + handler = null; hasOverlay = false; + overlaySprite = null; } } diff --git a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRenderHandlerRegistryImpl.java b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRenderHandlerRegistryImpl.java index 86737d1b4..bb54b63e7 100644 --- a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRenderHandlerRegistryImpl.java +++ b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRenderHandlerRegistryImpl.java @@ -18,16 +18,16 @@ package net.fabricmc.fabric.impl.client.rendering.fluid; import java.util.IdentityHashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.jetbrains.annotations.Nullable; import net.minecraft.block.Block; -import net.minecraft.block.BlockState; import net.minecraft.block.LeavesBlock; -import net.minecraft.block.TransparentBlock; +import net.minecraft.block.TranslucentBlock; import net.minecraft.client.MinecraftClient; import net.minecraft.client.color.world.BiomeColors; -import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.block.FluidRenderer; import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.SpriteAtlasTexture; @@ -43,15 +43,16 @@ import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler; import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry; public class FluidRenderHandlerRegistryImpl implements FluidRenderHandlerRegistry { - /** - * The water color of {@link BiomeKeys#OCEAN}. - */ - private static final int DEFAULT_WATER_COLOR = 0x3f76e4; private final Map<Fluid, FluidRenderHandler> handlers = new IdentityHashMap<>(); private final Map<Fluid, FluidRenderHandler> modHandlers = new IdentityHashMap<>(); - private final Map<Block, Boolean> overlayBlocks = new IdentityHashMap<>(); + private final ConcurrentMap<Block, Boolean> overlayBlocks = new ConcurrentHashMap<>(); - private FluidRenderer fluidRenderer; + { + handlers.put(Fluids.WATER, WaterRenderHandler.INSTANCE); + handlers.put(Fluids.FLOWING_WATER, WaterRenderHandler.INSTANCE); + handlers.put(Fluids.LAVA, LavaRenderHandler.INSTANCE); + handlers.put(Fluids.FLOWING_LAVA, LavaRenderHandler.INSTANCE); + } public FluidRenderHandlerRegistryImpl() { } @@ -81,42 +82,14 @@ public class FluidRenderHandlerRegistryImpl implements FluidRenderHandlerRegistr @Override public boolean isBlockTransparent(Block block) { - return overlayBlocks.computeIfAbsent(block, k -> k instanceof TransparentBlock || k instanceof LeavesBlock); + return overlayBlocks.computeIfAbsent(block, k -> k instanceof TranslucentBlock || k instanceof LeavesBlock); } public void onFluidRendererReload(FluidRenderer renderer, Sprite[] waterSprites, Sprite[] lavaSprites, Sprite waterOverlay) { - fluidRenderer = renderer; + FluidRenderingImpl.setVanillaRenderer(renderer); - Sprite[] waterSpritesFull = {waterSprites[0], waterSprites[1], waterOverlay}; - FluidRenderHandler waterHandler = new FluidRenderHandler() { - @Override - public Sprite[] getFluidSprites(BlockRenderView view, BlockPos pos, FluidState state) { - return waterSpritesFull; - } - - @Override - public int getFluidColor(BlockRenderView view, BlockPos pos, FluidState state) { - if (view != null && pos != null) { - return BiomeColors.getWaterColor(view, pos); - } else { - return DEFAULT_WATER_COLOR; - } - } - }; - - //noinspection Convert2Lambda - FluidRenderHandler lavaHandler = new FluidRenderHandler() { - @Override - public Sprite[] getFluidSprites(BlockRenderView view, BlockPos pos, FluidState state) { - return lavaSprites; - } - }; - - handlers.put(Fluids.WATER, waterHandler); - handlers.put(Fluids.FLOWING_WATER, waterHandler); - handlers.put(Fluids.LAVA, lavaHandler); - handlers.put(Fluids.FLOWING_LAVA, lavaHandler); - handlers.putAll(modHandlers); + WaterRenderHandler.INSTANCE.updateSprites(waterSprites, waterOverlay); + LavaRenderHandler.INSTANCE.updateSprites(lavaSprites); SpriteAtlasTexture texture = MinecraftClient.getInstance() .getBakedModelManager() @@ -127,7 +100,49 @@ public class FluidRenderHandlerRegistryImpl implements FluidRenderHandlerRegistr } } - public void renderFluid(BlockPos pos, BlockRenderView world, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState) { - fluidRenderer.render(world, pos, vertexConsumer, blockState, fluidState); + private static class WaterRenderHandler implements FluidRenderHandler { + public static final WaterRenderHandler INSTANCE = new WaterRenderHandler(); + + /** + * The water color of {@link BiomeKeys#OCEAN}. + */ + private static final int DEFAULT_WATER_COLOR = 0x3f76e4; + + private final Sprite[] sprites = new Sprite[3]; + + @Override + public Sprite[] getFluidSprites(@Nullable BlockRenderView view, @Nullable BlockPos pos, FluidState state) { + return sprites; + } + + @Override + public int getFluidColor(@Nullable BlockRenderView view, @Nullable BlockPos pos, FluidState state) { + if (view != null && pos != null) { + return BiomeColors.getWaterColor(view, pos); + } else { + return DEFAULT_WATER_COLOR; + } + } + + public void updateSprites(Sprite[] waterSprites, Sprite waterOverlay) { + sprites[0] = waterSprites[0]; + sprites[1] = waterSprites[1]; + sprites[2] = waterOverlay; + } + } + + private static class LavaRenderHandler implements FluidRenderHandler { + public static final LavaRenderHandler INSTANCE = new LavaRenderHandler(); + + private Sprite[] sprites; + + @Override + public Sprite[] getFluidSprites(@Nullable BlockRenderView view, @Nullable BlockPos pos, FluidState state) { + return sprites; + } + + public void updateSprites(Sprite[] lavaSprites) { + sprites = lavaSprites; + } } } diff --git a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRenderingImpl.java b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRenderingImpl.java new file mode 100644 index 000000000..9c7faaa2a --- /dev/null +++ b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/fluid/FluidRenderingImpl.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.client.rendering.fluid; + +import net.minecraft.block.BlockState; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.block.FluidRenderer; +import net.minecraft.fluid.FluidState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockRenderView; + +import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler; +import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRendering; + +public class FluidRenderingImpl { + private static final ThreadLocal<FluidRendering.DefaultRenderer> CURRENT_DEFAULT_RENDERER = new ThreadLocal<>(); + private static final ThreadLocal<FluidRenderHandlerInfo> CURRENT_INFO = ThreadLocal.withInitial(FluidRenderHandlerInfo::new); + private static FluidRenderer vanillaRenderer; + + // Only invoked manually from FluidRendering#render + public static void render(FluidRenderHandler handler, BlockRenderView world, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState, FluidRendering.DefaultRenderer defaultRenderer) { + CURRENT_DEFAULT_RENDERER.set(defaultRenderer); + + try { + handler.renderFluid(pos, world, vertexConsumer, blockState, fluidState); + } finally { + CURRENT_DEFAULT_RENDERER.remove(); + } + } + + // Only invoked when FluidRenderHandler#renderFluid calls super + public static void renderDefault(FluidRenderHandler handler, BlockRenderView world, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState) { + FluidRendering.DefaultRenderer renderer = CURRENT_DEFAULT_RENDERER.get(); + + if (renderer != null) { + renderer.render(handler, world, pos, vertexConsumer, blockState, fluidState); + } else { + renderVanillaDefault(handler, world, pos, vertexConsumer, blockState, fluidState); + } + } + + // Invoked when FluidRenderHandler#renderFluid is called directly without using FluidRendering#render (such as + // from vanilla FluidRenderer#render via mixin) or from the default implementation of DefaultRenderer#render + public static void renderVanillaDefault(FluidRenderHandler handler, BlockRenderView world, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState) { + FluidRenderHandlerInfo info = CURRENT_INFO.get(); + info.setup(handler, world, pos, fluidState); + + try { + vanillaRenderer.render(world, pos, vertexConsumer, blockState, fluidState); + } finally { + info.clear(); + } + } + + public static void setVanillaRenderer(FluidRenderer vanillaRenderer) { + FluidRenderingImpl.vanillaRenderer = vanillaRenderer; + } + + public static FluidRenderHandlerInfo getCurrentInfo() { + return CURRENT_INFO.get(); + } +} diff --git a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/fluid/FluidRendererMixin.java b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/fluid/FluidRendererMixin.java index 81735984e..89fc45490 100644 --- a/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/fluid/FluidRendererMixin.java +++ b/fabric-rendering-fluids-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/fluid/FluidRendererMixin.java @@ -20,7 +20,6 @@ import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; @@ -38,8 +37,9 @@ import net.minecraft.world.BlockRenderView; import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler; import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry; +import net.fabricmc.fabric.impl.client.rendering.fluid.FluidRenderHandlerInfo; import net.fabricmc.fabric.impl.client.rendering.fluid.FluidRenderHandlerRegistryImpl; -import net.fabricmc.fabric.impl.client.rendering.fluid.FluidRendererHookContainer; +import net.fabricmc.fabric.impl.client.rendering.fluid.FluidRenderingImpl; @Mixin(FluidRenderer.class) public class FluidRendererMixin { @@ -52,8 +52,6 @@ public class FluidRendererMixin { @Shadow private Sprite waterOverlaySprite; - private final ThreadLocal<FluidRendererHookContainer> fabric_renderHandler = ThreadLocal.withInitial(FluidRendererHookContainer::new); - private final ThreadLocal<Boolean> fabric_customRendering = ThreadLocal.withInitial(() -> false); private final ThreadLocal<Block> fabric_neighborBlock = new ThreadLocal<>(); @Inject(at = @At("RETURN"), method = "onResourceReload") @@ -63,78 +61,50 @@ public class FluidRendererMixin { } @Inject(at = @At("HEAD"), method = "render", cancellable = true) - public void tesselate(BlockRenderView view, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState, CallbackInfo info) { - if (!fabric_customRendering.get()) { - // Prevent recursively looking up custom fluid renderers when default behavior is being invoked - try { - fabric_customRendering.set(true); - tessellateViaHandler(view, pos, vertexConsumer, blockState, fluidState, info); - } finally { - fabric_customRendering.set(false); + public void onHeadRender(BlockRenderView view, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState, CallbackInfo ci) { + FluidRenderHandlerInfo info = FluidRenderingImpl.getCurrentInfo(); + + if (info.handler == null) { + FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(fluidState.getFluid()); + + if (handler != null) { + handler.renderFluid(pos, view, vertexConsumer, blockState, fluidState); + ci.cancel(); } } - - if (info.isCancelled()) { - return; - } - - FluidRendererHookContainer ctr = fabric_renderHandler.get(); - ctr.getSprites(view, pos, fluidState); - } - - @Unique - private void tessellateViaHandler(BlockRenderView view, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState, CallbackInfo info) { - FluidRendererHookContainer ctr = fabric_renderHandler.get(); - FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(fluidState.getFluid()); - - ctr.view = view; - ctr.pos = pos; - ctr.blockState = blockState; - ctr.fluidState = fluidState; - ctr.handler = handler; - - if (handler != null) { - handler.renderFluid(pos, view, vertexConsumer, blockState, fluidState); - info.cancel(); - } - } - - @Inject(at = @At("RETURN"), method = "render") - public void tesselateReturn(BlockRenderView world, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState, CallbackInfo ci) { - fabric_renderHandler.get().clear(); } @ModifyVariable(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/FluidRenderer;isSameFluid(Lnet/minecraft/fluid/FluidState;Lnet/minecraft/fluid/FluidState;)Z"), method = "render", ordinal = 0) public boolean modLavaCheck(boolean chk) { // First boolean local is set by vanilla according to 'matches lava' // but uses the negation consistent with 'matches water' - // for determining if special water sprite should be used behind glass. + // for determining if overlay water sprite should be used behind glass. // Has other uses but those are overridden by this mixin and have - // already happened by the time this hook is called + // already happened by the time this hook is called. - // If this fluid has an overlay texture, set this boolean too false - final FluidRendererHookContainer ctr = fabric_renderHandler.get(); - return !ctr.hasOverlay; + // If this fluid has an overlay texture, set this boolean to false. + final FluidRenderHandlerInfo info = FluidRenderingImpl.getCurrentInfo(); + return info.handler != null ? !info.hasOverlay : chk; } @ModifyVariable(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/FluidRenderer;isSameFluid(Lnet/minecraft/fluid/FluidState;Lnet/minecraft/fluid/FluidState;)Z"), method = "render", ordinal = 0) public Sprite[] modSpriteArray(Sprite[] chk) { - FluidRendererHookContainer ctr = fabric_renderHandler.get(); - return ctr.handler != null ? ctr.sprites : chk; + FluidRenderHandlerInfo info = FluidRenderingImpl.getCurrentInfo(); + return info.handler != null ? info.sprites : chk; + } + + @ModifyVariable(at = @At(value = "CONSTANT", args = "intValue=16", ordinal = 0, shift = At.Shift.BEFORE), method = "render", ordinal = 0) + public int modTintColor(int chk, BlockRenderView world, BlockPos pos, VertexConsumer vertexConsumer, BlockState blockState, FluidState fluidState) { + FluidRenderHandlerInfo info = FluidRenderingImpl.getCurrentInfo(); + return info.handler != null ? info.handler.getFluidColor(world, pos, fluidState) : chk; } // Redirect redirects all 'waterOverlaySprite' gets in 'render' to this method, this is correct @Redirect(at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/client/render/block/FluidRenderer;waterOverlaySprite:Lnet/minecraft/client/texture/Sprite;"), method = "render") public Sprite modWaterOverlaySprite(FluidRenderer self) { - FluidRendererHookContainer ctr = fabric_renderHandler.get(); - return ctr.handler != null && ctr.hasOverlay ? ctr.overlay : waterOverlaySprite; - } - - @ModifyVariable(at = @At(value = "CONSTANT", args = "intValue=16", ordinal = 0, shift = At.Shift.BEFORE), method = "render", ordinal = 0) - public int modTintColor(int chk) { - FluidRendererHookContainer ctr = fabric_renderHandler.get(); - return ctr.handler != null ? ctr.handler.getFluidColor(ctr.view, ctr.pos, ctr.fluidState) : chk; + FluidRenderHandlerInfo info = FluidRenderingImpl.getCurrentInfo(); + return info.handler != null && info.hasOverlay ? info.overlaySprite : waterOverlaySprite; } @Redirect(at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;getBlock()Lnet/minecraft/block/Block;"), method = "render") @@ -152,8 +122,8 @@ public class FluidRendererMixin { Block block = fabric_neighborBlock.get(); if (FluidRenderHandlerRegistry.INSTANCE.isBlockTransparent(block)) { - FluidRendererHookContainer ctr = fabric_renderHandler.get(); - return ctr.handler != null && ctr.hasOverlay ? ctr.overlay : waterOverlaySprite; + FluidRenderHandlerInfo info = FluidRenderingImpl.getCurrentInfo(); + return info.handler != null && info.hasOverlay ? info.overlaySprite : waterOverlaySprite; } return chk; diff --git a/fabric-rendering-fluids-v1/src/testmodClient/java/net/fabricmc/fabric/test/client/rendering/fluid/CustomizedFluidRenderer.java b/fabric-rendering-fluids-v1/src/testmodClient/java/net/fabricmc/fabric/test/client/rendering/fluid/CustomizedFluidRenderer.java index fea521b6a..0a57d5cb0 100644 --- a/fabric-rendering-fluids-v1/src/testmodClient/java/net/fabricmc/fabric/test/client/rendering/fluid/CustomizedFluidRenderer.java +++ b/fabric-rendering-fluids-v1/src/testmodClient/java/net/fabricmc/fabric/test/client/rendering/fluid/CustomizedFluidRenderer.java @@ -36,8 +36,8 @@ public class CustomizedFluidRenderer extends SimpleFluidRenderHandler { int light = getLight(world, pos); float u1 = sprites[2].getFrameU(0); float v1 = sprites[2].getFrameV(0); - float u2 = sprites[2].getFrameU(16); - float v2 = sprites[2].getFrameV(16 * fluidState.getHeight(world, pos)); + float u2 = sprites[2].getFrameU(1); + float v2 = sprites[2].getFrameV(fluidState.getHeight(world, pos)); float x1 = (pos.getX() & 15) + 0.1f; float y1 = pos.getY() & 15;