package mekanism.client.sound; import java.util.HashMap; import java.util.Map; import mekanism.api.ObfuscatedNames; import mekanism.api.util.ReflectionUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.ISound; import net.minecraft.client.audio.ITickableSound; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.audio.SoundManager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.SoundEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; /** * SoundHandler - a class that handles all Sounds used by Mekanism. * Runs off of PaulsCode's SoundSystem through Minecraft. * @author AidanBrady rewritten by unpairedbracket * */ @SideOnly(Side.CLIENT) public class SoundHandler { public static Map<String, Map<String, IResettableSound>> soundMaps = new HashMap<String, Map<String, IResettableSound>>(); public static Map<ISound, String> invPlayingSounds; public static Minecraft mc = Minecraft.getMinecraft(); public static enum Channel { JETPACK("jetpack", JetpackSound.class), GASMASK("gasMask", GasMaskSound.class), FLAMETHROWER("flamethrower", FlamethrowerSound.class); String channelName; Class<? extends PlayerSound> soundClass; private Channel(String name, Class<? extends PlayerSound> clazz) { channelName = name; soundClass = clazz; } public String getName() { return channelName; } public PlayerSound getNewSound(EntityPlayer player) { try { return soundClass.getDeclaredConstructor(EntityPlayer.class).newInstance(player); } catch(Exception e) { return null; } } } public static boolean soundPlaying(EntityPlayer player, Channel channel) { String name = player.getName(); Map<String, IResettableSound> map = getMap(name); IResettableSound sound = map.get(channel.getName()); return !(sound == null || sound.isDonePlaying()); } public static void addSound(EntityPlayer player, Channel channel, boolean replace) { String name = player.getName(); Map<String, IResettableSound> map = getMap(name); IResettableSound sound = map.get(channel.getName()); if(sound == null || replace) { PlayerSound newSound = channel.getNewSound(player); map.put(channel.getName(), newSound); } } public static boolean playSound(EntityPlayer player, Channel channel) { String name = player.getName(); Map<String, IResettableSound> map = getMap(name); IResettableSound sound = map.get(channel.getName()); if(sound != null) { if(canRestartSound(sound)) { sound.reset(); playSound(sound); } return true; } return false; } public static Map<String, IResettableSound> getMap(String name) { Map<String, IResettableSound> map = soundMaps.get(name); if(map == null) { map = new HashMap<String, IResettableSound>(); soundMaps.put(name, map); } return map; } public static SoundManager getSoundManager() { try { return (SoundManager)ReflectionUtils.getPrivateValue(mc.getSoundHandler(), net.minecraft.client.audio.SoundHandler.class, ObfuscatedNames.SoundHandler_sndManager); } catch(Exception e) { return null; } } //Fudge required because sound thread gets behind and the biMap crashes when rapidly toggling sounds. public static Map<ISound, String> getSoundMap() { if(invPlayingSounds == null) { try { invPlayingSounds = (Map<ISound, String>)ReflectionUtils.getPrivateValue(getSoundManager(), net.minecraft.client.audio.SoundManager.class, ObfuscatedNames.SoundManager_invPlayingSounds); } catch(Exception e) { invPlayingSounds = null; } } return invPlayingSounds; } public static boolean canRestartSound(ITickableSound sound) { return sound.isDonePlaying() && !getSoundMap().containsKey(sound); } public static void playSound(SoundEvent sound) { playSound(PositionedSoundRecord.getMasterRecord(sound, 1.0F)); } public static void playSound(ISound sound) { mc.getSoundHandler().playSound(sound); } }