filename:
common/src/main/java/rearth/oritech/util/AutoPlayingSoundKeyframeHandler.java
branch:
1.21
back to repo
package rearth.oritech.util;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.registry.Registries;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.random.Random;
import rearth.oritech.Oritech;
import software.bernie.geckolib.animatable.GeoAnimatable;
import software.bernie.geckolib.animation.AnimationController;
import software.bernie.geckolib.animation.keyframe.event.SoundKeyframeEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
// basically of fabric version of this: https://github.com/bernie-g/geckolib/blob/main/common/src/main/java/software/bernie/geckolib/animation/keyframe/event/builtin/AutoPlayingSoundKeyframeHandler.java
public class AutoPlayingSoundKeyframeHandler<A extends GeoAnimatable> implements AnimationController.SoundKeyframeHandler<A> {
private final Supplier<Float> speedSupplier;
private final Map<Identifier, Long> lastPlayedAt = new HashMap<>();
public AutoPlayingSoundKeyframeHandler(Supplier<Float> speedSupplier) {
this.speedSupplier = speedSupplier;
}
public AutoPlayingSoundKeyframeHandler() {
this.speedSupplier = AutoPlayingSoundKeyframeHandler::getDefaultSpeed;
}
private static float getDefaultSpeed() {
return 1f;
}
@Override
public void handle(SoundKeyframeEvent<A> event) {
var segments = event.getKeyframeData().getSound().split("\\|");
var sound = Registries.SOUND_EVENT.get(Identifier.of(segments[0]));
if (sound != null) {
var time = MinecraftClient.getInstance().player.clientWorld.getTime();
var age = time - lastPlayedAt.getOrDefault(sound.getId(), 0L);
if (age < 30) return; // don't play sounds if we just played it
var entity = (BlockEntity) event.getAnimatable();
var pos = entity.getPos().toCenterPos();
var distance = Math.sqrt(MinecraftClient.getInstance().gameRenderer.getCamera().getPos().squaredDistanceTo(pos));
var volumeFalloff = Math.min(1f, 1f / (distance / 4f));
if (distance > 25) return;
var speed = speedSupplier.get();
speed = Math.min(Math.max(speed, 0.125f), 8f);
var volume = segments.length > 1 ? Float.parseFloat(segments[1]) : 1f;
volume *= (float) (Oritech.CONFIG.machineVolumeMultiplier() * getPitchRandomMultiplier(entity.getWorld().random) * volumeFalloff * 0.5f);
var pitch = segments.length > 2 ? Float.parseFloat(segments[2]) : 1f;
pitch *= speed * getPitchRandomMultiplier(entity.getWorld().random);
var source = SoundCategory.BLOCKS;
MinecraftClient.getInstance().player.clientWorld.playSoundAtBlockCenter(entity.getPos(), sound, source, volume, pitch, true);
lastPlayedAt.put(sound.getId(), time);
}
}
private float getPitchRandomMultiplier(Random random) {
return random.nextFloat() * 0.15f + 1;
}
}