148 lines
5.3 KiB
Java
148 lines
5.3 KiB
Java
package net.minecraft.client.resources.sounds;
|
|
|
|
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
|
import java.util.Optional;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.client.player.LocalPlayer;
|
|
import net.minecraft.client.sounds.SoundManager;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.sounds.SoundEvent;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.LightLayer;
|
|
import net.minecraft.world.level.biome.AmbientAdditionsSettings;
|
|
import net.minecraft.world.level.biome.AmbientMoodSettings;
|
|
import net.minecraft.world.level.biome.Biome;
|
|
import net.minecraft.world.level.biome.BiomeManager;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class BiomeAmbientSoundsHandler implements AmbientSoundHandler {
|
|
private static final int LOOP_SOUND_CROSS_FADE_TIME = 40;
|
|
private static final float SKY_MOOD_RECOVERY_RATE = 0.001F;
|
|
private final LocalPlayer player;
|
|
private final SoundManager soundManager;
|
|
private final BiomeManager biomeManager;
|
|
private final RandomSource random;
|
|
private final Object2ObjectArrayMap<Biome, BiomeAmbientSoundsHandler.LoopSoundInstance> loopSounds = new Object2ObjectArrayMap<>();
|
|
private Optional<AmbientMoodSettings> moodSettings = Optional.empty();
|
|
private Optional<AmbientAdditionsSettings> additionsSettings = Optional.empty();
|
|
private float moodiness;
|
|
@Nullable
|
|
private Biome previousBiome;
|
|
|
|
public BiomeAmbientSoundsHandler(LocalPlayer player, SoundManager soundManager, BiomeManager biomeManager) {
|
|
this.random = player.level().getRandom();
|
|
this.player = player;
|
|
this.soundManager = soundManager;
|
|
this.biomeManager = biomeManager;
|
|
}
|
|
|
|
public float getMoodiness() {
|
|
return this.moodiness;
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
this.loopSounds.values().removeIf(AbstractTickableSoundInstance::isStopped);
|
|
Biome biome = this.biomeManager.getNoiseBiomeAtPosition(this.player.getX(), this.player.getY(), this.player.getZ()).value();
|
|
if (biome != this.previousBiome) {
|
|
this.previousBiome = biome;
|
|
this.moodSettings = biome.getAmbientMood();
|
|
this.additionsSettings = biome.getAmbientAdditions();
|
|
this.loopSounds.values().forEach(BiomeAmbientSoundsHandler.LoopSoundInstance::fadeOut);
|
|
biome.getAmbientLoop().ifPresent(holder -> this.loopSounds.compute(biome, (biomexx, loopSoundInstance) -> {
|
|
if (loopSoundInstance == null) {
|
|
loopSoundInstance = new BiomeAmbientSoundsHandler.LoopSoundInstance((SoundEvent)holder.value());
|
|
this.soundManager.play(loopSoundInstance);
|
|
}
|
|
|
|
loopSoundInstance.fadeIn();
|
|
return loopSoundInstance;
|
|
}));
|
|
}
|
|
|
|
this.additionsSettings.ifPresent(ambientAdditionsSettings -> {
|
|
if (this.random.nextDouble() < ambientAdditionsSettings.getTickChance()) {
|
|
this.soundManager.play(SimpleSoundInstance.forAmbientAddition(ambientAdditionsSettings.getSoundEvent().value()));
|
|
}
|
|
});
|
|
this.moodSettings
|
|
.ifPresent(
|
|
ambientMoodSettings -> {
|
|
Level level = this.player.level();
|
|
int i = ambientMoodSettings.getBlockSearchExtent() * 2 + 1;
|
|
BlockPos blockPos = BlockPos.containing(
|
|
this.player.getX() + this.random.nextInt(i) - ambientMoodSettings.getBlockSearchExtent(),
|
|
this.player.getEyeY() + this.random.nextInt(i) - ambientMoodSettings.getBlockSearchExtent(),
|
|
this.player.getZ() + this.random.nextInt(i) - ambientMoodSettings.getBlockSearchExtent()
|
|
);
|
|
int j = level.getBrightness(LightLayer.SKY, blockPos);
|
|
if (j > 0) {
|
|
this.moodiness -= j / 15.0F * 0.001F;
|
|
} else {
|
|
this.moodiness = this.moodiness - (float)(level.getBrightness(LightLayer.BLOCK, blockPos) - 1) / ambientMoodSettings.getTickDelay();
|
|
}
|
|
|
|
if (this.moodiness >= 1.0F) {
|
|
double d = blockPos.getX() + 0.5;
|
|
double e = blockPos.getY() + 0.5;
|
|
double f = blockPos.getZ() + 0.5;
|
|
double g = d - this.player.getX();
|
|
double h = e - this.player.getEyeY();
|
|
double k = f - this.player.getZ();
|
|
double l = Math.sqrt(g * g + h * h + k * k);
|
|
double m = l + ambientMoodSettings.getSoundPositionOffset();
|
|
SimpleSoundInstance simpleSoundInstance = SimpleSoundInstance.forAmbientMood(
|
|
ambientMoodSettings.getSoundEvent().value(),
|
|
this.random,
|
|
this.player.getX() + g / l * m,
|
|
this.player.getEyeY() + h / l * m,
|
|
this.player.getZ() + k / l * m
|
|
);
|
|
this.soundManager.play(simpleSoundInstance);
|
|
this.moodiness = 0.0F;
|
|
} else {
|
|
this.moodiness = Math.max(this.moodiness, 0.0F);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static class LoopSoundInstance extends AbstractTickableSoundInstance {
|
|
private int fadeDirection;
|
|
private int fade;
|
|
|
|
public LoopSoundInstance(SoundEvent soundEvent) {
|
|
super(soundEvent, SoundSource.AMBIENT, SoundInstance.createUnseededRandom());
|
|
this.looping = true;
|
|
this.delay = 0;
|
|
this.volume = 1.0F;
|
|
this.relative = true;
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
if (this.fade < 0) {
|
|
this.stop();
|
|
}
|
|
|
|
this.fade = this.fade + this.fadeDirection;
|
|
this.volume = Mth.clamp(this.fade / 40.0F, 0.0F, 1.0F);
|
|
}
|
|
|
|
public void fadeOut() {
|
|
this.fade = Math.min(this.fade, 40);
|
|
this.fadeDirection = -1;
|
|
}
|
|
|
|
public void fadeIn() {
|
|
this.fade = Math.max(0, this.fade);
|
|
this.fadeDirection = 1;
|
|
}
|
|
}
|
|
}
|