From 841d1b9db0b432899b2c36238832f5c32822d708 Mon Sep 17 00:00:00 2001 From: celeri Date: Mon, 19 Jun 2023 22:37:27 +0200 Subject: [PATCH] Better cave detection --- .../java/net/celeri/dynmus/DynamicMusic.java | 139 ++++++++---------- .../celeri/dynmus/config/GeneralConfig.java | 13 +- .../celeri/dynmus/config/MusicSelector.java | 6 + .../mixin/BiomeAmbientSoundsHandlerMixin.java | 15 +- .../dynmus/mixin/MinecraftClientMixin.java | 21 ++- .../resources/assets/dynmus/lang/en_us.json | 6 + gradle.properties | 2 +- 7 files changed, 95 insertions(+), 107 deletions(-) diff --git a/common/src/main/java/net/celeri/dynmus/DynamicMusic.java b/common/src/main/java/net/celeri/dynmus/DynamicMusic.java index de5379c..2bf0e44 100644 --- a/common/src/main/java/net/celeri/dynmus/DynamicMusic.java +++ b/common/src/main/java/net/celeri/dynmus/DynamicMusic.java @@ -13,8 +13,11 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.lighting.LayerLightEventListener; import net.minecraft.world.level.material.Material; +import java.util.stream.IntStream; + public class DynamicMusic { public static final String MOD_ID = "dynmus"; @@ -34,113 +37,87 @@ public static void init() { SOUND_EVENTS_REGISTER.register(); } - public static boolean isInCave(Level level, BlockPos pos) { - DynamicMusicConfig config = AutoConfig.getConfigHolder(DynamicMusicConfig.class).getConfig(); - - int searchRange = config.generalConfig.caveDetection.searchRange; - - if ( - searchRange >= 1 - // Block above position - && !level.canSeeSky(pos) - && (config.generalConfig.caveDetection.darknessPercent < 1 || config.generalConfig.caveDetection.stonePercent < 1) - ) { - int darkBlocks = 0; - int stoneBlocks = 0; - int airBlocks = 0; - - for (int x = -searchRange; x < searchRange; x++) { - for (int y = -searchRange; y < searchRange; y++) { - for (int z = -searchRange; z < searchRange; z++) { - BlockPos offsetPos = pos.offset(x, y, z); - if (level.isEmptyBlock(offsetPos)) { - airBlocks++; - if (level.getLightEngine().getLayerListener(LightLayer.BLOCK).getLightValue(offsetPos) - <= config.generalConfig.caveDetection.darknessCap) { - darkBlocks++; - } - } - if (level.getBlockState(offsetPos).getMaterial() == Material.LAVA) { - darkBlocks++; - } else if ( - level.getBlockState(offsetPos).getMaterial() == Material.STONE - || level.getBlockState(offsetPos).getMaterial() == Material.SCULK - ) { - stoneBlocks++; - } - } - } - } - - double blockCount = Math.pow(searchRange * 2, 3); + private static boolean inCave = false; - double stonePercentage = ((double) stoneBlocks) / (blockCount); - double darkPercentage = ((double) darkBlocks) / ((double) airBlocks); + private static boolean inPseudoMinecraft = false; - return darkPercentage >= config.generalConfig.caveDetection.darknessPercent && stonePercentage >= config.generalConfig.caveDetection.stonePercent; - } - return false; - } + private static double averageDarkness = 15; - public static double getAverageDarkness(Level level, BlockPos pos) { + public static void tick(Level level, BlockPos pos) { DynamicMusicConfig config = AutoConfig.getConfigHolder(DynamicMusicConfig.class).getConfig(); + LayerLightEventListener blockLightListener = level.getLightEngine().getLayerListener(LightLayer.BLOCK); + + int caveSearchRange = config.generalConfig.caveDetection.searchRange; + int mineshaftSearchRange = config.generalConfig.mineshaftDetection.searchRange; - int searchRange = config.generalConfig.caveDetection.searchRange; + int searchRange = Math.max(caveSearchRange, mineshaftSearchRange); if (searchRange >= 1) { int airBlocks = 0; - int lightTogether = 0; + int lightSum = 0; + + int caveAllSolidBlocks = 0; + int caveBlocks = 0; + + int mineshaftAllSolidBlock = 0; + int mineshaftBlocks = 0; for (int x = -searchRange; x < searchRange; x++) { for (int y = -searchRange; y < searchRange; y++) { for (int z = -searchRange; z < searchRange; z++) { - BlockPos offsetPos = pos.offset(x, y, z); - if (level.isEmptyBlock(offsetPos)) { - airBlocks++; - lightTogether += level.getLightEngine().getLayerListener(LightLayer.BLOCK).getLightValue(offsetPos); - } - } - } - } - - return (((double) lightTogether) / ((double) airBlocks)); - - } - return 15; - } + BlockPos offsetPos = new BlockPos(pos).offset(x, y, z); - public static boolean isInPseudoMinecraft(Level level, BlockPos pos) { - DynamicMusicConfig config = AutoConfig.getConfigHolder(DynamicMusicConfig.class).getConfig(); + Material blockMaterial = level.getBlockState(offsetPos).getMaterial(); - int searchRange = config.generalConfig.mineshaftDetection.searchRange; + if (blockMaterial == Material.AIR) { + airBlocks++; - if (searchRange >= 1 && config.generalConfig.mineshaftDetection.percent < 1) { + lightSum += blockLightListener.getLightValue(offsetPos); + } else if (blockMaterial != Material.LAVA && blockMaterial != Material.WATER) { + int biggestCoordinate = IntStream.of(x, y, z).max().getAsInt(); + int smallestCoordinate = IntStream.of(x, y, z).min().getAsInt(); - int pseudoMineshaftBlocks = 0; - int airBlocks = 0; + // Coordinates within cave search range + if (smallestCoordinate > -caveSearchRange && biggestCoordinate < caveSearchRange) { + caveAllSolidBlocks++; - for (int x = -searchRange; x < searchRange; x++) { - for (int y = -searchRange; y < searchRange; y++) { - for (int z = -searchRange; z < searchRange; z++) { - BlockPos offsetPos = pos.offset(x, y, z); + if ( + blockMaterial == Material.STONE + || blockMaterial == Material.SCULK + || blockMaterial == Material.AMETHYST + ) caveBlocks++; + } - if (level.getBlockState(offsetPos).getMaterial() == Material.WOOD || level.getBlockState(offsetPos).getBlock() == Blocks.RAIL || level.getBlockState(offsetPos).getMaterial() == Material.WEB) { - pseudoMineshaftBlocks++; - } + // Coordinates within mineshaft search range + if (smallestCoordinate > -mineshaftSearchRange && biggestCoordinate < mineshaftSearchRange) { + mineshaftAllSolidBlock++; - if (level.isEmptyBlock(offsetPos)) { - airBlocks++; + if ( + blockMaterial == Material.WOOD || blockMaterial == Material.WEB + || level.getBlockState(offsetPos).getBlock() == Blocks.RAIL + ) mineshaftBlocks++; + } } } } } - double mineshaftPercentage = ((double) pseudoMineshaftBlocks) / ((double) airBlocks); - - return mineshaftPercentage >= config.generalConfig.mineshaftDetection.percent; + inCave = !level.canSeeSky(pos) && config.generalConfig.caveDetection.stonePercent <= (double) caveBlocks / caveAllSolidBlocks; + inPseudoMinecraft = inCave && config.generalConfig.mineshaftDetection.percent <= (double) mineshaftBlocks / mineshaftAllSolidBlock; + averageDarkness = (double) lightSum / airBlocks; } + } + + public static boolean isInCave() { + return inCave; + } + + public static boolean isInPseudoMinecraft() { + return inPseudoMinecraft; + } - return false; + public static double getAverageDarkness() { + return averageDarkness; } } diff --git a/common/src/main/java/net/celeri/dynmus/config/GeneralConfig.java b/common/src/main/java/net/celeri/dynmus/config/GeneralConfig.java index cafed6b..39b8607 100644 --- a/common/src/main/java/net/celeri/dynmus/config/GeneralConfig.java +++ b/common/src/main/java/net/celeri/dynmus/config/GeneralConfig.java @@ -63,17 +63,10 @@ public int getAnchor() { public static class CaveDetection { @ConfigEntry.Gui.Tooltip() - public int searchRange = 5; + public int searchRange = 6; @ConfigEntry.Gui.Tooltip() - @ConfigEntry.BoundedDiscrete(max = 15) - public int darknessCap = 8; - - @ConfigEntry.Gui.Tooltip() - public double darknessPercent = 0.3; - - @ConfigEntry.Gui.Tooltip() - public double stonePercent = 0.15; + public double stonePercent = 0.6; } public static class MineshaftDetection { @@ -81,6 +74,6 @@ public static class MineshaftDetection { public int searchRange = 2; @ConfigEntry.Gui.Tooltip() - public double percent = 0.1; + public double percent = 0.2; } } diff --git a/common/src/main/java/net/celeri/dynmus/config/MusicSelector.java b/common/src/main/java/net/celeri/dynmus/config/MusicSelector.java index 3f8cdbf..f0743ef 100644 --- a/common/src/main/java/net/celeri/dynmus/config/MusicSelector.java +++ b/common/src/main/java/net/celeri/dynmus/config/MusicSelector.java @@ -20,6 +20,7 @@ public String toString() { } } + @ConfigEntry.Gui.Tooltip() @ConfigEntry.Gui.CollapsibleObject public MusicToggles caveMusic = new MusicToggles( MusicToggle.None, MusicToggle.None, MusicToggle.None, @@ -41,6 +42,7 @@ public String toString() { MusicToggle.None, MusicToggle.None ); + @ConfigEntry.Gui.Tooltip() @ConfigEntry.Gui.CollapsibleObject public MusicToggles coldMusic = new MusicToggles( MusicToggle.None, MusicToggle.None, MusicToggle.None, @@ -62,6 +64,7 @@ public String toString() { MusicToggle.None, MusicToggle.None ); + @ConfigEntry.Gui.Tooltip() @ConfigEntry.Gui.CollapsibleObject public MusicToggles hotMusic = new MusicToggles( MusicToggle.None, MusicToggle.None, MusicToggle.None, @@ -83,6 +86,7 @@ public String toString() { MusicToggle.None, MusicToggle.None ); + @ConfigEntry.Gui.Tooltip() @ConfigEntry.Gui.CollapsibleObject public MusicToggles niceMusic = new MusicToggles( MusicToggle.Both, MusicToggle.None, MusicToggle.Both, @@ -104,6 +108,7 @@ public String toString() { MusicToggle.None, MusicToggle.None ); + @ConfigEntry.Gui.Tooltip() @ConfigEntry.Gui.CollapsibleObject public MusicToggles downMusic = new MusicToggles( MusicToggle.None, MusicToggle.Both, MusicToggle.None, @@ -125,6 +130,7 @@ public String toString() { MusicToggle.None, MusicToggle.None ); + @ConfigEntry.Gui.Tooltip() @ConfigEntry.Gui.CollapsibleObject public MusicToggles endMusic = new MusicToggles( MusicToggle.None, MusicToggle.None, MusicToggle.None, diff --git a/common/src/main/java/net/celeri/dynmus/mixin/BiomeAmbientSoundsHandlerMixin.java b/common/src/main/java/net/celeri/dynmus/mixin/BiomeAmbientSoundsHandlerMixin.java index 3c80366..f27bd00 100644 --- a/common/src/main/java/net/celeri/dynmus/mixin/BiomeAmbientSoundsHandlerMixin.java +++ b/common/src/main/java/net/celeri/dynmus/mixin/BiomeAmbientSoundsHandlerMixin.java @@ -3,11 +3,8 @@ import net.celeri.dynmus.DynamicMusic; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.resources.sounds.BiomeAmbientSoundsHandler; -import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.AmbientMoodSettings; -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; @@ -22,10 +19,6 @@ public class BiomeAmbientSoundsHandlerMixin { @Shadow private float moodiness; - @Shadow - @Final - private LocalPlayer player; - @Shadow private Optional moodSettings = Optional.empty(); @@ -33,12 +26,8 @@ public class BiomeAmbientSoundsHandlerMixin { private void dynmus$tick(CallbackInfo ci) { this.moodSettings.ifPresent( ambientMoodSettings -> { - Level level = this.player.level; - if ( - DynamicMusic.isInCave(level, player.blockPosition()) && - DynamicMusic.isInPseudoMinecraft(level, player.blockPosition()) - ) { - this.moodiness += (float) ((15 - DynamicMusic.getAverageDarkness(level, player.blockPosition())) / (float) ambientMoodSettings.getTickDelay()); + if (DynamicMusic.isInPseudoMinecraft()) { + this.moodiness += (float) ((15 - DynamicMusic.getAverageDarkness()) / (float) ambientMoodSettings.getTickDelay()); } } ); diff --git a/common/src/main/java/net/celeri/dynmus/mixin/MinecraftClientMixin.java b/common/src/main/java/net/celeri/dynmus/mixin/MinecraftClientMixin.java index 20b8c67..47217e6 100644 --- a/common/src/main/java/net/celeri/dynmus/mixin/MinecraftClientMixin.java +++ b/common/src/main/java/net/celeri/dynmus/mixin/MinecraftClientMixin.java @@ -14,10 +14,13 @@ import net.minecraft.sounds.Musics; import net.minecraft.sounds.SoundEvent; import net.minecraft.world.level.Level; +import org.slf4j.Logger; +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.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; @@ -31,6 +34,20 @@ public class MinecraftClientMixin { @Shadow public ClientLevel level; + private static int tickCounter = 0; + + @Inject(method = "tick", at = @At("RETURN")) + private void dynmus$tick(CallbackInfo ci) { + tickCounter++; + + // Execute cave detection algorithm every second + if (tickCounter >= 20 && level != null && player != null) { + tickCounter = 0; + + DynamicMusic.tick(level, player.blockPosition()); + } + } + @Inject(method = "getSituationalMusic", at = @At("RETURN"), cancellable = true) private void dynmus$getSituationalMusic(CallbackInfoReturnable ci) { DynamicMusicConfig config = AutoConfig.getConfigHolder(DynamicMusicConfig.class).getConfig(); @@ -55,7 +72,7 @@ public class MinecraftClientMixin { ) { if ( // In cave - DynamicMusic.isInCave(level, player.blockPosition()) + DynamicMusic.isInCave() // Cave music enabled && config.generalConfig.musicTypesToggles.caveMusic // At least one music enabled @@ -117,7 +134,7 @@ public class MinecraftClientMixin { ) { if ( // In cave - DynamicMusic.isInCave(level, player.blockPosition()) + DynamicMusic.isInCave() // Cave music enabled && config.generalConfig.musicTypesToggles.caveMusic // At least one music enabled diff --git a/common/src/main/resources/assets/dynmus/lang/en_us.json b/common/src/main/resources/assets/dynmus/lang/en_us.json index 75c8725..173479c 100644 --- a/common/src/main/resources/assets/dynmus/lang/en_us.json +++ b/common/src/main/resources/assets/dynmus/lang/en_us.json @@ -46,6 +46,7 @@ "text.autoconfig.dynmus.category.musicSelector": "Music Selector", "text.autoconfig.dynmus.option.musicSelector.caveMusic": "Cave Music", + "text.autoconfig.dynmus.option.musicSelector.caveMusic.@Tooltip": "Music that plays in caves", "text.autoconfig.dynmus.option.musicSelector.caveMusic.creative1": "Biome Fest", "text.autoconfig.dynmus.option.musicSelector.caveMusic.creative2": "Blind Spots", "text.autoconfig.dynmus.option.musicSelector.caveMusic.creative3": "Haunt Muskie", @@ -98,6 +99,7 @@ "text.autoconfig.dynmus.option.musicSelector.caveMusic.end_creative4": "Edreit", "text.autoconfig.dynmus.option.musicSelector.coldMusic": "Cold Music", + "text.autoconfig.dynmus.option.musicSelector.coldMusic.@Tooltip": "Music that plays in cold biomes when the sun is out", "text.autoconfig.dynmus.option.musicSelector.coldMusic.creative1": "Biome Fest", "text.autoconfig.dynmus.option.musicSelector.coldMusic.creative2": "Blind Spots", "text.autoconfig.dynmus.option.musicSelector.coldMusic.creative3": "Haunt Muskie", @@ -150,6 +152,7 @@ "text.autoconfig.dynmus.option.musicSelector.coldMusic.end_creative4": "Edreit", "text.autoconfig.dynmus.option.musicSelector.hotMusic": "Hot Music", + "text.autoconfig.dynmus.option.musicSelector.hotMusic.@Tooltip": "Music that plays in hot biomes when the sun is out", "text.autoconfig.dynmus.option.musicSelector.hotMusic.creative1": "Biome Fest", "text.autoconfig.dynmus.option.musicSelector.hotMusic.creative2": "Blind Spots", "text.autoconfig.dynmus.option.musicSelector.hotMusic.creative3": "Haunt Muskie", @@ -202,6 +205,7 @@ "text.autoconfig.dynmus.option.musicSelector.hotMusic.end_creative4": "Edreit", "text.autoconfig.dynmus.option.musicSelector.niceMusic": "Nice Music", + "text.autoconfig.dynmus.option.musicSelector.niceMusic.@Tooltip": "Music that plays in temperate biomes when the sun is out", "text.autoconfig.dynmus.option.musicSelector.niceMusic.creative1": "Biome Fest", "text.autoconfig.dynmus.option.musicSelector.niceMusic.creative2": "Blind Spots", "text.autoconfig.dynmus.option.musicSelector.niceMusic.creative3": "Haunt Muskie", @@ -254,6 +258,7 @@ "text.autoconfig.dynmus.option.musicSelector.niceMusic.end_creative4": "Edreit", "text.autoconfig.dynmus.option.musicSelector.downMusic": "Down Music", + "text.autoconfig.dynmus.option.musicSelector.downMusic.@Tooltip": "Music that plays in during the night and when its raining", "text.autoconfig.dynmus.option.musicSelector.downMusic.creative1": "Biome Fest", "text.autoconfig.dynmus.option.musicSelector.downMusic.creative2": "Blind Spots", "text.autoconfig.dynmus.option.musicSelector.downMusic.creative3": "Haunt Muskie", @@ -306,6 +311,7 @@ "text.autoconfig.dynmus.option.musicSelector.downMusic.end_creative4": "Edreit", "text.autoconfig.dynmus.option.musicSelector.endMusic": "End Music", + "text.autoconfig.dynmus.option.musicSelector.endMusic.@Tooltip": "Music that plays in the End", "text.autoconfig.dynmus.option.musicSelector.endMusic.creative1": "Biome Fest", "text.autoconfig.dynmus.option.musicSelector.endMusic.creative2": "Blind Spots", "text.autoconfig.dynmus.option.musicSelector.endMusic.creative3": "Haunt Muskie", diff --git a/gradle.properties b/gradle.properties index e73beb7..dc5c6c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ minecraft_version=1.19.2 enabled_platforms=fabric,forge archives_base_name=dynmus -mod_version=2.3.0+1.19.2 +mod_version=2.3.1+1.19.2 maven_group=net.celeri.dynmus architectury_version=6.2.43