diff --git a/src/main/java/fr/adrien1106/reframed/ReFramed.java b/src/main/java/fr/adrien1106/reframed/ReFramed.java index 04c08ff..e106997 100644 --- a/src/main/java/fr/adrien1106/reframed/ReFramed.java +++ b/src/main/java/fr/adrien1106/reframed/ReFramed.java @@ -135,11 +135,11 @@ public class ReFramed implements ModInitializer { private static AbstractBlock.Settings cp(Block base) { return AbstractBlock.Settings.copy(base) .luminance(state -> state.contains(LIGHT) && state.get(LIGHT) ? 15 : 0) - .nonOpaque() .sounds(BlockSoundGroup.WOOD) .hardness(0.2f) - .suffocates((a,b,c) -> false) - .blockVision((a,b,c) -> false); + .suffocates(Blocks::never) + .solidBlock(Blocks::always) + .blockVision(Blocks::always); } private static I registerItem(String path, I item) { diff --git a/src/main/java/fr/adrien1106/reframed/block/ReFramedBlock.java b/src/main/java/fr/adrien1106/reframed/block/ReFramedBlock.java index 274099e..e10d7b8 100644 --- a/src/main/java/fr/adrien1106/reframed/block/ReFramedBlock.java +++ b/src/main/java/fr/adrien1106/reframed/block/ReFramedBlock.java @@ -2,9 +2,11 @@ package fr.adrien1106.reframed.block; import fr.adrien1106.reframed.ReFramed; import fr.adrien1106.reframed.util.blocks.BlockHelper; +import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity; import net.minecraft.block.*; import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.pathing.NavigationType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemPlacementContext; @@ -17,6 +19,7 @@ import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.ItemScatterer; import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.function.BooleanBiFunction; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; @@ -31,6 +34,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; import static fr.adrien1106.reframed.block.ReFramedEntity.BLOCKSTATE_KEY; @@ -39,10 +43,26 @@ import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT; public class ReFramedBlock extends Block implements BlockEntityProvider { public ReFramedBlock(Settings settings) { - super(settings); + super(settings.dynamicBounds()); setDefaultState(getDefaultState().with(LIGHT, false)); } + @Override + @SuppressWarnings("deprecation") + public int getOpacity(BlockState state, BlockView world, BlockPos pos) { + if (state.get(LIGHT)) return 0; + if (!(world.getBlockEntity(pos) instanceof ReFramedEntity frame_entity) + || frame_entity.getTheme(0).isOpaque()) + return world.getMaxLightLevel(); + return 0; + } + + @Override + @SuppressWarnings("deprecation") + public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { + return false; + } + @Override public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) { return ReFramed.REFRAMED_BLOCK_ENTITY.instantiate(pos, state); @@ -208,4 +228,17 @@ public class ReFramedBlock extends Block implements BlockEntityProvider { public Map getThemeMap(BlockState state, BlockState new_state) { return Map.of(); } + + public VoxelShape getShadingShape(BlockState state, BlockView world, BlockPos pos) { + if (!(world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity)) return this.getCollisionShape(state, world, pos, ShapeContext.absent()); + + AtomicInteger i = new AtomicInteger(1); + return framed_entity.getThemes().stream().map((theme) -> { + int index = i.getAndIncrement(); + return theme.isTransparent(world, pos) ? VoxelShapes.empty() : this.getShape(state, index); + }).reduce( + VoxelShapes.empty(), + (prev, current) -> VoxelShapes.combine(prev, current, BooleanBiFunction.OR) + ); + } } diff --git a/src/main/java/fr/adrien1106/reframed/block/WaterloggableReFramedBlock.java b/src/main/java/fr/adrien1106/reframed/block/WaterloggableReFramedBlock.java index b0040bb..02945b5 100644 --- a/src/main/java/fr/adrien1106/reframed/block/WaterloggableReFramedBlock.java +++ b/src/main/java/fr/adrien1106/reframed/block/WaterloggableReFramedBlock.java @@ -23,7 +23,13 @@ public class WaterloggableReFramedBlock extends ReFramedBlock implements Waterlo protected void appendProperties(StateManager.Builder builder) { super.appendProperties(builder.add(Properties.WATERLOGGED)); } - + + @Override + @SuppressWarnings("deprecation") + public boolean hasSidedTransparency(BlockState state) { + return true; + } + @Nullable @Override public BlockState getPlacementState(ItemPlacementContext ctx) { diff --git a/src/main/java/fr/adrien1106/reframed/client/model/apperance/CamoAppearanceManager.java b/src/main/java/fr/adrien1106/reframed/client/model/apperance/CamoAppearanceManager.java index f5d1b9d..c489de6 100644 --- a/src/main/java/fr/adrien1106/reframed/client/model/apperance/CamoAppearanceManager.java +++ b/src/main/java/fr/adrien1106/reframed/client/model/apperance/CamoAppearanceManager.java @@ -51,7 +51,7 @@ public class CamoAppearanceManager { for(BlendMode blend : BlendMode.values()) { finder.clear().disableDiffuse(false).blendMode(blend); - materials.put(blend, finder.ambientOcclusion(TriState.FALSE).find()); + materials.put(blend, finder.ambientOcclusion(TriState.TRUE).find()); ao_materials.put(blend, finder.ambientOcclusion(TriState.DEFAULT).find()); //not "true" since that *forces* AO, i just want to *allow* AO } diff --git a/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java b/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java index 054d8ad..1417a1a 100644 --- a/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java +++ b/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java @@ -31,6 +31,8 @@ public class CompatMixinPlugin implements IMixinConfigPlugin { CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumNonTerrainBlockRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1))); CONDITIONS.put("fr.adrien1106.reframed.mixin.render.BlockRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.SodiumBlockOcclusionCacheMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(2))); + CONDITIONS.put("fr.adrien1106.reframed.mixin.render.FluidRendererMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(2))); + CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.SodiumFluidRendererMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(2))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityConnectionPredicateMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityCTMBakedModelMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityCTMQuadTransformMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4))); diff --git a/src/main/java/fr/adrien1106/reframed/mixin/compat/SodiumFluidRendererMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/compat/SodiumFluidRendererMixin.java new file mode 100644 index 0000000..6618deb --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/compat/SodiumFluidRendererMixin.java @@ -0,0 +1,62 @@ +package fr.adrien1106.reframed.mixin.compat; + +import com.llamalad7.mixinextras.sugar.Local; +import fr.adrien1106.reframed.block.ReFramedBlock; +import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity; +import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer; +import me.jellysquid.mods.sodium.client.world.WorldSlice; +import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry; +import net.minecraft.block.*; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.BlockView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(FluidRenderer.class) +public abstract class SodiumFluidRendererMixin { + + @Redirect( + method = "isSideExposed", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/BlockState;isOpaque()Z" + ) + ) + private boolean isSideOpaqueExposed(BlockState state) { + if (!(state.getBlock() instanceof ReFramedBlock)) return state.isOpaque(); + return true; // forces to compute correct shape + } + + @Redirect( + method = "isSideExposed", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/BlockState;getCullingShape(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/util/shape/VoxelShape;" + ) + ) + private VoxelShape isSideShapeExposed(BlockState state, BlockView world, BlockPos pos) { + if (!(state.getBlock() instanceof ReFramedBlock block)) return state.getCullingShape(world, pos); + return block.getShadingShape(state, world, pos); + } + + @Redirect( + method = "render", + at = @At( + value = "INVOKE", + target = "Lnet/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandlerRegistry;isBlockTransparent(Lnet/minecraft/block/Block;)Z" + ) + ) + private boolean getThemeState(FluidRenderHandlerRegistry fluid_handler, Block block, @Local(argsOnly = true) WorldSlice world, @Local(ordinal = 2) BlockPos pos, @Local BlockState state, @Local Direction dir) { + if (!(block instanceof ReFramedBlock rfblock && world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity)) return fluid_handler.isBlockTransparent(block); + return !VoxelShapes.isSideCovered(VoxelShapes.fullCube(), rfblock.getShadingShape(state, world, pos), dir) + && framed_entity.getThemes().stream() + .anyMatch(s -> s.getBlock() instanceof LeavesBlock + || s.getBlock() instanceof TranslucentBlock + || s.getBlock() instanceof AirBlock + ); + } +} diff --git a/src/main/java/fr/adrien1106/reframed/mixin/render/FluidRendererMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/render/FluidRendererMixin.java new file mode 100644 index 0000000..44da9ba --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/render/FluidRendererMixin.java @@ -0,0 +1,56 @@ +package fr.adrien1106.reframed.mixin.render; + +import fr.adrien1106.reframed.block.ReFramedBlock; +import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity; +import net.minecraft.block.*; +import net.minecraft.client.render.block.FluidRenderer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.BlockRenderView; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(FluidRenderer.class) +public abstract class FluidRendererMixin { + + @Inject( + method = "isSideCovered(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/Direction;FLnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)Z", + at = @At("HEAD"), + cancellable = true + ) // force dynamic water side rendering + private static void isSameSideCovered(BlockView world, Direction direction, float height, BlockPos pos, BlockState state, CallbackInfoReturnable cir) { + if (!(state.getBlock() instanceof ReFramedBlock block) + ) return; + + boolean is_covered = VoxelShapes.isSideCovered( + VoxelShapes.cuboid(0.0, 0.0, 0.0, 1.0, height, 1.0), + block.getShadingShape(state, world, pos), + direction + ); + cir.setReturnValue(is_covered); + } + + @Redirect( + method = "render", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/BlockRenderView;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;", + ordinal = 7 + ) + ) + private BlockState getThemeState(BlockRenderView world, BlockPos pos) { + if (!(world.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity)) return world.getBlockState(pos); + return framed_entity.getThemes().stream() + .anyMatch(state -> state.getBlock() instanceof LeavesBlock + || state.getBlock() instanceof TranslucentBlock + || state.getBlock() instanceof AirBlock + ) + ? Blocks.GLASS.getDefaultState() + : world.getBlockState(pos) ; + } +} diff --git a/src/main/resources/reframed.mixins.json b/src/main/resources/reframed.mixins.json index aa9083f..ebbbf03 100644 --- a/src/main/resources/reframed.mixins.json +++ b/src/main/resources/reframed.mixins.json @@ -33,14 +33,17 @@ "compat.IndiumNonTerrainBlockRenderContextMixin", "compat.IndiumTerrainRenderContextMixin", "compat.SodiumBlockOcclusionCacheMixin", + "compat.SodiumFluidRendererMixin", "model.WeightedBakedModelAccessor", "particles.AccessorParticle", "particles.AccessorSpriteBillboardParticle", "particles.MixinBlockDustParticle", "render.AbstractBlockRenderContextMixin", + "render.BlockMixin", "render.BlockModelRendererMixin", "render.BlockRenderContextMixin", "render.BlockRenderInfoMixin", + "render.FluidRendererMixin", "render.MultipartBakedModelMixin", "render.TerrainRenderContextMixin", "render.WorldRendererMixin",