Skip to content

Commit

Permalink
Add API to allow conditional rendering of block entities (#2316)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
Jozufozu and IMS212 authored Aug 29, 2024
1 parent 06ad694 commit e7643f4
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>Upon chunk bake, block entities of the given type will have {@code shouldRender} evaluated.
* <br>If <b>all predicates</b> returns {@code true} (and the block entity has a renderer), the block entity will be
* added to the chunk for future rendering.</p>
* @param type The block entity type to associate the given predicate with.
* @param shouldRender The predicate for the block entity to evaluate.
*/
<T extends BlockEntity> void addRenderPredicate(BlockEntityType<T> type, BlockEntityRenderPredicate<T> shouldRender);

/**
* Removes a predicate added by {@code addRenderPredicate}. <b>It must be the same object that was added.</b>
*
* @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.
*/
<T extends BlockEntity> boolean removeRenderPredicate(BlockEntityType<T> type, BlockEntityRenderPredicate<T> shouldRender);
}
Original file line number Diff line number Diff line change
@@ -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<T extends BlockEntity> {
boolean shouldRender(BlockGetter blockGetter, BlockPos blockPos, T entity);
}
Original file line number Diff line number Diff line change
@@ -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 <T extends BlockEntity> void addRenderPredicate(BlockEntityType<T> type, BlockEntityRenderPredicate<T> predicate) {
ExtendedBlockEntityType.addRenderPredicate(type, predicate);
}

@Override
public <T extends BlockEntity> boolean removeRenderPredicate(BlockEntityType<T> type, BlockEntityRenderPredicate<T> predicate) {
return ExtendedBlockEntityType.removeRenderPredicate(type, predicate);
}
}
Original file line number Diff line number Diff line change
@@ -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<T extends BlockEntity> {
BlockEntityRenderPredicate<T>[] sodium$getRenderPredicates();

void sodium$addRenderPredicate(BlockEntityRenderPredicate<T> shouldAddRenderer);

boolean sodium$removeRenderPredicate(BlockEntityRenderPredicate<T> shouldAddRenderer);

static <T extends BlockEntity> boolean shouldRender(BlockEntityType<? extends T> type, BlockGetter blockGetter, BlockPos blockPos, T entity) {
BlockEntityRenderPredicate<T>[] predicates = ((ExtendedBlockEntityType<T>) type).sodium$getRenderPredicates();

for (int i = 0; i < predicates.length; i++) {
if (!predicates[i].shouldRender(blockGetter, blockPos, entity)) {
return false;
}
}

return true;
}

static <T extends BlockEntity> void addRenderPredicate(BlockEntityType<T> type, BlockEntityRenderPredicate<T> predicate) {
((ExtendedBlockEntityType<T>) type).sodium$addRenderPredicate(predicate);
}

static <T extends BlockEntity> boolean removeRenderPredicate(BlockEntityType<T> type, BlockEntityRenderPredicate<T> predicate) {
return ((ExtendedBlockEntityType<T>) type).sodium$removeRenderPredicate(predicate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<BlockEntity> renderer = Minecraft.getInstance().getBlockEntityRenderDispatcher().getRenderer(entity);

if (renderer != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<T extends BlockEntity> implements ExtendedBlockEntityType<T> {
@Unique
private BlockEntityRenderPredicate<T>[] sodium$renderPredicates = new BlockEntityRenderPredicate[0];

@Override
public BlockEntityRenderPredicate<T>[] sodium$getRenderPredicates() {
return sodium$renderPredicates;
}

@Override
public void sodium$addRenderPredicate(BlockEntityRenderPredicate<T> predicate) {
sodium$renderPredicates = ArrayUtils.add(sodium$renderPredicates, predicate);
}

@Override
public boolean sodium$removeRenderPredicate(BlockEntityRenderPredicate<T> 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;
}
}
1 change: 1 addition & 0 deletions common/src/main/resources/sodium.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit e7643f4

Please sign in to comment.