diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java index c156ff6e..72b43a2c 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java @@ -59,6 +59,7 @@ import org.jetbrains.annotations.NotNull; import thedarkcolour.exdeorum.block.BarrelBlock; import thedarkcolour.exdeorum.client.CompostColors; import thedarkcolour.exdeorum.config.EConfig; +import thedarkcolour.exdeorum.material.BarrelMaterial; import thedarkcolour.exdeorum.recipe.RecipeUtil; import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe; import thedarkcolour.exdeorum.registry.EBlockEntities; @@ -75,14 +76,17 @@ public class BarrelBlockEntity extends EBlockEntity { public short r, g, b; // Used to avoid triggering obsidian dupes in onContentsChanged, because Forge's FluidUtil actually modifies the tank for some reason private boolean isBeingFilledByPlayer; - - public BarrelBlockEntity(BlockPos pos, BlockState state) { - super(EBlockEntities.BARREL.get(), pos, state); - } + public final boolean transparent; private final LazyOptional itemHandler = LazyOptional.of(() -> this.item); private final LazyOptional fluidHandler = LazyOptional.of(() -> this.tank); + public BarrelBlockEntity(BlockPos pos, BlockState state) { + super(EBlockEntities.BARREL.get(), pos, state); + + this.transparent = BarrelMaterial.TRANSPARENT_BARRELS.contains(state.getBlock()); + } + @Override public LazyOptional getCapability(Capability cap, Direction side) { if (cap == ForgeCapabilities.FLUID_HANDLER) { diff --git a/src/main/java/thedarkcolour/exdeorum/client/RenderUtil.java b/src/main/java/thedarkcolour/exdeorum/client/RenderUtil.java index 82c36178..c134dff9 100644 --- a/src/main/java/thedarkcolour/exdeorum/client/RenderUtil.java +++ b/src/main/java/thedarkcolour/exdeorum/client/RenderUtil.java @@ -49,6 +49,7 @@ import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; import net.minecraftforge.client.model.CompositeModel; import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.registries.ForgeRegistries; +import org.joml.Matrix4f; import org.joml.Vector3f; import thedarkcolour.exdeorum.ExDeorum; import thedarkcolour.exdeorum.client.ter.SieveRenderer; @@ -171,6 +172,70 @@ public class RenderUtil { RenderUtil.renderFlatSprite(builder, stack, y, r, g, b, RenderUtil.blockAtlas.getSprite(extensions.getStillTexture(state, level, pos)), light, edge); } + @SuppressWarnings("DuplicatedCode") + public static void renderFluidCube(MultiBufferSource buffers, PoseStack stack, Level level, BlockPos pos, float minY, float maxY, float edge, int light, int r, int g, int b, Fluid fluid) { + var extensions = IClientFluidTypeExtensions.of(fluid); + var state = fluid.defaultFluidState(); + var builder = buffers.getBuffer(Sheets.translucentCullBlockSheet()); + var pose = stack.last().pose(); + var poseNormal = stack.last().normal(); + + Vector3f normal; + TextureAtlasSprite sprite = RenderUtil.blockAtlas.getSprite(extensions.getStillTexture(state, level, pos)); + float uMin = sprite.getU0(); + float uMax = sprite.getU1(); + float vMin = sprite.getV0(); + float vMax = sprite.getV1(); + + float edgeMin = edge / 16f; + float edgeMax = 1f - edge / 16f; + + // Top face + normal = poseNormal.transform(new Vector3f(0, 1, 0)); + builder.vertex(pose, edgeMin, maxY, edgeMin).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMin, maxY, edgeMax).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMax, maxY, edgeMax).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMax, maxY, edgeMin).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + // Bottom face + normal = poseNormal.transform(new Vector3f(0, -1, 0)); + builder.vertex(pose, edgeMin, minY, edgeMin).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMax, minY, edgeMin).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMax, minY, edgeMax).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMin, minY, edgeMax).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + + // Flowing texture coordinates + //sprite = RenderUtil.blockAtlas.getSprite(extensions.getFlowingTexture(state, level, pos)); + //uMin = sprite.getU0(); + //uMax = sprite.getU(8); + //vMin = sprite.getV0(); + //vMax = sprite.getV(8); + + // South face + normal = poseNormal.transform(new Vector3f(0, 0, 1)); + builder.vertex(pose, edgeMax, maxY, edgeMax).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMin, maxY, edgeMax).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMin, minY, edgeMax).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMax, minY, edgeMax).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + // North face + normal = poseNormal.transform(new Vector3f(0, 0, -1)); + builder.vertex(pose, edgeMin, maxY, edgeMin).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMax, maxY, edgeMin).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMax, minY, edgeMin).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMin, minY, edgeMin).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + // East face + normal = poseNormal.transform(new Vector3f(1, 0, 0)); + builder.vertex(pose, edgeMax, maxY, edgeMin).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMax, maxY, edgeMax).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMax, minY, edgeMax).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMax, minY, edgeMin).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + // West face + normal = poseNormal.transform(new Vector3f(-1, 0, 0)); + builder.vertex(pose, edgeMin, maxY, edgeMax).color(r, g, b, 255).uv(uMax, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMin, maxY, edgeMin).color(r, g, b, 255).uv(uMin, vMin).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMin, minY, edgeMin).color(r, g, b, 255).uv(uMin, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + builder.vertex(pose, edgeMin, minY, edgeMax).color(r, g, b, 255).uv(uMax, vMax).overlayCoords(0, 10).uv2(light).normal(normal.x, normal.y, normal.z).endVertex(); + } + // Renders a sprite inside the barrel with the height determined by how full the barrel is. public static void renderFlatSpriteLerp(VertexConsumer builder, PoseStack stack, float percentage, int r, int g, int b, TextureAtlasSprite sprite, int light, float edge, float yMin, float yMax) { float y = Mth.lerp(percentage, yMin, yMax) / 16f; diff --git a/src/main/java/thedarkcolour/exdeorum/client/ter/BarrelRenderer.java b/src/main/java/thedarkcolour/exdeorum/client/ter/BarrelRenderer.java index dd269ae1..68288451 100644 --- a/src/main/java/thedarkcolour/exdeorum/client/ter/BarrelRenderer.java +++ b/src/main/java/thedarkcolour/exdeorum/client/ter/BarrelRenderer.java @@ -97,7 +97,11 @@ public class BarrelRenderer implements BlockEntityRenderer { b = (int) Mth.lerp(progress, b, 65); } - RenderUtil.renderFlatFluidSprite(buffers, stack, level, pos, y, 2.0f, light, r, g, b, fluid); + if (barrel.transparent) { + RenderUtil.renderFluidCube(buffers, stack, level, pos, 1 / 16f, y, 2.0f, light, r, g, b, fluid); + } else { + RenderUtil.renderFlatFluidSprite(buffers, stack, level, pos, y, 2.0f, light, r, g, b, fluid); + } } }); diff --git a/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java b/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java index 2018dd78..a77963d2 100644 --- a/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java +++ b/src/main/java/thedarkcolour/exdeorum/event/EventHandler.java @@ -62,6 +62,7 @@ import thedarkcolour.exdeorum.compat.ModIds; import thedarkcolour.exdeorum.compat.top.ExDeorumTopCompat; import thedarkcolour.exdeorum.config.EConfig; import thedarkcolour.exdeorum.item.WateringCanItem; +import thedarkcolour.exdeorum.material.BarrelMaterial; import thedarkcolour.exdeorum.network.NetworkHandler; import thedarkcolour.exdeorum.network.VisualUpdateTracker; import thedarkcolour.exdeorum.recipe.RecipeUtil; @@ -170,6 +171,7 @@ public final class EventHandler { EFluids.WITCH_WATER_TYPE.get(), fluidState -> fluidState.isSource() ? Blocks.OBSIDIAN.defaultBlockState() : (EConfig.SERVER.witchWaterNetherrackGenerator.get() ? Blocks.NETHERRACK.defaultBlockState() : Blocks.COBBLESTONE.defaultBlockState()) )); + BarrelMaterial.loadTransparentBlocks(); }); } diff --git a/src/main/java/thedarkcolour/exdeorum/material/BarrelMaterial.java b/src/main/java/thedarkcolour/exdeorum/material/BarrelMaterial.java index b9b8d5b2..d0f1b18e 100644 --- a/src/main/java/thedarkcolour/exdeorum/material/BarrelMaterial.java +++ b/src/main/java/thedarkcolour/exdeorum/material/BarrelMaterial.java @@ -44,10 +44,12 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Set; public final class BarrelMaterial { // Use a linked hash map to maintain insertion order public static final List REGISTERED_MATERIALS = new ArrayList<>(); + public static final Set TRANSPARENT_BARRELS = new HashSet<>(); private static final Path CUSTOM_BARREL_MATERIAL_CONFIGS = Paths.get("config/exdeorum/barrel_materials"); @@ -226,6 +228,14 @@ public final class BarrelMaterial { return new BlockEntityType<>(BarrelBlockEntity::new, validBlocks, null); } + public static void loadTransparentBlocks() { + for (var material : REGISTERED_MATERIALS) { + if (material.transparent) { + TRANSPARENT_BARRELS.add(material.getBlock()); + } + } + } + // Does not check if the mod is registered public Item getItem() { return this.item.get();