/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.collect.Maps * com.google.gson.Gson * com.google.gson.GsonBuilder * com.google.gson.reflect.TypeToken * com.mojang.logging.LogUtils * org.jspecify.annotations.Nullable * org.slf4j.Logger */ package net.minecraft.client.sounds; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.mojang.blaze3d.audio.ListenerTransform; import com.mojang.logging.LogUtils; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import net.minecraft.SharedConstants; import net.minecraft.client.Camera; import net.minecraft.client.Options; import net.minecraft.client.resources.sounds.Sound; import net.minecraft.client.resources.sounds.SoundEventRegistration; import net.minecraft.client.resources.sounds.SoundEventRegistrationSerializer; import net.minecraft.client.resources.sounds.SoundInstance; import net.minecraft.client.resources.sounds.TickableSoundInstance; import net.minecraft.client.sounds.SoundEngine; import net.minecraft.client.sounds.SoundEventListener; import net.minecraft.client.sounds.WeighedSoundEvents; import net.minecraft.client.sounds.Weighted; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.ComponentUtils; import net.minecraft.resources.Identifier; import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceProvider; import net.minecraft.server.packs.resources.SimplePreparableReloadListener; import net.minecraft.sounds.SoundSource; import net.minecraft.util.GsonHelper; import net.minecraft.util.RandomSource; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.util.profiling.Zone; import net.minecraft.util.valueproviders.ConstantFloat; import net.minecraft.util.valueproviders.MultipliedFloats; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; public class SoundManager extends SimplePreparableReloadListener { public static final Identifier EMPTY_SOUND_LOCATION = Identifier.withDefaultNamespace("empty"); public static final Sound EMPTY_SOUND = new Sound(EMPTY_SOUND_LOCATION, ConstantFloat.of(1.0f), ConstantFloat.of(1.0f), 1, Sound.Type.FILE, false, false, 16); public static final Identifier INTENTIONALLY_EMPTY_SOUND_LOCATION = Identifier.withDefaultNamespace("intentionally_empty"); public static final WeighedSoundEvents INTENTIONALLY_EMPTY_SOUND_EVENT = new WeighedSoundEvents(INTENTIONALLY_EMPTY_SOUND_LOCATION, null); public static final Sound INTENTIONALLY_EMPTY_SOUND = new Sound(INTENTIONALLY_EMPTY_SOUND_LOCATION, ConstantFloat.of(1.0f), ConstantFloat.of(1.0f), 1, Sound.Type.FILE, false, false, 16); private static final Logger LOGGER = LogUtils.getLogger(); private static final String SOUNDS_PATH = "sounds.json"; private static final Gson GSON = new GsonBuilder().registerTypeAdapter(SoundEventRegistration.class, (Object)new SoundEventRegistrationSerializer()).create(); private static final TypeToken> SOUND_EVENT_REGISTRATION_TYPE = new TypeToken>(){}; private final Map registry = Maps.newHashMap(); private final SoundEngine soundEngine; private final Map soundCache = new HashMap(); public SoundManager(Options options) { this.soundEngine = new SoundEngine(this, options, ResourceProvider.fromMap(this.soundCache)); } @Override protected Preparations prepare(ResourceManager manager, ProfilerFiller profiler) { Preparations preparations = new Preparations(); try (Zone ignored = profiler.zone("list");){ preparations.listResources(manager); } for (String namespace : manager.getNamespaces()) { try { Zone ignored = profiler.zone(namespace); try { List resources = manager.getResourceStack(Identifier.fromNamespaceAndPath(namespace, SOUNDS_PATH)); for (Resource resource : resources) { profiler.push(resource.sourcePackId()); try (BufferedReader reader = resource.openAsReader();){ profiler.push("parse"); Map map = GsonHelper.fromJson(GSON, (Reader)reader, SOUND_EVENT_REGISTRATION_TYPE); profiler.popPush("register"); for (Map.Entry entry : map.entrySet()) { preparations.handleRegistration(Identifier.fromNamespaceAndPath(namespace, entry.getKey()), entry.getValue()); } profiler.pop(); } catch (RuntimeException e) { LOGGER.warn("Invalid {} in resourcepack: '{}'", new Object[]{SOUNDS_PATH, resource.sourcePackId(), e}); } profiler.pop(); } } finally { if (ignored == null) continue; ignored.close(); } } catch (IOException iOException) {} } return preparations; } @Override protected void apply(Preparations preparations, ResourceManager manager, ProfilerFiller profiler) { preparations.apply(this.registry, this.soundCache, this.soundEngine); if (SharedConstants.IS_RUNNING_IN_IDE) { for (Identifier location : this.registry.keySet()) { WeighedSoundEvents event = this.registry.get(location); if (ComponentUtils.isTranslationResolvable(event.getSubtitle()) || !BuiltInRegistries.SOUND_EVENT.containsKey(location)) continue; LOGGER.error("Missing subtitle {} for sound event: {}", (Object)event.getSubtitle(), (Object)location); } } if (LOGGER.isDebugEnabled()) { for (Identifier location : this.registry.keySet()) { if (BuiltInRegistries.SOUND_EVENT.containsKey(location)) continue; LOGGER.debug("Not having sound event for: {}", (Object)location); } } this.soundEngine.reload(); } public List getAvailableSoundDevices() { return this.soundEngine.getAvailableSoundDevices(); } public ListenerTransform getListenerTransform() { return this.soundEngine.getListenerTransform(); } private static boolean validateSoundResource(Sound sound, Identifier eventLocation, ResourceProvider resourceProvider) { Identifier soundPath = sound.getPath(); if (resourceProvider.getResource(soundPath).isEmpty()) { LOGGER.warn("File {} does not exist, cannot add it to event {}", (Object)soundPath, (Object)eventLocation); return false; } return true; } public @Nullable WeighedSoundEvents getSoundEvent(Identifier location) { return this.registry.get(location); } public Collection getAvailableSounds() { return this.registry.keySet(); } public void queueTickingSound(TickableSoundInstance instance) { this.soundEngine.queueTickingSound(instance); } public SoundEngine.PlayResult play(SoundInstance instance) { return this.soundEngine.play(instance); } public void playDelayed(SoundInstance instance, int delay) { this.soundEngine.playDelayed(instance, delay); } public void updateSource(Camera camera) { this.soundEngine.updateSource(camera); } public void pauseAllExcept(SoundSource ... ignoredSources) { this.soundEngine.pauseAllExcept(ignoredSources); } public void stop() { this.soundEngine.stopAll(); } public void destroy() { this.soundEngine.destroy(); } public void emergencyShutdown() { this.soundEngine.emergencyShutdown(); } public void tick(boolean paused) { this.soundEngine.tick(paused); } public void resume() { this.soundEngine.resume(); } public void refreshCategoryVolume(SoundSource category) { this.soundEngine.refreshCategoryVolume(category); } public void stop(SoundInstance soundInstance) { this.soundEngine.stop(soundInstance); } public void updateCategoryVolume(SoundSource source, float gain) { this.soundEngine.updateCategoryVolume(source, gain); } public boolean isActive(SoundInstance instance) { return this.soundEngine.isActive(instance); } public void addListener(SoundEventListener listener) { this.soundEngine.addEventListener(listener); } public void removeListener(SoundEventListener listener) { this.soundEngine.removeEventListener(listener); } public void stop(@Nullable Identifier sound, @Nullable SoundSource source) { this.soundEngine.stop(sound, source); } public String getDebugString() { return this.soundEngine.getDebugString(); } public void reload() { this.soundEngine.reload(); } protected static class Preparations { private final Map registry = Maps.newHashMap(); private Map soundCache = Map.of(); protected Preparations() { } private void listResources(ResourceManager resourceManager) { this.soundCache = Sound.SOUND_LISTER.listMatchingResources(resourceManager); } private void handleRegistration(Identifier eventLocation, SoundEventRegistration soundEventRegistration) { boolean missesRegistration; WeighedSoundEvents registration = this.registry.get(eventLocation); boolean bl = missesRegistration = registration == null; if (missesRegistration || soundEventRegistration.isReplace()) { if (!missesRegistration) { LOGGER.debug("Replaced sound event location {}", (Object)eventLocation); } registration = new WeighedSoundEvents(eventLocation, soundEventRegistration.getSubtitle()); this.registry.put(eventLocation, registration); } ResourceProvider cachedProvider = ResourceProvider.fromMap(this.soundCache); block4: for (final Sound sound : soundEventRegistration.getSounds()) { final Identifier soundLocation = sound.getLocation(); registration.addSound(switch (sound.getType()) { case Sound.Type.FILE -> { if (!SoundManager.validateSoundResource(sound, eventLocation, cachedProvider)) continue block4; yield sound; } case Sound.Type.SOUND_EVENT -> new Weighted(){ @Override public int getWeight() { WeighedSoundEvents registration = registry.get(soundLocation); return registration == null ? 0 : registration.getWeight(); } @Override public Sound getSound(RandomSource random) { WeighedSoundEvents registration = registry.get(soundLocation); if (registration == null) { return EMPTY_SOUND; } Sound wrappedSound = registration.getSound(random); return new Sound(wrappedSound.getLocation(), new MultipliedFloats(wrappedSound.getVolume(), sound.getVolume()), new MultipliedFloats(wrappedSound.getPitch(), sound.getPitch()), sound.getWeight(), Sound.Type.FILE, wrappedSound.shouldStream() || sound.shouldStream(), wrappedSound.shouldPreload(), wrappedSound.getAttenuationDistance()); } @Override public void preloadIfRequired(SoundEngine soundEngine) { WeighedSoundEvents registration = registry.get(soundLocation); if (registration == null) { return; } registration.preloadIfRequired(soundEngine); } }; default -> throw new IllegalStateException("Unknown SoundEventRegistration type: " + String.valueOf((Object)sound.getType())); }); } } public void apply(Map registry, Map soundCache, SoundEngine engine) { registry.clear(); soundCache.clear(); soundCache.putAll(this.soundCache); for (Map.Entry entry : this.registry.entrySet()) { registry.put(entry.getKey(), entry.getValue()); entry.getValue().preloadIfRequired(engine); } } } }