From b88a4abfe5e8421793bbc1d6701a90eed374121e Mon Sep 17 00:00:00 2001 From: Adrien1106 Date: Thu, 13 Jun 2024 22:51:05 +0200 Subject: [PATCH] feat: more axiom support (connected textures and culling in selections) + newer version --- .../model/DoubleRetexturingBakedModel.java | 5 +- .../client/model/RetexturingBakedModel.java | 1 + .../reframed/client/util/RenderHelper.java | 14 +-- .../reframed/mixin/CompatMixinPlugin.java | 5 +- .../compat/AxiomChunkedBlockRegionMixin.java | 88 +++++++++---------- .../AxiomMappedBlockAndTintGetterMixin.java | 32 +++++++ .../compat/IndiumBlockRenderInfoMixin.java | 66 ++++++++++++++ ...diumNonTerrainBlockRenderContextMixin.java | 84 ++++++++++++++++++ .../IndiumTerrainBlockRenderInfoMixin.java | 55 ------------ .../mixin/render/BlockModelRendererMixin.java | 40 +++++++++ .../mixin/render/BlockRenderContextMixin.java | 78 ++++++++++++++++ src/main/resources/reframed.mixins.json | 6 +- 12 files changed, 364 insertions(+), 110 deletions(-) create mode 100644 src/main/java/fr/adrien1106/reframed/mixin/compat/AxiomMappedBlockAndTintGetterMixin.java create mode 100644 src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumBlockRenderInfoMixin.java create mode 100644 src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumNonTerrainBlockRenderContextMixin.java delete mode 100644 src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumTerrainBlockRenderInfoMixin.java create mode 100644 src/main/java/fr/adrien1106/reframed/mixin/render/BlockModelRendererMixin.java create mode 100644 src/main/java/fr/adrien1106/reframed/mixin/render/BlockRenderContextMixin.java diff --git a/src/main/java/fr/adrien1106/reframed/client/model/DoubleRetexturingBakedModel.java b/src/main/java/fr/adrien1106/reframed/client/model/DoubleRetexturingBakedModel.java index 2661a1f..6757e42 100644 --- a/src/main/java/fr/adrien1106/reframed/client/model/DoubleRetexturingBakedModel.java +++ b/src/main/java/fr/adrien1106/reframed/client/model/DoubleRetexturingBakedModel.java @@ -45,7 +45,10 @@ public class DoubleRetexturingBakedModel extends ForwardingBakedModel implements } @Override - public void emitBlockQuads(BlockRenderView world, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) {} + public void emitBlockQuads(BlockRenderView world, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { + model_1.emitBlockQuads(world, state, pos, randomSupplier, context); + model_2.emitBlockQuads(world, state, pos, randomSupplier, context); + } @Override // models are emitted here because no checks are done on items public void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) { diff --git a/src/main/java/fr/adrien1106/reframed/client/model/RetexturingBakedModel.java b/src/main/java/fr/adrien1106/reframed/client/model/RetexturingBakedModel.java index 9dcbc87..4c1ad02 100644 --- a/src/main/java/fr/adrien1106/reframed/client/model/RetexturingBakedModel.java +++ b/src/main/java/fr/adrien1106/reframed/client/model/RetexturingBakedModel.java @@ -125,6 +125,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel { @Override public void emitBlockQuads(BlockRenderView world, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { BlockState theme = (world.getBlockEntity(pos) instanceof ThemeableBlockEntity s) ? s.getTheme(theme_index) : null; + QuadEmitter quad_emitter = context.getEmitter(); if(theme == null || theme.isAir()) { getRetexturedMesh( 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 a881b7d..095e714 100644 --- a/src/main/java/fr/adrien1106/reframed/client/util/RenderHelper.java +++ b/src/main/java/fr/adrien1106/reframed/client/util/RenderHelper.java @@ -12,7 +12,6 @@ import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.renderer.v1.Renderer; import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; -import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.util.function.BooleanBiFunction; @@ -52,8 +51,6 @@ public class RenderHelper { Random random = Random.create(); List> model_bounds = models.stream() - .map(ForwardingBakedModel::getWrappedModel) - .filter(Objects::nonNull) .map(wrapped -> wrapped.getQuads(state, null, random)) .map(quads -> quads.stream().map(quad -> { quad_emitter.fromVanilla(quad, material, null); @@ -98,12 +95,17 @@ public class RenderHelper { // Doing this method from scratch as it is simpler to do than injecting everywhere public static boolean shouldDrawSide(BlockState self_state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, int theme_index) { - ThemeableBlockEntity self = world.getBlockEntity(pos) instanceof ThemeableBlockEntity e ? e : null; - ThemeableBlockEntity other = world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity e ? e : null; BlockState other_state = world.getBlockState(other_pos); + ThemeableBlockEntity self = world.getBlockEntity(pos) instanceof ThemeableBlockEntity e + && self_state.getBlock() instanceof ReFramedBlock + ? e : null; + ThemeableBlockEntity other = world.getBlockEntity(other_pos) instanceof ThemeableBlockEntity e + && other_state.getBlock() instanceof ReFramedBlock + ? e : null; // normal behaviour - if (self == null && other == null) return Block.shouldDrawSide(self_state, world, pos, side, other_pos); + if (theme_index == 0 || (self == null && other == null)) + return Block.shouldDrawSide(self_state, world, pos, side, other_pos); // self is a normal Block if (self == null && other_state.getBlock() instanceof ReFramedBlock other_block) { diff --git a/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java b/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java index 81f784f..054d8ad 100644 --- a/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java +++ b/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java @@ -26,8 +26,10 @@ public class CompatMixinPlugin implements IMixinConfigPlugin { CONDITIONS.put("fr.adrien1106.reframed.mixin.render.BlockRenderInfoMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1))); CONDITIONS.put("fr.adrien1106.reframed.mixin.render.AbstractBlockRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumTerrainRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1))); - CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumTerrainBlockRenderInfoMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumAbstractBlockRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1))); + CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.IndiumBlockRenderInfoMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1))); + 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.compat.ContinuityConnectionPredicateMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.ContinuityCTMBakedModelMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(4))); @@ -38,6 +40,7 @@ public class CompatMixinPlugin implements IMixinConfigPlugin { CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomClipboardMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomCloneBuilderToolMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomPlacementMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5))); + CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomMappedBlockAndTintGetterMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomMoveBuilderToolMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomScale3xMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5))); CONDITIONS.put("fr.adrien1106.reframed.mixin.compat.AxiomRotSpriteMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(5))); diff --git a/src/main/java/fr/adrien1106/reframed/mixin/compat/AxiomChunkedBlockRegionMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/compat/AxiomChunkedBlockRegionMixin.java index d5b2ad9..1ded159 100644 --- a/src/main/java/fr/adrien1106/reframed/mixin/compat/AxiomChunkedBlockRegionMixin.java +++ b/src/main/java/fr/adrien1106/reframed/mixin/compat/AxiomChunkedBlockRegionMixin.java @@ -1,5 +1,6 @@ package fr.adrien1106.reframed.mixin.compat; +import com.llamalad7.mixinextras.sugar.Local; import com.moulberry.axiom.render.regions.ChunkedBlockRegion; import com.moulberry.axiom.utils.IntMatrix; import com.moulberry.axiom.world_modification.CompressedBlockEntity; @@ -9,29 +10,27 @@ import fr.adrien1106.reframed.util.mixin.IAxiomChunkedBlockRegionMixin; import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin; import fr.adrien1106.reframed.util.mixin.ThemedBlockEntity; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.Camera; +import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.block.BlockRenderManager; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtHelper; -import net.minecraft.registry.Registries; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.random.Random; import net.minecraft.world.BlockRenderView; +import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; 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.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -43,11 +42,10 @@ import static fr.adrien1106.reframed.block.ReFramedEntity.BLOCKSTATE_KEY; @Mixin(ChunkedBlockRegion.class) // TODO: Look here for better rotation/flip support public abstract class AxiomChunkedBlockRegionMixin implements IAxiomChunkedBlockRegionMixin { - @Shadow - private static void renderBlock(BufferBuilder blockBuilder, BlockRenderManager renderManager, BlockPos.Mutable blockPos, Random rand, MatrixStack matrices, BlockRenderView blockAndTintGetter, Matrix4f currentPoseMatrix, Matrix4f basePoseMatrix, int x, int y, int z, BlockState dataState, boolean useAmbientOcclusion) {} - @Shadow public abstract BlockState getBlockState(BlockPos pos); + @Shadow public abstract @Nullable BlockEntity getBlockEntity(BlockPos pos); + @Unique private IntMatrix transform; @Unique @@ -55,48 +53,46 @@ public abstract class AxiomChunkedBlockRegionMixin implements IAxiomChunkedBlock @Unique private Long2ObjectMap block_entities; + @Unique + private static boolean isFrameModel(BakedModel model) { + return model instanceof RetexturingBakedModel || model instanceof MultiRetexturableModel; + } - @Redirect( - method = "uploadDirty", + @Unique + private static List getModels(BakedModel model, BlockState state) { + if (isFrameModel(model)) + return List.of(model); + else if (model instanceof IMultipartBakedModelMixin mpm) + return mpm.getModels(state).stream().filter(AxiomChunkedBlockRegionMixin::isFrameModel).toList(); + else + return List.of(); + } + + @Inject( + method = "renderBlock", at = @At( - value = "INVOKE", - target = "Lcom/moulberry/axiom/render/regions/ChunkedBlockRegion;renderBlock(Lnet/minecraft/client/render/BufferBuilder;Lnet/minecraft/client/render/block/BlockRenderManager;Lnet/minecraft/util/math/BlockPos$Mutable;Lnet/minecraft/util/math/random/Random;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/world/BlockRenderView;Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;IIILnet/minecraft/block/BlockState;Z)V" - ) - ) - private void onRenderBlock(BufferBuilder buffer, BlockRenderManager renderer, BlockPos.Mutable pos, Random rand, MatrixStack matrices, BlockRenderView world, Matrix4f current_pos, Matrix4f base_pos, int x, int y, int z, BlockState state, boolean use_ao) { - BakedModel model; + value = "INVOKE_ASSIGN", + target = "Lnet/minecraft/client/render/block/BlockRenderManager;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BakedModel;", + shift = At.Shift.AFTER + ), + cancellable = true) + private static void onRenderBlock(BufferBuilder blockBuilder, BlockRenderManager renderer, BlockPos.Mutable pos, Random rand, MatrixStack matrices, BlockRenderView world, Matrix4f currentPoseMatrix, Matrix4f basePoseMatrix, int x, int y, int z, BlockState state, boolean useAmbientOcclusion, CallbackInfo ci, @Local BakedModel model) { List models; - if (block_entities != null - && state.getRenderType() == BlockRenderType.MODEL - && (model = renderer.getModel(state)) != null - && model instanceof IMultipartBakedModelMixin mpm - && !(models = mpm.getModels(state) - .stream() - .filter(m -> m instanceof RetexturingBakedModel || m instanceof MultiRetexturableModel) - .toList()).isEmpty() - ) { - long key = BlockPos.asLong( - inverse_transform.transformX(pos.getX(), pos.getY(), pos.getZ()), - inverse_transform.transformY(pos.getX(), pos.getY(), pos.getZ()), - inverse_transform.transformZ(pos.getX(), pos.getY(), pos.getZ()) - ); - if (block_entities.containsKey(key)) { - NbtCompound compound = block_entities.get(key).decompress(); - models.stream() - .flatMap(m -> m instanceof MultiRetexturableModel mm - ? mm.models().stream() - : Stream.of((RetexturingBakedModel)m) - ) - .forEach(m -> m.setCamo( - world, - compound.contains(BLOCKSTATE_KEY + m.getThemeIndex()) - ? NbtHelper.toBlockState(Registries.BLOCK.getReadOnlyWrapper(), compound.getCompound(BLOCKSTATE_KEY + m.getThemeIndex())) - : null, - pos - )); - } - } - renderBlock(buffer, renderer, pos, rand, matrices, world, current_pos, base_pos, x, y, z, state, use_ao); + if ((models = getModels(model, state)).isEmpty() // not a retexturable model + || !(world.getBlockEntity(pos) instanceof ThemedBlockEntity block_entity) // not a themed block entity + ) return; + + models.stream().flatMap(m -> m instanceof MultiRetexturableModel mm + ? mm.models().stream() + : Stream.of((RetexturingBakedModel)m) + ).forEach(m -> { + m.setCamo(world, block_entity.getTheme(m.getThemeIndex()), pos); + if (useAmbientOcclusion && state.getLuminance() == 0 && m.useAmbientOcclusion()) renderer.getModelRenderer() + .renderSmooth(world, m, state, pos, matrices, blockBuilder, true, rand, state.getRenderingSeed(pos), OverlayTexture.DEFAULT_UV); + else renderer.getModelRenderer() + .renderFlat(world, m, state, pos, matrices, blockBuilder, true, rand, state.getRenderingSeed(pos), OverlayTexture.DEFAULT_UV); + }); + ci.cancel(); } @Inject( diff --git a/src/main/java/fr/adrien1106/reframed/mixin/compat/AxiomMappedBlockAndTintGetterMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/compat/AxiomMappedBlockAndTintGetterMixin.java new file mode 100644 index 0000000..45fb241 --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/compat/AxiomMappedBlockAndTintGetterMixin.java @@ -0,0 +1,32 @@ +package fr.adrien1106.reframed.mixin.compat; + +import fr.adrien1106.reframed.block.ReFramedEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(targets = "com.moulberry.axiom.render.ChunkRenderOverrider$MappedBlockAndTintGetter") +public class AxiomMappedBlockAndTintGetterMixin { + + @Shadow @Final private World level; + + @Inject( + method = "getBlockEntity", + at = @At( + value = "RETURN" + ), + remap = false, + cancellable = true + ) + private void onGetBlockEntity(BlockPos pos, CallbackInfoReturnable cir) { + if (!(level.getBlockEntity(pos) instanceof ReFramedEntity frame_entity)) return; + cir.setReturnValue(frame_entity); + } + +} diff --git a/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumBlockRenderInfoMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumBlockRenderInfoMixin.java new file mode 100644 index 0000000..cfe0aaf --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumBlockRenderInfoMixin.java @@ -0,0 +1,66 @@ +package fr.adrien1106.reframed.mixin.compat; + +import com.llamalad7.mixinextras.sugar.Local; +import fr.adrien1106.reframed.client.util.RenderHelper; +import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity; +import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin; +import link.infra.indium.renderer.render.BlockRenderInfo; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.BlockRenderView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(BlockRenderInfo.class) +public abstract class IndiumBlockRenderInfoMixin implements IBlockRenderInfoMixin { + + @Shadow public abstract void prepareForBlock(BlockState blockState, BlockPos blockPos, long seed, boolean modelAo); + + @Shadow public BlockPos blockPos; + @Shadow public BlockRenderView blockView; + @Shadow public BlockState blockState; + @Shadow(remap = false) private int cullResultFlags; + + @Unique private int theme_index = 0; + @Unique private int model_hash = 0; + + @Inject( + method = "shouldDrawFace", + at = @At( + value = "INVOKE", + target = "Llink/infra/indium/renderer/render/BlockRenderInfo;shouldDrawFaceInner(Lnet/minecraft/util/math/Direction;)Z" + ), + cancellable = true + ) + private void shouldDrawInnerFace(Direction face, CallbackInfoReturnable cir, @Local int mask) { + BlockPos other_pos = blockPos.offset(face); + if (!(blockView.getBlockEntity(blockPos) instanceof ThemeableBlockEntity + || blockView.getBlockEntity(other_pos) instanceof ThemeableBlockEntity) + ) return; + boolean result = RenderHelper.shouldDrawSide(blockState, blockView, blockPos, face, other_pos, theme_index); + if (result) cullResultFlags |= mask; + cir.setReturnValue(result); + } + + @Override + public void prepareForBlock(BlockState blockState, BlockPos blockPos, long seed, boolean modelAo, int theme_index, int model_hash) { + this.theme_index = theme_index; + this.model_hash = model_hash; + prepareForBlock(blockState, blockPos, seed, modelAo); + } + + @Override + public int getThemeIndex() { + return theme_index; + } + + @Override + public int getModelHash() { + return model_hash; + } +} diff --git a/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumNonTerrainBlockRenderContextMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumNonTerrainBlockRenderContextMixin.java new file mode 100644 index 0000000..f435b3d --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumNonTerrainBlockRenderContextMixin.java @@ -0,0 +1,84 @@ +package fr.adrien1106.reframed.mixin.compat; + +import fr.adrien1106.reframed.client.model.MultiRetexturableModel; +import fr.adrien1106.reframed.client.model.RetexturingBakedModel; +import fr.adrien1106.reframed.client.util.RenderHelper; +import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin; +import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin; +import link.infra.indium.renderer.aocalc.AoCalculator; +import link.infra.indium.renderer.render.AbstractBlockRenderContext; +import link.infra.indium.renderer.render.BlockRenderInfo; +import link.infra.indium.renderer.render.NonTerrainBlockRenderContext; +import link.infra.indium.renderer.render.SingleBlockLightDataCache; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.BlockRenderView; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(NonTerrainBlockRenderContext.class) +public abstract class IndiumNonTerrainBlockRenderContextMixin extends AbstractBlockRenderContext { + + @Shadow(remap = false) @Final private SingleBlockLightDataCache lightCache; + + @Shadow private VertexConsumer vertexConsumer; + + @Inject( + method = "render", + at = @At( + value = "INVOKE", + target = "Llink/infra/indium/renderer/render/BlockRenderInfo;prepareForWorld(Lnet/minecraft/world/BlockRenderView;Z)V", + shift = At.Shift.AFTER + ), + remap = false, + cancellable = true + ) + private void renderMultipleModels(BlockRenderView blockView, BakedModel wrapper, BlockState state, BlockPos pos, MatrixStack matrixStack, VertexConsumer buffer, boolean cull, Random random, long seed, int overlay, CallbackInfo ci) { + if (!(wrapper instanceof IMultipartBakedModelMixin wrapped)) return; + List models = wrapped.getModels(state); + if (models.stream().noneMatch(bakedModel -> + bakedModel instanceof MultiRetexturableModel + || bakedModel instanceof RetexturingBakedModel + )) return; + + models.forEach(model -> { + if (model instanceof MultiRetexturableModel multi_model) { + RenderHelper.computeInnerCull(state, multi_model.models(), model.hashCode()); + multi_model.models().forEach(rexteruable_model -> + renderModel(state, pos, seed, rexteruable_model, aoCalc, blockInfo, this, model.hashCode()) + ); + } else if (model instanceof RetexturingBakedModel rexteruable_model) + renderModel(state, pos, seed, rexteruable_model, aoCalc, blockInfo, this, model.hashCode()); + else model.emitBlockQuads(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, blockInfo.randomSupplier, this); + }); + + blockInfo.release(); + lightCache.release(); + vertexConsumer = null; + ci.cancel(); + } + + @Unique + private static void renderModel(BlockState state, BlockPos pos, long seed, RetexturingBakedModel model, AoCalculator aoCalc, BlockRenderInfo block_info, RenderContext context, int model_hash) { + aoCalc.clear(); + ((IBlockRenderInfoMixin) block_info).prepareForBlock( + state, pos, seed, + model.useAmbientOcclusion(block_info.blockView, pos), + model.getThemeIndex(), model_hash + ); + model.emitBlockQuads(block_info.blockView, block_info.blockState, block_info.blockPos, block_info.randomSupplier, context); + } + +} diff --git a/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumTerrainBlockRenderInfoMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumTerrainBlockRenderInfoMixin.java deleted file mode 100644 index 2e925c5..0000000 --- a/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumTerrainBlockRenderInfoMixin.java +++ /dev/null @@ -1,55 +0,0 @@ -package fr.adrien1106.reframed.mixin.compat; - -import fr.adrien1106.reframed.client.util.RenderHelper; -import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin; -import fr.adrien1106.reframed.util.blocks.ThemeableBlockEntity; -import link.infra.indium.renderer.render.BlockRenderInfo; -import link.infra.indium.renderer.render.TerrainBlockRenderInfo; -import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache; -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.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(TerrainBlockRenderInfo.class) -public abstract class IndiumTerrainBlockRenderInfoMixin extends BlockRenderInfo implements IBlockRenderInfoMixin { - - @Unique private int theme_index = 0; - @Unique private int model_hash = 0; - - @Redirect( - method = "shouldDrawFaceInner", - at = @At( - value = "INVOKE", - target = "Lme/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache;shouldDrawSide(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;)Z" - ) - ) - private boolean shouldDrawCamoSide(BlockOcclusionCache instance, BlockState state, BlockView view, BlockPos pos, Direction face) { - BlockPos other_pos = pos.offset(face); - if (!(view.getBlockEntity(pos) instanceof ThemeableBlockEntity - || view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)) - return instance.shouldDrawSide(state, view, pos, face); - return RenderHelper.shouldDrawSide(state, view, pos, face, other_pos, theme_index); - } - - @Override - public void prepareForBlock(BlockState blockState, BlockPos blockPos, long seed, boolean modelAo, int theme_index, int model_hash) { - this.theme_index = theme_index; - this.model_hash = model_hash; - prepareForBlock(blockState, blockPos, seed, modelAo); - } - - @Override - public int getThemeIndex() { - return theme_index; - } - - @Override - public int getModelHash() { - return model_hash; - } -} diff --git a/src/main/java/fr/adrien1106/reframed/mixin/render/BlockModelRendererMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/render/BlockModelRendererMixin.java new file mode 100644 index 0000000..136be5c --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/render/BlockModelRendererMixin.java @@ -0,0 +1,40 @@ +package fr.adrien1106.reframed.mixin.render; + +import com.llamalad7.mixinextras.sugar.Local; +import fr.adrien1106.reframed.client.model.RetexturingBakedModel; +import fr.adrien1106.reframed.client.util.RenderHelper; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.block.BlockModelRenderer; +import net.minecraft.client.render.model.BakedModel; +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.Redirect; + +@Mixin(BlockModelRenderer.class) +public class BlockModelRendererMixin { + + @Redirect( + method = "renderSmooth", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/Block;shouldDrawSide(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;Lnet/minecraft/util/math/BlockPos;)Z" + ) + ) + private boolean shouldDrawFrameSideS(BlockState state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, @Local(argsOnly = true) BakedModel model) { + return RenderHelper.shouldDrawSide(state, world, pos, side, other_pos, model instanceof RetexturingBakedModel rm ? rm.getThemeIndex() : 0); + } + + @Redirect( + method = "renderFlat", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/Block;shouldDrawSide(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;Lnet/minecraft/util/math/BlockPos;)Z" + ) + ) + private boolean shouldDrawFrameSideF(BlockState state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos, @Local(argsOnly = true) BakedModel model) { + return RenderHelper.shouldDrawSide(state, world, pos, side, other_pos, model instanceof RetexturingBakedModel rm ? rm.getThemeIndex() : 0); + } +} diff --git a/src/main/java/fr/adrien1106/reframed/mixin/render/BlockRenderContextMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/render/BlockRenderContextMixin.java new file mode 100644 index 0000000..eba2635 --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/render/BlockRenderContextMixin.java @@ -0,0 +1,78 @@ +package fr.adrien1106.reframed.mixin.render; + +import fr.adrien1106.reframed.client.model.MultiRetexturableModel; +import fr.adrien1106.reframed.client.model.RetexturingBakedModel; +import fr.adrien1106.reframed.client.util.RenderHelper; +import fr.adrien1106.reframed.util.mixin.IBlockRenderInfoMixin; +import fr.adrien1106.reframed.util.mixin.IMultipartBakedModelMixin; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.impl.client.indigo.renderer.aocalc.AoCalculator; +import net.fabricmc.fabric.impl.client.indigo.renderer.render.AbstractBlockRenderContext; +import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderContext; +import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.BlockRenderView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(BlockRenderContext.class) +public abstract class BlockRenderContextMixin extends AbstractBlockRenderContext { + + @Shadow private VertexConsumer vertexConsumer; + + @Inject( + method = "render", + at = @At( + value = "INVOKE", + target = "Lnet/fabricmc/fabric/impl/client/indigo/renderer/render/BlockRenderInfo;prepareForWorld(Lnet/minecraft/world/BlockRenderView;Z)V", + shift = At.Shift.AFTER + ), + cancellable = true + ) + private void renderMultipleModels(BlockRenderView blockView, BakedModel wrapper, BlockState state, BlockPos pos, MatrixStack matrixStack, VertexConsumer buffer, boolean cull, Random random, long seed, int overlay, CallbackInfo ci) { + if (!(wrapper instanceof IMultipartBakedModelMixin wrapped)) return; + List models = wrapped.getModels(state); + if (models.stream().noneMatch(bakedModel -> + bakedModel instanceof MultiRetexturableModel + || bakedModel instanceof RetexturingBakedModel + )) return; + + models.forEach(model -> { + if (model instanceof MultiRetexturableModel multi_model) { + RenderHelper.computeInnerCull(state, multi_model.models(), model.hashCode()); + multi_model.models().forEach(rexteruable_model -> + renderModel(state, pos, rexteruable_model, aoCalc, blockInfo, this, model.hashCode()) + ); + } else if (model instanceof RetexturingBakedModel rexteruable_model) + renderModel(state, pos, rexteruable_model, aoCalc, blockInfo, this, model.hashCode()); + else model.emitBlockQuads(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, blockInfo.randomSupplier, this); + }); + + blockInfo.release(); + vertexConsumer = null; + ci.cancel(); + } + + @Unique + private static void renderModel(BlockState state, BlockPos pos, RetexturingBakedModel model, AoCalculator aoCalc, BlockRenderInfo block_info, RenderContext context, int model_hash) { + aoCalc.clear(); + ((IBlockRenderInfoMixin) block_info).prepareForBlock( + state, pos, + model.useAmbientOcclusion(block_info.blockView, pos), + model.getThemeIndex(), model_hash + ); + model.emitBlockQuads(block_info.blockView, block_info.blockState, block_info.blockPos, block_info.randomSupplier, context); + } + +} diff --git a/src/main/resources/reframed.mixins.json b/src/main/resources/reframed.mixins.json index 14488fb..aa9083f 100644 --- a/src/main/resources/reframed.mixins.json +++ b/src/main/resources/reframed.mixins.json @@ -19,6 +19,7 @@ "compat.AxiomClientBlockEntitySerializerMixin", "compat.AxiomClipboardMixin", "compat.AxiomCloneBuilderToolMixin", + "compat.AxiomMappedBlockAndTintGetterMixin", "compat.AxiomMoveBuilderToolMixin", "compat.AxiomPlacementMixin", "compat.AxiomRotSpriteMixin", @@ -28,7 +29,8 @@ "compat.ContinuityCTMQuadTransformMixin", "compat.ContinuityModelWrappingHandlerMixin", "compat.IndiumAbstractBlockRenderContextMixin", - "compat.IndiumTerrainBlockRenderInfoMixin", + "compat.IndiumBlockRenderInfoMixin", + "compat.IndiumNonTerrainBlockRenderContextMixin", "compat.IndiumTerrainRenderContextMixin", "compat.SodiumBlockOcclusionCacheMixin", "model.WeightedBakedModelAccessor", @@ -36,6 +38,8 @@ "particles.AccessorSpriteBillboardParticle", "particles.MixinBlockDustParticle", "render.AbstractBlockRenderContextMixin", + "render.BlockModelRendererMixin", + "render.BlockRenderContextMixin", "render.BlockRenderInfoMixin", "render.MultipartBakedModelMixin", "render.TerrainRenderContextMixin",