mirror of
https://github.com/FabricMC/fabric.git
synced 2025-04-12 06:54:27 -04:00
Custom fluid renderers and enhanced vanilla fluid renderer customization (#1687)
* Implement custom fluid rendering * Move custom renderers in FluidRenderer mixin and add overlay sprite support to FluidRenderHandlers * Add vanilla-like fluid renderer. Maybe very unnecessary, might remove. * Optimize imports * Allow custom fluid renderers to call the default renderer. Re-add DEFAULT. * Add interface to implement by blocks that enforces overlay texture on fluids * Some comments * Simplify API and remove DefaultLikeFluidRenderer * Make simple renderer overlay texture nullable Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com> * Expand test mod * Checkstyle and licenses * Easy shortcut for custom colored vanilla water fluids * Easy way to register a renderer for two (still+flowing) fluids * Update fabric-rendering-fluids-v1/src/main/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandlerRegistry.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> * Update fabric-rendering-fluids-v1/src/main/java/net/fabricmc/fabric/mixin/client/rendering/fluid/MixinFluidRenderer.java Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com> Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com> Co-authored-by: modmuss50 <modmuss50@gmail.com> Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>
This commit is contained in:
parent
d4df60101d
commit
d77a0a3a6e
21 changed files with 1234 additions and 30 deletions
fabric-rendering-fluids-v1
build.gradle
src
main
java/net/fabricmc/fabric
api/client/render/fluid/v1
impl/client/rendering/fluid
mixin/client/rendering/fluid
resources
testmod
java/net/fabricmc/fabric/test/client/rendering/fluid
CustomFluid.javaCustomizedFluidRenderer.javaFabricFluidRenderingTestMod.javaFabricFluidRenderingTestModClient.javaNoOverlayFluid.javaOverlayFluid.javaTestFluids.javaUnregisteredFluid.java
resources
assets/fabric-rendering-fluids-v1-testmod/textures/block
fabric.mod.json
|
@ -2,5 +2,10 @@ archivesBaseName = "fabric-rendering-fluids-v1"
|
|||
version = getSubprojectVersion(project, "0.1.14")
|
||||
|
||||
moduleDependencies(project, [
|
||||
'fabric-api-base'
|
||||
'fabric-api-base',
|
||||
'fabric-textures-v0'
|
||||
])
|
||||
|
||||
dependencies {
|
||||
testmodImplementation project(path: ':fabric-textures-v0', configuration: 'dev')
|
||||
}
|
||||
|
|
|
@ -18,27 +18,35 @@ package net.fabricmc.fabric.api.client.render.fluid.v1;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Interface for handling the rendering of a FluidState.
|
||||
*/
|
||||
public interface FluidRenderHandler {
|
||||
/**
|
||||
* Get the sprites for a fluid being rendered at a given position.
|
||||
* For optimal performance, the sprites should be loaded as part of a
|
||||
* resource reload and *not* looked up every time the method is called!
|
||||
* Get the sprites for a fluid being rendered at a given position. For
|
||||
* optimal performance, the sprites should be loaded as part of a resource
|
||||
* reload and *not* looked up every time the method is called! You likely
|
||||
* want to override {@link #reloadTextures} to reload your fluid sprites.
|
||||
*
|
||||
* <p>The "fabric-textures" module contains sprite rendering facilities, which may come in handy here.
|
||||
* <p>The "fabric-textures" module contains sprite rendering facilities,
|
||||
* which may come in handy here.
|
||||
*
|
||||
* @param view The world view pertaining to the fluid. May be null!
|
||||
* @param pos The position of the fluid in the world. May be null!
|
||||
* @param view The world view pertaining to the fluid. May be null!
|
||||
* @param pos The position of the fluid in the world. May be null!
|
||||
* @param state The current state of the fluid.
|
||||
* @return An array of size two: the first entry contains the "still" sprite,
|
||||
* while the second entry contains the "flowing" sprite.
|
||||
* @return An array of size two or more: the first entry contains the
|
||||
* "still" sprite, while the second entry contains the "flowing" sprite. If
|
||||
* it contains a third sprite, that sprite is used as overlay behind glass
|
||||
* and leaves.
|
||||
*/
|
||||
Sprite[] getFluidSprites(@Nullable BlockRenderView view, @Nullable BlockPos pos, FluidState state);
|
||||
|
||||
|
@ -48,12 +56,46 @@ public interface FluidRenderHandler {
|
|||
* <p>Note: As of right now, our hook cannot handle setting a custom alpha
|
||||
* tint here - as such, it must be contained in the texture itself!
|
||||
*
|
||||
* @param view The world view pertaining to the fluid. May be null!
|
||||
* @param pos The position of the fluid in the world. May be null!
|
||||
* @param view The world view pertaining to the fluid. May be null!
|
||||
* @param pos The position of the fluid in the world. May be null!
|
||||
* @param state The current state of the fluid.
|
||||
* @return The tint color of the fluid.
|
||||
*/
|
||||
default int getFluidColor(@Nullable BlockRenderView view, @Nullable BlockPos pos, FluidState state) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
*
|
||||
* @param pos The position in the world, of the fluid to render.
|
||||
* @param world The world the fluid is in
|
||||
* @param vertexConsumer The vertex consumer to tessellate the fluid in.
|
||||
* @param state The fluid state being rendered.
|
||||
* @return Whether anything is tessellated.
|
||||
*/
|
||||
default boolean renderFluid(BlockPos pos, BlockRenderView world, VertexConsumer vertexConsumer, FluidState state) {
|
||||
return FluidRenderHandlerRegistryImpl.INSTANCE.renderFluid(pos, world, vertexConsumer, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up your Fluid's sprites from the texture atlas. Called when the
|
||||
* fluid renderer reloads its textures. This is a convenient way of
|
||||
* reloading and does not require an advanced resource manager reload
|
||||
* listener.
|
||||
*
|
||||
* <p>The "fabric-textures" module contains sprite rendering facilities,
|
||||
* which may come in handy here.
|
||||
*
|
||||
* @param textureAtlas The blocks texture atlas, provided for convenience.
|
||||
*/
|
||||
default void reloadTextures(SpriteAtlasTexture textureAtlas) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package net.fabricmc.fabric.api.client.render.fluid.v1;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.TransparentBlock;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
|
||||
import net.fabricmc.fabric.impl.client.rendering.fluid.FluidRenderHandlerRegistryImpl;
|
||||
|
@ -30,8 +33,8 @@ public interface FluidRenderHandlerRegistry {
|
|||
FluidRenderHandlerRegistry INSTANCE = FluidRenderHandlerRegistryImpl.INSTANCE;
|
||||
|
||||
/**
|
||||
* Get a {@link FluidRenderHandler} for a given Fluid.
|
||||
* Supports vanilla and Fabric fluids.
|
||||
* Get a {@link FluidRenderHandler} for a given Fluid. Supports vanilla and
|
||||
* Fabric fluids.
|
||||
*
|
||||
* @param fluid The Fluid.
|
||||
* @return The FluidRenderHandler.
|
||||
|
@ -41,8 +44,54 @@ public interface FluidRenderHandlerRegistry {
|
|||
/**
|
||||
* Register a {@link FluidRenderHandler} for a given Fluid.
|
||||
*
|
||||
* <p>Note that most fluids have a still and a flowing type, and a
|
||||
* FluidRenderHandler must be registered for each type separately. To easily
|
||||
* register a render handler for a pair of still and flowing fluids, use
|
||||
* {@link #register(Fluid, Fluid, FluidRenderHandler)}.
|
||||
*
|
||||
* @param fluid The Fluid.
|
||||
* @param renderer The FluidRenderHandler.
|
||||
*/
|
||||
void register(Fluid fluid, FluidRenderHandler renderer);
|
||||
|
||||
/**
|
||||
* Register a {@link FluidRenderHandler} for two given Fluids, usually a
|
||||
* pair of a still and a flowing fluid type that use the same fluid
|
||||
* renderer.
|
||||
*
|
||||
* @param still The still Fluid.
|
||||
* @param flow The flowing Fluid.
|
||||
* @param renderer The FluidRenderHandler.
|
||||
*/
|
||||
default void register(Fluid still, Fluid flow, FluidRenderHandler renderer) {
|
||||
register(still, renderer);
|
||||
register(flow, renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers whether a block is transparent or not. When a block is
|
||||
* transparent, the flowing fluid texture to the sides of that block is
|
||||
* replaced by a special overlay texture. This happens by default with glass
|
||||
* and leaves, and hence blocks inheriting {@link TransparentBlock} and
|
||||
* {@link LeavesBlock} are by default transparent. Use this method to
|
||||
* override the default behavior for a block.
|
||||
*
|
||||
* @param block The block to register transparency for.
|
||||
* @param transparent Whether the block is transparent (e.g. gets the
|
||||
* overlay textures) or not.
|
||||
*/
|
||||
void setBlockTransparency(Block block, boolean transparent);
|
||||
|
||||
/**
|
||||
* Looks up whether a block is transparent and gets a fluid overlay texture
|
||||
* instead of a falling fluid texture. If transparency is registered for a
|
||||
* block (via {@link #setBlockTransparency}), this method returns that
|
||||
* registered transparency. Otherwise, this method returns whether the block
|
||||
* is a subclass of {@link TransparentBlock} or {@link LeavesBlock}.
|
||||
*
|
||||
* @param block The block to get transparency for.
|
||||
* @return Whether the block is transparent (e.g. gets the overlay textures)
|
||||
* or not.
|
||||
*/
|
||||
boolean isBlockTransparent(Block block);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* 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 org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
/**
|
||||
* A simple fluid render handler that uses and loads sprites given by their
|
||||
* identifiers. Most fluids don't need more than this. In fact, if a fluid just
|
||||
* needs the vanilla water texture with a custom color, {@link #coloredWater}
|
||||
* can be used to easily create a fluid render handler for that.
|
||||
*
|
||||
* <p>Note that it's assumed that the fluid textures are assumed to be
|
||||
* registered to the blocks sprite atlas. If they are not, you have to manually
|
||||
* register the fluid textures. The "fabric-textures" API may come in handy for
|
||||
* that.
|
||||
*/
|
||||
public class SimpleFluidRenderHandler implements FluidRenderHandler {
|
||||
/**
|
||||
* The vanilla still water texture identifier.
|
||||
*/
|
||||
public static final Identifier WATER_STILL = new Identifier("block/water_still");
|
||||
|
||||
/**
|
||||
* The vanilla flowing water texture identifier.
|
||||
*/
|
||||
public static final Identifier WATER_FLOWING = new Identifier("block/water_flow");
|
||||
|
||||
/**
|
||||
* The vanilla water overlay texture identifier.
|
||||
*/
|
||||
public static final Identifier WATER_OVERLAY = new Identifier("block/water_overlay");
|
||||
|
||||
/**
|
||||
* The vanilla still lava texture identifier.
|
||||
*/
|
||||
public static final Identifier LAVA_STILL = new Identifier("block/lava_still");
|
||||
|
||||
/**
|
||||
* The vanilla flowing lava texture identifier.
|
||||
*/
|
||||
public static final Identifier LAVA_FLOWING = new Identifier("block/lava_flow");
|
||||
|
||||
protected final Identifier stillTexture;
|
||||
protected final Identifier flowingTexture;
|
||||
protected final Identifier overlayTexture;
|
||||
|
||||
protected final Sprite[] sprites;
|
||||
|
||||
protected final int tint;
|
||||
|
||||
/**
|
||||
* Creates a fluid render handler with an overlay texture and a custom,
|
||||
* fixed tint.
|
||||
*
|
||||
* @param stillTexture The texture for still fluid.
|
||||
* @param flowingTexture The texture for flowing/falling fluid.
|
||||
* @param overlayTexture The texture behind glass, leaves and other
|
||||
* {@linkplain FluidRenderHandlerRegistry#setBlockTransparency registered
|
||||
* transparent blocks}.
|
||||
* @param tint The fluid color RGB. Alpha is ignored.
|
||||
*/
|
||||
public SimpleFluidRenderHandler(Identifier stillTexture, Identifier flowingTexture, @Nullable Identifier overlayTexture, int tint) {
|
||||
this.stillTexture = stillTexture;
|
||||
this.flowingTexture = flowingTexture;
|
||||
this.overlayTexture = overlayTexture;
|
||||
this.sprites = new Sprite[overlayTexture == null ? 2 : 3];
|
||||
this.tint = tint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a fluid render handler with an overlay texture and no tint.
|
||||
*
|
||||
* @param stillTexture The texture for still fluid.
|
||||
* @param flowingTexture The texture for flowing/falling fluid.
|
||||
* @param overlayTexture The texture behind glass, leaves and other
|
||||
* {@linkplain FluidRenderHandlerRegistry#setBlockTransparency registered
|
||||
* transparent blocks}.
|
||||
*/
|
||||
public SimpleFluidRenderHandler(Identifier stillTexture, Identifier flowingTexture, Identifier overlayTexture) {
|
||||
this(stillTexture, flowingTexture, overlayTexture, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a fluid render handler without an overlay texture and a custom,
|
||||
* fixed tint.
|
||||
*
|
||||
* @param stillTexture The texture for still fluid.
|
||||
* @param flowingTexture The texture for flowing/falling fluid.
|
||||
* @param tint The fluid color RGB. Alpha is ignored.
|
||||
*/
|
||||
public SimpleFluidRenderHandler(Identifier stillTexture, Identifier flowingTexture, int tint) {
|
||||
this(stillTexture, flowingTexture, null, tint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a fluid render handler without an overlay texture and no tint.
|
||||
*
|
||||
* @param stillTexture The texture for still fluid.
|
||||
* @param flowingTexture The texture for flowing/falling fluid.
|
||||
*/
|
||||
public SimpleFluidRenderHandler(Identifier stillTexture, Identifier flowingTexture) {
|
||||
this(stillTexture, flowingTexture, null, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a fluid render handler that uses the vanilla water texture with a
|
||||
* fixed, custom color.
|
||||
*
|
||||
* @param tint The fluid color RGB. Alpha is ignored.
|
||||
* @see #WATER_STILL
|
||||
* @see #WATER_FLOWING
|
||||
* @see #WATER_OVERLAY
|
||||
*/
|
||||
public static SimpleFluidRenderHandler coloredWater(int tint) {
|
||||
return new SimpleFluidRenderHandler(WATER_STILL, WATER_FLOWING, WATER_OVERLAY, tint);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Sprite[] getFluidSprites(@Nullable BlockRenderView view, @Nullable BlockPos pos, FluidState state) {
|
||||
return sprites;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void reloadTextures(SpriteAtlasTexture textureAtlas) {
|
||||
sprites[0] = textureAtlas.getSprite(stillTexture);
|
||||
sprites[1] = textureAtlas.getSprite(flowingTexture);
|
||||
|
||||
if (overlayTexture != null) {
|
||||
sprites[2] = textureAtlas.getSprite(overlayTexture);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int getFluidColor(@Nullable BlockRenderView view, @Nullable BlockPos pos, FluidState state) {
|
||||
return tint;
|
||||
}
|
||||
}
|
|
@ -19,11 +19,19 @@ package net.fabricmc.fabric.impl.client.rendering.fluid;
|
|||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.TransparentBlock;
|
||||
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;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.screen.PlayerScreenHandler;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.registry.BuiltinRegistries;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
@ -37,6 +45,9 @@ public class FluidRenderHandlerRegistryImpl implements FluidRenderHandlerRegistr
|
|||
private static final int DEFAULT_WATER_COLOR = BuiltinRegistries.BIOME.get(BiomeKeys.OCEAN).getWaterColor();
|
||||
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 FluidRenderer fluidRenderer;
|
||||
|
||||
private FluidRenderHandlerRegistryImpl() {
|
||||
}
|
||||
|
@ -56,11 +67,24 @@ public class FluidRenderHandlerRegistryImpl implements FluidRenderHandlerRegistr
|
|||
modHandlers.put(fluid, renderer);
|
||||
}
|
||||
|
||||
public void onFluidRendererReload(Sprite[] waterSprites, Sprite[] lavaSprites) {
|
||||
@Override
|
||||
public void setBlockTransparency(Block block, boolean transparent) {
|
||||
overlayBlocks.put(block, transparent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlockTransparent(Block block) {
|
||||
return overlayBlocks.computeIfAbsent(block, k -> k instanceof TransparentBlock || k instanceof LeavesBlock);
|
||||
}
|
||||
|
||||
public void onFluidRendererReload(FluidRenderer renderer, Sprite[] waterSprites, Sprite[] lavaSprites, Sprite waterOverlay) {
|
||||
fluidRenderer = renderer;
|
||||
|
||||
Sprite[] waterSpritesFull = {waterSprites[0], waterSprites[1], waterOverlay};
|
||||
FluidRenderHandler waterHandler = new FluidRenderHandler() {
|
||||
@Override
|
||||
public Sprite[] getFluidSprites(BlockRenderView view, BlockPos pos, FluidState state) {
|
||||
return waterSprites;
|
||||
return waterSpritesFull;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,5 +110,17 @@ public class FluidRenderHandlerRegistryImpl implements FluidRenderHandlerRegistr
|
|||
register(Fluids.LAVA, lavaHandler);
|
||||
register(Fluids.FLOWING_LAVA, lavaHandler);
|
||||
handlers.putAll(modHandlers);
|
||||
|
||||
SpriteAtlasTexture texture = MinecraftClient.getInstance()
|
||||
.getBakedModelManager()
|
||||
.getAtlas(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE);
|
||||
|
||||
for (FluidRenderHandler handler : handlers.values()) {
|
||||
handler.reloadTextures(texture);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean renderFluid(BlockPos pos, BlockRenderView world, VertexConsumer vertexConsumer, FluidState state) {
|
||||
return fluidRenderer.render(world, pos, vertexConsumer, state);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package net.fabricmc.fabric.impl.client.rendering.fluid;
|
||||
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
@ -27,11 +28,34 @@ public class FluidRendererHookContainer {
|
|||
public BlockPos pos;
|
||||
public FluidState state;
|
||||
public FluidRenderHandler handler;
|
||||
public final Sprite[] sprites = new Sprite[2];
|
||||
public Sprite overlay;
|
||||
public boolean hasOverlay;
|
||||
|
||||
public void getSprites(BlockRenderView world, BlockPos pos, FluidState fluid) {
|
||||
if (handler != null) {
|
||||
Sprite[] sprites = handler.getFluidSprites(world, pos, state);
|
||||
|
||||
this.sprites[0] = sprites[0];
|
||||
this.sprites[1] = sprites[1];
|
||||
|
||||
if (sprites.length > 2) {
|
||||
hasOverlay = true;
|
||||
overlay = sprites[2];
|
||||
}
|
||||
} else {
|
||||
hasOverlay = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
view = null;
|
||||
pos = null;
|
||||
state = null;
|
||||
handler = null;
|
||||
sprites[0] = null;
|
||||
sprites[1] = null;
|
||||
overlay = null;
|
||||
hasOverlay = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,19 +16,23 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.client.rendering.fluid;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
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;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
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.fluid.FluidState;
|
||||
import net.minecraft.tag.FluidTags;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
|
@ -42,16 +46,41 @@ public class MixinFluidRenderer {
|
|||
private Sprite[] lavaSprites;
|
||||
@Shadow
|
||||
private Sprite[] waterSprites;
|
||||
@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")
|
||||
public void onResourceReloadReturn(CallbackInfo info) {
|
||||
FluidRenderHandlerRegistryImpl.INSTANCE.onFluidRendererReload(waterSprites, lavaSprites);
|
||||
FluidRenderer self = (FluidRenderer) (Object) this;
|
||||
FluidRenderHandlerRegistryImpl.INSTANCE.onFluidRendererReload(self, waterSprites, lavaSprites, waterOverlaySprite);
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "render", cancellable = true)
|
||||
public void tesselate(BlockRenderView view, BlockPos pos, VertexConsumer vertexConsumer, FluidState state, CallbackInfoReturnable<Boolean> info) {
|
||||
if (!fabric_customRendering.get()) {
|
||||
// Prevent recursively looking up custom fluid renderers when default behaviour is being invoked
|
||||
try {
|
||||
fabric_customRendering.set(true);
|
||||
tessellateViaHandler(view, pos, vertexConsumer, state, info);
|
||||
} finally {
|
||||
fabric_customRendering.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (info.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FluidRendererHookContainer ctr = fabric_renderHandler.get();
|
||||
ctr.getSprites(view, pos, state);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void tessellateViaHandler(BlockRenderView view, BlockPos pos, VertexConsumer vertexConsumer, FluidState state, CallbackInfoReturnable<Boolean> info) {
|
||||
FluidRendererHookContainer ctr = fabric_renderHandler.get();
|
||||
FluidRenderHandler handler = FluidRenderHandlerRegistryImpl.INSTANCE.getOverride(state.getFluid());
|
||||
|
||||
|
@ -60,16 +89,9 @@ public class MixinFluidRenderer {
|
|||
ctr.state = state;
|
||||
ctr.handler = handler;
|
||||
|
||||
/* if (handler == null) {
|
||||
return;
|
||||
if (handler != null) {
|
||||
info.setReturnValue(handler.renderFluid(pos, view, vertexConsumer, state));
|
||||
}
|
||||
|
||||
ActionResult hResult = handler.tesselate(view, pos, bufferBuilder, state);
|
||||
|
||||
if (hResult != ActionResult.PASS) {
|
||||
info.setReturnValue(hResult == ActionResult.SUCCESS);
|
||||
return;
|
||||
} */
|
||||
}
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "render")
|
||||
|
@ -83,15 +105,25 @@ public class MixinFluidRenderer {
|
|||
// but uses the negation consistent with 'matches water'
|
||||
// for determining if special water sprite should be used behind glass.
|
||||
|
||||
// Has other uses but those have already happened by the time the hook is called.
|
||||
// Has other uses but those are overridden by this mixin and have
|
||||
// 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 chk || !ctr.state.isIn(FluidTags.WATER);
|
||||
return !ctr.hasOverlay;
|
||||
}
|
||||
|
||||
@ModifyVariable(at = @At(value = "INVOKE", target = "net/minecraft/client/render/block/FluidRenderer.isSameFluid(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;Lnet/minecraft/fluid/FluidState;)Z"), method = "render", ordinal = 0)
|
||||
public Sprite[] modSpriteArray(Sprite[] chk) {
|
||||
FluidRendererHookContainer ctr = fabric_renderHandler.get();
|
||||
return ctr.handler != null ? ctr.handler.getFluidSprites(ctr.view, ctr.pos, ctr.state) : chk;
|
||||
return ctr.handler != null ? ctr.sprites : 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)
|
||||
|
@ -99,4 +131,26 @@ public class MixinFluidRenderer {
|
|||
FluidRendererHookContainer ctr = fabric_renderHandler.get();
|
||||
return ctr.handler != null ? ctr.handler.getFluidColor(ctr.view, ctr.pos, ctr.state) : chk;
|
||||
}
|
||||
|
||||
@Redirect(at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;getBlock()Lnet/minecraft/block/Block;"), method = "render")
|
||||
public Block getOverlayBlock(BlockState state) {
|
||||
Block block = state.getBlock();
|
||||
fabric_neighborBlock.set(block);
|
||||
|
||||
// An if-statement follows, we don't want this anymore and 'null' makes
|
||||
// its condition always false (due to instanceof)
|
||||
return null;
|
||||
}
|
||||
|
||||
@ModifyVariable(at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;getBlock()Lnet/minecraft/block/Block;", shift = At.Shift.BY, by = 2), method = "render", ordinal = 0)
|
||||
public Sprite modSideSpriteForOverlay(Sprite chk) {
|
||||
Block block = fabric_neighborBlock.get();
|
||||
|
||||
if (FluidRenderHandlerRegistryImpl.INSTANCE.isBlockTransparent(block)) {
|
||||
FluidRendererHookContainer ctr = fabric_renderHandler.get();
|
||||
return ctr.handler != null && ctr.hasOverlay ? ctr.overlay : waterOverlaySprite;
|
||||
}
|
||||
|
||||
return chk;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"MixinFluidRenderer"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
"defaultRequire": 1,
|
||||
"maxShiftBy": 5
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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.test.client.rendering.fluid;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FluidBlock;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.fluid.FlowableFluid;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.WorldView;
|
||||
|
||||
public abstract class CustomFluid extends FlowableFluid {
|
||||
public CustomFluid() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fluid getFlowing() {
|
||||
return TestFluids.CUSTOM_FLOWING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fluid getStill() {
|
||||
return TestFluids.CUSTOM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBucketItem() {
|
||||
return Items.WATER_BUCKET;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isInfinite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeBreakingBlock(WorldAccess world, BlockPos pos, BlockState state) {
|
||||
BlockEntity blockEntity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
||||
Block.dropStacks(state, world, pos, blockEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFlowSpeed(WorldView world) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState toBlockState(FluidState state) {
|
||||
return TestFluids.CUSTOM_BLOCK.getDefaultState().with(FluidBlock.LEVEL, getBlockStateLevel(state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesType(Fluid fluid) {
|
||||
return fluid == TestFluids.CUSTOM || fluid == TestFluids.CUSTOM_FLOWING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevelDecreasePerBlock(WorldView world) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTickRate(WorldView world) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeReplacedWith(FluidState state, BlockView world, BlockPos pos, Fluid fluid, Direction direction) {
|
||||
return direction == Direction.DOWN && !fluid.matchesType(TestFluids.NO_OVERLAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getBlastResistance() {
|
||||
return 100.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<SoundEvent> getBucketFillSound() {
|
||||
return Optional.of(SoundEvents.ITEM_BUCKET_FILL);
|
||||
}
|
||||
|
||||
public static class Flowing extends CustomFluid {
|
||||
public Flowing() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Fluid, FluidState> builder) {
|
||||
super.appendProperties(builder);
|
||||
builder.add(LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel(FluidState state) {
|
||||
return state.get(LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStill(FluidState state) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Still extends CustomFluid {
|
||||
public Still() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel(FluidState state) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStill(FluidState state) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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.test.client.rendering.fluid;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.WorldRenderer;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
import net.fabricmc.fabric.api.client.render.fluid.v1.SimpleFluidRenderHandler;
|
||||
|
||||
public class CustomizedFluidRenderer extends SimpleFluidRenderHandler {
|
||||
public CustomizedFluidRenderer(Identifier overlayTexture) {
|
||||
super(null, null, overlayTexture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean renderFluid(BlockPos pos, BlockRenderView world, VertexConsumer vertexConsumer, FluidState state) {
|
||||
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 * state.getHeight(world, pos));
|
||||
|
||||
float x1 = (pos.getX() & 15) + 0.1f;
|
||||
float y1 = pos.getY() & 15;
|
||||
float z1 = (pos.getZ() & 15) + 0.1f;
|
||||
|
||||
float x2 = (pos.getX() & 15) + 0.9f;
|
||||
float y2 = (pos.getY() & 15) + state.getHeight(world, pos);
|
||||
float z2 = (pos.getZ() & 15) + 0.9f;
|
||||
|
||||
vertex(vertexConsumer, x1, y1, z1, 1, 1, 1, u1, v1, light);
|
||||
vertex(vertexConsumer, x2, y1, z2, 1, 1, 1, u2, v1, light);
|
||||
vertex(vertexConsumer, x2, y2, z2, 1, 1, 1, u2, v2, light);
|
||||
vertex(vertexConsumer, x1, y2, z1, 1, 1, 1, u1, v2, light);
|
||||
|
||||
vertex(vertexConsumer, x1, y2, z1, 1, 1, 1, u1, v2, light);
|
||||
vertex(vertexConsumer, x2, y2, z2, 1, 1, 1, u2, v2, light);
|
||||
vertex(vertexConsumer, x2, y1, z2, 1, 1, 1, u2, v1, light);
|
||||
vertex(vertexConsumer, x1, y1, z1, 1, 1, 1, u1, v1, light);
|
||||
|
||||
vertex(vertexConsumer, x1, y2, z2, 1, 1, 1, u1, v2, light);
|
||||
vertex(vertexConsumer, x2, y2, z1, 1, 1, 1, u2, v2, light);
|
||||
vertex(vertexConsumer, x2, y1, z1, 1, 1, 1, u2, v1, light);
|
||||
vertex(vertexConsumer, x1, y1, z2, 1, 1, 1, u1, v1, light);
|
||||
|
||||
vertex(vertexConsumer, x1, y1, z2, 1, 1, 1, u1, v1, light);
|
||||
vertex(vertexConsumer, x2, y1, z1, 1, 1, 1, u2, v1, light);
|
||||
vertex(vertexConsumer, x2, y2, z1, 1, 1, 1, u2, v2, light);
|
||||
vertex(vertexConsumer, x1, y2, z2, 1, 1, 1, u1, v2, light);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void vertex(VertexConsumer vertexConsumer, double x, double y, double z, float red, float green, float blue, float u, float v, int light) {
|
||||
vertexConsumer.vertex(x, y, z).color(red, green, blue, 1.0F).texture(u, v).light(light).normal(0.0F, 1.0F, 0.0F).next();
|
||||
}
|
||||
|
||||
private int getLight(BlockRenderView world, BlockPos pos) {
|
||||
int i = WorldRenderer.getLightmapCoordinates(world, pos);
|
||||
int j = WorldRenderer.getLightmapCoordinates(world, pos.up());
|
||||
int k = i & 255;
|
||||
int l = j & 255;
|
||||
int m = i >> 16 & 255;
|
||||
int n = j >> 16 & 255;
|
||||
return (k > l ? k : l) | (m > n ? m : n) << 16;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.test.client.rendering.fluid;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
|
||||
public class FabricFluidRenderingTestMod implements ModInitializer {
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
new TestFluids();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.test.client.rendering.fluid;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.screen.PlayerScreenHandler;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
|
||||
import net.fabricmc.fabric.api.client.render.fluid.v1.SimpleFluidRenderHandler;
|
||||
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
|
||||
|
||||
public class FabricFluidRenderingTestModClient implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
// Doors now will have overlay textures to the side
|
||||
FluidRenderHandlerRegistry.INSTANCE.setBlockTransparency(Blocks.ACACIA_DOOR, true);
|
||||
FluidRenderHandlerRegistry.INSTANCE.setBlockTransparency(Blocks.DARK_OAK_DOOR, true);
|
||||
FluidRenderHandlerRegistry.INSTANCE.setBlockTransparency(Blocks.BIRCH_DOOR, true);
|
||||
FluidRenderHandlerRegistry.INSTANCE.setBlockTransparency(Blocks.CRIMSON_DOOR, true);
|
||||
FluidRenderHandlerRegistry.INSTANCE.setBlockTransparency(Blocks.IRON_DOOR, true);
|
||||
FluidRenderHandlerRegistry.INSTANCE.setBlockTransparency(Blocks.JUNGLE_DOOR, true);
|
||||
FluidRenderHandlerRegistry.INSTANCE.setBlockTransparency(Blocks.OAK_DOOR, true);
|
||||
FluidRenderHandlerRegistry.INSTANCE.setBlockTransparency(Blocks.SPRUCE_DOOR, true);
|
||||
FluidRenderHandlerRegistry.INSTANCE.setBlockTransparency(Blocks.WARPED_DOOR, true);
|
||||
|
||||
// Red stained glass will have falling fluid textures to the side
|
||||
FluidRenderHandlerRegistry.INSTANCE.setBlockTransparency(Blocks.RED_STAINED_GLASS, false);
|
||||
|
||||
FluidRenderHandlerRegistry.INSTANCE.register(TestFluids.NO_OVERLAY, TestFluids.NO_OVERLAY_FLOWING, new SimpleFluidRenderHandler(
|
||||
new Identifier("fabric-rendering-fluids-v1-testmod:block/test_fluid_still"),
|
||||
new Identifier("fabric-rendering-fluids-v1-testmod:block/test_fluid_flowing"),
|
||||
0xFF5555
|
||||
));
|
||||
|
||||
FluidRenderHandlerRegistry.INSTANCE.register(TestFluids.OVERLAY, TestFluids.OVERLAY_FLOWING, new SimpleFluidRenderHandler(
|
||||
new Identifier("fabric-rendering-fluids-v1-testmod:block/test_fluid_still"),
|
||||
new Identifier("fabric-rendering-fluids-v1-testmod:block/test_fluid_flowing"),
|
||||
new Identifier("fabric-rendering-fluids-v1-testmod:block/test_fluid_overlay"),
|
||||
0x5555FF
|
||||
));
|
||||
|
||||
FluidRenderHandlerRegistry.INSTANCE.register(TestFluids.CUSTOM, TestFluids.CUSTOM_FLOWING, new CustomizedFluidRenderer(
|
||||
new Identifier("fabric-rendering-fluids-v1-testmod:block/test_fluid_overlay")
|
||||
));
|
||||
|
||||
ClientSpriteRegistryCallback.event(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE).register((atlasTexture, registry) -> {
|
||||
registry.register(new Identifier("fabric-rendering-fluids-v1-testmod:block/test_fluid_still"));
|
||||
registry.register(new Identifier("fabric-rendering-fluids-v1-testmod:block/test_fluid_flowing"));
|
||||
registry.register(new Identifier("fabric-rendering-fluids-v1-testmod:block/test_fluid_overlay"));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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.test.client.rendering.fluid;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FluidBlock;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.fluid.FlowableFluid;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.WorldView;
|
||||
|
||||
public abstract class NoOverlayFluid extends FlowableFluid {
|
||||
public NoOverlayFluid() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fluid getFlowing() {
|
||||
return TestFluids.NO_OVERLAY_FLOWING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fluid getStill() {
|
||||
return TestFluids.NO_OVERLAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBucketItem() {
|
||||
return Items.WATER_BUCKET;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isInfinite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeBreakingBlock(WorldAccess world, BlockPos pos, BlockState state) {
|
||||
BlockEntity blockEntity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
||||
Block.dropStacks(state, world, pos, blockEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFlowSpeed(WorldView world) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState toBlockState(FluidState state) {
|
||||
return TestFluids.NO_OVERLAY_BLOCK.getDefaultState().with(FluidBlock.LEVEL, getBlockStateLevel(state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesType(Fluid fluid) {
|
||||
return fluid == TestFluids.NO_OVERLAY || fluid == TestFluids.NO_OVERLAY_FLOWING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevelDecreasePerBlock(WorldView world) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTickRate(WorldView world) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeReplacedWith(FluidState state, BlockView world, BlockPos pos, Fluid fluid, Direction direction) {
|
||||
return direction == Direction.DOWN && !fluid.matchesType(TestFluids.NO_OVERLAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getBlastResistance() {
|
||||
return 100.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<SoundEvent> getBucketFillSound() {
|
||||
return Optional.of(SoundEvents.ITEM_BUCKET_FILL);
|
||||
}
|
||||
|
||||
public static class Flowing extends NoOverlayFluid {
|
||||
public Flowing() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Fluid, FluidState> builder) {
|
||||
super.appendProperties(builder);
|
||||
builder.add(LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel(FluidState state) {
|
||||
return state.get(LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStill(FluidState state) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Still extends NoOverlayFluid {
|
||||
public Still() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel(FluidState state) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStill(FluidState state) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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.test.client.rendering.fluid;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FluidBlock;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.fluid.FlowableFluid;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.WorldView;
|
||||
|
||||
public abstract class OverlayFluid extends FlowableFluid {
|
||||
public OverlayFluid() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fluid getFlowing() {
|
||||
return TestFluids.OVERLAY_FLOWING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fluid getStill() {
|
||||
return TestFluids.OVERLAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBucketItem() {
|
||||
return Items.WATER_BUCKET;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isInfinite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeBreakingBlock(WorldAccess world, BlockPos pos, BlockState state) {
|
||||
BlockEntity blockEntity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
||||
Block.dropStacks(state, world, pos, blockEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFlowSpeed(WorldView world) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState toBlockState(FluidState state) {
|
||||
return TestFluids.OVERLAY_BLOCK.getDefaultState().with(FluidBlock.LEVEL, getBlockStateLevel(state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesType(Fluid fluid) {
|
||||
return fluid == TestFluids.OVERLAY || fluid == TestFluids.OVERLAY_FLOWING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevelDecreasePerBlock(WorldView world) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTickRate(WorldView world) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeReplacedWith(FluidState state, BlockView world, BlockPos pos, Fluid fluid, Direction direction) {
|
||||
return direction == Direction.DOWN && !fluid.matchesType(TestFluids.NO_OVERLAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getBlastResistance() {
|
||||
return 100.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<SoundEvent> getBucketFillSound() {
|
||||
return Optional.of(SoundEvents.ITEM_BUCKET_FILL);
|
||||
}
|
||||
|
||||
public static class Flowing extends OverlayFluid {
|
||||
public Flowing() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Fluid, FluidState> builder) {
|
||||
super.appendProperties(builder);
|
||||
builder.add(LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel(FluidState state) {
|
||||
return state.get(LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStill(FluidState state) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Still extends OverlayFluid {
|
||||
public Still() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel(FluidState state) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStill(FluidState state) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.test.client.rendering.fluid;
|
||||
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.FluidBlock;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
public class TestFluids {
|
||||
public static final NoOverlayFluid NO_OVERLAY = Registry.register(Registry.FLUID, "fabric-rendering-fluids-v1-testmod:no_overlay", new NoOverlayFluid.Still());
|
||||
public static final NoOverlayFluid NO_OVERLAY_FLOWING = Registry.register(Registry.FLUID, "fabric-rendering-fluids-v1-testmod:no_overlay_flowing", new NoOverlayFluid.Flowing());
|
||||
|
||||
public static final FluidBlock NO_OVERLAY_BLOCK = Registry.register(Registry.BLOCK, "fabric-rendering-fluids-v1-testmod:no_overlay", new FluidBlock(NO_OVERLAY, AbstractBlock.Settings.copy(Blocks.WATER)) {
|
||||
});
|
||||
|
||||
public static final OverlayFluid OVERLAY = Registry.register(Registry.FLUID, "fabric-rendering-fluids-v1-testmod:overlay", new OverlayFluid.Still());
|
||||
public static final OverlayFluid OVERLAY_FLOWING = Registry.register(Registry.FLUID, "fabric-rendering-fluids-v1-testmod:overlay_flowing", new OverlayFluid.Flowing());
|
||||
|
||||
public static final FluidBlock OVERLAY_BLOCK = Registry.register(Registry.BLOCK, "fabric-rendering-fluids-v1-testmod:overlay", new FluidBlock(OVERLAY, AbstractBlock.Settings.copy(Blocks.WATER)) {
|
||||
});
|
||||
|
||||
public static final UnregisteredFluid UNREGISTERED = Registry.register(Registry.FLUID, "fabric-rendering-fluids-v1-testmod:unregistered", new UnregisteredFluid.Still());
|
||||
public static final UnregisteredFluid UNREGISTERED_FLOWING = Registry.register(Registry.FLUID, "fabric-rendering-fluids-v1-testmod:unregistered_flowing", new UnregisteredFluid.Flowing());
|
||||
|
||||
public static final FluidBlock UNREGISTERED_BLOCK = Registry.register(Registry.BLOCK, "fabric-rendering-fluids-v1-testmod:unregistered", new FluidBlock(UNREGISTERED, AbstractBlock.Settings.copy(Blocks.WATER)) {
|
||||
});
|
||||
|
||||
public static final CustomFluid CUSTOM = Registry.register(Registry.FLUID, "fabric-rendering-fluids-v1-testmod:custom", new CustomFluid.Still());
|
||||
public static final CustomFluid CUSTOM_FLOWING = Registry.register(Registry.FLUID, "fabric-rendering-fluids-v1-testmod:custom_flowing", new CustomFluid.Flowing());
|
||||
|
||||
public static final FluidBlock CUSTOM_BLOCK = Registry.register(Registry.BLOCK, "fabric-rendering-fluids-v1-testmod:custom", new FluidBlock(CUSTOM, AbstractBlock.Settings.copy(Blocks.WATER)) {
|
||||
});
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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.test.client.rendering.fluid;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FluidBlock;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.fluid.FlowableFluid;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.WorldView;
|
||||
|
||||
public abstract class UnregisteredFluid extends FlowableFluid {
|
||||
public UnregisteredFluid() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fluid getFlowing() {
|
||||
return TestFluids.UNREGISTERED_FLOWING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fluid getStill() {
|
||||
return TestFluids.UNREGISTERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBucketItem() {
|
||||
return Items.WATER_BUCKET;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isInfinite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeBreakingBlock(WorldAccess world, BlockPos pos, BlockState state) {
|
||||
BlockEntity blockEntity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
||||
Block.dropStacks(state, world, pos, blockEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFlowSpeed(WorldView world) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState toBlockState(FluidState state) {
|
||||
return TestFluids.UNREGISTERED_BLOCK.getDefaultState().with(FluidBlock.LEVEL, getBlockStateLevel(state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesType(Fluid fluid) {
|
||||
return fluid == TestFluids.UNREGISTERED || fluid == TestFluids.UNREGISTERED_FLOWING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevelDecreasePerBlock(WorldView world) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTickRate(WorldView world) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeReplacedWith(FluidState state, BlockView world, BlockPos pos, Fluid fluid, Direction direction) {
|
||||
return direction == Direction.DOWN && !fluid.matchesType(TestFluids.NO_OVERLAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getBlastResistance() {
|
||||
return 100.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<SoundEvent> getBucketFillSound() {
|
||||
return Optional.of(SoundEvents.ITEM_BUCKET_FILL);
|
||||
}
|
||||
|
||||
public static class Flowing extends UnregisteredFluid {
|
||||
public Flowing() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Fluid, FluidState> builder) {
|
||||
super.appendProperties(builder);
|
||||
builder.add(LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel(FluidState state) {
|
||||
return state.get(LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStill(FluidState state) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Still extends UnregisteredFluid {
|
||||
public Still() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel(FluidState state) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStill(FluidState state) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After ![]() (image error) Size: 639 B |
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"animation": {}
|
||||
}
|
Binary file not shown.
After ![]() (image error) Size: 152 B |
Binary file not shown.
After ![]() (image error) Size: 124 B |
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "fabric-rendering-fluids-v1-testmod",
|
||||
"name": "Fabric Rendering Fluids (v1) Test Mod",
|
||||
"version": "1.0.0",
|
||||
"environment": "*",
|
||||
"license": "Apache-2.0",
|
||||
"depends": {
|
||||
"fabric-rendering-fluids-v1": "*"
|
||||
},
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"net.fabricmc.fabric.test.client.rendering.fluid.FabricFluidRenderingTestMod"
|
||||
],
|
||||
"client": [
|
||||
"net.fabricmc.fabric.test.client.rendering.fluid.FabricFluidRenderingTestModClient"
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue