diff --git a/build.gradle b/build.gradle index dfe9f23..5f3cecb 100755 --- a/build.gradle +++ b/build.gradle @@ -72,6 +72,17 @@ repositories { maven { url "https://maven.resourcefulbees.com/repository/maven-public/" } + exclusiveContent { + forRepository { + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + } + filter { + includeGroup "maven.modrinth" + } + } mavenCentral() // Add repositories to retrieve artifacts from in here. @@ -88,6 +99,12 @@ dependencies { mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + // Indium and sodium for sodium support + modCompileOnly "maven.modrinth:indium:${project.indium_version}+mc${project.minecraft_version}" + modCompileOnly "maven.modrinth:sodium:mc${project.minecraft_version}-${project.sodium_version}" + modRuntimeOnly "maven.modrinth:indium:${project.indium_version}+mc${project.minecraft_version}" + modRuntimeOnly "maven.modrinth:sodium:mc${project.minecraft_version}-${project.sodium_version}" + // Athena for connected texture modCompileOnly "earth.terrarium.athena:athena-fabric-${project.minecraft_version}:${project.athena_version}" modRuntimeOnly "earth.terrarium.athena:athena-fabric-${project.minecraft_version}:${project.athena_version}" @@ -106,6 +123,8 @@ processResources { inputs.property "loader_version", project.loader_version inputs.property "mod_id", project.mod_id inputs.property "athena_version", project.athena_version + inputs.property "indium_version", project.indium_version + inputs.property "sodium_version", project.sodium_version filteringCharset "UTF-8" filesMatching("fabric.mod.json") { diff --git a/gradle.properties b/gradle.properties index 458489a..f2dd625 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ yarn_mappings=1.20.4+build.3 loader_version=0.15.6 # Mod Properties -mod_version = 1.3 +mod_version = 1.3.1 maven_group = fr.adrien1106 archives_base_name = ReFramed mod_id = reframed @@ -21,3 +21,5 @@ git_owner=Altarik git_repo=ReFramed athena_version=3.3.0 +sodium_version=0.5.8 +indium_version=1.0.30 diff --git a/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java b/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java index c62fda6..da1115b 100644 --- a/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java +++ b/src/main/java/fr/adrien1106/reframed/mixin/CompatMixinPlugin.java @@ -2,6 +2,8 @@ package fr.adrien1106.reframed.mixin; import net.fabricmc.loader.api.FabricLoader; import org.objectweb.asm.tree.ClassNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; @@ -12,9 +14,17 @@ import java.util.function.Supplier; public class CompatMixinPlugin implements IMixinConfigPlugin { + private static final FabricLoader LOADER = FabricLoader.getInstance(); + private static final Logger LOGGER = LoggerFactory.getLogger("ReFramed MIXIN"); + private static final List COMPAT_MOD = List.of("athena", "indium", "sodium"); private static final Map> CONDITIONS = Map.of( - "fr.adrien1106.reframed.mixin.compat.AthenaBakedModelMixin", () -> FabricLoader.getInstance().isModLoaded("athena"), - "fr.adrien1106.reframed.mixin.compat.AthenaWrappedGetterMixin", () -> FabricLoader.getInstance().isModLoaded("athena") + "fr.adrien1106.reframed.mixin.compat.AthenaBakedModelMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(0)), + "fr.adrien1106.reframed.mixin.compat.AthenaWrappedGetterMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(0)), + "fr.adrien1106.reframed.mixin.render.TerrainRenderContextMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)), + "fr.adrien1106.reframed.mixin.compat.IndiumTerrainRenderContextMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)), + "fr.adrien1106.reframed.mixin.render.BlockRenderInfoMixin", () -> !LOADER.isModLoaded(COMPAT_MOD.get(1)), + "fr.adrien1106.reframed.mixin.compat.IndiumTerrainBlockRenderInfoMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(1)), + "fr.adrien1106.reframed.mixin.compat.SodiumBlockOcclusionCacheMixin", () -> LOADER.isModLoaded(COMPAT_MOD.get(2)) ); @@ -44,12 +54,16 @@ public class CompatMixinPlugin implements IMixinConfigPlugin { } @Override - public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + public void preApply(String target_class_name, ClassNode target_class, String mixin_class_name, IMixinInfo mixin_info) { } @Override - public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { - + public void postApply(String target_class, ClassNode target, String mixin_class, IMixinInfo mixin_info) { + String mixin_class_name = mixin_class.substring(mixin_class.lastIndexOf('.') + 1); + COMPAT_MOD.forEach(mod -> { + if (mixin_class_name.toLowerCase().startsWith(mod)) + LOGGER.info("Loaded compatibility mixin class for mod \"" + mod + "\" (class: " + target_class + ")"); + }); } } diff --git a/src/main/java/fr/adrien1106/reframed/mixin/compat/AthenaBakedModelMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/compat/AthenaBakedModelMixin.java index 89c699f..ba6833d 100644 --- a/src/main/java/fr/adrien1106/reframed/mixin/compat/AthenaBakedModelMixin.java +++ b/src/main/java/fr/adrien1106/reframed/mixin/compat/AthenaBakedModelMixin.java @@ -27,9 +27,9 @@ import java.util.*; @Mixin(AthenaBakedModel.class) public abstract class AthenaBakedModelMixin implements DynamicBakedModel, BakedModel { - @Shadow @Final private AthenaBlockModel model; + @Shadow(remap = false) @Final private AthenaBlockModel model; - @Shadow @Final private Int2ObjectMap textures; + @Shadow(remap = false) @Final private Int2ObjectMap textures; /** * Reuses the emitQuad method to compute the quads to be used by the frame diff --git a/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumTerrainBlockRenderInfoMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumTerrainBlockRenderInfoMixin.java new file mode 100644 index 0000000..e204369 --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumTerrainBlockRenderInfoMixin.java @@ -0,0 +1,43 @@ +package fr.adrien1106.reframed.mixin.compat; + +import fr.adrien1106.reframed.block.ReFramedBlock; +import fr.adrien1106.reframed.util.IBlockRenderInfoMixin; +import fr.adrien1106.reframed.util.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 = 1; + + @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 ReFramedBlock.shouldDrawSide(state, view, pos, face, other_pos, theme_index); + } + + @Override + public void prepareForBlock(BlockState blockState, BlockPos blockPos, long seed, boolean modelAo, int theme_index) { + this.theme_index = theme_index; + prepareForBlock(blockState, blockPos, seed, modelAo); + } +} diff --git a/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumTerrainRenderContextMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumTerrainRenderContextMixin.java new file mode 100644 index 0000000..c7ebd61 --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/compat/IndiumTerrainRenderContextMixin.java @@ -0,0 +1,42 @@ +package fr.adrien1106.reframed.mixin.compat; + +import fr.adrien1106.reframed.client.model.MultiRetexturableModel; +import fr.adrien1106.reframed.util.IBlockRenderInfoMixin; +import fr.adrien1106.reframed.util.IMultipartBakedModelMixin; +import link.infra.indium.renderer.render.AbstractBlockRenderContext; +import link.infra.indium.renderer.render.TerrainRenderContext; +import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderContext; +import net.minecraft.client.render.model.BakedModel; +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.CallbackInfo; + +import java.util.List; + + +@Mixin(TerrainRenderContext.class) +public abstract class IndiumTerrainRenderContextMixin extends AbstractBlockRenderContext { + + @Inject( + method = "tessellateBlock", + at = @At( + value = "INVOKE", + target = "Llink/infra/indium/renderer/aocalc/AoCalculator;clear()V" + ), remap = false, + cancellable = true) + private void renderMultipleModels(BlockRenderContext ctx, CallbackInfo ci) { + if (!(ctx.model() instanceof IMultipartBakedModelMixin wrapped) + || !(wrapped.getModel(ctx.state()) instanceof MultiRetexturableModel retexturing_model)) return; + + List models = retexturing_model.models(); + int i = 0; + for (BakedModel bakedModel : models) { + i++; + aoCalc.clear(); + ((IBlockRenderInfoMixin) blockInfo).prepareForBlock(ctx.state(), ctx.pos(), ctx.seed(), bakedModel.useAmbientOcclusion(), i); + bakedModel.emitBlockQuads(blockInfo.blockView, blockInfo.blockState, blockInfo.blockPos, blockInfo.randomSupplier, this); + } + ci.cancel(); + } +} diff --git a/src/main/java/fr/adrien1106/reframed/mixin/compat/SodiumBlockOcclusionCacheMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/compat/SodiumBlockOcclusionCacheMixin.java new file mode 100644 index 0000000..2bc9760 --- /dev/null +++ b/src/main/java/fr/adrien1106/reframed/mixin/compat/SodiumBlockOcclusionCacheMixin.java @@ -0,0 +1,30 @@ +package fr.adrien1106.reframed.mixin.compat; + +import com.llamalad7.mixinextras.sugar.Local; +import fr.adrien1106.reframed.block.ReFramedBlock; +import fr.adrien1106.reframed.util.ThemeableBlockEntity; +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.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(BlockOcclusionCache.class) +public class SodiumBlockOcclusionCacheMixin { + + @Inject( + method = "shouldDrawSide", + at = @At( + value = "INVOKE_ASSIGN", + target = "Lnet/minecraft/world/BlockView;getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;", + shift = At.Shift.AFTER + ), cancellable = true) + private void shouldDrawFrameNeighborSide(BlockState self_state, BlockView view, BlockPos self_pos, Direction face, CallbackInfoReturnable cir, @Local BlockPos.Mutable other_pos) { + if (!(view.getBlockEntity(other_pos) instanceof ThemeableBlockEntity)) return; + cir.setReturnValue(ReFramedBlock.shouldDrawSide(self_state, view, self_pos, face, other_pos, 0)); + } +} diff --git a/src/main/java/fr/adrien1106/reframed/mixin/render/BlockRenderInfoMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/render/BlockRenderInfoMixin.java index 23f9f3c..ac1746f 100644 --- a/src/main/java/fr/adrien1106/reframed/mixin/render/BlockRenderInfoMixin.java +++ b/src/main/java/fr/adrien1106/reframed/mixin/render/BlockRenderInfoMixin.java @@ -7,34 +7,23 @@ import fr.adrien1106.reframed.util.ThemeableBlockEntity; import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.MinecraftClient; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.BlockRenderView; import net.minecraft.world.BlockView; -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.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(BlockRenderInfo.class) public abstract class BlockRenderInfoMixin implements IBlockRenderInfoMixin { - @Shadow public BlockPos blockPos; - - @Shadow public BlockState blockState; - - @Shadow public BlockRenderView blockView; - - @Shadow @Final private BlockPos.Mutable searchPos; - @Shadow public abstract void prepareForBlock(BlockState blockState, BlockPos blockPos, boolean modelAo); + @Shadow public BlockRenderView blockView; @Unique private int theme_index = 1; @@ -42,27 +31,18 @@ public abstract class BlockRenderInfoMixin implements IBlockRenderInfoMixin { at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayers;" + "getBlockLayer(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/RenderLayer;")) public BlockState prepareCamoLayer(BlockState state, @Local(argsOnly = true) BlockPos pos) { - BlockEntity block_entity = MinecraftClient.getInstance().world.getBlockEntity(pos); + BlockEntity block_entity = blockView.getBlockEntity(pos); if (!(block_entity instanceof ThemeableBlockEntity frame_entity)) return state; return frame_entity.getTheme(theme_index); } - @Inject(method = "shouldDrawFace", - at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/util/math/Direction;getId()I"), - cancellable = true) - private void shouldDrawCamoFace(Direction face, CallbackInfoReturnable cir) { - // early injection for camos themselves - BlockEntity block_entity = MinecraftClient.getInstance().world.getBlockEntity(blockPos); - if (!(block_entity instanceof ThemeableBlockEntity)) return; - cir.setReturnValue(ReFramedBlock.shouldDrawSide(blockState, blockView, blockPos, face, searchPos.set(blockPos, face), theme_index)); - } - @Redirect(method = "shouldDrawFace", 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 shouldDrawAdjacentCamoSide(BlockState state, BlockView world, BlockPos pos, Direction side, BlockPos other_pos) { return ReFramedBlock.shouldDrawSide(state, world, pos, side, other_pos, theme_index); } @Override + @Unique public void prepareForBlock(BlockState state, BlockPos pos, boolean ao, int theme_index) { this.theme_index = theme_index; prepareForBlock(state, pos, ao); diff --git a/src/main/java/fr/adrien1106/reframed/mixin/render/TerrainRenderContextMixin.java b/src/main/java/fr/adrien1106/reframed/mixin/render/TerrainRenderContextMixin.java index 3fa58df..18eac23 100644 --- a/src/main/java/fr/adrien1106/reframed/mixin/render/TerrainRenderContextMixin.java +++ b/src/main/java/fr/adrien1106/reframed/mixin/render/TerrainRenderContextMixin.java @@ -21,9 +21,9 @@ public abstract class TerrainRenderContextMixin extends AbstractBlockRenderConte @Inject(method = "tessellateBlock", at = @At( value = "INVOKE", - target = "Lnet/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator;clear()V", - shift = At.Shift.AFTER - ), cancellable = true) + target = "Lnet/fabricmc/fabric/impl/client/indigo/renderer/aocalc/AoCalculator;clear()V" + ), remap = false, + cancellable = true) private void renderMultipleModels(BlockState state, BlockPos pos, BakedModel wrapper, MatrixStack matrixStack, CallbackInfo ci) { if (!(wrapper instanceof IMultipartBakedModelMixin wrapped) || !(wrapped.getModel(state) instanceof MultiRetexturableModel retexturing_model)) return; diff --git a/src/main/java/fr/adrien1106/reframed/util/IBlockRenderInfoMixin.java b/src/main/java/fr/adrien1106/reframed/util/IBlockRenderInfoMixin.java index ca7c51c..69aaeb6 100644 --- a/src/main/java/fr/adrien1106/reframed/util/IBlockRenderInfoMixin.java +++ b/src/main/java/fr/adrien1106/reframed/util/IBlockRenderInfoMixin.java @@ -6,4 +6,6 @@ import net.minecraft.util.math.BlockPos; public interface IBlockRenderInfoMixin { void prepareForBlock(BlockState state, BlockPos pos, boolean ao, int theme_index); + + void prepareForBlock(BlockState state, BlockPos pos, long seed, boolean ao, int theme_index); } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index bf1592a..b96c19f 100755 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -31,6 +31,8 @@ "fabric-api": "*" }, "suggest": { - "athena": "^${athena_version}" + "athena": "^${athena_version}", + "sodium": "^${sodium_version}", + "indium": "^${indium_version}" } } \ No newline at end of file diff --git a/src/main/resources/reframed.mixins.json b/src/main/resources/reframed.mixins.json index b3858b4..48c8ec5 100644 --- a/src/main/resources/reframed.mixins.json +++ b/src/main/resources/reframed.mixins.json @@ -6,13 +6,17 @@ "mixins": [ "WallBlockAccessor", "particles.MixinEntity", - "particles.MixinLivingEntity" + "particles.MixinLivingEntity", + "sound.LivingEntityMixin" ], "client": [ "MinecraftAccessor", "compat.AthenaBakedModelMixin", "compat.AthenaConnectedBlockModelMixin", "compat.AthenaWrappedGetterMixin", + "compat.IndiumTerrainBlockRenderInfoMixin", + "compat.IndiumTerrainRenderContextMixin", + "compat.SodiumBlockOcclusionCacheMixin", "model.WeightedBakedModelAccessor", "particles.AccessorParticle", "particles.AccessorSpriteBillboardParticle",