Skip to content

Commit

Permalink
Better cave detection
Browse files Browse the repository at this point in the history
  • Loading branch information
c-leri committed Jun 19, 2023
1 parent f8b6953 commit 841d1b9
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 107 deletions.
139 changes: 58 additions & 81 deletions common/src/main/java/net/celeri/dynmus/DynamicMusic.java
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand All @@ -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;
}
}
13 changes: 3 additions & 10 deletions common/src/main/java/net/celeri/dynmus/config/GeneralConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,17 @@ 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 {
@ConfigEntry.Gui.Tooltip()
public int searchRange = 2;

@ConfigEntry.Gui.Tooltip()
public double percent = 0.1;
public double percent = 0.2;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public String toString() {
}
}

@ConfigEntry.Gui.Tooltip()
@ConfigEntry.Gui.CollapsibleObject
public MusicToggles caveMusic = new MusicToggles(
MusicToggle.None, MusicToggle.None, MusicToggle.None,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -22,23 +19,15 @@ public class BiomeAmbientSoundsHandlerMixin {
@Shadow
private float moodiness;

@Shadow
@Final
private LocalPlayer player;

@Shadow
private Optional<AmbientMoodSettings> moodSettings = Optional.empty();

@Inject(method = "tick", at = @At("HEAD"))
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());
}
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<Music> ci) {
DynamicMusicConfig config = AutoConfig.getConfigHolder(DynamicMusicConfig.class).getConfig();
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions common/src/main/resources/assets/dynmus/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
Loading

0 comments on commit 841d1b9

Please sign in to comment.