diff --git a/build.gradle b/build.gradle index b11e585..92d4cc6 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,14 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. + + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + content { + includeGroup "maven.modrinth" + } + } } loom { @@ -38,6 +46,8 @@ dependencies { // Fabric API. This is technically optional, but you probably want it anyway. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + modCompileOnly "maven.modrinth:sodium:${project.sodium_version}" } processResources { diff --git a/src/client/java/tobinio/denseflowers/OffsetGenerator.java b/src/client/java/tobinio/denseflowers/OffsetGenerator.java new file mode 100644 index 0000000..5037316 --- /dev/null +++ b/src/client/java/tobinio/denseflowers/OffsetGenerator.java @@ -0,0 +1,59 @@ +package tobinio.denseflowers; + +import net.minecraft.block.BlockState; +import net.minecraft.block.FlowerBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.BlockView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created: 31.07.24 + * + * @author Tobias Frischmann + */ +public class OffsetGenerator { + + public static List getFlowerOffsets(BlockState blockState, BlockView world, BlockPos flowerPos) { + var baseLocation = blockState.getModelOffset(world, flowerPos); + + var allLocations = new ArrayList(); + allLocations.add(baseLocation); + + var locations = new ArrayList(); + + outer: + for (int i = 0; i < getNumberOfSurroundingFlowers(world, flowerPos); i++) { + var newLocation = blockState.getModelOffset(world, flowerPos.add((i + 1) * 5, 0, (i + 1) * 3)); + + for (Vec3d location : allLocations) { + if (location.distanceTo(newLocation) <= 0.4) { + continue outer; + } + } + + allLocations.add(newLocation); + locations.add(newLocation); + } + + return locations; + } + + private static int getNumberOfSurroundingFlowers(BlockView world, BlockPos flowerPos) { + var count = 0; + Direction[] directions = {Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; + + for (Direction dir : directions) { + if (world.getBlockState(flowerPos.add(dir.getOffsetX(), 0, dir.getOffsetZ())) + .getBlock() instanceof FlowerBlock) { + count++; + } + } + + return count; + } + +} diff --git a/src/client/java/tobinio/denseflowers/mixin/client/SectionBuilderMixin.java b/src/client/java/tobinio/denseflowers/mixin/client/SectionBuilderMixin.java index 84be4c3..6ee15d8 100644 --- a/src/client/java/tobinio/denseflowers/mixin/client/SectionBuilderMixin.java +++ b/src/client/java/tobinio/denseflowers/mixin/client/SectionBuilderMixin.java @@ -3,6 +3,7 @@ package tobinio.denseflowers.mixin.client; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.systems.VertexSorter; import net.minecraft.block.BlockState; +import net.minecraft.block.FlowerBlock; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.block.BlockRenderManager; import net.minecraft.client.render.chunk.BlockBufferAllocatorStorage; @@ -11,6 +12,7 @@ import net.minecraft.client.render.chunk.SectionBuilder; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkSectionPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.random.Random; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -18,6 +20,7 @@ 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; +import tobinio.denseflowers.OffsetGenerator; /** * Created: 30.07.24 @@ -32,14 +35,24 @@ public class SectionBuilderMixin { @Inject (method = "build", at = @At (value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockRenderManager;renderBlock(Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;ZLnet/minecraft/util/math/random/Random;)V")) private void render(ChunkSectionPos sectionPos, ChunkRendererRegion renderRegion, VertexSorter vertexSorter, - BlockBufferAllocatorStorage allocatorStorage, CallbackInfoReturnable cir, @Local - BlockState blockState, @Local (ordinal = 2) BlockPos blockPos, @Local MatrixStack matrixStack, - @Local BufferBuilder bufferBuilder, @Local - Random random) { + BlockBufferAllocatorStorage allocatorStorage, CallbackInfoReturnable cir, + @Local BlockState blockState, @Local (ordinal = 2) BlockPos blockPos, @Local MatrixStack matrixStack, + @Local BufferBuilder bufferBuilder, @Local Random random) { + if (blockState.getBlock() instanceof FlowerBlock) { + matrixStack.push(); - matrixStack.push(); - matrixStack.translate(0.5, 0.5, 0.5); - blockRenderManager.renderBlock(blockState, blockPos, renderRegion, matrixStack, bufferBuilder, true, random); - matrixStack.pop(); + var realOffset = blockState.getModelOffset(renderRegion, blockPos); + matrixStack.translate(-realOffset.getX(), -realOffset.getY(), -realOffset.getZ()); + + for (Vec3d flowerOffset : OffsetGenerator.getFlowerOffsets(blockState, renderRegion, blockPos)) { + matrixStack.push(); + + matrixStack.translate(flowerOffset.getX(), flowerOffset.getY(), flowerOffset.getZ()); + blockRenderManager.renderBlock(blockState, blockPos, renderRegion, matrixStack, bufferBuilder, true, random); + + matrixStack.pop(); + } + matrixStack.pop(); + } } } diff --git a/src/client/java/tobinio/denseflowers/mixin/client/sodium/BlockRenderMixin.java b/src/client/java/tobinio/denseflowers/mixin/client/sodium/BlockRenderMixin.java new file mode 100644 index 0000000..b0fe74c --- /dev/null +++ b/src/client/java/tobinio/denseflowers/mixin/client/sodium/BlockRenderMixin.java @@ -0,0 +1,43 @@ +package tobinio.denseflowers.mixin.client.sodium; + +import com.llamalad7.mixinextras.sugar.Local; +import me.jellysquid.mods.sodium.client.model.color.ColorProvider; +import me.jellysquid.mods.sodium.client.model.light.LightPipeline; +import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; +import me.jellysquid.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder; +import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderContext; +import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderer; +import me.jellysquid.mods.sodium.client.render.chunk.terrain.material.Material; +import net.minecraft.block.BlockState; +import net.minecraft.block.FlowerBlock; +import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.util.math.Vec3d; +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 tobinio.denseflowers.OffsetGenerator; + +import java.util.List; + +/** + * Created: 31.07.24 + * + * @author Tobias Frischmann + */ +@Mixin (BlockRenderer.class) +public class BlockRenderMixin { + @Inject (method = "renderModel", at = @At (value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer;renderQuadList(Lme/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderContext;Lme/jellysquid/mods/sodium/client/render/chunk/terrain/material/Material;Lme/jellysquid/mods/sodium/client/model/light/LightPipeline;Lme/jellysquid/mods/sodium/client/model/color/ColorProvider;Lnet/minecraft/util/math/Vec3d;Lme/jellysquid/mods/sodium/client/render/chunk/compile/buffers/ChunkModelBuilder;Ljava/util/List;Lnet/minecraft/util/math/Direction;)V", ordinal = 1)) + private void render(BlockRenderContext ctx, ChunkBuildBuffers buffers, CallbackInfo ci, @Local Material material, + @Local LightPipeline lighter, @Local ColorProvider colorizer, + @Local ChunkModelBuilder meshBuilder, @Local List all) { + + if (ctx.state().getBlock() instanceof FlowerBlock) { + var renderer = (BlockRendererAccessor) this; + + for (Vec3d flowerOffset : OffsetGenerator.getFlowerOffsets(ctx.state(), ctx.world(), ctx.pos())) { + renderer.callRenderQuadList(ctx, material, lighter, colorizer, flowerOffset, meshBuilder, all, null); + } + } + } +} diff --git a/src/client/java/tobinio/denseflowers/mixin/client/sodium/BlockRendererAccessor.java b/src/client/java/tobinio/denseflowers/mixin/client/sodium/BlockRendererAccessor.java new file mode 100644 index 0000000..0d98b6b --- /dev/null +++ b/src/client/java/tobinio/denseflowers/mixin/client/sodium/BlockRendererAccessor.java @@ -0,0 +1,29 @@ +package tobinio.denseflowers.mixin.client.sodium; + +import me.jellysquid.mods.sodium.client.model.color.ColorProvider; +import me.jellysquid.mods.sodium.client.model.light.LightPipeline; +import me.jellysquid.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder; +import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderContext; +import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderer; +import me.jellysquid.mods.sodium.client.render.chunk.terrain.material.Material; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.List; + +/** + * Created: 31.07.24 + * + * @author Tobias Frischmann + */ +@Mixin (BlockRenderer.class) +public interface BlockRendererAccessor { + @Invoker + void callRenderQuadList(BlockRenderContext ctx, Material material, LightPipeline lighter, + ColorProvider colorizer, Vec3d offset, + ChunkModelBuilder builder, List quads, Direction cullFace); +} diff --git a/src/client/resources/dense-flowers.client.mixins.json b/src/client/resources/dense-flowers.client.mixins.json index 2ccca21..c590c5a 100644 --- a/src/client/resources/dense-flowers.client.mixins.json +++ b/src/client/resources/dense-flowers.client.mixins.json @@ -3,7 +3,9 @@ "package": "tobinio.denseflowers.mixin.client", "compatibilityLevel": "JAVA_21", "client": [ - "SectionBuilderMixin" + "SectionBuilderMixin", + "sodium.BlockRendererAccessor", + "sodium.BlockRenderMixin" ], "injectors": { "defaultRequire": 1