package openblocks.client; import com.google.common.collect.Lists; import cpw.mods.fml.client.FMLClientHandler; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import java.util.Iterator; import java.util.List; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.ISound; import net.minecraft.client.audio.SoundHandler; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.client.event.sound.PlaySoundEvent17; import net.minecraftforge.common.MinecraftForge; import openblocks.Config; import openblocks.client.Icons.IDrawableIcon; import openblocks.common.item.ItemSonicGlasses; import openmods.config.properties.ConfigurationChange; import openmods.renderer.ManualDisplayList; import openmods.renderer.ManualDisplayList.Renderer; import openmods.utils.render.RenderUtils; import org.lwjgl.opengl.GL11; public class SoundEventsManager { private SoundEventsManager() {} public void init() { icons.registerDefaults(); MinecraftForge.EVENT_BUS.register(icons); } public static final SoundEventsManager instance = new SoundEventsManager(); public final SoundIconRegistry icons = new SoundIconRegistry(); private static class SoundEvent { public final IDrawableIcon icon; public final double size; public final ISound sound; private boolean isPlaying = true; private int ticks; private final int TTL; private SoundEvent(ISound sound, IDrawableIcon icon, double size, double TTL) { this.sound = sound; this.icon = icon; this.size = size; this.TTL = MathHelper.floor_double(20 * TTL); } public void update(SoundHandler handler) { if (isPlaying) { isPlaying = handler.isSoundPlaying(sound); } else { ticks++; } } public boolean isAlive() { return ticks <= TTL; } public double getAlpha(double partialTick) { return 1 - (ticks + partialTick) / TTL; } } private final List<SoundEvent> events = Lists.newLinkedList(); public static boolean isEntityWearingGlasses(Entity e) { if (e instanceof EntityPlayer) { ItemStack helmet = ((EntityPlayer)e).inventory.armorItemInSlot(3); return helmet != null && helmet.getItem() instanceof ItemSonicGlasses; } return false; } public static boolean isPlayerWearingGlasses() { final Entity e = FMLClientHandler.instance().getClient().renderViewEntity; return isEntityWearingGlasses(e); } @SubscribeEvent public void onSoundEvent(PlaySoundEvent17 evt) { if (SoundEventsManager.isPlayerWearingGlasses()) { final ISound sound = evt.sound; final IDrawableIcon icon = icons.getIcon(sound.getPositionedSoundLocation()); synchronized (events) { events.add(new SoundEvent(sound, icon, Math.log(sound.getVolume() + 1), sound.getPitch())); } } } @SubscribeEvent public void onReconfig(ConfigurationChange.Post evt) { if (evt.category.equals("glasses")) notPumpkinOverlay.invalidate(); } public void tickUpdate() { synchronized (events) { final SoundHandler handler = Minecraft.getMinecraft().getSoundHandler(); Iterator<SoundEvent> it = events.iterator(); while (it.hasNext()) { SoundEvent evt = it.next(); evt.update(handler); if (!evt.isAlive()) it.remove(); } } } private ManualDisplayList notPumpkinOverlay = new ManualDisplayList(); private static final ResourceLocation notPumpkin = new ResourceLocation("openblocks:textures/misc/glasses_obsidian.png"); private void dimWorld(final TextureManager tex, final Minecraft mc) { final double level = Config.sonicGlassesOpacity; if (level <= 0) return; if (level >= 1 && !Config.sonicGlassesUseTexture) { GL11.glColor3f(0, 0, 0); GL11.glClearColor(0, 0, 0, 1); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); return; } if (!notPumpkinOverlay.isCompiled()) { notPumpkinOverlay.compile(new Renderer() { @Override public void render() { GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glPushMatrix(); GL11.glLoadIdentity(); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glPushMatrix(); GL11.glLoadIdentity(); GL11.glOrtho(-1, 1, -1, 1, -1, 1); GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glDisable(GL11.GL_ALPHA_TEST); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); final float maxU = (float)mc.displayWidth / 1024; final float maxV = (float)mc.displayHeight / 1024; if (Config.sonicGlassesUseTexture) { GL11.glColor4f(1, 1, 1, (float)level); tex.bindTexture(notPumpkin); GL11.glBegin(GL11.GL_QUADS); GL11.glTexCoord2f(0, 0); GL11.glVertex3f(-1, -1, 0); GL11.glTexCoord2f(maxU, 0); GL11.glVertex3f(+1, -1, 0); GL11.glTexCoord2f(maxU, maxV); GL11.glVertex3f(+1, +1, 0); GL11.glTexCoord2f(0, maxV); GL11.glVertex3f(-1, +1, 0); GL11.glEnd(); } else { GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glColor4f(0.085f, 0.074f, 0.129f, (float)level); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex3f(-1, -1, 0); GL11.glVertex3f(+1, -1, 0); GL11.glVertex3f(+1, +1, 0); GL11.glVertex3f(-1, +1, 0); GL11.glEnd(); GL11.glEnable(GL11.GL_TEXTURE_2D); } GL11.glDisable(GL11.GL_BLEND); GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_ALPHA_TEST); GL11.glEnable(GL11.GL_LIGHTING); GL11.glPopMatrix(); GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glPopMatrix(); } }); } notPumpkinOverlay.render(); } @SubscribeEvent public void renderEvents(RenderWorldLastEvent evt) { final Minecraft mc = Minecraft.getMinecraft(); if (mc.gameSettings.thirdPersonView != 0) return; final TextureManager tex = mc.renderEngine; final Entity rve = mc.renderViewEntity; if (!isEntityWearingGlasses(rve)) return; GL11.glDisable(GL11.GL_FOG); GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT); dimWorld(tex, mc); final double interpX = rve.prevPosX + (rve.posX - rve.prevPosX) * evt.partialTicks; final double interpY = rve.prevPosY + (rve.posY - rve.prevPosY) * evt.partialTicks; final double interpZ = rve.prevPosZ + (rve.posZ - rve.prevPosZ) * evt.partialTicks; GL11.glDisable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); synchronized (events) { for (SoundEvent snd : events) { final double px = snd.sound.getXPosF() - interpX; final double py = snd.sound.getYPosF() - interpY; final double pz = snd.sound.getZPosF() - interpZ; GL11.glPushMatrix(); GL11.glTranslated(px, py, pz); RenderUtils.setupBillboard(rve); snd.icon.draw(tex, snd.getAlpha(evt.partialTicks), snd.size); GL11.glPopMatrix(); } } GL11.glEnable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_BLEND); } }