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