package net.minecraft.client.sounds; import com.google.common.collect.Maps; import com.mojang.blaze3d.audio.SoundBuffer; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.util.Collection; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.Util; import net.minecraft.client.resources.sounds.Sound; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceProvider; /** * The {@linkplain SoundBufferLibrary} class provides a cache containing instances of {@linkplain SoundBuffer} and {@linkplain AudioStream} for use in Minecraft sound handling. */ @Environment(EnvType.CLIENT) public class SoundBufferLibrary { /** * The {@linkplain ResourceProvider} used for loading sound resources. */ private final ResourceProvider resourceManager; private final Map> cache = Maps.>newHashMap(); public SoundBufferLibrary(ResourceProvider resourceManager) { this.resourceManager = resourceManager; } /** * {@return Returns a {@linkplain CompletableFuture} containing the complete {@linkplain SoundBuffer}. The {@linkplain SoundBuffer} is loaded asynchronously and cached.} * * @param soundID the {@linkplain ResourceLocation} of the sound */ public CompletableFuture getCompleteBuffer(ResourceLocation soundID) { return (CompletableFuture)this.cache.computeIfAbsent(soundID, resourceLocation -> CompletableFuture.supplyAsync(() -> { try { InputStream inputStream = this.resourceManager.open(resourceLocation); SoundBuffer var5; try { FiniteAudioStream finiteAudioStream = new JOrbisAudioStream(inputStream); try { ByteBuffer byteBuffer = finiteAudioStream.readAll(); var5 = new SoundBuffer(byteBuffer, finiteAudioStream.getFormat()); } catch (Throwable var8) { try { finiteAudioStream.close(); } catch (Throwable var7) { var8.addSuppressed(var7); } throw var8; } finiteAudioStream.close(); } catch (Throwable var9) { if (inputStream != null) { try { inputStream.close(); } catch (Throwable var6) { var9.addSuppressed(var6); } } throw var9; } if (inputStream != null) { inputStream.close(); } return var5; } catch (IOException var10) { throw new CompletionException(var10); } }, Util.nonCriticalIoPool())); } /** * {@return Returns a {@linkplain CompletableFuture} containing the {@linkplain AudioStream}. The {@linkplain AudioStream} is loaded asynchronously.} * * @param resourceLocation the {@linkplain ResourceLocation} of the sound * @param isWrapper whether the {@linkplain AudioStream} should be a {@linkplain LoopingAudioStream} */ public CompletableFuture getStream(ResourceLocation resourceLocation, boolean isWrapper) { return CompletableFuture.supplyAsync(() -> { try { InputStream inputStream = this.resourceManager.open(resourceLocation); return (AudioStream)(isWrapper ? new LoopingAudioStream(JOrbisAudioStream::new, inputStream) : new JOrbisAudioStream(inputStream)); } catch (IOException var4) { throw new CompletionException(var4); } }, Util.nonCriticalIoPool()); } /** * Clears the cache of all {@linkplain SoundBuffer} instances. */ public void clear() { this.cache.values().forEach(completableFuture -> completableFuture.thenAccept(SoundBuffer::discardAlBuffer)); this.cache.clear(); } /** * Preloads the {@linkplain SoundBuffer} objects for the specified collection of sounds. *

* @return a {@linkplain CompletableFuture} representing the completion of the preload operation * * @param sounds the collection of sounds to preload */ public CompletableFuture preload(Collection sounds) { return CompletableFuture.allOf((CompletableFuture[])sounds.stream().map(sound -> this.getCompleteBuffer(sound.getPath())).toArray(CompletableFuture[]::new)); } }