001package net.minecraftforge.client;
002
003import java.awt.Color;
004import java.util.ArrayList;
005import java.util.Collection;
006import java.util.Iterator;
007import java.util.List;
008import java.util.Random;
009
010import org.lwjgl.opengl.GL11;
011import org.lwjgl.opengl.GL12;
012
013import cpw.mods.fml.common.FMLCommonHandler;
014
015import net.minecraft.block.Block;
016import net.minecraft.block.material.Material;
017import net.minecraft.client.Minecraft;
018import net.minecraft.client.gui.FontRenderer;
019import net.minecraft.client.gui.GuiIngame;
020import net.minecraft.client.gui.GuiNewChat;
021import net.minecraft.client.gui.GuiPlayerInfo;
022import net.minecraft.client.gui.ScaledResolution;
023import net.minecraft.client.multiplayer.NetClientHandler;
024import net.minecraft.client.renderer.RenderHelper;
025import net.minecraft.client.renderer.Tessellator;
026import net.minecraft.client.renderer.entity.RenderItem;
027import net.minecraft.entity.boss.BossStatus;
028import net.minecraft.entity.player.InventoryPlayer;
029import net.minecraft.item.ItemStack;
030import net.minecraft.potion.Potion;
031import net.minecraft.scoreboard.Score;
032import net.minecraft.scoreboard.ScoreObjective;
033import net.minecraft.scoreboard.ScorePlayerTeam;
034import net.minecraft.scoreboard.Scoreboard;
035import net.minecraft.util.Direction;
036import net.minecraft.util.EnumChatFormatting;
037import net.minecraft.util.FoodStats;
038import net.minecraft.util.Icon;
039import net.minecraft.util.MathHelper;
040import net.minecraft.util.StatCollector;
041import net.minecraft.util.StringUtils;
042import net.minecraft.world.EnumSkyBlock;
043import net.minecraft.world.chunk.Chunk;
044import net.minecraftforge.client.event.RenderGameOverlayEvent;
045import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType;
046import net.minecraftforge.common.ForgeHooks;
047import net.minecraftforge.common.MinecraftForge;
048import static net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType.*;
049
050public class GuiIngameForge extends GuiIngame
051{
052    private static final int WHITE = 0xFFFFFF;
053
054    //Flags to toggle the rendering of certain aspects of the HUD, valid conditions
055    //must be met for them to render normally. If those conditions are met, but this flag
056    //is false, they will not be rendered.
057    public static boolean renderHelmet = true;
058    public static boolean renderPortal = true;
059    public static boolean renderHotbar = true;
060    public static boolean renderCrosshairs = true;
061    public static boolean renderBossHealth = true;
062    public static boolean renderHealth = true;
063    public static boolean renderArmor = true;
064    public static boolean renderFood = true;
065    public static boolean renderAir = true;
066    public static boolean renderExperiance = true;
067    public static boolean renderObjective = true;
068
069    private ScaledResolution res = null;
070    private FontRenderer fontrenderer = null;
071    private RenderGameOverlayEvent eventParent;
072
073    public GuiIngameForge(Minecraft mc)
074    {
075        super(mc);
076    }
077
078    @Override
079    public void renderGameOverlay(float partialTicks, boolean hasScreen, int mouseX, int mouseY)
080    {
081        res = new ScaledResolution(mc.gameSettings, mc.displayWidth, mc.displayHeight);
082        eventParent = new RenderGameOverlayEvent(partialTicks, res, mouseX, mouseY);
083        int width = res.getScaledWidth();
084        int height = res.getScaledHeight();
085
086        if (pre(ALL)) return;
087
088        fontrenderer = mc.fontRenderer;
089        mc.entityRenderer.setupOverlayRendering();
090        GL11.glEnable(GL11.GL_BLEND);
091
092        if (Minecraft.isFancyGraphicsEnabled())
093        {
094            renderVignette(mc.thePlayer.getBrightness(partialTicks), width, height);
095        }
096        else
097        {
098            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
099        }
100
101        if (renderHelmet) renderHelmet(res, partialTicks, hasScreen, mouseX, mouseY);
102
103        if (renderPortal && !mc.thePlayer.isPotionActive(Potion.confusion))
104        {
105            renderPortal(width, height, partialTicks);
106        }
107
108        if (!mc.playerController.enableEverythingIsScrewedUpMode())
109        {
110            GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
111            zLevel = -90.0F;
112            rand.setSeed((long)(updateCounter * 312871));
113            mc.renderEngine.bindTexture("/gui/icons.png");
114
115            if (renderCrosshairs) renderCrosshairs(width, height);
116            if (renderBossHealth) renderBossHealth();
117
118            if (this.mc.playerController.shouldDrawHUD())
119            {
120                if (renderArmor)  renderArmor(width, height);
121                if (renderHealth) renderHealth(width, height);
122                if (renderFood)   renderFood(width, height);
123                if (renderAir)    renderAir(width, height);
124            }
125            if (renderHotbar) renderHotbar(width, height, partialTicks);
126        }
127
128        if (renderExperiance) renderExperience(width, height);
129        renderSleepFade(width, height);
130        renderToolHightlight(width, height);
131        renderHUDText(width, height);
132        renderRecordOverlay(width, height, partialTicks);
133
134        ScoreObjective objective = mc.theWorld.getScoreboard().func_96539_a(1);
135        if (renderObjective && objective != null)
136        {
137            this.func_96136_a(objective, height, width, fontrenderer);
138        }
139
140        GL11.glEnable(GL11.GL_BLEND);
141        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
142        GL11.glDisable(GL11.GL_ALPHA_TEST);
143
144        renderChat(width, height);
145
146        renderPlayerList(width, height);
147
148        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
149        GL11.glDisable(GL11.GL_LIGHTING);
150        GL11.glEnable(GL11.GL_ALPHA_TEST);
151    }
152
153    public ScaledResolution getResolution()
154    {
155        return res;
156    }
157
158    protected void renderHotbar(int width, int height, float partialTicks)
159    {
160        if (pre(HOTBAR)) return;
161        mc.mcProfiler.startSection("actionBar");
162
163        mc.renderEngine.bindTexture("/gui/gui.png");
164
165        InventoryPlayer inv = mc.thePlayer.inventory;
166        drawTexturedModalRect(width / 2 - 91, height - 22, 0, 0, 182, 22);
167        drawTexturedModalRect(width / 2 - 91 - 1 + inv.currentItem * 20, height - 22 - 1, 0, 22, 24, 22);
168
169        GL11.glDisable(GL11.GL_BLEND);
170        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
171        RenderHelper.enableGUIStandardItemLighting();
172
173        for (int i = 0; i < 9; ++i)
174        {
175            int x = width / 2 - 90 + i * 20 + 2;
176            int z = height - 16 - 3;
177            renderInventorySlot(i, x, z, partialTicks);
178        }
179
180        RenderHelper.disableStandardItemLighting();
181        GL11.glDisable(GL12.GL_RESCALE_NORMAL);
182        mc.mcProfiler.endSection();
183        post(HOTBAR);
184    }
185
186    protected void renderCrosshairs(int width, int height)
187    {
188        if (pre(CROSSHAIRS)) return;
189        GL11.glEnable(GL11.GL_BLEND);
190        GL11.glBlendFunc(GL11.GL_ONE_MINUS_DST_COLOR, GL11.GL_ONE_MINUS_SRC_COLOR);
191        drawTexturedModalRect(width / 2 - 7, height / 2 - 7, 0, 0, 16, 16);
192        GL11.glDisable(GL11.GL_BLEND);
193        post(CROSSHAIRS);
194    }
195
196    @Override
197    protected void renderBossHealth()
198    {
199        if (pre(BOSSHEALTH)) return;
200        mc.mcProfiler.startSection("bossHealth");
201        super.renderBossHealth();
202        mc.mcProfiler.endSection();
203        post(BOSSHEALTH);
204    }
205
206    private void renderHelmet(ScaledResolution res, float partialTicks, boolean hasScreen, int mouseX, int mouseY)
207    {
208        if (pre(HELMET)) return;
209
210        ItemStack itemstack = this.mc.thePlayer.inventory.armorItemInSlot(3);
211
212        if (this.mc.gameSettings.thirdPersonView == 0 && itemstack != null && itemstack.getItem() != null)
213        {
214            if (itemstack.itemID == Block.pumpkin.blockID)
215            {
216                renderPumpkinBlur(res.getScaledWidth(), res.getScaledHeight());
217            }
218            else
219            {
220                itemstack.getItem().renderHelmetOverlay(itemstack, mc.thePlayer, res, partialTicks, hasScreen, mouseX, mouseY);
221            }
222        }
223
224        post(HELMET);
225    }
226
227    protected void renderArmor(int width, int height)
228    {
229        if (pre(ARMOR)) return;
230        mc.mcProfiler.startSection("armor");
231
232        int left = width / 2 - 91;
233        int top = height - 49;
234
235        int level = ForgeHooks.getTotalArmorValue(mc.thePlayer);
236        for (int i = 1; level > 0 && i < 20; i += 2)
237        {
238            if (i < level)
239            {
240                drawTexturedModalRect(left, top, 34, 9, 9, 9);
241            }
242            else if (i == level)
243            {
244                drawTexturedModalRect(left, top, 25, 9, 9, 9);
245            }
246            else if (i > level)
247            {
248                drawTexturedModalRect(left, top, 16, 9, 9, 9);
249            }
250            left += 8;
251        }
252
253        mc.mcProfiler.endSection();
254        post(ARMOR);
255    }
256
257    protected void renderPortal(int width, int height, float partialTicks)
258    {
259        if (pre(PORTAL)) return;
260
261        float f1 = mc.thePlayer.prevTimeInPortal + (mc.thePlayer.timeInPortal - mc.thePlayer.prevTimeInPortal) * partialTicks;
262
263        if (f1 > 0.0F)
264        {
265            renderPortalOverlay(f1, width, height);
266        }
267
268        post(PORTAL);
269    }
270
271    protected void renderAir(int width, int height)
272    {
273        if (pre(AIR)) return;
274        mc.mcProfiler.startSection("air");
275        int left = width / 2 + 91;
276        int top = height - 49;
277
278        if (mc.thePlayer.isInsideOfMaterial(Material.water))
279        {
280            int air = mc.thePlayer.getAir();
281            int full = MathHelper.ceiling_double_int((double)(air - 2) * 10.0D / 300.0D);
282            int partial = MathHelper.ceiling_double_int((double)air * 10.0D / 300.0D) - full;
283
284            for (int i = 0; i < full + partial; ++i)
285            {
286                drawTexturedModalRect(left - i * 8 - 9, top, (i < full ? 16 : 25), 18, 9, 9);
287            }
288        }
289
290        mc.mcProfiler.endSection();
291        post(AIR);
292    }
293
294    public void renderHealth(int width, int height)
295    {
296        if (pre(HEALTH)) return;
297        mc.mcProfiler.startSection("health");
298
299        boolean highlight = mc.thePlayer.hurtResistantTime / 3 % 2 == 1;
300
301        if (mc.thePlayer.hurtResistantTime < 10)
302        {
303            highlight = false;
304        }
305
306        int health = mc.thePlayer.getHealth();
307        int healthLast = mc.thePlayer.prevHealth;
308        int left = width / 2 - 91;
309        int top = height - 39;
310
311        int regen = -1;
312        if (mc.thePlayer.isPotionActive(Potion.regeneration))
313        {
314            regen = this.updateCounter % 25;
315        }
316
317        for (int i = 0; i < 10; ++i)
318        {
319            int idx = i * 2 + 1;
320            int iconX = 16;
321            if (mc.thePlayer.isPotionActive(Potion.poison)) iconX += 36;
322            else if (mc.thePlayer.isPotionActive(Potion.wither)) iconX += 72;
323
324            int x = left + i * 8;
325            int y = top;
326            if (health <= 4) y = top + rand.nextInt(2);
327            if (i == regen) y -= 2;
328
329            byte iconY = 0;
330            if (mc.theWorld.getWorldInfo().isHardcoreModeEnabled()) iconY = 5;
331
332            drawTexturedModalRect(x, y, 16 + (highlight ? 9 : 0), 9 * iconY, 9, 9);
333
334            if (highlight)
335            {
336                if (idx < healthLast)
337                    drawTexturedModalRect(x, y, iconX + 54, 9 * iconY, 9, 9);
338                else if (idx == healthLast)
339                    drawTexturedModalRect(x, y, iconX + 63, 9 * iconY, 9, 9);
340            }
341
342            if (idx < health)
343                drawTexturedModalRect(x, y, iconX + 36, 9 * iconY, 9, 9);
344            else if (idx == health)
345                drawTexturedModalRect(x, y, iconX + 45, 9 * iconY, 9, 9);
346        }
347        mc.mcProfiler.endSection();
348        post(HEALTH);
349    }
350
351    public void renderFood(int width, int height)
352    {
353        if (pre(FOOD)) return;
354        mc.mcProfiler.startSection("food");
355
356        int left = width / 2 + 91;
357        int top = height - 39;
358        boolean unused = false;// Unused flag in vanilla, seems to be part of a 'fade out' mechanic
359
360        FoodStats stats = mc.thePlayer.getFoodStats();
361        int level = stats.getFoodLevel();
362        int levelLast = stats.getPrevFoodLevel();
363
364        for (int i = 0; i < 10; ++i)
365        {
366            int idx = i * 2 + 1;
367            int x = left - i * 8 - 9;
368            int y = top;
369            int icon = 16;
370            byte backgound = 0;
371
372            if (mc.thePlayer.isPotionActive(Potion.hunger))
373            {
374                icon += 36;
375                backgound = 13;
376            }
377            if (unused) backgound = 1; //Probably should be a += 1 but vanilla never uses this
378
379            if (mc.thePlayer.getFoodStats().getSaturationLevel() <= 0.0F && updateCounter % (level * 3 + 1) == 0)
380            {
381                y = top + (rand.nextInt(3) - 1);
382            }
383
384            this.drawTexturedModalRect(x, y, 16 + backgound * 9, 27, 9, 9);
385
386            if (unused)
387            {
388                if (idx < levelLast)
389                {
390                    drawTexturedModalRect(x, y, icon + 54, 27, 9, 9);
391                }
392
393                if (idx == levelLast)
394                {
395                    drawTexturedModalRect(x, y, icon + 63, 27, 9, 9);
396                }
397            }
398
399            if (idx < level)
400            {
401                drawTexturedModalRect(x, y, icon + 36, 27, 9, 9);
402            }
403
404            if (idx == level)
405            {
406                drawTexturedModalRect(x, y, icon + 45, 27, 9, 9);
407            }
408        }
409        mc.mcProfiler.endSection();
410        post(FOOD);
411    }
412
413    protected void renderSleepFade(int width, int height)
414    {
415        if (mc.thePlayer.getSleepTimer() > 0)
416        {
417            mc.mcProfiler.startSection("sleep");
418            GL11.glDisable(GL11.GL_DEPTH_TEST);
419            GL11.glDisable(GL11.GL_ALPHA_TEST);
420            int sleepTime = mc.thePlayer.getSleepTimer();
421            float opacity = (float)sleepTime / 100.0F;
422
423            if (opacity > 1.0F)
424            {
425                opacity = 1.0F - (float)(sleepTime - 100) / 10.0F;
426            }
427
428            int color = (int)(220.0F * opacity) << 24 | 1052704;
429            drawRect(0, 0, width, height, color);
430            GL11.glEnable(GL11.GL_ALPHA_TEST);
431            GL11.glEnable(GL11.GL_DEPTH_TEST);
432            mc.mcProfiler.endSection();
433        }
434    }
435
436    protected void renderExperience(int width, int height)
437    {
438        if (pre(EXPERIENCE)) return;
439        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
440        if (mc.playerController.shouldDrawHUD())
441        {
442            mc.mcProfiler.startSection("expBar");
443            mc.renderEngine.bindTexture("/gui/icons.png");
444            int cap = this.mc.thePlayer.xpBarCap();
445            int left = width / 2 - 91;
446
447            if (cap > 0)
448            {
449                short short1 = 182;
450                int l2 = (int)(this.mc.thePlayer.experience * (float)(short1 + 1));
451                int k2 = height - 32 + 3;
452                this.drawTexturedModalRect(left, k2, 0, 64, short1, 5);
453
454                if (l2 > 0)
455                {
456                    this.drawTexturedModalRect(left, k2, 0, 69, l2, 5);
457                }
458            }
459            mc.mcProfiler.endSection();
460        }
461
462        if (mc.playerController.func_78763_f() && mc.thePlayer.experienceLevel > 0)
463        {
464            mc.mcProfiler.startSection("expLevel");
465            boolean flag1 = false;
466            int color = flag1 ? 16777215 : 8453920;
467            String text = "" + mc.thePlayer.experienceLevel;
468            int x = (width - fontrenderer.getStringWidth(text)) / 2;
469            int y = height - 31 - 4;
470            fontrenderer.drawString(text, x + 1, y, 0);
471            fontrenderer.drawString(text, x - 1, y, 0);
472            fontrenderer.drawString(text, x, y + 1, 0);
473            fontrenderer.drawString(text, x, y - 1, 0);
474            fontrenderer.drawString(text, x, y, color);
475            mc.mcProfiler.endSection();
476        }
477        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
478
479        post(EXPERIENCE);
480    }
481
482    protected void renderToolHightlight(int width, int height)
483    {
484        if (this.mc.gameSettings.heldItemTooltips)
485        {
486            mc.mcProfiler.startSection("toolHighlight");
487
488            if (this.field_92017_k > 0 && this.field_92016_l != null)
489            {
490                String name = this.field_92016_l.getDisplayName();
491
492                int opacity = (int)((float)this.field_92017_k * 256.0F / 10.0F);
493                if (opacity > 255) opacity = 255;
494
495                if (opacity > 0)
496                {
497                    int y = height - 59;
498                    if (!mc.playerController.shouldDrawHUD()) y += 14;
499
500                    GL11.glPushMatrix();
501                    GL11.glEnable(GL11.GL_BLEND);
502                    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
503                    FontRenderer font = field_92016_l.getItem().getFontRenderer(field_92016_l);
504                    if (font != null)
505                    {
506                        int x = (width - font.getStringWidth(name)) / 2;
507                        font.drawStringWithShadow(name, x, y, WHITE | (opacity << 24));
508                    }
509                    else
510                    {
511                        int x = (width - fontrenderer.getStringWidth(name)) / 2;
512                        fontrenderer.drawStringWithShadow(name, x, y, WHITE | (opacity << 24));
513                    }
514                    GL11.glDisable(GL11.GL_BLEND);
515                    GL11.glPopMatrix();
516                }
517            }
518
519            mc.mcProfiler.endSection();
520        }
521    }
522
523    protected void renderHUDText(int width, int height)
524    {
525        mc.mcProfiler.startSection("forgeHudText");
526        ArrayList<String> left = new ArrayList<String>();
527        ArrayList<String> right = new ArrayList<String>();
528
529        if (mc.isDemo())
530        {
531            long time = mc.theWorld.getTotalWorldTime();
532            if (time >= 120500L)
533            {
534                right.add(StatCollector.translateToLocal("demo.demoExpired"));
535            }
536            else
537            {
538                right.add(String.format(StatCollector.translateToLocal("demo.remainingTime"), StringUtils.ticksToElapsedTime((int)(120500L - time))));
539            }
540        }
541
542
543        if (this.mc.gameSettings.showDebugInfo)
544        {
545            mc.mcProfiler.startSection("debug");
546            GL11.glPushMatrix();
547            left.add("Minecraft 1.5.1 (" + this.mc.debug + ")");
548            left.add(mc.debugInfoRenders());
549            left.add(mc.getEntityDebug());
550            left.add(mc.debugInfoEntities());
551            left.add(mc.getWorldProviderName());
552            left.add(null); //Spacer
553
554            long max = Runtime.getRuntime().maxMemory();
555            long total = Runtime.getRuntime().totalMemory();
556            long free = Runtime.getRuntime().freeMemory();
557            long used = total - free;
558
559            right.add("Used memory: " + used * 100L / max + "% (" + used / 1024L / 1024L + "MB) of " + max / 1024L / 1024L + "MB");
560            right.add("Allocated memory: " + total * 100L / max + "% (" + total / 1024L / 1024L + "MB)");
561
562            int x = MathHelper.floor_double(mc.thePlayer.posX);
563            int y = MathHelper.floor_double(mc.thePlayer.posY);
564            int z = MathHelper.floor_double(mc.thePlayer.posZ);
565            float yaw = mc.thePlayer.rotationYaw;
566            int heading = MathHelper.floor_double((double)(mc.thePlayer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
567
568            left.add(String.format("x: %.5f (%d) // c: %d (%d)", mc.thePlayer.posX, x, x >> 4, x & 15));
569            left.add(String.format("y: %.3f (feet pos, %.3f eyes pos)", mc.thePlayer.boundingBox.minY, mc.thePlayer.posY));
570            left.add(String.format("z: %.5f (%d) // c: %d (%d)", mc.thePlayer.posZ, z, z >> 4, z & 15));
571            left.add(String.format("f: %d (%s) / %f", heading, Direction.directions[heading], MathHelper.wrapAngleTo180_float(yaw)));
572
573            if (mc.theWorld != null && mc.theWorld.blockExists(x, y, z))
574            {
575                Chunk chunk = this.mc.theWorld.getChunkFromBlockCoords(x, z);
576                left.add(String.format("lc: %d b: %s bl: %d sl: %d rl: %d",
577                  chunk.getTopFilledSegment() + 15,
578                  chunk.getBiomeGenForWorldCoords(x & 15, z & 15, mc.theWorld.getWorldChunkManager()).biomeName,
579                  chunk.getSavedLightValue(EnumSkyBlock.Block, x & 15, y, z & 15),
580                  chunk.getSavedLightValue(EnumSkyBlock.Sky, x & 15, y, z & 15),
581                  chunk.getBlockLightValue(x & 15, y, z & 15, 0)));
582            }
583            else
584            {
585                left.add(null);
586            }
587
588            left.add(String.format("ws: %.3f, fs: %.3f, g: %b, fl: %d", mc.thePlayer.capabilities.getWalkSpeed(), mc.thePlayer.capabilities.getFlySpeed(), mc.thePlayer.onGround, mc.theWorld.getHeightValue(x, z)));
589            right.add(null);
590            for (String s : FMLCommonHandler.instance().getBrandings().subList(1, FMLCommonHandler.instance().getBrandings().size()))
591            {
592                right.add(s);
593            }
594            GL11.glPopMatrix();
595            mc.mcProfiler.endSection();
596        }
597
598        RenderGameOverlayEvent.Text event = new RenderGameOverlayEvent.Text(eventParent, left, right);
599        if (!MinecraftForge.EVENT_BUS.post(event))
600        {
601            for (int x = 0; x < left.size(); x++)
602            {
603                String msg = left.get(x);
604                if (msg == null) continue;
605                fontrenderer.drawStringWithShadow(msg, 2, 2 + x * 10, WHITE);
606            }
607
608            for (int x = 0; x < right.size(); x++)
609            {
610                String msg = right.get(x);
611                if (msg == null) continue;
612                int w = fontrenderer.getStringWidth(msg);
613                fontrenderer.drawStringWithShadow(msg, width - w - 10, 2 + x * 10, WHITE);
614            }
615        }
616
617        mc.mcProfiler.endSection();
618        post(TEXT);
619    }
620
621    protected void renderRecordOverlay(int width, int height, float partialTicks)
622    {
623        if (recordPlayingUpFor > 0)
624        {
625            mc.mcProfiler.startSection("overlayMessage");
626            float hue = (float)recordPlayingUpFor - partialTicks;
627            int opacity = (int)(hue * 256.0F / 20.0F);
628            if (opacity > 255) opacity = 255;
629
630            if (opacity > 0)
631            {
632                GL11.glPushMatrix();
633                GL11.glTranslatef((float)(width / 2), (float)(height - 48), 0.0F);
634                GL11.glEnable(GL11.GL_BLEND);
635                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
636                int color = (recordIsPlaying ? Color.HSBtoRGB(hue / 50.0F, 0.7F, 0.6F) & WHITE : WHITE);
637                fontrenderer.drawString(recordPlaying, -fontrenderer.getStringWidth(recordPlaying) / 2, -4, color | (opacity << 24));
638                GL11.glDisable(GL11.GL_BLEND);
639                GL11.glPopMatrix();
640            }
641
642            mc.mcProfiler.endSection();
643        }
644    }
645
646    protected void renderChat(int width, int height)
647    {
648        GL11.glPushMatrix();
649        GL11.glTranslatef(0.0F, (float)(height - 48), 0.0F);
650        mc.mcProfiler.startSection("chat");
651        persistantChatGUI.drawChat(updateCounter);
652        mc.mcProfiler.endSection();
653        GL11.glPopMatrix();
654    }
655
656    protected void renderPlayerList(int width, int height)
657    {
658        ScoreObjective scoreobjective = this.mc.theWorld.getScoreboard().func_96539_a(0);
659        NetClientHandler handler = mc.thePlayer.sendQueue;
660
661        if (mc.gameSettings.keyBindPlayerList.pressed && (!mc.isIntegratedServerRunning() || handler.playerInfoList.size() > 1 || scoreobjective != null))
662        {
663            this.mc.mcProfiler.startSection("playerList");
664            List players = handler.playerInfoList;
665            int maxPlayers = handler.currentServerMaxPlayers;
666            int rows = maxPlayers;
667            int columns = 1;
668
669            for (columns = 1; rows > 20; rows = (maxPlayers + columns - 1) / columns)
670            {
671                columns++;
672            }
673
674            int columnWidth = 300 / columns;
675
676            if (columnWidth > 150)
677            {
678                columnWidth = 150;
679            }
680
681            int left = (width - columns * columnWidth) / 2;
682            byte border = 10;
683            drawRect(left - 1, border - 1, left + columnWidth * columns, border + 9 * rows, Integer.MIN_VALUE);
684
685            for (int i = 0; i < maxPlayers; i++)
686            {
687                int xPos = left + i % columns * columnWidth;
688                int yPos = border + i / columns * 9;
689                drawRect(xPos, yPos, xPos + columnWidth - 1, yPos + 8, 553648127);
690                GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
691                GL11.glEnable(GL11.GL_ALPHA_TEST);
692
693                if (i < players.size())
694                {
695                    GuiPlayerInfo player = (GuiPlayerInfo)players.get(i);
696                    ScorePlayerTeam team = mc.theWorld.getScoreboard().func_96509_i(player.name);
697                    String displayName = ScorePlayerTeam.func_96667_a(team, player.name);
698                    fontrenderer.drawStringWithShadow(displayName, xPos, yPos, 16777215);
699
700                    if (scoreobjective != null)
701                    {
702                        int endX = xPos + fontrenderer.getStringWidth(displayName) + 5;
703                        int maxX = xPos + columnWidth - 12 - 5;
704
705                        if (maxX - endX > 5)
706                        {
707                            Score score = scoreobjective.getScoreboard().func_96529_a(player.name, scoreobjective);
708                            String scoreDisplay = EnumChatFormatting.YELLOW + "" + score.func_96652_c();
709                            fontrenderer.drawStringWithShadow(scoreDisplay, maxX - fontrenderer.getStringWidth(scoreDisplay), yPos, 16777215);
710                        }
711                    }
712
713                    GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
714
715                    mc.renderEngine.bindTexture("/gui/icons.png");
716                    int pingIndex = 4;
717                    int ping = player.responseTime;
718                    if (ping < 0) pingIndex = 5;
719                    else if (ping < 150) pingIndex = 0;
720                    else if (ping < 300) pingIndex = 1;
721                    else if (ping < 600) pingIndex = 2;
722                    else if (ping < 1000) pingIndex = 3;
723
724                    zLevel += 100.0F;
725                    drawTexturedModalRect(xPos + columnWidth - 12, yPos, 0, 176 + pingIndex * 8, 10, 8);
726                    zLevel -= 100.0F;
727                }
728            }
729        }
730    }
731
732    //Helper macros
733    private boolean pre(ElementType type)
734    {
735        return MinecraftForge.EVENT_BUS.post(new RenderGameOverlayEvent.Pre(eventParent, type));
736    }
737    private void post(ElementType type)
738    {
739        MinecraftForge.EVENT_BUS.post(new RenderGameOverlayEvent.Post(eventParent, type));
740    }
741}