diff --git a/build.gradle b/build.gradle index 3577bc0..377d943 100644 --- a/build.gradle +++ b/build.gradle @@ -1,90 +1,108 @@ plugins { - id 'fabric-loom' version '1.7-SNAPSHOT' - id 'maven-publish' + id 'fabric-loom' version '1.7-SNAPSHOT' + id 'maven-publish' } version = project.mod_version group = project.maven_group base { - archivesName = project.archives_base_name + archivesName = project.archives_base_name } repositories { - maven { - name = "Modrinth" - url = "https://api.modrinth.com/maven" - content { - includeGroup "maven.modrinth" - } - } + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + content { + includeGroup "maven.modrinth" + } + } + + maven { + name 'Xander Maven' + url 'https://maven.isxander.dev/releases' + } + + maven { + name = "Terraformers" + url = "https://maven.terraformersmc.com/" + } } loom { - splitEnvironmentSourceSets() - - mods { - "better-snow-coverage" { - sourceSet sourceSets.main - sourceSet sourceSets.client - } - } + splitEnvironmentSourceSets() + + mods { + "better-snow-coverage" { + sourceSet sourceSets.main + sourceSet sourceSets.client + } + } } dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + modImplementation "dev.isxander:yet-another-config-lib:${project.yacl_version}" + modImplementation("com.terraformersmc:modmenu:${project.modmenu_version}") - modCompileOnly "maven.modrinth:sodium:${project.sodium_version}" + modCompileOnly "maven.modrinth:sodium:${project.sodium_version}" } processResources { - inputs.property "version", project.version - - filesMatching("fabric.mod.json") { - expand "version": project.version - } + inputs.property "version", project.version + inputs.property "loader_version", project.loader_version + inputs.property "yacl_version", project.yacl_version + inputs.property "modmenu_version", project.modmenu_version + + filesMatching("fabric.mod.json") { + expand "version": project.version, + "loader_version": project.loader_version, + "yacl_version": project.yacl_version, + "modmenu_version": project.modmenu_version + } } tasks.withType(JavaCompile).configureEach { - it.options.release = 21 + it.options.release = 21 } java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } jar { - from("LICENSE") { - rename { "${it}_${project.base.archivesName.get()}"} - } + from("LICENSE") { + rename { "${it}_${project.base.archivesName.get()}" } + } } // configure the maven publication publishing { - publications { - create("mavenJava", MavenPublication) { - artifactId = project.archives_base_name - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } + publications { + create("mavenJava", MavenPublication) { + artifactId = project.archives_base_name + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 437526b..ed71039 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,7 @@ archives_base_name=better-snow-coverage # Dependencies fabric_version=0.100.8+1.21 +yacl_version=3.5.0+1.21-fabric +modmenu_version=11.0.1 + sodium_version=mc1.21-0.5.9 \ No newline at end of file diff --git a/src/client/java/tobinio/bettersnowcoverage/BetterSnowChecker.java b/src/client/java/tobinio/bettersnowcoverage/BetterSnowChecker.java index 4f3ec2e..574dde6 100644 --- a/src/client/java/tobinio/bettersnowcoverage/BetterSnowChecker.java +++ b/src/client/java/tobinio/bettersnowcoverage/BetterSnowChecker.java @@ -1,13 +1,18 @@ package tobinio.bettersnowcoverage; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.block.FlowerBlock; -import net.minecraft.block.SnowBlock; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.world.ClientWorld; import net.minecraft.registry.tag.BlockTags; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.BlockRenderView; -import net.minecraft.world.World; +import tobinio.bettersnowcoverage.config.Config; + +import java.util.logging.Logger; /** * Created: 02.08.24 @@ -16,18 +21,45 @@ import net.minecraft.world.World; */ public class BetterSnowChecker { public static boolean shouldHaveSnow(BlockState state, BlockPos pos, BlockRenderView world) { - if (!world.getBlockState(pos.down()).isIn(BlockTags.DIRT)) { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + + if (player == null) { + BetterSnowCoverage.LOGGER.warn("no player found"); + return false; + } + + if (state.isSideSolidFullSquare(world, pos, Direction.DOWN)) { return false; } - if (!hasSnowNeighbor(pos, world)) { + if (!world.getBlockState(pos.down()).isFullCube(world, pos.down())) { return false; } - return state.isIn(BlockTags.FLOWERS); + if (isExcludedBlock(state)) { + return false; + } + + return hasSnowNeighbor(pos, world); + } + + private static boolean isExcludedBlock(BlockState state) { + for (TagKey tag : Config.EXCLUDED_TAGS) { + if (state.isIn(tag)) { + return true; + } + } + + for (Block block : Config.EXCLUDED_BLOCKS) { + if (state.getBlock().equals(block)) { + return true; + } + } + + return false; } - public static boolean hasSnowNeighbor(BlockPos pos, BlockRenderView world) { + private static boolean hasSnowNeighbor(BlockPos pos, BlockRenderView world) { var directions = new Direction[]{Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; for (Direction direction : directions) { diff --git a/src/client/java/tobinio/bettersnowcoverage/BetterSnowCoverageClient.java b/src/client/java/tobinio/bettersnowcoverage/BetterSnowCoverageClient.java index f64e12d..1684801 100644 --- a/src/client/java/tobinio/bettersnowcoverage/BetterSnowCoverageClient.java +++ b/src/client/java/tobinio/bettersnowcoverage/BetterSnowCoverageClient.java @@ -1,10 +1,12 @@ package tobinio.bettersnowcoverage; import net.fabricmc.api.ClientModInitializer; +import tobinio.bettersnowcoverage.config.Config; public class BetterSnowCoverageClient implements ClientModInitializer { - @Override - public void onInitializeClient() { - // This entrypoint is suitable for setting up client-specific logic, such as rendering. - } + @Override + public void onInitializeClient() { + Config.HANDLER.load(); + Config.update(); + } } \ No newline at end of file diff --git a/src/client/java/tobinio/bettersnowcoverage/config/Config.java b/src/client/java/tobinio/bettersnowcoverage/config/Config.java new file mode 100644 index 0000000..024dcd3 --- /dev/null +++ b/src/client/java/tobinio/bettersnowcoverage/config/Config.java @@ -0,0 +1,87 @@ +package tobinio.bettersnowcoverage.config; + +import com.google.gson.GsonBuilder; +import dev.isxander.yacl3.config.v2.api.ConfigClassHandler; +import dev.isxander.yacl3.config.v2.api.SerialEntry; +import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.block.Block; +import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.util.Identifier; + +import java.util.ArrayList; +import java.util.List; + +import static tobinio.bettersnowcoverage.BetterSnowCoverage.*; + +/** + * Created: 02.08.24 + * + * @author Tobias Frischmann + */ +public class Config { + public static List DEFAULT_EXCLUDED_BLOCKS = List.of("light_weighted_pressure_plate", "heavy_weighted_pressure_plate", "polished_blackstone_pressure_plate", "stone_pressure_plate"); + public static List DEFAULT_EXCLUDED_TAGS = List.of("buttons", "wooden_pressure_plates", "rails", "leaves"); + + public static List EXCLUDED_BLOCKS = new ArrayList<>(); + public static List> EXCLUDED_TAGS = new ArrayList<>(); + + public static void update() { + setBlocks(HANDLER.instance().excluded_blocks, EXCLUDED_BLOCKS); + setTags(HANDLER.instance().excluded_tags, EXCLUDED_TAGS); + } + + private static void setTags(List strings, List> tags) { + tags.clear(); + + for (String id : strings) { + Identifier identifier = Identifier.tryParse(id); + + if (identifier == null) { + LOGGER.error("Could not parse tag id {}", id); + continue; + } + + var tagKey = TagKey.of(RegistryKeys.BLOCK, identifier); + tags.add(tagKey); + } + } + + private static void setBlocks(List strings, List blocks) { + blocks.clear(); + + for (String id : strings) { + Identifier identifier = Identifier.tryParse(id); + + if (identifier == null) { + LOGGER.error("Could not parse block id {}", id); + continue; + } + + var block = Registries.BLOCK.getOrEmpty(identifier); + + if (block.isPresent()) { + blocks.add(block.get()); + } else { + LOGGER.error("Could not find block {}", id); + } + } + } + + public static ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(Config.class) + .id(id("config")) + .serializer(config -> GsonConfigSerializerBuilder.create(config) + .setPath(FabricLoader.getInstance().getConfigDir().resolve("%s.json5".formatted(MOD_ID))) + .appendGsonBuilder(GsonBuilder::setPrettyPrinting) + .setJson5(true) + .build()) + .build(); + + @SerialEntry + public List excluded_blocks = new ArrayList<>(DEFAULT_EXCLUDED_BLOCKS); + + @SerialEntry + public List excluded_tags = new ArrayList<>(DEFAULT_EXCLUDED_TAGS); +} diff --git a/src/client/java/tobinio/bettersnowcoverage/config/ConfigMenu.java b/src/client/java/tobinio/bettersnowcoverage/config/ConfigMenu.java new file mode 100644 index 0000000..74ebe8e --- /dev/null +++ b/src/client/java/tobinio/bettersnowcoverage/config/ConfigMenu.java @@ -0,0 +1,47 @@ +package tobinio.bettersnowcoverage.config; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; +import dev.isxander.yacl3.api.*; +import dev.isxander.yacl3.api.controller.StringControllerBuilder; +import net.minecraft.text.Text; + +/** + * Created: 02.08.24 + * + * @author Tobias Frischmann + */ + +public class ConfigMenu implements ModMenuApi { + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return parentScreen -> YetAnotherConfigLib.createBuilder() + .title(Text.literal("Better Snow Coverage")) + .category(ConfigCategory.createBuilder() + .name(Text.literal("Better Snow Coverage")) + .tooltip(Text.literal("All the settings")) + .option(ListOption.createBuilder() + .name(Text.literal("Excluded Blocks")) + .description(OptionDescription.of(Text.literal("These blocks will NEVER show snow underneath them."))) + .binding(Config.DEFAULT_EXCLUDED_BLOCKS, () -> Config.HANDLER.instance().excluded_blocks, newVal -> Config.HANDLER.instance().excluded_blocks = newVal) + .controller(StringControllerBuilder::create) + .initial("") + .collapsed(true) + .build()) + .option(ListOption.createBuilder() + .name(Text.literal("Excluded Tags")) + .description(OptionDescription.of(Text.literal("All blocks within these tags will NEVER show snow underneath them."))) + .binding(Config.DEFAULT_EXCLUDED_TAGS, () -> Config.HANDLER.instance().excluded_tags, newVal -> Config.HANDLER.instance().excluded_tags = newVal) + .controller(StringControllerBuilder::create) + .initial("") + .collapsed(true) + .build()) + .build()) + .save(() -> { + Config.HANDLER.save(); + Config.update(); + }) + .build() + .generateScreen(parentScreen); + } +} \ No newline at end of file diff --git a/src/client/java/tobinio/bettersnowcoverage/mixin/client/AbstractBlockAccessor.java b/src/client/java/tobinio/bettersnowcoverage/mixin/client/AbstractBlockAccessor.java deleted file mode 100644 index 70d97ea..0000000 --- a/src/client/java/tobinio/bettersnowcoverage/mixin/client/AbstractBlockAccessor.java +++ /dev/null @@ -1,16 +0,0 @@ -package tobinio.bettersnowcoverage.mixin.client; - -import net.minecraft.block.AbstractBlock; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -/** - * Created: 31.07.24 - * - * @author Tobias Frischmann - */ -@Mixin (AbstractBlock.class) -public interface AbstractBlockAccessor { - @Invoker - float callGetMaxHorizontalModelOffset(); -} diff --git a/src/client/java/tobinio/bettersnowcoverage/mixin/client/sodium/BlockRenderContextAccessor.java b/src/client/java/tobinio/bettersnowcoverage/mixin/client/sodium/BlockRenderContextAccessor.java deleted file mode 100644 index b0dc5de..0000000 --- a/src/client/java/tobinio/bettersnowcoverage/mixin/client/sodium/BlockRenderContextAccessor.java +++ /dev/null @@ -1,24 +0,0 @@ -package tobinio.bettersnowcoverage.mixin.client.sodium; - -import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderContext; -import net.minecraft.block.BlockState; -import org.joml.Vector3f; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.gen.Accessor; - -/** - * Created: 31.07.24 - * - * @author Tobias Frischmann - */ -@Mixin (BlockRenderContext.class) -public interface BlockRenderContextAccessor { - @Mutable - @Accessor (remap = false) - void setOrigin(Vector3f origin); - - @Mutable - @Accessor (remap = false) - void setState(BlockState state); -} diff --git a/src/client/java/tobinio/bettersnowcoverage/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java b/src/client/java/tobinio/bettersnowcoverage/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java index 2f66c40..6c0a535 100644 --- a/src/client/java/tobinio/bettersnowcoverage/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java +++ b/src/client/java/tobinio/bettersnowcoverage/mixin/client/sodium/ChunkBuilderMeshingTaskMixin.java @@ -8,8 +8,11 @@ import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRende import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderContext; import me.jellysquid.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask; import me.jellysquid.mods.sodium.client.util.task.CancellationToken; +import me.jellysquid.mods.sodium.client.world.WorldSlice; +import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.FlowerBlock; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import org.joml.Vector3f; import org.joml.Vector3fc; @@ -29,22 +32,19 @@ public class ChunkBuilderMeshingTaskMixin { @Inject (method = "execute(Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lme/jellysquid/mods/sodium/client/util/task/CancellationToken;)Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;", at = @At (value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer;renderModel(Lme/jellysquid/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderContext;Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildBuffers;)V", remap = false), remap = false) private void execute(ChunkBuildContext buildContext, CancellationToken cancellationToken, CallbackInfoReturnable cir, @Local BlockRenderContext ctx, - @Local ChunkBuildBuffers buffers, @Local BlockRenderCache cache) { + @Local ChunkBuildBuffers buffers, @Local BlockRenderCache cache, @Local WorldSlice slice) { if (BetterSnowChecker.shouldHaveSnow(ctx.state(), ctx.pos(), ctx.world())) { Vector3fc origin = ctx.origin(); - var newOrigen = new Vector3f(origin); - var baseOffset = ctx.state().getModelOffset(ctx.world(), ctx.pos()); - newOrigen.sub((float) baseOffset.getX(), (float) baseOffset.getY(), (float) baseOffset.getZ()); + BlockRenderContext context = new BlockRenderContext(slice); - var context = (BlockRenderContextAccessor) ctx; + BlockState snow = Blocks.SNOW.getDefaultState(); + var model = cache.getBlockModels() + .getModel(snow); - context.setState(Blocks.SNOW.getDefaultState()); - context.setOrigin(newOrigen); + context.update(ctx.pos(), new BlockPos((int) origin.x(), (int) origin.y(), (int) origin.z()), snow, model, ctx.seed()); - cache.getBlockRenderer().renderModel((BlockRenderContext) context, buffers); - - context.setOrigin((Vector3f) origin); + cache.getBlockRenderer().renderModel(context, buffers); } } } diff --git a/src/client/resources/better-snow-coverage.client.mixins.json b/src/client/resources/better-snow-coverage.client.mixins.json index a4208da..f682b10 100644 --- a/src/client/resources/better-snow-coverage.client.mixins.json +++ b/src/client/resources/better-snow-coverage.client.mixins.json @@ -4,8 +4,6 @@ "compatibilityLevel": "JAVA_21", "client": [ "SectionBuilderMixin", - "AbstractBlockAccessor", - "sodium.BlockRenderContextAccessor", "sodium.ChunkBuilderMeshingTaskMixin" ], "injectors": { diff --git a/src/main/java/tobinio/bettersnowcoverage/BetterSnowCoverage.java b/src/main/java/tobinio/bettersnowcoverage/BetterSnowCoverage.java index 1e8c72d..13a63b5 100644 --- a/src/main/java/tobinio/bettersnowcoverage/BetterSnowCoverage.java +++ b/src/main/java/tobinio/bettersnowcoverage/BetterSnowCoverage.java @@ -2,21 +2,20 @@ package tobinio.bettersnowcoverage; import net.fabricmc.api.ModInitializer; +import net.minecraft.util.Identifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BetterSnowCoverage implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - public static final Logger LOGGER = LoggerFactory.getLogger("better-snow-coverage"); + public static final String MOD_ID = "better-snow-coverage"; + public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); - @Override - public void onInitialize() { - // This code runs as soon as Minecraft is in a mod-load-ready state. - // However, some things (like resources) may still be uninitialized. - // Proceed with mild caution. + public static Identifier id(String path) { + return Identifier.of(MOD_ID, path); + } - LOGGER.info("Hello Fabric world!"); - } + + @Override + public void onInitialize() { + } } \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 81fdfa2..389a2d0 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -20,6 +20,9 @@ ], "client": [ "tobinio.bettersnowcoverage.BetterSnowCoverageClient" + ], + "modmenu": [ + "tobinio.bettersnowcoverage.config.ConfigMenu" ] }, "mixins": [ @@ -30,10 +33,12 @@ } ], "depends": { - "fabricloader": ">=0.15.11", + "fabricloader": ">=${loader_version}", "minecraft": "~1.21", "java": ">=21", - "fabric-api": "*" + "fabric-api": "*", + "yet_another_config_lib_v3": "${yacl_version}", + "modmenu": "${modmenu_version}" }, "suggests": { "another-mod": "*"