forked from FabricMC/fabric
[#111] fluid rendering hooks
This commit is contained in:
parent
59147463cc
commit
76d184ea21
10 changed files with 398 additions and 0 deletions
6
fabric-rendering-fluids-v1/build.gradle
Normal file
6
fabric-rendering-fluids-v1/build.gradle
Normal file
|
@ -0,0 +1,6 @@
|
|||
archivesBaseName = "fabric-rendering-fluids-v1"
|
||||
version = getSubprojectVersion(project, "0.1.0")
|
||||
|
||||
dependencies {
|
||||
compile project(path: ':fabric-api-base', configuration: 'dev')
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.client.texture.Sprite;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ExtendedBlockView;
|
||||
|
||||
/**
|
||||
* 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!
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
Sprite[] getFluidSprites(/* Nullable */ ExtendedBlockView view, /* Nullable */ BlockPos pos, FluidState state);
|
||||
|
||||
/**
|
||||
* Get the tint color for a fluid being rendered at a given position.
|
||||
*
|
||||
* 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 state The current state of the fluid.
|
||||
* @return The tint color of the fluid.
|
||||
*/
|
||||
default int getFluidColor(ExtendedBlockView view, BlockPos pos, FluidState state) {
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.fabricmc.fabric.impl.client.render.fluid.FluidRenderHandlerRegistryImpl;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
|
||||
/**
|
||||
* Registry for {@link FluidRenderHandler} instances.
|
||||
*
|
||||
* Notably, this supports querying, overriding and wrapping vanilla fluid
|
||||
* rendering.
|
||||
*/
|
||||
public interface FluidRenderHandlerRegistry {
|
||||
FluidRenderHandlerRegistry INSTANCE = FluidRenderHandlerRegistryImpl.INSTANCE;
|
||||
|
||||
/**
|
||||
* Get a {@link FluidRenderHandler} for a given Fluid.
|
||||
* Supports vanilla and Fabric fluids.
|
||||
*
|
||||
* @param fluid The Fluid.
|
||||
* @return The FluidRenderHandler.
|
||||
*/
|
||||
FluidRenderHandler get(Fluid fluid);
|
||||
|
||||
/**
|
||||
* Register a {@link FluidRenderHandler} for a given Fluid.
|
||||
*
|
||||
* @param fluid The Fluid.
|
||||
* @param renderer The FluidRenderHandler.
|
||||
*/
|
||||
void register(Fluid fluid, FluidRenderHandler renderer);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.render.fluid;
|
||||
|
||||
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler;
|
||||
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
|
||||
import net.minecraft.client.color.world.BiomeColors;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ExtendedBlockView;
|
||||
import net.minecraft.world.biome.Biomes;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class FluidRenderHandlerRegistryImpl implements FluidRenderHandlerRegistry {
|
||||
public static final FluidRenderHandlerRegistryImpl INSTANCE = new FluidRenderHandlerRegistryImpl();
|
||||
private final Map<Fluid, FluidRenderHandler> handlers = new IdentityHashMap<>();
|
||||
private final Map<Fluid, FluidRenderHandler> modHandlers = new IdentityHashMap<>();
|
||||
|
||||
private FluidRenderHandlerRegistryImpl() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidRenderHandler get(Fluid fluid) {
|
||||
return handlers.get(fluid);
|
||||
}
|
||||
|
||||
public FluidRenderHandler getOverride(Fluid fluid) {
|
||||
return modHandlers.get(fluid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Fluid fluid, FluidRenderHandler renderer) {
|
||||
handlers.put(fluid, renderer);
|
||||
modHandlers.put(fluid, renderer);
|
||||
}
|
||||
|
||||
public void onFluidRendererReload(Sprite[] waterSprites, Sprite[] lavaSprites) {
|
||||
FluidRenderHandler waterHandler = new FluidRenderHandler() {
|
||||
@Override
|
||||
public Sprite[] getFluidSprites(ExtendedBlockView view, BlockPos pos, FluidState state) {
|
||||
return waterSprites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFluidColor(ExtendedBlockView view, BlockPos pos, FluidState state) {
|
||||
if (view != null && pos != null) {
|
||||
return BiomeColors.getWaterColor(view, pos);
|
||||
} else {
|
||||
return Biomes.DEFAULT.getWaterColor();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//noinspection Convert2Lambda
|
||||
FluidRenderHandler lavaHandler = new FluidRenderHandler() {
|
||||
@Override
|
||||
public Sprite[] getFluidSprites(ExtendedBlockView view, BlockPos pos, FluidState state) {
|
||||
return lavaSprites;
|
||||
}
|
||||
};
|
||||
|
||||
register(Fluids.WATER, waterHandler);
|
||||
register(Fluids.FLOWING_WATER, waterHandler);
|
||||
register(Fluids.LAVA, lavaHandler);
|
||||
register(Fluids.FLOWING_LAVA, lavaHandler);
|
||||
handlers.putAll(modHandlers);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.render.fluid;
|
||||
|
||||
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ExtendedBlockView;
|
||||
|
||||
public class FluidRendererHookContainer {
|
||||
public ExtendedBlockView view;
|
||||
public BlockPos pos;
|
||||
public FluidState state;
|
||||
public FluidRenderHandler handler;
|
||||
|
||||
public void clear() {
|
||||
view = null;
|
||||
pos = null;
|
||||
state = null;
|
||||
handler = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.mixin.client.render.fluid;
|
||||
|
||||
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler;
|
||||
import net.fabricmc.fabric.impl.client.render.fluid.FluidRendererHookContainer;
|
||||
import net.fabricmc.fabric.impl.client.render.fluid.FluidRenderHandlerRegistryImpl;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.block.FluidRenderer;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ExtendedBlockView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
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.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(FluidRenderer.class)
|
||||
public class MixinFluidRenderer {
|
||||
@Shadow
|
||||
private Sprite[] lavaSprites;
|
||||
@Shadow
|
||||
private Sprite[] waterSprites;
|
||||
|
||||
private final ThreadLocal<FluidRendererHookContainer> fabric_renderHandler = ThreadLocal.withInitial(FluidRendererHookContainer::new);
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "onResourceReload")
|
||||
public void onResourceReloadReturn(CallbackInfo info) {
|
||||
FluidRenderHandlerRegistryImpl.INSTANCE.onFluidRendererReload(waterSprites, lavaSprites);
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "tesselate", cancellable = true)
|
||||
public void tesselate(ExtendedBlockView view, BlockPos pos, BufferBuilder bufferBuilder, FluidState state, CallbackInfoReturnable<Boolean> info) {
|
||||
FluidRendererHookContainer ctr = fabric_renderHandler.get();
|
||||
FluidRenderHandler handler = FluidRenderHandlerRegistryImpl.INSTANCE.getOverride(state.getFluid());
|
||||
if (handler == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* ActionResult hResult = handler.tesselate(view, pos, bufferBuilder, state);
|
||||
if (hResult != ActionResult.PASS) {
|
||||
info.setReturnValue(hResult == ActionResult.SUCCESS);
|
||||
return;
|
||||
} */
|
||||
|
||||
ctr.view = view;
|
||||
ctr.pos = pos;
|
||||
ctr.state = state;
|
||||
ctr.handler = handler;
|
||||
}
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "tesselate")
|
||||
public void tesselateReturn(ExtendedBlockView view, BlockPos pos, BufferBuilder bufferBuilder, FluidState state, CallbackInfoReturnable<Boolean> info) {
|
||||
fabric_renderHandler.get().clear();
|
||||
}
|
||||
|
||||
@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 = "tesselate", ordinal = 0)
|
||||
public boolean modLavaCheck(boolean chk) {
|
||||
return fabric_renderHandler.get().handler != null || chk;
|
||||
}
|
||||
|
||||
@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 = "tesselate", 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;
|
||||
}
|
||||
|
||||
@ModifyVariable(at = @At(value = "CONSTANT", args = "intValue=16", ordinal = 0, shift = At.Shift.BEFORE), method = "tesselate", ordinal = 0)
|
||||
public int modTintColor(int chk) {
|
||||
FluidRendererHookContainer ctr = fabric_renderHandler.get();
|
||||
return ctr.handler != null ? ctr.handler.getFluidColor(ctr.view, ctr.pos, ctr.state) : chk;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "net.fabricmc.fabric.mixin.client.render.fluid",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"client": [
|
||||
"MixinFluidRenderer"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "fabric-rendering-fluids-v1",
|
||||
"version": "${version}",
|
||||
"license": "Apache-2.0",
|
||||
"depends": {
|
||||
"fabricloader": ">=0.4.0",
|
||||
"fabric-api-base": "*"
|
||||
},
|
||||
"recommends": {
|
||||
"fabric-textures-v0": "*"
|
||||
},
|
||||
"mixins": [
|
||||
"fabric-rendering-fluids-v1.mixins.json"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018 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.fluidrender;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.client.render.FluidRenderHandler;
|
||||
import net.fabricmc.fabric.api.client.render.FluidRenderHandlerRegistry;
|
||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.ResourceType;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class FluidRendererModClient implements ClientModInitializer, SimpleSynchronousResourceReloadListener {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
ResourceManagerHelper.get(ResourceType.ASSETS).registerReloadListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return new Identifier("fabric:fluid_renderer_test");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(ResourceManager rm) {
|
||||
FluidRenderHandler lavaHandler = FluidRenderHandlerRegistry.INSTANCE.get(Fluids.LAVA);
|
||||
FluidRenderHandlerRegistry.INSTANCE.register(Fluids.WATER, lavaHandler);
|
||||
FluidRenderHandlerRegistry.INSTANCE.register(Fluids.FLOWING_WATER, lavaHandler);
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ include 'fabric-networking-blockentity-v0'
|
|||
include 'fabric-object-builders-v0'
|
||||
include 'fabric-registry-sync-v0'
|
||||
include 'fabric-rendering-v0'
|
||||
include 'fabric-rendering-fluids-v1'
|
||||
include 'fabric-resource-loader-v0'
|
||||
include 'fabric-tag-extensions-v0'
|
||||
include 'fabric-textures-v0'
|
||||
|
|
Loading…
Reference in a new issue