From e7643f4544f61180ed2f0ff4952d7daa2c1feaf4 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Thu, 29 Aug 2024 16:21:02 -0700 Subject: [PATCH] Add API to allow conditional rendering of block entities (#2316) * Add API to allow conditional rendering of block entities - Extend BlockEntityType to store a predicate, always returning true by default. - Evaluate the predicate in ChunkBuilderMeshingTask before fetching the BlockEntityRenderer. - Expose a method to set the predicate for a given BlockEntityType in the API. * Update to latest dev * Fix build * Merge files * Make the predicate an array * Use custom predicate class --------- Co-authored-by: IMS212 --- .../blockentity/BlockEntityRenderHandler.java | 39 +++++++++++++++++++ .../BlockEntityRenderPredicate.java | 13 +++++++ .../chunk/BlockEntityRenderHandlerImpl.java | 20 ++++++++++ .../render/chunk/ExtendedBlockEntityType.java | 38 ++++++++++++++++++ .../tasks/ChunkBuilderMeshingTask.java | 3 +- .../core/render/BlockEntityTypeMixin.java | 39 +++++++++++++++++++ common/src/main/resources/sodium.mixins.json | 1 + 7 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 common/src/api/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderHandler.java create mode 100644 common/src/api/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderPredicate.java create mode 100644 common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/BlockEntityRenderHandlerImpl.java create mode 100644 common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ExtendedBlockEntityType.java create mode 100644 common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/BlockEntityTypeMixin.java diff --git a/common/src/api/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderHandler.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderHandler.java new file mode 100644 index 0000000000..b5de855a17 --- /dev/null +++ b/common/src/api/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderHandler.java @@ -0,0 +1,39 @@ +package net.caffeinemc.mods.sodium.api.blockentity; + +import java.util.function.Predicate; + +import net.caffeinemc.mods.sodium.api.internal.DependencyInjection; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Experimental +@ApiStatus.AvailableSince("0.6.0") +public interface BlockEntityRenderHandler { + BlockEntityRenderHandler INSTANCE = DependencyInjection.load(BlockEntityRenderHandler.class, + "net.caffeinemc.mods.sodium.client.render.chunk.BlockEntityRenderHandlerImpl"); + + static BlockEntityRenderHandler instance() { + return INSTANCE; + } + + /** + * Adds a predicate to determine if a block entity should be rendered. + * + *

Upon chunk bake, block entities of the given type will have {@code shouldRender} evaluated. + *
If all predicates returns {@code true} (and the block entity has a renderer), the block entity will be + * added to the chunk for future rendering.

+ * @param type The block entity type to associate the given predicate with. + * @param shouldRender The predicate for the block entity to evaluate. + */ + void addRenderPredicate(BlockEntityType type, BlockEntityRenderPredicate shouldRender); + + /** + * Removes a predicate added by {@code addRenderPredicate}. It must be the same object that was added. + * + * @param type The block entity type to associate the given predicate with. + * @param shouldRender The predicate to remove. + * @return If the predicate existed and was removed. + */ + boolean removeRenderPredicate(BlockEntityType type, BlockEntityRenderPredicate shouldRender); +} diff --git a/common/src/api/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderPredicate.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderPredicate.java new file mode 100644 index 0000000000..8ea1f6aa2b --- /dev/null +++ b/common/src/api/java/net/caffeinemc/mods/sodium/api/blockentity/BlockEntityRenderPredicate.java @@ -0,0 +1,13 @@ +package net.caffeinemc.mods.sodium.api.blockentity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.entity.BlockEntity; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Experimental +@ApiStatus.AvailableSince("0.6.0") +@FunctionalInterface +public interface BlockEntityRenderPredicate { + boolean shouldRender(BlockGetter blockGetter, BlockPos blockPos, T entity); +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/BlockEntityRenderHandlerImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/BlockEntityRenderHandlerImpl.java new file mode 100644 index 0000000000..56f323d708 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/BlockEntityRenderHandlerImpl.java @@ -0,0 +1,20 @@ +package net.caffeinemc.mods.sodium.client.render.chunk; + +import java.util.function.Predicate; + +import net.caffeinemc.mods.sodium.api.blockentity.BlockEntityRenderHandler; +import net.caffeinemc.mods.sodium.api.blockentity.BlockEntityRenderPredicate; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; + +public class BlockEntityRenderHandlerImpl implements BlockEntityRenderHandler { + @Override + public void addRenderPredicate(BlockEntityType type, BlockEntityRenderPredicate predicate) { + ExtendedBlockEntityType.addRenderPredicate(type, predicate); + } + + @Override + public boolean removeRenderPredicate(BlockEntityType type, BlockEntityRenderPredicate predicate) { + return ExtendedBlockEntityType.removeRenderPredicate(type, predicate); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ExtendedBlockEntityType.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ExtendedBlockEntityType.java new file mode 100644 index 0000000000..c74e5712a6 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ExtendedBlockEntityType.java @@ -0,0 +1,38 @@ +package net.caffeinemc.mods.sodium.client.render.chunk; + +import net.caffeinemc.mods.sodium.api.blockentity.BlockEntityRenderPredicate; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; + +import java.util.function.Predicate; + +@SuppressWarnings("unchecked") +public interface ExtendedBlockEntityType { + BlockEntityRenderPredicate[] sodium$getRenderPredicates(); + + void sodium$addRenderPredicate(BlockEntityRenderPredicate shouldAddRenderer); + + boolean sodium$removeRenderPredicate(BlockEntityRenderPredicate shouldAddRenderer); + + static boolean shouldRender(BlockEntityType type, BlockGetter blockGetter, BlockPos blockPos, T entity) { + BlockEntityRenderPredicate[] predicates = ((ExtendedBlockEntityType) type).sodium$getRenderPredicates(); + + for (int i = 0; i < predicates.length; i++) { + if (!predicates[i].shouldRender(blockGetter, blockPos, entity)) { + return false; + } + } + + return true; + } + + static void addRenderPredicate(BlockEntityType type, BlockEntityRenderPredicate predicate) { + ((ExtendedBlockEntityType) type).sodium$addRenderPredicate(predicate); + } + + static boolean removeRenderPredicate(BlockEntityType type, BlockEntityRenderPredicate predicate) { + return ((ExtendedBlockEntityType) type).sodium$removeRenderPredicate(predicate); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderMeshingTask.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderMeshingTask.java index 6a523f90c9..f3992c935a 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderMeshingTask.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderMeshingTask.java @@ -2,6 +2,7 @@ import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; import net.caffeinemc.mods.sodium.client.SodiumClientMod; +import net.caffeinemc.mods.sodium.client.render.chunk.ExtendedBlockEntityType; import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildContext; @@ -120,7 +121,7 @@ public ChunkBuildOutput execute(ChunkBuildContext buildContext, CancellationToke if (blockState.hasBlockEntity()) { BlockEntity entity = slice.getBlockEntity(blockPos); - if (entity != null) { + if (entity != null && ExtendedBlockEntityType.shouldRender(entity.getType(), slice, blockPos, entity)) { BlockEntityRenderer renderer = Minecraft.getInstance().getBlockEntityRenderDispatcher().getRenderer(entity); if (renderer != null) { diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/BlockEntityTypeMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/BlockEntityTypeMixin.java new file mode 100644 index 0000000000..63709d4ce4 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/BlockEntityTypeMixin.java @@ -0,0 +1,39 @@ +package net.caffeinemc.mods.sodium.mixin.core.render; + +import java.util.function.Predicate; + +import net.caffeinemc.mods.sodium.api.blockentity.BlockEntityRenderPredicate; +import net.caffeinemc.mods.sodium.client.render.chunk.ExtendedBlockEntityType; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import org.apache.commons.lang3.ArrayUtils; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(BlockEntityType.class) +public class BlockEntityTypeMixin implements ExtendedBlockEntityType { + @Unique + private BlockEntityRenderPredicate[] sodium$renderPredicates = new BlockEntityRenderPredicate[0]; + + @Override + public BlockEntityRenderPredicate[] sodium$getRenderPredicates() { + return sodium$renderPredicates; + } + + @Override + public void sodium$addRenderPredicate(BlockEntityRenderPredicate predicate) { + sodium$renderPredicates = ArrayUtils.add(sodium$renderPredicates, predicate); + } + + @Override + public boolean sodium$removeRenderPredicate(BlockEntityRenderPredicate predicate) { + int index = ArrayUtils.indexOf(sodium$renderPredicates, predicate); + + if (index == ArrayUtils.INDEX_NOT_FOUND) { + return false; + } + + sodium$renderPredicates = ArrayUtils.remove(sodium$renderPredicates, index); + return true; + } +} diff --git a/common/src/main/resources/sodium.mixins.json b/common/src/main/resources/sodium.mixins.json index e0edb7849f..c6b418863b 100644 --- a/common/src/main/resources/sodium.mixins.json +++ b/common/src/main/resources/sodium.mixins.json @@ -16,6 +16,7 @@ "core.model.colors.BlockColorsMixin", "core.model.colors.ItemColorsMixin", "core.model.FaceBakeryMixin", + "core.render.BlockEntityTypeMixin", "core.render.VertexFormatMixin", "core.render.frustum.FrustumMixin", "core.render.immediate.consumer.BufferBuilderMixin",