From e547e049d39fa45d10d010584ac5c727d2d75a5c Mon Sep 17 00:00:00 2001 From: OreCruncher Date: Wed, 7 Jun 2017 05:35:40 -0700 Subject: [PATCH] Backports for sounds and performance --- .../mod/DynSurround/asm/Transformer.java | 78 ++++- .../client/PlayerSoundEffectHandler.java | 2 - .../client/footsteps/Footsteps.java | 6 +- .../footsteps/game/system/PFReaderH.java | 25 +- .../footsteps/game/system/PFSolver.java | 31 +- .../client/sound/SoundManager.java | 125 -------- .../client/sound/SoundManagerReplacement.java | 301 ++++++++++++++++++ .../sound/cache/MemoryStreamHandler.java | 51 +++ .../sound/cache/MemoryURLConnection.java | 57 ++++ .../sound/cache/ResourceURLConnection.java | 60 ++++ .../client/sound/cache/SoundCache.java | 111 +++++++ .../client/sound/cache/SoundInputStream.java | 85 +++++ .../sound/cache/SoundStreamHandler.java | 63 ++++ .../mod/DynSurround/proxy/ProxyClient.java | 3 - src/main/resources/META-INF/dsurround_at.cfg | 18 +- .../dsurround/data/footsteps/blockmap.json | 4 +- 16 files changed, 834 insertions(+), 186 deletions(-) create mode 100644 src/main/java/org/blockartistry/mod/DynSurround/client/sound/SoundManagerReplacement.java create mode 100644 src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/MemoryStreamHandler.java create mode 100644 src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/MemoryURLConnection.java create mode 100644 src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/ResourceURLConnection.java create mode 100644 src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundCache.java create mode 100644 src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundInputStream.java create mode 100644 src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundStreamHandler.java diff --git a/src/main/java/org/blockartistry/mod/DynSurround/asm/Transformer.java b/src/main/java/org/blockartistry/mod/DynSurround/asm/Transformer.java index 0089496..7ec8d87 100644 --- a/src/main/java/org/blockartistry/mod/DynSurround/asm/Transformer.java +++ b/src/main/java/org/blockartistry/mod/DynSurround/asm/Transformer.java @@ -26,13 +26,17 @@ import static org.objectweb.asm.Opcodes.*; +import java.util.ListIterator; + import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.InsnNode; import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TypeInsnNode; import org.objectweb.asm.tree.VarInsnNode; import net.minecraft.launchwrapper.IClassTransformer; @@ -55,6 +59,9 @@ public byte[] transform(final String name, final String transformedName, byte[] } else if ("net.minecraft.world.World".equals(name) || "ahb".equals(name)) { logger.debug("Transforming World..."); return transformWorld(basicClass); + } else if ("net.minecraft.client.audio.SoundHandler".equals(name) || "btp".equals(name)) { + logger.debug("Transforming SoundHandler..."); + return transformSoundHandler(basicClass); } else if ("net.minecraft.client.audio.SoundManager".equals(name) || "btj".equals(name)) { logger.debug("Transforming SoundManager..."); return transformSoundManager(basicClass); @@ -171,33 +178,70 @@ private byte[] transformWorld(final byte[] classBytes) { return cw.toByteArray(); } + private byte[] transformSoundHandler(final byte[] classBytes) { + final String managerToReplace = "net/minecraft/client/audio/SoundManager"; + final String newManager = "org/blockartistry/mod/DynSurround/client/sound/SoundManagerReplacement"; + + final ClassReader cr = new ClassReader(classBytes); + final ClassNode cn = new ClassNode(ASM5); + cr.accept(cn, 0); + + for (final MethodNode m : cn.methods) { + final ListIterator itr = m.instructions.iterator(); + boolean foundNew = false; + while (itr.hasNext()) { + final AbstractInsnNode node = itr.next(); + if (node.getOpcode() == NEW) { + final TypeInsnNode theNew = (TypeInsnNode) node; + if (managerToReplace.equals(theNew.desc)) { + m.instructions.set(node, new TypeInsnNode(NEW, newManager)); + foundNew = true; + } + } else if (node.getOpcode() == INVOKESPECIAL) { + final MethodInsnNode theInvoke = (MethodInsnNode) node; + if (managerToReplace.equals(theInvoke.owner)) { + if (foundNew) { + m.instructions.set(node, new MethodInsnNode(INVOKESPECIAL, newManager, theInvoke.name, + theInvoke.desc, false)); + foundNew = false; + } + } + } + } + } + + final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + cn.accept(cw); + return cw.toByteArray(); + } + private byte[] transformSoundManager(final byte[] classBytes) { - final String names[]; + final String urlNames[]; - if (TransformLoader.runtimeDeobEnabled) - names = new String[] { "func_148594_a" }; - else - names = new String[] { "getNormalizedVolume" }; + if (TransformLoader.runtimeDeobEnabled) { + urlNames = new String[] { "func_148612_a" }; + } else { + urlNames = new String[] { "getURLForSoundResource" }; + } - final String targetName[] = new String[] { "getNormalizedVolume" }; + final String urlTargetName[] = new String[] { "getURLForSoundResource" }; final ClassReader cr = new ClassReader(classBytes); final ClassNode cn = new ClassNode(ASM5); cr.accept(cn, 0); for (final MethodNode m : cn.methods) { - if (m.name.equals(names[0])) { - logger.debug("Hooking " + names[0]); - final InsnList list = new InsnList(); - list.add(new VarInsnNode(ALOAD, 1)); - list.add(new VarInsnNode(ALOAD, 2)); - list.add(new VarInsnNode(ALOAD, 3)); - final String sig = "(Lnet/minecraft/client/audio/ISound;Lnet/minecraft/client/audio/SoundPoolEntry;Lnet/minecraft/client/audio/SoundCategory;)F"; - list.add(new MethodInsnNode(INVOKESTATIC, "org/blockartistry/mod/DynSurround/client/sound/SoundManager", - targetName[0], sig, false)); - list.add(new InsnNode(FRETURN)); + if (m.name.equals(urlNames[0])) { + logger.debug("Hooking " + m.name); + InsnList list = new InsnList(); + list.add(new VarInsnNode(ALOAD, 0)); + final String sig = "(Lnet/minecraft/util/ResourceLocation;)Ljava/net/URL;"; + list.add(new MethodInsnNode(INVOKESTATIC, + "org/blockartistry/mod/DynSurround/client/sound/cache/SoundCache", urlTargetName[0], sig, + false)); + list.add(new InsnNode(ARETURN)); m.instructions.insertBefore(m.instructions.getFirst(), list); - break; + } } diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/PlayerSoundEffectHandler.java b/src/main/java/org/blockartistry/mod/DynSurround/client/PlayerSoundEffectHandler.java index 73ef8cd..155985c 100644 --- a/src/main/java/org/blockartistry/mod/DynSurround/client/PlayerSoundEffectHandler.java +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/PlayerSoundEffectHandler.java @@ -92,8 +92,6 @@ private static void resetSounds() { @Override public void process(final World world, final EntityPlayer player) { - SoundManager.keepAlive(); - // Dead players hear no sounds if (player.isDead) { resetSounds(); diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/Footsteps.java b/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/Footsteps.java index ed81038..5ad5a79 100644 --- a/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/Footsteps.java +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/Footsteps.java @@ -30,6 +30,7 @@ import java.util.Scanner; import org.blockartistry.mod.DynSurround.ModLog; +import org.blockartistry.mod.DynSurround.ModOptions; import org.blockartistry.mod.DynSurround.client.IClientEffectHandler; import org.blockartistry.mod.DynSurround.client.footsteps.game.system.ForgeDictionary; import org.blockartistry.mod.DynSurround.client.footsteps.game.system.PFIsolator; @@ -212,7 +213,10 @@ public void process(World world, EntityPlayer player) { reloadEverything(); } this.isolator.onFrame(); - player.nextStepDistance = Integer.MAX_VALUE; + if (ModOptions.footstepsSoundFactor > 0) + player.nextStepDistance = Integer.MAX_VALUE; + else if(player.nextStepDistance == Integer.MAX_VALUE) + player.nextStepDistance = 0; } @SubscribeEvent(priority = EventPriority.LOWEST) diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/game/system/PFReaderH.java b/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/game/system/PFReaderH.java index 028b8b0..52d8bd1 100644 --- a/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/game/system/PFReaderH.java +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/game/system/PFReaderH.java @@ -28,6 +28,7 @@ import org.blockartistry.mod.DynSurround.client.footsteps.mcpackage.implem.NormalVariator; import org.blockartistry.mod.DynSurround.client.footsteps.mcpackage.interfaces.IGenerator; import org.blockartistry.mod.DynSurround.client.footsteps.mcpackage.interfaces.IIsolator; +import org.blockartistry.mod.DynSurround.client.footsteps.mcpackage.interfaces.ISolver; import org.blockartistry.mod.DynSurround.client.footsteps.mcpackage.interfaces.IVariator; import org.blockartistry.mod.DynSurround.client.footsteps.mcpackage.interfaces.IVariatorSettable; import org.blockartistry.mod.DynSurround.util.MyUtils; @@ -268,8 +269,6 @@ private void simulateBrushes(final EntityPlayer ply) { if ((ply.motionX == 0d && ply.motionZ == 0d) || ply.isSneaking()) return; - // if (true || ply.onGround || ply.isOnLadder()) - // { final int yy = MathHelper.floor_double(ply.posY - 0.1d - ply.getYOffset() - (ply.onGround ? 0d : 0.25d)); final Association assos = mod.getSolver().findAssociationForBlock(MathHelper.floor_double(ply.posX), yy, MathHelper.floor_double(ply.posZ), "find_messy_foliage"); @@ -279,15 +278,10 @@ private void simulateBrushes(final EntityPlayer ply) { this.mod.getSolver().playAssociation(ply, assos, EventType.WALK); } } else { - if (this.isMessyFoliage) { - this.isMessyFoliage = false; - } + this.isMessyFoliage = false; } - // } } - // - protected void playSinglefoot(final EntityPlayer ply, final double verticalOffsetAsMinus, final EventType eventType, final boolean foot) { final Association assos = mod.getSolver().findAssociationForPlayer(ply, verticalOffsetAsMinus, isRightFoot); @@ -297,16 +291,11 @@ protected void playSinglefoot(final EntityPlayer ply, final double verticalOffse protected void playMultifoot(final EntityPlayer ply, final double verticalOffsetAsMinus, final EventType eventType) { // STILL JUMP - final Association leftFoot = mod.getSolver().findAssociationForPlayer(ply, verticalOffsetAsMinus, false); - Association rightFoot = mod.getSolver().findAssociationForPlayer(ply, verticalOffsetAsMinus, true); - - if (leftFoot != null && leftFoot.equals(rightFoot) && !leftFoot.getNoAssociation()) { - rightFoot = null; // If the two feet solve to the same sound, except - // NO_ASSOCIATION, only play the sound once - } - - mod.getSolver().playAssociation(ply, leftFoot, eventType); - mod.getSolver().playAssociation(ply, rightFoot, eventType); + final ISolver s = this.mod.getSolver(); + final Association leftFoot = s.findAssociationForPlayer(ply, verticalOffsetAsMinus, false); + Association rightFoot = s.findAssociationForPlayer(ply, verticalOffsetAsMinus, true); + s.playAssociation(ply, leftFoot, eventType); + s.playAssociation(ply, rightFoot, eventType); } protected float scalex(final float number, final float min, final float max) { diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/game/system/PFSolver.java b/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/game/system/PFSolver.java index a413b45..5cee91c 100644 --- a/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/game/system/PFSolver.java +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/footsteps/game/system/PFSolver.java @@ -81,6 +81,8 @@ public void playAssociation(final EntityPlayer ply, final Association assos, fin @Override public Association findAssociationForPlayer(final EntityPlayer ply, final double verticalOffsetAsMinus, final boolean isRightFoot) { + if (Math.abs(ply.motionY) < 0.02) + return null; // Don't play sounds on every tiny bounce final int yy = MathHelper.floor_double(ply.boundingBox.minY - 0.1d - verticalOffsetAsMinus); final double rot = MathStuff.toRadians(MathHelper.wrapAngleTo180_float(ply.rotationYaw)); final double xn = MathStuff.cos(rot); @@ -102,8 +104,6 @@ public Association findAssociationForPlayer(final EntityPlayer ply, final double @Override public Association findAssociationForLocation(final EntityPlayer player, final int x, final int y, final int z) { - if (Math.abs(player.motionY) < 0.02) - return null; // Don't play sounds on every tiny bounce if (player.isInWater()) ModLog.debug( "WARNING!!! Playing a sound while in the water! This is supposed to be halted by the stopping conditions!!"); @@ -176,16 +176,9 @@ public Association findAssociationForBlock(final int xx, int yy, final int zz) { Block above = world.getBlock(xx, yy + 1, zz); int aboveMeta = world.getBlockMetadata(xx, yy + 1, zz); - String association = this.isolator.getBlockMap().getBlockMapSubstrate(above, aboveMeta, "carpet"); // Try - // to - // see - // if - // the - // block - // above - // is - // a - // carpet... + String association = null; + if (above != Blocks.air) + association = this.isolator.getBlockMap().getBlockMapSubstrate(above, aboveMeta, "carpet"); // PFLog.debugf("Walking on block: %0 -- Being in block: %1", in, // above); @@ -220,10 +213,12 @@ public Association findAssociationForBlock(final int xx, int yy, final int zz) { // => this block of code is here, not outside this if else // group. - String foliage = this.isolator.getBlockMap().getBlockMapSubstrate(above, aboveMeta, "foliage"); - if (foliage != null && !foliage.equals("NOT_EMITTER")) { - association = association + "," + foliage; - ModLog.debug("Foliage detected: " + foliage); + if (above != Blocks.air) { + String foliage = this.isolator.getBlockMap().getBlockMapSubstrate(above, aboveMeta, "foliage"); + if (foliage != null && !foliage.equals("NOT_EMITTER")) { + association = association + "," + foliage; + ModLog.debug("Foliage detected: " + foliage); + } } } } else { @@ -344,6 +339,10 @@ public Association findAssociationForBlock(final int xx, int yy, final int zz, S */ Block above = world.getBlock(xx, yy + 1, zz); + + if (above == Blocks.air) + return null; + int aboveMeta = world.getBlockMetadata(xx, yy + 1, zz); String association = null; diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/sound/SoundManager.java b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/SoundManager.java index 07c8c76..38dd02c 100644 --- a/src/main/java/org/blockartistry/mod/DynSurround/client/sound/SoundManager.java +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/SoundManager.java @@ -24,8 +24,6 @@ package org.blockartistry.mod.DynSurround.client.sound; -import java.lang.reflect.Field; -import java.nio.IntBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -38,58 +36,22 @@ import org.blockartistry.mod.DynSurround.ModOptions; import org.blockartistry.mod.DynSurround.client.EnvironStateHandler.EnvironState; import org.blockartistry.mod.DynSurround.compat.BlockPos; -import org.blockartistry.mod.DynSurround.data.SoundRegistry; -import org.lwjgl.BufferUtils; -import org.lwjgl.openal.AL; -import org.lwjgl.openal.ALC10; -import org.lwjgl.openal.ALC11; - -import cpw.mods.fml.relauncher.ReflectionHelper; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.ISound; -import net.minecraft.client.audio.SoundCategory; -import net.minecraft.client.audio.SoundPoolEntry; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.util.ChatComponentText; -import net.minecraft.util.MathHelper; -import paulscode.sound.Library; -import paulscode.sound.SoundSystem; import paulscode.sound.SoundSystemConfig; -import paulscode.sound.StreamThread; @SideOnly(Side.CLIENT) public class SoundManager { - private static int normalChannelCount = 0; - private static int streamChannelCount = 0; - private static final int AGE_THRESHOLD_TICKS = 5; private static final int SOUND_QUEUE_SLACK = 6; private static final Map emitters = new HashMap(); private static final List pending = new ArrayList(); - private static Field sndSystem = null; - private static Field soundLibrary = null; - private static Field streamThread = null; - - static { - - try { - sndSystem = ReflectionHelper.findField(SoundManager.class, "field_148620_e", "sndSystem"); - soundLibrary = ReflectionHelper.findField(SoundSystem.class, "soundLibrary"); - streamThread = ReflectionHelper.findField(Library.class, "streamThread"); - } catch (final Throwable t) { - ModLog.warn("Cannot find sound manager fields; auto restart not enabled"); - sndSystem = null; - soundLibrary = null; - streamThread = null; - } - - } - public static void clearSounds() { for (final Emitter emit : emitters.values()) emit.fade(); @@ -200,91 +162,4 @@ public static List getSounds() { return result; } - public static void configureSound() { - int totalChannels = -1; - - try { - final boolean create = !AL.isCreated(); - if (create) - AL.create(); - final IntBuffer ib = BufferUtils.createIntBuffer(1); - ALC10.alcGetInteger(AL.getDevice(), ALC11.ALC_MONO_SOURCES, ib); - totalChannels = ib.get(0); - if (create) - AL.destroy(); - } catch (final Throwable e) { - e.printStackTrace(); - } - - normalChannelCount = ModOptions.normalSoundChannelCount; - streamChannelCount = ModOptions.streamingSoundChannelCount; - - if (ModOptions.autoConfigureChannels && totalChannels > 64) { - totalChannels = ((totalChannels + 1) * 3) / 4; - streamChannelCount = totalChannels / 5; - normalChannelCount = totalChannels - streamChannelCount; - } - - ModLog.info("Sound channels: %d normal, %d streaming (total avail: %s)", normalChannelCount, streamChannelCount, - totalChannels == -1 ? "UNKNOWN" : Integer.toString(totalChannels)); - SoundSystemConfig.setNumberNormalChannels(normalChannelCount); - SoundSystemConfig.setNumberStreamingChannels(streamChannelCount); - - } - - // Redirect hook from Minecraft's SoundManager so we can scale the volume - // for each individual sound. - public static float getNormalizedVolume(final ISound sound, final SoundPoolEntry poolEntry, - final SoundCategory category) { - float result = 0.0F; - if (sound == null) { - ModLog.warn("getNormalizedVolume(): Null sound parameter"); - } else if (poolEntry == null) { - ModLog.warn("getNormalizedVolume(): Null poolEntry parameter"); - } else if (category == null) { - ModLog.warn("getNormalizedVolume(): Null category parameter"); - } else { - final String soundName = sound.getPositionedSoundLocation().toString(); - try { - final float volumeScale = SoundRegistry.getVolumeScale(soundName); - result = (float) MathHelper.clamp_double((double) sound.getVolume() * poolEntry.getVolume() - * (double) getSoundCategoryVolume(category) * volumeScale, 0.0D, 1.0D); - } catch (final Throwable t) { - ModLog.error("getNormalizedVolume(): Unable to calculate " + soundName, t); - } - } - return result; - } - - public static float getSoundCategoryVolume(final SoundCategory category) { - return category != null && category != SoundCategory.MASTER - ? Minecraft.getMinecraft().gameSettings.getSoundLevel(category) : 1.0F; - } - - public static void keepAlive() { - if (streamThread == null) - return; - - try { - final net.minecraft.client.audio.SoundManager manager = Minecraft.getMinecraft().getSoundHandler().sndManager; - final SoundSystem sys = (SoundSystem) sndSystem.get(manager); - if (sys != null) { - final Library l = (Library) soundLibrary.get(sys); - if (l != null) { - final StreamThread t = (StreamThread) streamThread.get(l); - if (t != null && !t.isAlive()) { - if (ModLog.DEBUGGING) { - EnvironState.getPlayer() - .addChatMessage(new ChatComponentText("Autorestart of sound system!")); - } - ModLog.warn("Autorestart of sound system!"); - manager.reloadSoundSystem(); - } - } - } - } catch (final Throwable t) { - - } - } - } diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/sound/SoundManagerReplacement.java b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/SoundManagerReplacement.java new file mode 100644 index 0000000..54cc41b --- /dev/null +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/SoundManagerReplacement.java @@ -0,0 +1,301 @@ +/* + * This file is part of Dynamic Surroundings, licensed under the MIT License (MIT). + * + * Copyright (c) OreCruncher, Abastro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.blockartistry.mod.DynSurround.client.sound; + +import java.lang.reflect.Field; +import java.nio.IntBuffer; +import java.util.Iterator; +import java.util.Map.Entry; + +import org.blockartistry.mod.DynSurround.ModLog; +import org.blockartistry.mod.DynSurround.ModOptions; +import org.blockartistry.mod.DynSurround.client.EnvironStateHandler.EnvironState; +import org.blockartistry.mod.DynSurround.data.SoundRegistry; +import org.lwjgl.BufferUtils; +import org.lwjgl.openal.AL; +import org.lwjgl.openal.ALC10; +import org.lwjgl.openal.ALC11; + +import cpw.mods.fml.relauncher.ReflectionHelper; +import cpw.mods.fml.relauncher.SideOnly; +import cpw.mods.fml.relauncher.Side; +import net.minecraft.client.audio.ISound; +import net.minecraft.client.audio.ITickableSound; +import net.minecraft.client.audio.SoundCategory; +import net.minecraft.client.audio.SoundHandler; +import net.minecraft.client.audio.SoundManager; +import net.minecraft.client.audio.SoundPoolEntry; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.MathHelper; +import net.minecraftforge.common.MinecraftForge; +import paulscode.sound.Library; +import paulscode.sound.SoundSystem; +import paulscode.sound.SoundSystemConfig; +import paulscode.sound.StreamThread; + +@SideOnly(Side.CLIENT) +public class SoundManagerReplacement extends SoundManager { + + private static int normalChannelCount = 0; + private static int streamChannelCount = 0; + + private static Field soundLibrary = null; + private static Field streamThread = null; + + static { + + try { + soundLibrary = ReflectionHelper.findField(SoundSystem.class, "soundLibrary"); + streamThread = ReflectionHelper.findField(Library.class, "streamThread"); + } catch (final Throwable t) { + ModLog.warn("Cannot find sound manager fields; auto-restart not enabled"); + soundLibrary = null; + streamThread = null; + } + + } + + private final static int CHECK_INTERVAL = 30 * 20; // 30 seconds + private int nextCheck = 0; + + public SoundManagerReplacement(final SoundHandler handler, final GameSettings settings) { + super(handler, settings); + MinecraftForge.EVENT_BUS.register(this); + + configureSound(); + } + + private void keepAlive() { + if (!this.loaded || streamThread == null) + return; + + // Don't want to spam attempts + if (this.playTime < this.nextCheck) + return; + + this.nextCheck = this.playTime + CHECK_INTERVAL; + + try { + final Library l = (Library) soundLibrary.get(this.sndSystem); + final StreamThread t = (StreamThread) streamThread.get(l); + if (t != null && !t.isAlive()) { + if (ModLog.DEBUGGING) { + EnvironState.getPlayer().addChatMessage(new ChatComponentText("Autorestart of sound system!")); + } + ModLog.warn("Autorestart of sound system!"); + this.reloadSoundSystem(); + } + } catch (final Throwable t) { + ; + } + } + + @Override + public boolean isSoundPlaying(final ISound sound) { + return sound == null ? false : super.isSoundPlaying(sound); + } + + @Override + public void stopSound(final ISound sound) { + if (sound != null) + super.stopSound(sound); + } + + @Override + public void playSound(final ISound sound) { + if (sound != null) + super.playSound(sound); + } + + @Override + public void addDelayedSound(final ISound sound, final int delay) { + if (sound != null) + super.addDelayedSound(sound, delay); + } + + @SuppressWarnings("unchecked") + @Override + public void updateAllSounds() { + + keepAlive(); + + final SoundSystem sndSystem = this.sndSystem; + + ++this.playTime; + Iterator iterator = this.tickableSounds.iterator(); + String s; + + while (iterator.hasNext()) { + ITickableSound itickablesound = (ITickableSound) iterator.next(); + itickablesound.update(); + + if (itickablesound.isDonePlaying()) { + this.stopSound(itickablesound); + } else { + + s = (String) this.invPlayingSounds.get(itickablesound); + final SoundPoolEntry poolEntry = (SoundPoolEntry) this.playingSoundPoolEntries.get(itickablesound); + + if (poolEntry == null) + this.stopSound(itickablesound); + else + synchronized (SoundSystemConfig.THREAD_SYNC) { + sndSystem.setVolume(s, this.getNormalizedVolume(itickablesound, poolEntry, this.sndHandler + .getSound(itickablesound.getPositionedSoundLocation()).getSoundCategory())); + sndSystem.setPitch(s, this.getNormalizedPitch(itickablesound, poolEntry)); + sndSystem.setPosition(s, itickablesound.getXPosF(), itickablesound.getYPosF(), + itickablesound.getZPosF()); + } + } + } + + iterator = this.playingSounds.entrySet().iterator(); + ISound isound; + + while (iterator.hasNext()) { + Entry entry = (Entry) iterator.next(); + s = (String) entry.getKey(); + isound = (ISound) entry.getValue(); + + if (!sndSystem.playing(s)) { + int i = ((Integer) this.playingSoundsStopTime.get(s)).intValue(); + + if (i <= this.playTime) { + int j = isound.getRepeatDelay(); + + if (isound.canRepeat() && j > 0) { + this.delayedSounds.put(isound, Integer.valueOf(this.playTime + j)); + } + + sndSystem.removeSource(s); + iterator.remove(); + this.playingSoundsStopTime.remove(s); + this.playingSoundPoolEntries.remove(isound); + + try { + this.categorySounds.remove( + this.sndHandler.getSound(isound.getPositionedSoundLocation()).getSoundCategory(), s); + } catch (RuntimeException runtimeexception) { + ; + } + + if (isound instanceof ITickableSound) { + this.tickableSounds.remove(isound); + } + } + } + } + + Iterator iterator1 = this.delayedSounds.entrySet().iterator(); + + while (iterator1.hasNext()) { + Entry entry1 = (Entry) iterator1.next(); + + if (this.playTime >= ((Integer) entry1.getValue()).intValue()) { + isound = (ISound) entry1.getKey(); + + if (isound instanceof ITickableSound) { + ((ITickableSound) isound).update(); + } + + this.playSound(isound); + iterator1.remove(); + } + } + } + + /** + * Normalizes pitch from parameters and clamps to [0.5, 2.0] + */ + public float getNormalizedPitch(final ISound sound, final SoundPoolEntry poolEntry) { + float result = 1.0F; + if (sound == null) { + ModLog.warn("getNormalizedPitch(): Null sound parameter"); + } else if (poolEntry == null) { + ModLog.warn("getNormalizedPitch(): Null poolEntry parameter"); + result = sound.getPitch(); + } else { + result = (float) (sound.getPitch() * poolEntry.getPitch()); + } + + return (float) MathHelper.clamp_double(result, 0.5D, 2.0D); + } + + @Override + public float getNormalizedVolume(final ISound sound, final SoundPoolEntry poolEntry, final SoundCategory category) { + float result = 0.0F; + if (sound == null) { + ModLog.warn("getNormalizedVolume(): Null sound parameter"); + } else if (poolEntry == null) { + ModLog.warn("getNormalizedVolume(): Null poolEntry parameter"); + } else if (category == null) { + ModLog.warn("getNormalizedVolume(): Null category parameter"); + } else { + final String soundName = sound.getPositionedSoundLocation().toString(); + try { + final float volumeScale = SoundRegistry.getVolumeScale(soundName); + result = (float) MathHelper.clamp_double((double) sound.getVolume() * poolEntry.getVolume() + * (double) getSoundCategoryVolume(category) * volumeScale, 0.0D, 1.0D); + } catch (final Throwable t) { + ModLog.error("getNormalizedVolume(): Unable to calculate " + soundName, t); + } + } + return result; + } + + public static void configureSound() { + int totalChannels = -1; + + try { + final boolean create = !AL.isCreated(); + if (create) + AL.create(); + final IntBuffer ib = BufferUtils.createIntBuffer(1); + ALC10.alcGetInteger(AL.getDevice(), ALC11.ALC_MONO_SOURCES, ib); + totalChannels = ib.get(0); + if (create) + AL.destroy(); + } catch (final Throwable e) { + e.printStackTrace(); + } + + normalChannelCount = ModOptions.normalSoundChannelCount; + streamChannelCount = ModOptions.streamingSoundChannelCount; + + if (ModOptions.autoConfigureChannels && totalChannels > 64) { + totalChannels = ((totalChannels + 1) * 3) / 4; + streamChannelCount = totalChannels / 5; + normalChannelCount = totalChannels - streamChannelCount; + } + + ModLog.info("Sound channels: %d normal, %d streaming (total avail: %s)", normalChannelCount, streamChannelCount, + totalChannels == -1 ? "UNKNOWN" : Integer.toString(totalChannels)); + SoundSystemConfig.setNumberNormalChannels(normalChannelCount); + SoundSystemConfig.setNumberStreamingChannels(streamChannelCount); + + } + +} diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/MemoryStreamHandler.java b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/MemoryStreamHandler.java new file mode 100644 index 0000000..5902759 --- /dev/null +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/MemoryStreamHandler.java @@ -0,0 +1,51 @@ +/* This file is part of Dynamic Surroundings, licensed under the MIT License (MIT). + * + * Copyright (c) OreCruncher + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.blockartistry.mod.DynSurround.client.sound.cache; + +import java.net.URL; +import java.net.URLConnection; + +import javax.annotation.Nonnull; + +import cpw.mods.fml.relauncher.SideOnly; +import cpw.mods.fml.relauncher.Side; + +import net.minecraft.util.ResourceLocation; + +@SideOnly(Side.CLIENT) +public class MemoryStreamHandler extends SoundStreamHandler { + + protected final byte[] buffer; + + public MemoryStreamHandler(@Nonnull final ResourceLocation resource, @Nonnull final byte[] buffer) { + super(resource); + this.buffer = buffer; + } + + @Override + protected URLConnection createConnection(@Nonnull final URL url) { + return new MemoryURLConnection(url, this.buffer); + } + +} diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/MemoryURLConnection.java b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/MemoryURLConnection.java new file mode 100644 index 0000000..1a73698 --- /dev/null +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/MemoryURLConnection.java @@ -0,0 +1,57 @@ +/* This file is part of Dynamic Surroundings, licensed under the MIT License (MIT). + * + * Copyright (c) OreCruncher + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.blockartistry.mod.DynSurround.client.sound.cache; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; + +import javax.annotation.Nonnull; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class MemoryURLConnection extends URLConnection { + + protected final byte[] buffer; + + protected MemoryURLConnection(@Nonnull final URL url, @Nonnull final byte[] buffer) { + super(url); + + this.buffer = buffer; + } + + @Override + public void connect() throws IOException { + } + + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(this.buffer); + } + +} diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/ResourceURLConnection.java b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/ResourceURLConnection.java new file mode 100644 index 0000000..1271f67 --- /dev/null +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/ResourceURLConnection.java @@ -0,0 +1,60 @@ +/* This file is part of Dynamic Surroundings, licensed under the MIT License (MIT). + * + * Copyright (c) OreCruncher + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.blockartistry.mod.DynSurround.client.sound.cache; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; + +import javax.annotation.Nonnull; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; + +@SideOnly(Side.CLIENT) +public class ResourceURLConnection extends URLConnection { + + protected final ResourceLocation resource; + + protected ResourceURLConnection(@Nonnull final URL url, @Nonnull final ResourceLocation resource) { + super(url); + + this.resource = resource; + } + + @Override + public void connect() throws IOException { + } + + @Override + public InputStream getInputStream() throws IOException { + final InputStream stream = Minecraft.getMinecraft().getResourceManager().getResource(this.resource) + .getInputStream(); + return new SoundInputStream(stream); + } + +} diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundCache.java b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundCache.java new file mode 100644 index 0000000..487a81f --- /dev/null +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundCache.java @@ -0,0 +1,111 @@ +/* This file is part of Dynamic Surroundings, licensed under the MIT License (MIT). + * + * Copyright (c) OreCruncher + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.blockartistry.mod.DynSurround.client.sound.cache; + +import java.io.InputStream; +import java.net.URL; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.Nonnull; + +import com.google.common.io.ByteStreams; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.util.ResourceLocation; + +@SideOnly(Side.CLIENT) +public final class SoundCache { + + private static final int BUFFER_SIZE = 64 * 1024; + private static final byte[] BUFFER = new byte[BUFFER_SIZE]; + private static final IResourceManager manager = Minecraft.getMinecraft().getResourceManager(); + private static final Map cache = new HashMap(256); + + private static byte[] getBuffer(@Nonnull final ResourceLocation resource) { + InputStream stream = null; + + try { + stream = manager.getResource(resource).getInputStream(); + // It's possible that available() returns 0. This generally means + // the stream has no idea about the number of bytes. If it reports + // 64K or greater assume it needs to be streamed from the JAR. + if (stream != null && stream.available() < BUFFER_SIZE) { + final int bytesRead = ByteStreams.read(stream, BUFFER, 0, BUFFER_SIZE); + // If no bytes were returned, or the total read was 64K, assume + // that it needs to be streamed. + if (bytesRead == 0 || bytesRead == BUFFER_SIZE) + return null; + // Make a new array containing the data. Don't want to + // pass back BUFFER. + return Arrays.copyOf(BUFFER, bytesRead); + } + } catch (@Nonnull final Throwable t) { + return null; + } finally { + if (stream != null) + try { + stream.close(); + } catch (final Throwable t) { + ; + } + } + + return null; + } + + private static URL load(@Nonnull final ResourceLocation key) throws Exception { + + final byte[] buffer = getBuffer(key); + final SoundStreamHandler handler; + + if (buffer == null) { + handler = new SoundStreamHandler(key); + } else { + handler = new MemoryStreamHandler(key, buffer); + } + + return new URL((URL) null, handler.getSpec(), handler); + } + + private SoundCache() { + + } + + public static URL getURLForSoundResource(@Nonnull final ResourceLocation soundResource) { + URL result = cache.get(soundResource); + if (result == null) + try { + cache.put(soundResource, result = load(soundResource)); + } catch (@Nonnull final Throwable t) { + throw new Error("Unable to load sound from cache!"); + } + return result; + } + +} diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundInputStream.java b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundInputStream.java new file mode 100644 index 0000000..034d76c --- /dev/null +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundInputStream.java @@ -0,0 +1,85 @@ +/* This file is part of Dynamic Surroundings, licensed under the MIT License (MIT). + * + * Copyright (c) OreCruncher + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.blockartistry.mod.DynSurround.client.sound.cache; + +import java.io.IOException; +import java.io.InputStream; + +import javax.annotation.Nonnull; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class SoundInputStream extends InputStream { + + protected final InputStream stream; + + public SoundInputStream(@Nonnull final InputStream stream) { + this.stream = stream; + } + + @Override + public int read() throws IOException { + try { + return this.stream.read(); + } catch(@Nonnull final Throwable t) { + return -1; + } + } + + @Override + public int available() throws IOException { + try { + return this.stream.available(); + } catch(@Nonnull final Throwable t) { + return 0; + } + } + + @Override + public void close() { + try { + this.stream.close(); + } catch(@Nonnull final Throwable t) { + ; + } + } + + @Override + public void mark(final int readlimit) { + this.stream.mark(readlimit); + } + + @Override + public boolean markSupported() { + return this.stream.markSupported(); + } + + @Override + public void reset() throws IOException { + this.stream.reset(); + } + +} diff --git a/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundStreamHandler.java b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundStreamHandler.java new file mode 100644 index 0000000..9bc1ecf --- /dev/null +++ b/src/main/java/org/blockartistry/mod/DynSurround/client/sound/cache/SoundStreamHandler.java @@ -0,0 +1,63 @@ +/* This file is part of Dynamic Surroundings, licensed under the MIT License (MIT). + * + * Copyright (c) OreCruncher + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.blockartistry.mod.DynSurround.client.sound.cache; + +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + +import javax.annotation.Nonnull; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.util.ResourceLocation; + +@SideOnly(Side.CLIENT) +public class SoundStreamHandler extends URLStreamHandler { + + protected final ResourceLocation resource; + protected URLConnection connection; + + public SoundStreamHandler(@Nonnull final ResourceLocation resource) { + this.resource = resource; + } + + protected URLConnection createConnection(@Nonnull final URL url) { + return new ResourceURLConnection(url, this.resource); + } + + @Override + protected URLConnection openConnection(@Nonnull final URL url) throws IOException { + if (this.connection == null) + this.connection = createConnection(url); + return this.connection; + } + + public String getSpec() { + return String.format("%s:%s:%s", + new Object[] { "mcsounddomain", this.resource.getResourceDomain(), this.resource.getResourcePath() }); + } + +} diff --git a/src/main/java/org/blockartistry/mod/DynSurround/proxy/ProxyClient.java b/src/main/java/org/blockartistry/mod/DynSurround/proxy/ProxyClient.java index 05644a0..40eb552 100644 --- a/src/main/java/org/blockartistry/mod/DynSurround/proxy/ProxyClient.java +++ b/src/main/java/org/blockartistry/mod/DynSurround/proxy/ProxyClient.java @@ -33,7 +33,6 @@ import org.blockartistry.mod.DynSurround.client.footsteps.game.system.ForgeDictionary; import org.blockartistry.mod.DynSurround.client.footsteps.game.user.GenerateBlockReport; import org.blockartistry.mod.DynSurround.client.hud.GuiHUDHandler; -import org.blockartistry.mod.DynSurround.client.sound.SoundManager; import org.blockartistry.mod.DynSurround.data.BlockRegistry; import org.blockartistry.mod.DynSurround.data.SoundRegistry; @@ -51,8 +50,6 @@ public class ProxyClient extends Proxy { @Override public void preInit(final FMLPreInitializationEvent event) { super.preInit(event); - - SoundManager.configureSound(); } @Override diff --git a/src/main/resources/META-INF/dsurround_at.cfg b/src/main/resources/META-INF/dsurround_at.cfg index ea74f31..612d42b 100644 --- a/src/main/resources/META-INF/dsurround_at.cfg +++ b/src/main/resources/META-INF/dsurround_at.cfg @@ -5,9 +5,23 @@ public net.minecraft.world.biome.BiomeGenBase field_76766_R # enableSnow public net.minecraft.client.particle.EntityFlameFX field_70562_a # flameScale public net.minecraft.client.renderer.RenderGlobal field_72773_u # cloudTickCounter public-f net.minecraft.world.World field_73011_w # provider -public net.minecraft.client.audio.SoundHandler field_147697_e # sndRegistry -public net.minecraft.client.audio.SoundHandler field_147694_f # sndManager +public net.minecraft.client.audio.SoundHandler field_147697_e # soundRegistry +public net.minecraft.client.audio.SoundHandler field_147694_f # soundManager public net.minecraft.client.audio.SoundManager field_148629_h # playingSounds +public net.minecraft.client.audio.SoundManager field_148627_j # playingSoundPoolEntries +public net.minecraft.client.audio.SoundManager field_148630_i # invPlayingSounds public net.minecraft.client.audio.SoundManager field_148626_m # delayedSounds +public net.minecraft.client.audio.SoundManager field_148620_e # sndSystem +public net.minecraft.client.audio.SoundManager field_148618_g # playTime +public net.minecraft.client.audio.SoundManager field_148625_l # tickableSounds +public net.minecraft.client.audio.SoundManager field_148624_n # playingSoundsStopTime +public net.minecraft.client.audio.SoundManager field_148628_k # categorySounds +public net.minecraft.client.audio.SoundManager field_148617_f # loaded +public net.minecraft.client.audio.SoundManager field_188777_o # listeners +public net.minecraft.client.audio.SoundManager field_188775_c # UNABLE_TO_PLAY +public net.minecraft.client.audio.SoundManager func_148606_a(Lnet/minecraft/client/audio/ISound;Lnet/minecraft/client/audio/SoundPoolEntry;)F # getNormalizedPitch +public net.minecraft.client.audio.SoundManager func_148594_a(Lnet/minecraft/client/audio/ISound;Lnet/minecraft/client/audio/SoundPoolEntry;Lnet/minecraft/client/audio/SoundCategory;)F # getNormalizedVolume +public net.minecraft.client.audio.SoundManager func_148612_a(Lnet/minecraft/util/ResourceLocation;)Ljava/net/URL; # getURLForSoundResource +public net.minecraft.client.audio.SoundManager func_148595_a(Lnet/minecraft/client/audio/SoundCategory;)F # getSoundCategoryVolume public net.minecraft.entity.Entity field_70150_b # nextStepDistance public net.minecraft.entity.EntityLivingBase field_70703_bu # isJumping diff --git a/src/main/resources/assets/dsurround/data/footsteps/blockmap.json b/src/main/resources/assets/dsurround/data/footsteps/blockmap.json index 89731ea..69b2ba9 100644 --- a/src/main/resources/assets/dsurround/data/footsteps/blockmap.json +++ b/src/main/resources/assets/dsurround/data/footsteps/blockmap.json @@ -143,7 +143,7 @@ "minecraft:reeds":"#reed", "minecraft:jukebox":"woodutility", "minecraft:fence":"#fence", - "minecraft:pumpkin":"organic_solid", + "minecraft:pumpkin":"organic_dry", "minecraft:netherrack":"stone", "minecraft:soul_sand":"quicksand", "minecraft:glowstone":"glowstone", @@ -162,7 +162,7 @@ "minecraft:red_mushroom_block":"organic", "minecraft:iron_bars":"metalbar", "minecraft:glass_pane":"glass", - "minecraft:melon_block":"organic", + "minecraft:melon_block":"organic_dry", "minecraft:pumpkin_stem":"NOT_EMITTER", "minecraft:melon_stem":"NOT_EMITTER", "minecraft:vine":"leaves",