From b825959626025f91806e78a093d22d54a5ac45cf Mon Sep 17 00:00:00 2001 From: Adrien1106 Date: Wed, 14 May 2025 02:25:15 +0200 Subject: [PATCH] fix: render issue with non collidable reframed + culling issue with vanilla blocks + Fixed #22 --- .../reframed/block/ReFramedEntity.java | 13 +++++---- .../reframed/client/util/RenderHelper.java | 14 ++++++---- .../reframed/mixin/render/BlockMixin.java | 27 +++++++++++++++++++ .../util/blocks/ThemeableBlockEntity.java | 2 ++ .../util/mixin/ThemedBlockEntity.java | 9 ++++++- 5 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 src/main/java/fr/adrien1106/reframed/mixin/render/BlockMixin.java diff --git a/src/main/java/fr/adrien1106/reframed/block/ReFramedEntity.java b/src/main/java/fr/adrien1106/reframed/block/ReFramedEntity.java index 73ec631..0f65247 100644 --- a/src/main/java/fr/adrien1106/reframed/block/ReFramedEntity.java +++ b/src/main/java/fr/adrien1106/reframed/block/ReFramedEntity.java @@ -32,12 +32,12 @@ public class ReFramedEntity extends BlockEntity implements ThemeableBlockEntity protected BlockState first_state = Blocks.AIR.getDefaultState(); protected byte bit_field = SOLIDITY_MASK; - protected static final byte LIGHT_MASK = 0b001; - protected static final byte REDSTONE_MASK = 0b010; - protected static final byte SOLIDITY_MASK = 0b100; + public static final byte LIGHT_MASK = 0b001; + public static final byte REDSTONE_MASK = 0b010; + public static final byte SOLIDITY_MASK = 0b100; public static final String BLOCKSTATE_KEY = "s"; - protected static final String BITFIELD_KEY = "b"; + public static final String BITFIELD_KEY = "b"; public ReFramedEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -145,7 +145,10 @@ public class ReFramedEntity extends BlockEntity implements ThemeableBlockEntity if (isSolid()) bit_field &= ~SOLIDITY_MASK; else bit_field |= SOLIDITY_MASK; - if(world != null) world.setBlockState(pos, getCachedState()); + if(world != null) { + world.setBlockState(pos, getCachedState()); + ReFramed.chunkRerenderProxy.accept(world, pos); + } markDirtyAndDispatch(); } diff --git a/src/main/java/fr/adrien1106/reframed/client/util/RenderHelper.java b/src/main/java/fr/adrien1106/reframed/client/util/RenderHelper.java index 095e714..93123a0 100644 --- a/src/main/java/fr/adrien1106/reframed/client/util/RenderHelper.java +++ b/src/main/java/fr/adrien1106/reframed/client/util/RenderHelper.java @@ -89,7 +89,11 @@ public class RenderHelper { BlockState self_theme = frame_entity.getTheme(theme_index); BlockState other_theme = frame_entity.getTheme(cull_theme); - if (self_theme.isSideInvisible(other_theme, null)) return false; + try { + if (self_theme.isSideInvisible(other_theme, null)) return false; + } catch (NullPointerException e) { // this can happen if mod haven't thought about inner faces + return true; + } return !self_theme.isOpaque() || !other_theme.isOpaque(); } @@ -104,7 +108,7 @@ public class RenderHelper { ? e : null; // normal behaviour - if (theme_index == 0 || (self == null && other == null)) + if ((theme_index == 0 && self != null) || (self == null && other == null)) return Block.shouldDrawSide(self_state, world, pos, side, other_pos); // self is a normal Block @@ -116,7 +120,7 @@ public class RenderHelper { VoxelShape other_shape = VoxelShapes.empty(); for (BlockState s: other.getThemes()) { i++; - if (self_state.isSideInvisible(s, side) || s.isOpaque()) + if (self_state.isSideInvisible(s, side) || (s.isOpaque() && (other.isSolid() || self_state.isTransparent(world ,pos)))) other_shape = combine( other_shape, other_block @@ -137,7 +141,7 @@ public class RenderHelper { if (self_theme.isSideInvisible(other_state, side)) return false; // Opaque is also simple as each model are rendered one by one - if (other_state.isOpaque()) { + if (other_state.isOpaque() && self.isSolid()) { // no cache section :( because it differs between each instance of the frame VoxelShape self_shape = self_block.getShape(self_state, theme_index).getFace(side); if (self_shape.isEmpty()) return true; @@ -160,7 +164,7 @@ public class RenderHelper { VoxelShape other_shape = VoxelShapes.empty(); for (BlockState s: other.getThemes()) { i++; - if (self_theme.isSideInvisible(s, side) || s.isOpaque()) + if (self_theme.isSideInvisible(s, side) || (s.isOpaque() && (!self.isSolid() || (other.isSolid() == self.isSolid())))) other_shape = combine( other_shape, other_block diff --git a/src/main/java/fr/adrien1106/reframed/mixin/render/BlockMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/render/BlockMixin.java new file mode 100644 index 0000000..08bc710 --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/render/BlockMixin.java @@ -0,0 +1,27 @@ +package fr.adrien1106.reframed.mixin.render; + +import fr.adrien1106.reframed.client.util.RenderHelper; +import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.BlockView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Block.class) +public abstract class BlockMixin { + + @Inject( + method = "shouldDrawSide", + at = @At("HEAD"), + cancellable = true + ) // serves as a safety sometimes mods implements culling cache and hence will break some injections... + private static void shouldDrawSide(BlockState state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, CallbackInfoReturnable cir) { + if (!(world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)) return; + cir.setReturnValue(RenderHelper.shouldDrawSide(state, world, pos, side, other_pos, 0)); + } +} diff --git a/src/main/java/fr/adrien1106/reframed/util/blocks/ThemeableBlockEntity.java b/src/main/java/fr/adrien1106/reframed/util/blocks/ThemeableBlockEntity.java index ace75e0..f2a096a 100644 --- a/src/main/java/fr/adrien1106/reframed/util/blocks/ThemeableBlockEntity.java +++ b/src/main/java/fr/adrien1106/reframed/util/blocks/ThemeableBlockEntity.java @@ -10,4 +10,6 @@ public interface ThemeableBlockEntity { void setTheme(BlockState state, int i); List getThemes(); + + boolean isSolid(); } diff --git a/src/main/java/fr/adrien1106/reframed/util/mixin/ThemedBlockEntity.java b/src/main/java/fr/adrien1106/reframed/util/mixin/ThemedBlockEntity.java index 9f5e6a2..d986cf2 100644 --- a/src/main/java/fr/adrien1106/reframed/util/mixin/ThemedBlockEntity.java +++ b/src/main/java/fr/adrien1106/reframed/util/mixin/ThemedBlockEntity.java @@ -12,10 +12,11 @@ import net.minecraft.util.math.BlockPos; import java.util.ArrayList; import java.util.List; -import static fr.adrien1106.reframed.block.ReFramedEntity.BLOCKSTATE_KEY; +import static fr.adrien1106.reframed.block.ReFramedEntity.*; public class ThemedBlockEntity extends BlockEntity implements ThemeableBlockEntity { private final List themes; + private final boolean isSolid; public ThemedBlockEntity(NbtCompound compound, BlockPos pos, BlockState state) { super(null, pos, state); @@ -26,6 +27,7 @@ public class ThemedBlockEntity extends BlockEntity implements ThemeableBlockEnti compound.getCompound(BLOCKSTATE_KEY + i) )); } + isSolid = !compound.contains(BITFIELD_KEY) || (compound.getByte(BITFIELD_KEY) & SOLIDITY_MASK) != 0; } @Override @@ -47,4 +49,9 @@ public class ThemedBlockEntity extends BlockEntity implements ThemeableBlockEnti public List getThemes() { return themes; } + + @Override + public boolean isSolid() { + return isSolid; + } }