001package net.minecraft.client;
002
003import cpw.mods.fml.client.FMLClientHandler;
004import cpw.mods.fml.common.FMLCommonHandler;
005import cpw.mods.fml.common.registry.GameData;
006import cpw.mods.fml.common.registry.ItemData;
007import cpw.mods.fml.relauncher.ArgsWrapper;
008import cpw.mods.fml.relauncher.FMLRelauncher;
009import cpw.mods.fml.relauncher.Side;
010import cpw.mods.fml.relauncher.SideOnly;
011import java.awt.BorderLayout;
012import java.awt.Canvas;
013import java.awt.Color;
014import java.awt.Component;
015import java.awt.Dimension;
016import java.awt.Frame;
017import java.awt.Graphics;
018import java.io.File;
019import java.io.IOException;
020import java.nio.ByteBuffer;
021import java.text.DecimalFormat;
022import java.util.ArrayList;
023import java.util.HashMap;
024import java.util.Iterator;
025import java.util.List;
026import javax.swing.JPanel;
027import net.minecraft.block.Block;
028import net.minecraft.client.audio.SoundManager;
029import net.minecraft.client.entity.EntityClientPlayerMP;
030import net.minecraft.client.gui.FontRenderer;
031import net.minecraft.client.gui.GuiChat;
032import net.minecraft.client.gui.GuiGameOver;
033import net.minecraft.client.gui.GuiIngame;
034import net.minecraft.client.gui.GuiIngameMenu;
035import net.minecraft.client.gui.GuiMainMenu;
036import net.minecraft.client.gui.GuiMemoryErrorScreen;
037import net.minecraft.client.gui.GuiScreen;
038import net.minecraft.client.gui.GuiSleepMP;
039import net.minecraft.client.gui.LoadingScreenRenderer;
040import net.minecraft.client.gui.ScaledResolution;
041import net.minecraft.client.gui.achievement.GuiAchievement;
042import net.minecraft.client.gui.inventory.GuiInventory;
043import net.minecraft.client.multiplayer.GuiConnecting;
044import net.minecraft.client.multiplayer.NetClientHandler;
045import net.minecraft.client.multiplayer.PlayerControllerMP;
046import net.minecraft.client.multiplayer.ServerData;
047import net.minecraft.client.multiplayer.WorldClient;
048import net.minecraft.client.particle.EffectRenderer;
049import net.minecraft.client.renderer.CallableParticleScreenName;
050import net.minecraft.client.renderer.EntityRenderer;
051import net.minecraft.client.renderer.GLAllocation;
052import net.minecraft.client.renderer.ItemRenderer;
053import net.minecraft.client.renderer.OpenGlHelper;
054import net.minecraft.client.renderer.RenderBlocks;
055import net.minecraft.client.renderer.RenderEngine;
056import net.minecraft.client.renderer.RenderGlobal;
057import net.minecraft.client.renderer.Tessellator;
058import net.minecraft.client.renderer.WorldRenderer;
059import net.minecraft.client.renderer.entity.RenderManager;
060import net.minecraft.client.renderer.texture.TextureManager;
061import net.minecraft.client.settings.EnumOptions;
062import net.minecraft.client.settings.GameSettings;
063import net.minecraft.client.settings.KeyBinding;
064import net.minecraft.client.texturepacks.TexturePackList;
065import net.minecraft.crash.CrashReport;
066import net.minecraft.crash.CrashReportCategory;
067import net.minecraft.entity.EntityList;
068import net.minecraft.entity.EntityLiving;
069import net.minecraft.entity.item.EntityBoat;
070import net.minecraft.entity.item.EntityItemFrame;
071import net.minecraft.entity.item.EntityMinecart;
072import net.minecraft.entity.item.EntityPainting;
073import net.minecraft.item.Item;
074import net.minecraft.item.ItemStack;
075import net.minecraft.logging.ILogAgent;
076import net.minecraft.logging.LogAgent;
077import net.minecraft.network.INetworkManager;
078import net.minecraft.network.MemoryConnection;
079import net.minecraft.network.packet.Packet3Chat;
080import net.minecraft.profiler.IPlayerUsage;
081import net.minecraft.profiler.PlayerUsageSnooper;
082import net.minecraft.profiler.Profiler;
083import net.minecraft.profiler.ProfilerResult;
084import net.minecraft.server.integrated.IntegratedServer;
085import net.minecraft.stats.AchievementList;
086import net.minecraft.stats.StatFileWriter;
087import net.minecraft.stats.StatList;
088import net.minecraft.util.AxisAlignedBB;
089import net.minecraft.util.EnumMovingObjectType;
090import net.minecraft.util.EnumOS;
091import net.minecraft.util.HttpUtil;
092import net.minecraft.util.MathHelper;
093import net.minecraft.util.MinecraftError;
094import net.minecraft.util.MouseHelper;
095import net.minecraft.util.MovementInputFromOptions;
096import net.minecraft.util.MovingObjectPosition;
097import net.minecraft.util.ReportedException;
098import net.minecraft.util.ScreenShotHelper;
099import net.minecraft.util.Session;
100import net.minecraft.util.StatCollector;
101import net.minecraft.util.StringTranslate;
102import net.minecraft.util.ThreadDownloadResources;
103import net.minecraft.util.Timer;
104import net.minecraft.world.ColorizerFoliage;
105import net.minecraft.world.ColorizerGrass;
106import net.minecraft.world.WorldSettings;
107import net.minecraft.world.chunk.storage.AnvilSaveConverter;
108import net.minecraft.world.storage.ISaveFormat;
109import net.minecraft.world.storage.ISaveHandler;
110import net.minecraft.world.storage.WorldInfo;
111import org.lwjgl.LWJGLException;
112import org.lwjgl.Sys;
113import org.lwjgl.input.Keyboard;
114import org.lwjgl.input.Mouse;
115import org.lwjgl.opengl.ContextCapabilities;
116import org.lwjgl.opengl.Display;
117import org.lwjgl.opengl.DisplayMode;
118import org.lwjgl.opengl.GL11;
119import org.lwjgl.opengl.GL20;
120import org.lwjgl.opengl.GLContext;
121import org.lwjgl.opengl.PixelFormat;
122import org.lwjgl.util.glu.GLU;
123
124import com.google.common.collect.MapDifference;
125
126import net.minecraftforge.common.ForgeHooks;
127import net.minecraftforge.common.MinecraftForge;
128import net.minecraftforge.event.ForgeEventFactory;
129import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
130import net.minecraftforge.event.world.WorldEvent;
131
132@SideOnly(Side.CLIENT)
133public abstract class Minecraft implements Runnable, IPlayerUsage
134{
135    /** A 10MiB preallocation to ensure the heap is reasonably sized. */
136    public static byte[] memoryReserve = new byte[10485760];
137    private final ILogAgent field_94139_O = new LogAgent("Minecraft-Client", " [CLIENT]", (new File(getMinecraftDir(), "output-client.log")).getAbsolutePath());
138    private ServerData currentServerData;
139
140    /**
141     * Set to 'this' in Minecraft constructor; used by some settings get methods
142     */
143    private static Minecraft theMinecraft;
144    public PlayerControllerMP playerController;
145    private boolean fullscreen = false;
146    private boolean hasCrashed = false;
147
148    /** Instance of CrashReport. */
149    private CrashReport crashReporter;
150    public int displayWidth;
151    public int displayHeight;
152    private Timer timer = new Timer(20.0F);
153
154    /** Instance of PlayerUsageSnooper. */
155    private PlayerUsageSnooper usageSnooper = new PlayerUsageSnooper("client", this);
156    public WorldClient theWorld;
157    public RenderGlobal renderGlobal;
158    public EntityClientPlayerMP thePlayer;
159
160    /**
161     * The Entity from which the renderer determines the render viewpoint. Currently is always the parent Minecraft
162     * class's 'thePlayer' instance. Modification of its location, rotation, or other settings at render time will
163     * modify the camera likewise, with the caveat of triggering chunk rebuilds as it moves, making it unsuitable for
164     * changing the viewpoint mid-render.
165     */
166    public EntityLiving renderViewEntity;
167    public EntityLiving pointedEntityLiving;
168    public EffectRenderer effectRenderer;
169    public Session session = null;
170    public String minecraftUri;
171    public Canvas mcCanvas;
172
173    /** a boolean to hide a Quit button from the main menu */
174    public boolean hideQuitButton = false;
175    public volatile boolean isGamePaused = false;
176
177    /** The RenderEngine instance used by Minecraft */
178    public RenderEngine renderEngine;
179
180    /** The font renderer used for displaying and measuring text. */
181    public FontRenderer fontRenderer;
182    public FontRenderer standardGalacticFontRenderer;
183
184    /** The GuiScreen that's being displayed at the moment. */
185    public GuiScreen currentScreen = null;
186    public LoadingScreenRenderer loadingScreen;
187    public EntityRenderer entityRenderer;
188
189    /** Reference to the download resources thread. */
190    private ThreadDownloadResources downloadResourcesThread;
191
192    /** Mouse left click counter */
193    private int leftClickCounter = 0;
194
195    /** Display width */
196    private int tempDisplayWidth;
197
198    /** Display height */
199    private int tempDisplayHeight;
200
201    /** Instance of IntegratedServer. */
202    private IntegratedServer theIntegratedServer;
203
204    /** Gui achievement */
205    public GuiAchievement guiAchievement;
206    public GuiIngame ingameGUI;
207
208    /** Skip render world */
209    public boolean skipRenderWorld = false;
210
211    /** The ray trace hit that the mouse is over. */
212    public MovingObjectPosition objectMouseOver = null;
213
214    /** The game settings that currently hold effect. */
215    public GameSettings gameSettings;
216    protected MinecraftApplet mcApplet;
217    public SoundManager sndManager = new SoundManager();
218
219    /** Mouse helper instance. */
220    public MouseHelper mouseHelper;
221
222    /** The TexturePackLister used by this instance of Minecraft... */
223    public TexturePackList texturePackList;
224    public File mcDataDir;
225    private ISaveFormat saveLoader;
226
227    /**
228     * This is set to fpsCounter every debug screen update, and is shown on the debug screen. It's also sent as part of
229     * the usage snooping.
230     */
231    private static int debugFPS;
232
233    /**
234     * When you place a block, it's set to 6, decremented once per tick, when it's 0, you can place another block.
235     */
236    private int rightClickDelayTimer = 0;
237
238    /**
239     * Checked in Minecraft's while(running) loop, if true it's set to false and the textures refreshed.
240     */
241    private boolean refreshTexturePacksScheduled;
242
243    /** Stat file writer */
244    public StatFileWriter statFileWriter;
245    private String serverName;
246    private int serverPort;
247
248    /**
249     * Makes sure it doesn't keep taking screenshots when both buttons are down.
250     */
251    boolean isTakingScreenshot = false;
252
253    /**
254     * Does the actual gameplay have focus. If so then mouse and keys will effect the player instead of menus.
255     */
256    public boolean inGameHasFocus = false;
257    long systemTime = getSystemTime();
258
259    /** Join player counter */
260    private int joinPlayerCounter = 0;
261    private boolean isDemo;
262    private INetworkManager myNetworkManager;
263    private boolean integratedServerIsRunning;
264
265    /** The profiler instance */
266    public final Profiler mcProfiler = new Profiler();
267    private long field_83002_am = -1L;
268
269    /** The working dir (OS specific) for minecraft */
270    private static File minecraftDir = null;
271
272    /**
273     * Set to true to keep the game loop running. Set to false by shutdown() to allow the game loop to exit cleanly.
274     */
275    public volatile boolean running = true;
276
277    /** String that shows the debug information */
278    public String debug = "";
279
280    /** Approximate time (in ms) of last update to debug string */
281    long debugUpdateTime = getSystemTime();
282
283    /** holds the current fps */
284    int fpsCounter = 0;
285    long prevFrameTime = -1L;
286
287    /** Profiler currently displayed in the debug screen pie chart */
288    private String debugProfilerName = "root";
289
290    public Minecraft(Canvas par1Canvas, MinecraftApplet par2MinecraftApplet, int par3, int par4, boolean par5)
291    {
292        StatList.nopInit();
293        this.tempDisplayHeight = par4;
294        this.fullscreen = par5;
295        this.mcApplet = par2MinecraftApplet;
296        Packet3Chat.maxChatLength = 32767;
297        this.startTimerHackThread();
298        this.mcCanvas = par1Canvas;
299        this.displayWidth = par3;
300        this.displayHeight = par4;
301        this.fullscreen = par5;
302        theMinecraft = this;
303        TextureManager.init();
304        this.guiAchievement = new GuiAchievement(this);
305    }
306
307    private void startTimerHackThread()
308    {
309        ThreadClientSleep threadclientsleep = new ThreadClientSleep(this, "Timer hack thread");
310        threadclientsleep.setDaemon(true);
311        threadclientsleep.start();
312    }
313
314    public void crashed(CrashReport par1CrashReport)
315    {
316        this.hasCrashed = true;
317        this.crashReporter = par1CrashReport;
318    }
319
320    /**
321     * Wrapper around displayCrashReportInternal
322     */
323    public void displayCrashReport(CrashReport par1CrashReport)
324    {
325        this.hasCrashed = true;
326        this.displayCrashReportInternal(par1CrashReport);
327    }
328
329    public abstract void displayCrashReportInternal(CrashReport crashreport);
330
331    public void setServer(String par1Str, int par2)
332    {
333        this.serverName = par1Str;
334        this.serverPort = par2;
335    }
336
337    /**
338     * Starts the game: initializes the canvas, the title, the settings, etcetera.
339     */
340    public void startGame() throws LWJGLException
341    {
342        if (this.mcCanvas != null)
343        {
344            Graphics graphics = this.mcCanvas.getGraphics();
345
346            if (graphics != null)
347            {
348                graphics.setColor(Color.BLACK);
349                graphics.fillRect(0, 0, this.displayWidth, this.displayHeight);
350                graphics.dispose();
351            }
352
353            Display.setParent(this.mcCanvas);
354        }
355        else if (this.fullscreen)
356        {
357            Display.setFullscreen(true);
358            this.displayWidth = Display.getDisplayMode().getWidth();
359            this.displayHeight = Display.getDisplayMode().getHeight();
360
361            if (this.displayWidth <= 0)
362            {
363                this.displayWidth = 1;
364            }
365
366            if (this.displayHeight <= 0)
367            {
368                this.displayHeight = 1;
369            }
370        }
371        else
372        {
373            Display.setDisplayMode(new DisplayMode(this.displayWidth, this.displayHeight));
374        }
375
376        Display.setTitle("Minecraft Minecraft 1.5.1");
377        this.getLogAgent().logInfo("LWJGL Version: " + Sys.getVersion());
378
379        try
380        {
381            Display.create((new PixelFormat()).withDepthBits(24));
382        }
383        catch (LWJGLException lwjglexception)
384        {
385            lwjglexception.printStackTrace();
386
387            try
388            {
389                Thread.sleep(1000L);
390            }
391            catch (InterruptedException interruptedexception)
392            {
393                ;
394            }
395
396            Display.create();
397        }
398
399        OpenGlHelper.initializeTextures();
400        this.mcDataDir = getMinecraftDir();
401        this.saveLoader = new AnvilSaveConverter(new File(this.mcDataDir, "saves"));
402        this.gameSettings = new GameSettings(this, this.mcDataDir);
403        this.texturePackList = new TexturePackList(this.mcDataDir, this);
404        this.renderEngine = new RenderEngine(this.texturePackList, this.gameSettings);
405        this.loadScreen();
406        this.fontRenderer = new FontRenderer(this.gameSettings, "/font/default.png", this.renderEngine, false);
407        this.standardGalacticFontRenderer = new FontRenderer(this.gameSettings, "/font/alternate.png", this.renderEngine, false);
408
409        FMLClientHandler.instance().beginMinecraftLoading(this);
410
411        if (this.gameSettings.language != null)
412        {
413            StringTranslate.getInstance().setLanguage(this.gameSettings.language, false);
414            this.fontRenderer.setUnicodeFlag(StringTranslate.getInstance().isUnicode());
415            this.fontRenderer.setBidiFlag(StringTranslate.isBidirectional(this.gameSettings.language));
416        }
417
418        ColorizerGrass.setGrassBiomeColorizer(this.renderEngine.getTextureContents("/misc/grasscolor.png"));
419        ColorizerFoliage.setFoliageBiomeColorizer(this.renderEngine.getTextureContents("/misc/foliagecolor.png"));
420        this.entityRenderer = new EntityRenderer(this);
421        RenderManager.instance.itemRenderer = new ItemRenderer(this);
422        this.statFileWriter = new StatFileWriter(this.session, this.mcDataDir);
423        AchievementList.openInventory.setStatStringFormatter(new StatStringFormatKeyInv(this));
424        this.loadScreen();
425        Mouse.create();
426        this.mouseHelper = new MouseHelper(this.mcCanvas, this.gameSettings);
427        this.checkGLError("Pre startup");
428        GL11.glEnable(GL11.GL_TEXTURE_2D);
429        GL11.glShadeModel(GL11.GL_SMOOTH);
430        GL11.glClearDepth(1.0D);
431        GL11.glEnable(GL11.GL_DEPTH_TEST);
432        GL11.glDepthFunc(GL11.GL_LEQUAL);
433        GL11.glEnable(GL11.GL_ALPHA_TEST);
434        GL11.glAlphaFunc(GL11.GL_GREATER, 0.1F);
435        GL11.glCullFace(GL11.GL_BACK);
436        GL11.glMatrixMode(GL11.GL_PROJECTION);
437        GL11.glLoadIdentity();
438        GL11.glMatrixMode(GL11.GL_MODELVIEW);
439        this.checkGLError("Startup");
440        this.sndManager.loadSoundSettings(this.gameSettings);
441        this.renderGlobal = new RenderGlobal(this, this.renderEngine);
442        this.renderEngine.refreshTextureMaps();
443        GL11.glViewport(0, 0, this.displayWidth, this.displayHeight);
444        this.effectRenderer = new EffectRenderer(this.theWorld, this.renderEngine);
445
446        FMLClientHandler.instance().finishMinecraftLoading();
447
448        try
449        {
450            this.downloadResourcesThread = new ThreadDownloadResources(this.mcDataDir, this);
451            this.downloadResourcesThread.start();
452        }
453        catch (Exception exception)
454        {
455            ;
456        }
457
458        this.checkGLError("Post startup");
459        this.ingameGUI = new GuiIngame(this);
460
461        if (this.serverName != null)
462        {
463            this.displayGuiScreen(new GuiConnecting(new GuiMainMenu(), this, this.serverName, this.serverPort));
464        }
465        else
466        {
467            this.displayGuiScreen(new GuiMainMenu());
468        }
469
470        this.loadingScreen = new LoadingScreenRenderer(this);
471
472        if (this.gameSettings.fullScreen && !this.fullscreen)
473        {
474            this.toggleFullscreen();
475        }
476
477        FMLClientHandler.instance().onInitializationComplete();
478    }
479
480    /**
481     * Displays a new screen.
482     */
483    private void loadScreen() throws LWJGLException
484    {
485        ScaledResolution scaledresolution = new ScaledResolution(this.gameSettings, this.displayWidth, this.displayHeight);
486        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
487        GL11.glMatrixMode(GL11.GL_PROJECTION);
488        GL11.glLoadIdentity();
489        GL11.glOrtho(0.0D, scaledresolution.getScaledWidth_double(), scaledresolution.getScaledHeight_double(), 0.0D, 1000.0D, 3000.0D);
490        GL11.glMatrixMode(GL11.GL_MODELVIEW);
491        GL11.glLoadIdentity();
492        GL11.glTranslatef(0.0F, 0.0F, -2000.0F);
493        GL11.glViewport(0, 0, this.displayWidth, this.displayHeight);
494        GL11.glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
495        GL11.glDisable(GL11.GL_LIGHTING);
496        GL11.glEnable(GL11.GL_TEXTURE_2D);
497        GL11.glDisable(GL11.GL_FOG);
498        Tessellator tessellator = Tessellator.instance;
499        this.renderEngine.bindTexture("/title/mojang.png");
500        tessellator.startDrawingQuads();
501        tessellator.setColorOpaque_I(16777215);
502        tessellator.addVertexWithUV(0.0D, (double)this.displayHeight, 0.0D, 0.0D, 0.0D);
503        tessellator.addVertexWithUV((double)this.displayWidth, (double)this.displayHeight, 0.0D, 0.0D, 0.0D);
504        tessellator.addVertexWithUV((double)this.displayWidth, 0.0D, 0.0D, 0.0D, 0.0D);
505        tessellator.addVertexWithUV(0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
506        tessellator.draw();
507        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
508        tessellator.setColorOpaque_I(16777215);
509        short short1 = 256;
510        short short2 = 256;
511        this.scaledTessellator((scaledresolution.getScaledWidth() - short1) / 2, (scaledresolution.getScaledHeight() - short2) / 2, 0, 0, short1, short2);
512        GL11.glDisable(GL11.GL_LIGHTING);
513        GL11.glDisable(GL11.GL_FOG);
514        GL11.glEnable(GL11.GL_ALPHA_TEST);
515        GL11.glAlphaFunc(GL11.GL_GREATER, 0.1F);
516        Display.swapBuffers();
517    }
518
519    /**
520     * Loads Tessellator with a scaled resolution
521     */
522    public void scaledTessellator(int par1, int par2, int par3, int par4, int par5, int par6)
523    {
524        float f = 0.00390625F;
525        float f1 = 0.00390625F;
526        Tessellator tessellator = Tessellator.instance;
527        tessellator.startDrawingQuads();
528        tessellator.addVertexWithUV((double)(par1 + 0), (double)(par2 + par6), 0.0D, (double)((float)(par3 + 0) * f), (double)((float)(par4 + par6) * f1));
529        tessellator.addVertexWithUV((double)(par1 + par5), (double)(par2 + par6), 0.0D, (double)((float)(par3 + par5) * f), (double)((float)(par4 + par6) * f1));
530        tessellator.addVertexWithUV((double)(par1 + par5), (double)(par2 + 0), 0.0D, (double)((float)(par3 + par5) * f), (double)((float)(par4 + 0) * f1));
531        tessellator.addVertexWithUV((double)(par1 + 0), (double)(par2 + 0), 0.0D, (double)((float)(par3 + 0) * f), (double)((float)(par4 + 0) * f1));
532        tessellator.draw();
533    }
534
535    /**
536     * gets the working dir (OS specific) for minecraft
537     */
538    public static File getMinecraftDir()
539    {
540        if (minecraftDir == null)
541        {
542            minecraftDir = getAppDir("minecraft");
543        }
544
545        return minecraftDir;
546    }
547
548    /**
549     * gets the working dir (OS specific) for the specific application (which is always minecraft)
550     */
551    public static File getAppDir(String par0Str)
552    {
553        String s1 = System.getProperty("user.home", ".");
554        File file1;
555
556        switch (EnumOSHelper.field_90049_a[getOs().ordinal()])
557        {
558            case 1:
559            case 2:
560                file1 = new File(s1, '.' + par0Str + '/');
561                break;
562            case 3:
563                String s2 = System.getenv("APPDATA");
564
565                if (s2 != null)
566                {
567                    file1 = new File(s2, "." + par0Str + '/');
568                }
569                else
570                {
571                    file1 = new File(s1, '.' + par0Str + '/');
572                }
573
574                break;
575            case 4:
576                file1 = new File(s1, "Library/Application Support/" + par0Str);
577                break;
578            default:
579                file1 = new File(s1, par0Str + '/');
580        }
581
582        if (!file1.exists() && !file1.mkdirs())
583        {
584            throw new RuntimeException("The working directory could not be created: " + file1);
585        }
586        else
587        {
588            return file1;
589        }
590    }
591
592    public static EnumOS getOs()
593    {
594        String s = System.getProperty("os.name").toLowerCase();
595        return s.contains("win") ? EnumOS.WINDOWS : (s.contains("mac") ? EnumOS.MACOS : (s.contains("solaris") ? EnumOS.SOLARIS : (s.contains("sunos") ? EnumOS.SOLARIS : (s.contains("linux") ? EnumOS.LINUX : (s.contains("unix") ? EnumOS.LINUX : EnumOS.UNKNOWN)))));
596    }
597
598    /**
599     * Returns the save loader that is currently being used
600     */
601    public ISaveFormat getSaveLoader()
602    {
603        return this.saveLoader;
604    }
605
606    /**
607     * Sets the argument GuiScreen as the main (topmost visible) screen.
608     */
609    public void displayGuiScreen(GuiScreen par1GuiScreen)
610    {
611        if (this.currentScreen != null)
612        {
613            this.currentScreen.onGuiClosed();
614        }
615
616        this.statFileWriter.syncStats();
617
618        if (par1GuiScreen == null && this.theWorld == null)
619        {
620            par1GuiScreen = new GuiMainMenu();
621        }
622        else if (par1GuiScreen == null && this.thePlayer.getHealth() <= 0)
623        {
624            par1GuiScreen = new GuiGameOver();
625        }
626
627        if (par1GuiScreen instanceof GuiMainMenu)
628        {
629            this.gameSettings.showDebugInfo = false;
630            this.ingameGUI.getChatGUI().clearChatMessages();
631        }
632
633        this.currentScreen = (GuiScreen)par1GuiScreen;
634
635        if (par1GuiScreen != null)
636        {
637            this.setIngameNotInFocus();
638            ScaledResolution scaledresolution = new ScaledResolution(this.gameSettings, this.displayWidth, this.displayHeight);
639            int i = scaledresolution.getScaledWidth();
640            int j = scaledresolution.getScaledHeight();
641            ((GuiScreen)par1GuiScreen).setWorldAndResolution(this, i, j);
642            this.skipRenderWorld = false;
643        }
644        else
645        {
646            this.setIngameFocus();
647        }
648    }
649
650    /**
651     * Checks for an OpenGL error. If there is one, prints the error ID and error string.
652     */
653    private void checkGLError(String par1Str)
654    {
655        int i = GL11.glGetError();
656
657        if (i != 0)
658        {
659            String s1 = GLU.gluErrorString(i);
660            this.getLogAgent().logSevere("########## GL ERROR ##########");
661            this.getLogAgent().logSevere("@ " + par1Str);
662            this.getLogAgent().logSevere(i + ": " + s1);
663        }
664    }
665
666    /**
667     * Shuts down the minecraft applet by stopping the resource downloads, and clearing up GL stuff; called when the
668     * application (or web page) is exited.
669     */
670    public void shutdownMinecraftApplet()
671    {
672        try
673        {
674            this.statFileWriter.syncStats();
675
676            try
677            {
678                if (this.downloadResourcesThread != null)
679                {
680                    this.downloadResourcesThread.closeMinecraft();
681                }
682            }
683            catch (Exception exception)
684            {
685                ;
686            }
687
688            this.getLogAgent().logInfo("Stopping!");
689
690            try
691            {
692                this.loadWorld((WorldClient)null);
693            }
694            catch (Throwable throwable)
695            {
696                ;
697            }
698
699            try
700            {
701                GLAllocation.deleteTexturesAndDisplayLists();
702            }
703            catch (Throwable throwable1)
704            {
705                ;
706            }
707
708            this.sndManager.closeMinecraft();
709            Mouse.destroy();
710            Keyboard.destroy();
711        }
712        finally
713        {
714            Display.destroy();
715
716            if (!this.hasCrashed)
717            {
718                System.exit(0);
719            }
720        }
721
722        System.gc();
723    }
724
725    public void run()
726    {
727        this.running = true;
728
729        try
730        {
731            this.startGame();
732        }
733        catch (Exception exception)
734        {
735            exception.printStackTrace();
736            this.displayCrashReport(this.addGraphicsAndWorldToCrashReport(new CrashReport("Failed to start game", exception)));
737            return;
738        }
739
740        try
741        {
742            while (this.running)
743            {
744                if (this.hasCrashed && this.crashReporter != null)
745                {
746                    this.displayCrashReport(this.crashReporter);
747                    return;
748                }
749
750                if (this.refreshTexturePacksScheduled)
751                {
752                    this.refreshTexturePacksScheduled = false;
753                    this.renderEngine.refreshTextures();
754                }
755
756                try
757                {
758                    this.runGameLoop();
759                }
760                catch (OutOfMemoryError outofmemoryerror)
761                {
762                    this.freeMemory();
763                    this.displayGuiScreen(new GuiMemoryErrorScreen());
764                    System.gc();
765                }
766            }
767        }
768        catch (MinecraftError minecrafterror)
769        {
770            ;
771        }
772        catch (ReportedException reportedexception)
773        {
774            this.addGraphicsAndWorldToCrashReport(reportedexception.getCrashReport());
775            this.freeMemory();
776            reportedexception.printStackTrace();
777            this.displayCrashReport(reportedexception.getCrashReport());
778        }
779        catch (Throwable throwable)
780        {
781            CrashReport crashreport = this.addGraphicsAndWorldToCrashReport(new CrashReport("Unexpected error", throwable));
782            this.freeMemory();
783            throwable.printStackTrace();
784            this.displayCrashReport(crashreport);
785        }
786        finally
787        {
788            this.shutdownMinecraftApplet();
789        }
790    }
791
792    /**
793     * Called repeatedly from run()
794     */
795    private void runGameLoop()
796    {
797        if (this.mcApplet != null && !this.mcApplet.isActive())
798        {
799            this.running = false;
800        }
801        else
802        {
803            AxisAlignedBB.getAABBPool().cleanPool();
804
805            if (this.theWorld != null)
806            {
807                this.theWorld.getWorldVec3Pool().clear();
808            }
809
810            this.mcProfiler.startSection("root");
811
812            if (this.mcCanvas == null && Display.isCloseRequested())
813            {
814                this.shutdown();
815            }
816
817            if (this.isGamePaused && this.theWorld != null)
818            {
819                float f = this.timer.renderPartialTicks;
820                this.timer.updateTimer();
821                this.timer.renderPartialTicks = f;
822            }
823            else
824            {
825                this.timer.updateTimer();
826            }
827
828            long i = System.nanoTime();
829            this.mcProfiler.startSection("tick");
830
831            for (int j = 0; j < this.timer.elapsedTicks; ++j)
832            {
833                this.runTick();
834            }
835
836            this.mcProfiler.endStartSection("preRenderErrors");
837            long k = System.nanoTime() - i;
838            this.checkGLError("Pre render");
839            RenderBlocks.fancyGrass = this.gameSettings.fancyGraphics;
840            this.mcProfiler.endStartSection("sound");
841            this.sndManager.setListener(this.thePlayer, this.timer.renderPartialTicks);
842
843            if (!this.isGamePaused)
844            {
845                this.sndManager.func_92071_g();
846            }
847
848            this.mcProfiler.endSection();
849            this.mcProfiler.startSection("render");
850            this.mcProfiler.startSection("display");
851            GL11.glEnable(GL11.GL_TEXTURE_2D);
852
853            if (!Keyboard.isKeyDown(65))
854            {
855                Display.update();
856            }
857
858            if (this.thePlayer != null && this.thePlayer.isEntityInsideOpaqueBlock())
859            {
860                this.gameSettings.thirdPersonView = 0;
861            }
862
863            this.mcProfiler.endSection();
864
865            if (!this.skipRenderWorld)
866            {
867                FMLCommonHandler.instance().onRenderTickStart(this.timer.renderPartialTicks);
868                this.mcProfiler.endStartSection("gameRenderer");
869                this.entityRenderer.updateCameraAndRender(this.timer.renderPartialTicks);
870                this.mcProfiler.endSection();
871                FMLCommonHandler.instance().onRenderTickEnd(this.timer.renderPartialTicks);
872            }
873
874            GL11.glFlush();
875            this.mcProfiler.endSection();
876
877            if (!Display.isActive() && this.fullscreen)
878            {
879                this.toggleFullscreen();
880            }
881
882            if (this.gameSettings.showDebugInfo && this.gameSettings.showDebugProfilerChart)
883            {
884                if (!this.mcProfiler.profilingEnabled)
885                {
886                    this.mcProfiler.clearProfiling();
887                }
888
889                this.mcProfiler.profilingEnabled = true;
890                this.displayDebugInfo(k);
891            }
892            else
893            {
894                this.mcProfiler.profilingEnabled = false;
895                this.prevFrameTime = System.nanoTime();
896            }
897
898            this.guiAchievement.updateAchievementWindow();
899            this.mcProfiler.startSection("root");
900            Thread.yield();
901
902            if (Keyboard.isKeyDown(65))
903            {
904                Display.update();
905            }
906
907            this.screenshotListener();
908
909            if (this.mcCanvas != null && !this.fullscreen && (this.mcCanvas.getWidth() != this.displayWidth || this.mcCanvas.getHeight() != this.displayHeight))
910            {
911                this.displayWidth = this.mcCanvas.getWidth();
912                this.displayHeight = this.mcCanvas.getHeight();
913
914                if (this.displayWidth <= 0)
915                {
916                    this.displayWidth = 1;
917                }
918
919                if (this.displayHeight <= 0)
920                {
921                    this.displayHeight = 1;
922                }
923
924                this.resize(this.displayWidth, this.displayHeight);
925            }
926
927            this.checkGLError("Post render");
928            ++this.fpsCounter;
929            boolean flag = this.isGamePaused;
930            this.isGamePaused = this.isSingleplayer() && this.currentScreen != null && this.currentScreen.doesGuiPauseGame() && !this.theIntegratedServer.getPublic();
931
932            if (this.isIntegratedServerRunning() && this.thePlayer != null && this.thePlayer.sendQueue != null && this.isGamePaused != flag)
933            {
934                ((MemoryConnection)this.thePlayer.sendQueue.getNetManager()).setGamePaused(this.isGamePaused);
935            }
936
937            while (getSystemTime() >= this.debugUpdateTime + 1000L)
938            {
939                debugFPS = this.fpsCounter;
940                this.debug = debugFPS + " fps, " + WorldRenderer.chunksUpdated + " chunk updates";
941                WorldRenderer.chunksUpdated = 0;
942                this.debugUpdateTime += 1000L;
943                this.fpsCounter = 0;
944                this.usageSnooper.addMemoryStatsToSnooper();
945
946                if (!this.usageSnooper.isSnooperRunning())
947                {
948                    this.usageSnooper.startSnooper();
949                }
950            }
951
952            this.mcProfiler.endSection();
953
954            if (this.func_90020_K() > 0)
955            {
956                Display.sync(EntityRenderer.performanceToFps(this.func_90020_K()));
957            }
958        }
959    }
960
961    private int func_90020_K()
962    {
963        return this.currentScreen != null && this.currentScreen instanceof GuiMainMenu ? 2 : this.gameSettings.limitFramerate;
964    }
965
966    public void freeMemory()
967    {
968        try
969        {
970            memoryReserve = new byte[0];
971            this.renderGlobal.deleteAllDisplayLists();
972        }
973        catch (Throwable throwable)
974        {
975            ;
976        }
977
978        try
979        {
980            System.gc();
981            AxisAlignedBB.getAABBPool().clearPool();
982            this.theWorld.getWorldVec3Pool().clearAndFreeCache();
983        }
984        catch (Throwable throwable1)
985        {
986            ;
987        }
988
989        try
990        {
991            System.gc();
992            this.loadWorld((WorldClient)null);
993        }
994        catch (Throwable throwable2)
995        {
996            ;
997        }
998
999        System.gc();
1000    }
1001
1002    /**
1003     * checks if keys are down
1004     */
1005    private void screenshotListener()
1006    {
1007        if (Keyboard.isKeyDown(60))
1008        {
1009            if (!this.isTakingScreenshot)
1010            {
1011                this.isTakingScreenshot = true;
1012                this.ingameGUI.getChatGUI().printChatMessage(ScreenShotHelper.saveScreenshot(minecraftDir, this.displayWidth, this.displayHeight));
1013            }
1014        }
1015        else
1016        {
1017            this.isTakingScreenshot = false;
1018        }
1019    }
1020
1021    /**
1022     * Update debugProfilerName in response to number keys in debug screen
1023     */
1024    private void updateDebugProfilerName(int par1)
1025    {
1026        List list = this.mcProfiler.getProfilingData(this.debugProfilerName);
1027
1028        if (list != null && !list.isEmpty())
1029        {
1030            ProfilerResult profilerresult = (ProfilerResult)list.remove(0);
1031
1032            if (par1 == 0)
1033            {
1034                if (profilerresult.field_76331_c.length() > 0)
1035                {
1036                    int j = this.debugProfilerName.lastIndexOf(".");
1037
1038                    if (j >= 0)
1039                    {
1040                        this.debugProfilerName = this.debugProfilerName.substring(0, j);
1041                    }
1042                }
1043            }
1044            else
1045            {
1046                --par1;
1047
1048                if (par1 < list.size() && !((ProfilerResult)list.get(par1)).field_76331_c.equals("unspecified"))
1049                {
1050                    if (this.debugProfilerName.length() > 0)
1051                    {
1052                        this.debugProfilerName = this.debugProfilerName + ".";
1053                    }
1054
1055                    this.debugProfilerName = this.debugProfilerName + ((ProfilerResult)list.get(par1)).field_76331_c;
1056                }
1057            }
1058        }
1059    }
1060
1061    private void displayDebugInfo(long par1)
1062    {
1063        if (this.mcProfiler.profilingEnabled)
1064        {
1065            List list = this.mcProfiler.getProfilingData(this.debugProfilerName);
1066            ProfilerResult profilerresult = (ProfilerResult)list.remove(0);
1067            GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
1068            GL11.glMatrixMode(GL11.GL_PROJECTION);
1069            GL11.glEnable(GL11.GL_COLOR_MATERIAL);
1070            GL11.glLoadIdentity();
1071            GL11.glOrtho(0.0D, (double)this.displayWidth, (double)this.displayHeight, 0.0D, 1000.0D, 3000.0D);
1072            GL11.glMatrixMode(GL11.GL_MODELVIEW);
1073            GL11.glLoadIdentity();
1074            GL11.glTranslatef(0.0F, 0.0F, -2000.0F);
1075            GL11.glLineWidth(1.0F);
1076            GL11.glDisable(GL11.GL_TEXTURE_2D);
1077            Tessellator tessellator = Tessellator.instance;
1078            short short1 = 160;
1079            int j = this.displayWidth - short1 - 10;
1080            int k = this.displayHeight - short1 * 2;
1081            GL11.glEnable(GL11.GL_BLEND);
1082            tessellator.startDrawingQuads();
1083            tessellator.setColorRGBA_I(0, 200);
1084            tessellator.addVertex((double)((float)j - (float)short1 * 1.1F), (double)((float)k - (float)short1 * 0.6F - 16.0F), 0.0D);
1085            tessellator.addVertex((double)((float)j - (float)short1 * 1.1F), (double)(k + short1 * 2), 0.0D);
1086            tessellator.addVertex((double)((float)j + (float)short1 * 1.1F), (double)(k + short1 * 2), 0.0D);
1087            tessellator.addVertex((double)((float)j + (float)short1 * 1.1F), (double)((float)k - (float)short1 * 0.6F - 16.0F), 0.0D);
1088            tessellator.draw();
1089            GL11.glDisable(GL11.GL_BLEND);
1090            double d0 = 0.0D;
1091            int l;
1092
1093            for (int i1 = 0; i1 < list.size(); ++i1)
1094            {
1095                ProfilerResult profilerresult1 = (ProfilerResult)list.get(i1);
1096                l = MathHelper.floor_double(profilerresult1.field_76332_a / 4.0D) + 1;
1097                tessellator.startDrawing(6);
1098                tessellator.setColorOpaque_I(profilerresult1.func_76329_a());
1099                tessellator.addVertex((double)j, (double)k, 0.0D);
1100                int j1;
1101                float f;
1102                float f1;
1103                float f2;
1104
1105                for (j1 = l; j1 >= 0; --j1)
1106                {
1107                    f = (float)((d0 + profilerresult1.field_76332_a * (double)j1 / (double)l) * Math.PI * 2.0D / 100.0D);
1108                    f2 = MathHelper.sin(f) * (float)short1;
1109                    f1 = MathHelper.cos(f) * (float)short1 * 0.5F;
1110                    tessellator.addVertex((double)((float)j + f2), (double)((float)k - f1), 0.0D);
1111                }
1112
1113                tessellator.draw();
1114                tessellator.startDrawing(5);
1115                tessellator.setColorOpaque_I((profilerresult1.func_76329_a() & 16711422) >> 1);
1116
1117                for (j1 = l; j1 >= 0; --j1)
1118                {
1119                    f = (float)((d0 + profilerresult1.field_76332_a * (double)j1 / (double)l) * Math.PI * 2.0D / 100.0D);
1120                    f2 = MathHelper.sin(f) * (float)short1;
1121                    f1 = MathHelper.cos(f) * (float)short1 * 0.5F;
1122                    tessellator.addVertex((double)((float)j + f2), (double)((float)k - f1), 0.0D);
1123                    tessellator.addVertex((double)((float)j + f2), (double)((float)k - f1 + 10.0F), 0.0D);
1124                }
1125
1126                tessellator.draw();
1127                d0 += profilerresult1.field_76332_a;
1128            }
1129
1130            DecimalFormat decimalformat = new DecimalFormat("##0.00");
1131            GL11.glEnable(GL11.GL_TEXTURE_2D);
1132            String s = "";
1133
1134            if (!profilerresult.field_76331_c.equals("unspecified"))
1135            {
1136                s = s + "[0] ";
1137            }
1138
1139            if (profilerresult.field_76331_c.length() == 0)
1140            {
1141                s = s + "ROOT ";
1142            }
1143            else
1144            {
1145                s = s + profilerresult.field_76331_c + " ";
1146            }
1147
1148            l = 16777215;
1149            this.fontRenderer.drawStringWithShadow(s, j - short1, k - short1 / 2 - 16, l);
1150            this.fontRenderer.drawStringWithShadow(s = decimalformat.format(profilerresult.field_76330_b) + "%", j + short1 - this.fontRenderer.getStringWidth(s), k - short1 / 2 - 16, l);
1151
1152            for (int k1 = 0; k1 < list.size(); ++k1)
1153            {
1154                ProfilerResult profilerresult2 = (ProfilerResult)list.get(k1);
1155                String s1 = "";
1156
1157                if (profilerresult2.field_76331_c.equals("unspecified"))
1158                {
1159                    s1 = s1 + "[?] ";
1160                }
1161                else
1162                {
1163                    s1 = s1 + "[" + (k1 + 1) + "] ";
1164                }
1165
1166                s1 = s1 + profilerresult2.field_76331_c;
1167                this.fontRenderer.drawStringWithShadow(s1, j - short1, k + short1 / 2 + k1 * 8 + 20, profilerresult2.func_76329_a());
1168                this.fontRenderer.drawStringWithShadow(s1 = decimalformat.format(profilerresult2.field_76332_a) + "%", j + short1 - 50 - this.fontRenderer.getStringWidth(s1), k + short1 / 2 + k1 * 8 + 20, profilerresult2.func_76329_a());
1169                this.fontRenderer.drawStringWithShadow(s1 = decimalformat.format(profilerresult2.field_76330_b) + "%", j + short1 - this.fontRenderer.getStringWidth(s1), k + short1 / 2 + k1 * 8 + 20, profilerresult2.func_76329_a());
1170            }
1171        }
1172    }
1173
1174    /**
1175     * Called when the window is closing. Sets 'running' to false which allows the game loop to exit cleanly.
1176     */
1177    public void shutdown()
1178    {
1179        this.running = false;
1180    }
1181
1182    /**
1183     * Will set the focus to ingame if the Minecraft window is the active with focus. Also clears any GUI screen
1184     * currently displayed
1185     */
1186    public void setIngameFocus()
1187    {
1188        if (Display.isActive())
1189        {
1190            if (!this.inGameHasFocus)
1191            {
1192                this.inGameHasFocus = true;
1193                this.mouseHelper.grabMouseCursor();
1194                this.displayGuiScreen((GuiScreen)null);
1195                this.leftClickCounter = 10000;
1196            }
1197        }
1198    }
1199
1200    /**
1201     * Resets the player keystate, disables the ingame focus, and ungrabs the mouse cursor.
1202     */
1203    public void setIngameNotInFocus()
1204    {
1205        if (this.inGameHasFocus)
1206        {
1207            KeyBinding.unPressAllKeys();
1208            this.inGameHasFocus = false;
1209            this.mouseHelper.ungrabMouseCursor();
1210        }
1211    }
1212
1213    /**
1214     * Displays the ingame menu
1215     */
1216    public void displayInGameMenu()
1217    {
1218        if (this.currentScreen == null)
1219        {
1220            this.displayGuiScreen(new GuiIngameMenu());
1221
1222            if (this.isSingleplayer() && !this.theIntegratedServer.getPublic())
1223            {
1224                this.sndManager.pauseAllSounds();
1225            }
1226        }
1227    }
1228
1229    private void sendClickBlockToController(int par1, boolean par2)
1230    {
1231        if (!par2)
1232        {
1233            this.leftClickCounter = 0;
1234        }
1235
1236        if (par1 != 0 || this.leftClickCounter <= 0)
1237        {
1238            if (par2 && this.objectMouseOver != null && this.objectMouseOver.typeOfHit == EnumMovingObjectType.TILE && par1 == 0)
1239            {
1240                int j = this.objectMouseOver.blockX;
1241                int k = this.objectMouseOver.blockY;
1242                int l = this.objectMouseOver.blockZ;
1243                this.playerController.onPlayerDamageBlock(j, k, l, this.objectMouseOver.sideHit);
1244
1245                if (this.thePlayer.canCurrentToolHarvestBlock(j, k, l))
1246                {
1247                    this.effectRenderer.addBlockHitEffects(j, k, l, this.objectMouseOver);
1248                    this.thePlayer.swingItem();
1249                }
1250            }
1251            else
1252            {
1253                this.playerController.resetBlockRemoving();
1254            }
1255        }
1256    }
1257
1258    /**
1259     * Called whenever the mouse is clicked. Button clicked is 0 for left clicking and 1 for right clicking. Args:
1260     * buttonClicked
1261     */
1262    private void clickMouse(int par1)
1263    {
1264        if (par1 != 0 || this.leftClickCounter <= 0)
1265        {
1266            if (par1 == 0)
1267            {
1268                this.thePlayer.swingItem();
1269            }
1270
1271            if (par1 == 1)
1272            {
1273                this.rightClickDelayTimer = 4;
1274            }
1275
1276            boolean flag = true;
1277            ItemStack itemstack = this.thePlayer.inventory.getCurrentItem();
1278
1279            if (this.objectMouseOver == null)
1280            {
1281                if (par1 == 0 && this.playerController.isNotCreative())
1282                {
1283                    this.leftClickCounter = 10;
1284                }
1285            }
1286            else if (this.objectMouseOver.typeOfHit == EnumMovingObjectType.ENTITY)
1287            {
1288                if (par1 == 0)
1289                {
1290                    this.playerController.attackEntity(this.thePlayer, this.objectMouseOver.entityHit);
1291                }
1292
1293                if (par1 == 1 && this.playerController.func_78768_b(this.thePlayer, this.objectMouseOver.entityHit))
1294                {
1295                    flag = false;
1296                }
1297            }
1298            else if (this.objectMouseOver.typeOfHit == EnumMovingObjectType.TILE)
1299            {
1300                int j = this.objectMouseOver.blockX;
1301                int k = this.objectMouseOver.blockY;
1302                int l = this.objectMouseOver.blockZ;
1303                int i1 = this.objectMouseOver.sideHit;
1304
1305                if (par1 == 0)
1306                {
1307                    this.playerController.clickBlock(j, k, l, this.objectMouseOver.sideHit);
1308                }
1309                else
1310                {
1311                    int j1 = itemstack != null ? itemstack.stackSize : 0;
1312
1313                    boolean result = !ForgeEventFactory.onPlayerInteract(thePlayer, Action.RIGHT_CLICK_BLOCK, j, k, l, i1).isCanceled();
1314                    if (result && this.playerController.onPlayerRightClick(this.thePlayer, this.theWorld, itemstack, j, k, l, i1, this.objectMouseOver.hitVec))
1315                    {
1316                        flag = false;
1317                        this.thePlayer.swingItem();
1318                    }
1319
1320                    if (itemstack == null)
1321                    {
1322                        return;
1323                    }
1324
1325                    if (itemstack.stackSize == 0)
1326                    {
1327                        this.thePlayer.inventory.mainInventory[this.thePlayer.inventory.currentItem] = null;
1328                    }
1329                    else if (itemstack.stackSize != j1 || this.playerController.isInCreativeMode())
1330                    {
1331                        this.entityRenderer.itemRenderer.resetEquippedProgress();
1332                    }
1333                }
1334            }
1335
1336            if (flag && par1 == 1)
1337            {
1338                ItemStack itemstack1 = this.thePlayer.inventory.getCurrentItem();
1339
1340                boolean result = !ForgeEventFactory.onPlayerInteract(thePlayer, Action.RIGHT_CLICK_AIR, 0, 0, 0, -1).isCanceled();
1341                if (result && itemstack1 != null && this.playerController.sendUseItem(this.thePlayer, this.theWorld, itemstack1))
1342                {
1343                    this.entityRenderer.itemRenderer.resetEquippedProgress2();
1344                }
1345            }
1346        }
1347    }
1348
1349    /**
1350     * Toggles fullscreen mode.
1351     */
1352    public void toggleFullscreen()
1353    {
1354        try
1355        {
1356            this.fullscreen = !this.fullscreen;
1357
1358            if (this.fullscreen)
1359            {
1360                Display.setDisplayMode(Display.getDesktopDisplayMode());
1361                this.displayWidth = Display.getDisplayMode().getWidth();
1362                this.displayHeight = Display.getDisplayMode().getHeight();
1363
1364                if (this.displayWidth <= 0)
1365                {
1366                    this.displayWidth = 1;
1367                }
1368
1369                if (this.displayHeight <= 0)
1370                {
1371                    this.displayHeight = 1;
1372                }
1373            }
1374            else
1375            {
1376                if (this.mcCanvas != null)
1377                {
1378                    this.displayWidth = this.mcCanvas.getWidth();
1379                    this.displayHeight = this.mcCanvas.getHeight();
1380                }
1381                else
1382                {
1383                    this.displayWidth = this.tempDisplayWidth;
1384                    this.displayHeight = this.tempDisplayHeight;
1385                }
1386
1387                if (this.displayWidth <= 0)
1388                {
1389                    this.displayWidth = 1;
1390                }
1391
1392                if (this.displayHeight <= 0)
1393                {
1394                    this.displayHeight = 1;
1395                }
1396            }
1397
1398            if (this.currentScreen != null)
1399            {
1400                this.resize(this.displayWidth, this.displayHeight);
1401            }
1402
1403            Display.setFullscreen(this.fullscreen);
1404            Display.setVSyncEnabled(this.gameSettings.enableVsync);
1405            Display.update();
1406        }
1407        catch (Exception exception)
1408        {
1409            exception.printStackTrace();
1410        }
1411    }
1412
1413    /**
1414     * Called to resize the current screen.
1415     */
1416    private void resize(int par1, int par2)
1417    {
1418        this.displayWidth = par1 <= 0 ? 1 : par1;
1419        this.displayHeight = par2 <= 0 ? 1 : par2;
1420
1421        if (this.currentScreen != null)
1422        {
1423            ScaledResolution scaledresolution = new ScaledResolution(this.gameSettings, par1, par2);
1424            int k = scaledresolution.getScaledWidth();
1425            int l = scaledresolution.getScaledHeight();
1426            this.currentScreen.setWorldAndResolution(this, k, l);
1427        }
1428    }
1429
1430    /**
1431     * Runs the current tick.
1432     */
1433    public void runTick()
1434    {
1435        FMLCommonHandler.instance().rescheduleTicks(Side.CLIENT);
1436
1437        if (this.rightClickDelayTimer > 0)
1438        {
1439            --this.rightClickDelayTimer;
1440        }
1441
1442        FMLCommonHandler.instance().onPreClientTick();
1443
1444        this.mcProfiler.startSection("stats");
1445        this.statFileWriter.func_77449_e();
1446        this.mcProfiler.endStartSection("gui");
1447
1448        if (!this.isGamePaused)
1449        {
1450            this.ingameGUI.updateTick();
1451        }
1452
1453        this.mcProfiler.endStartSection("pick");
1454        this.entityRenderer.getMouseOver(1.0F);
1455        this.mcProfiler.endStartSection("gameMode");
1456
1457        if (!this.isGamePaused && this.theWorld != null)
1458        {
1459            this.playerController.updateController();
1460        }
1461
1462        this.renderEngine.bindTexture("/terrain.png");
1463        this.mcProfiler.endStartSection("textures");
1464
1465        if (!this.isGamePaused)
1466        {
1467            this.renderEngine.updateDynamicTextures();
1468        }
1469
1470        if (this.currentScreen == null && this.thePlayer != null)
1471        {
1472            if (this.thePlayer.getHealth() <= 0)
1473            {
1474                this.displayGuiScreen((GuiScreen)null);
1475            }
1476            else if (this.thePlayer.isPlayerSleeping() && this.theWorld != null)
1477            {
1478                this.displayGuiScreen(new GuiSleepMP());
1479            }
1480        }
1481        else if (this.currentScreen != null && this.currentScreen instanceof GuiSleepMP && !this.thePlayer.isPlayerSleeping())
1482        {
1483            this.displayGuiScreen((GuiScreen)null);
1484        }
1485
1486        if (this.currentScreen != null)
1487        {
1488            this.leftClickCounter = 10000;
1489        }
1490
1491        CrashReport crashreport;
1492        CrashReportCategory crashreportcategory;
1493
1494        if (this.currentScreen != null)
1495        {
1496            try
1497            {
1498                this.currentScreen.handleInput();
1499            }
1500            catch (Throwable throwable)
1501            {
1502                crashreport = CrashReport.makeCrashReport(throwable, "Updating screen events");
1503                crashreportcategory = crashreport.makeCategory("Affected screen");
1504                crashreportcategory.addCrashSectionCallable("Screen name", new CallableUpdatingScreenName(this));
1505                throw new ReportedException(crashreport);
1506            }
1507
1508            if (this.currentScreen != null)
1509            {
1510                try
1511                {
1512                    this.currentScreen.guiParticles.update();
1513                }
1514                catch (Throwable throwable1)
1515                {
1516                    crashreport = CrashReport.makeCrashReport(throwable1, "Ticking screen particles");
1517                    crashreportcategory = crashreport.makeCategory("Affected screen");
1518                    crashreportcategory.addCrashSectionCallable("Screen name", new CallableParticleScreenName(this));
1519                    throw new ReportedException(crashreport);
1520                }
1521
1522                try
1523                {
1524                    this.currentScreen.updateScreen();
1525                }
1526                catch (Throwable throwable2)
1527                {
1528                    crashreport = CrashReport.makeCrashReport(throwable2, "Ticking screen");
1529                    crashreportcategory = crashreport.makeCategory("Affected screen");
1530                    crashreportcategory.addCrashSectionCallable("Screen name", new CallableTickingScreenName(this));
1531                    throw new ReportedException(crashreport);
1532                }
1533            }
1534        }
1535
1536        if (this.currentScreen == null || this.currentScreen.allowUserInput)
1537        {
1538            this.mcProfiler.endStartSection("mouse");
1539
1540            while (Mouse.next())
1541            {
1542                KeyBinding.setKeyBindState(Mouse.getEventButton() - 100, Mouse.getEventButtonState());
1543
1544                if (Mouse.getEventButtonState())
1545                {
1546                    KeyBinding.onTick(Mouse.getEventButton() - 100);
1547                }
1548
1549                long i = getSystemTime() - this.systemTime;
1550
1551                if (i <= 200L)
1552                {
1553                    int j = Mouse.getEventDWheel();
1554
1555                    if (j != 0)
1556                    {
1557                        this.thePlayer.inventory.changeCurrentItem(j);
1558
1559                        if (this.gameSettings.noclip)
1560                        {
1561                            if (j > 0)
1562                            {
1563                                j = 1;
1564                            }
1565
1566                            if (j < 0)
1567                            {
1568                                j = -1;
1569                            }
1570
1571                            this.gameSettings.noclipRate += (float)j * 0.25F;
1572                        }
1573                    }
1574
1575                    if (this.currentScreen == null)
1576                    {
1577                        if (!this.inGameHasFocus && Mouse.getEventButtonState())
1578                        {
1579                            this.setIngameFocus();
1580                        }
1581                    }
1582                    else if (this.currentScreen != null)
1583                    {
1584                        this.currentScreen.handleMouseInput();
1585                    }
1586                }
1587            }
1588
1589            if (this.leftClickCounter > 0)
1590            {
1591                --this.leftClickCounter;
1592            }
1593
1594            this.mcProfiler.endStartSection("keyboard");
1595            boolean flag;
1596
1597            while (Keyboard.next())
1598            {
1599                KeyBinding.setKeyBindState(Keyboard.getEventKey(), Keyboard.getEventKeyState());
1600
1601                if (Keyboard.getEventKeyState())
1602                {
1603                    KeyBinding.onTick(Keyboard.getEventKey());
1604                }
1605
1606                if (this.field_83002_am > 0L)
1607                {
1608                    if (getSystemTime() - this.field_83002_am >= 6000L)
1609                    {
1610                        throw new ReportedException(new CrashReport("Manually triggered debug crash", new Throwable()));
1611                    }
1612
1613                    if (!Keyboard.isKeyDown(46) || !Keyboard.isKeyDown(61))
1614                    {
1615                        this.field_83002_am = -1L;
1616                    }
1617                }
1618                else if (Keyboard.isKeyDown(46) && Keyboard.isKeyDown(61))
1619                {
1620                    this.field_83002_am = getSystemTime();
1621                }
1622
1623                if (Keyboard.getEventKeyState())
1624                {
1625                    if (Keyboard.getEventKey() == 87)
1626                    {
1627                        this.toggleFullscreen();
1628                    }
1629                    else
1630                    {
1631                        if (this.currentScreen != null)
1632                        {
1633                            this.currentScreen.handleKeyboardInput();
1634                        }
1635                        else
1636                        {
1637                            if (Keyboard.getEventKey() == 1)
1638                            {
1639                                this.displayInGameMenu();
1640                            }
1641
1642                            if (Keyboard.getEventKey() == 31 && Keyboard.isKeyDown(61))
1643                            {
1644                                this.forceReload();
1645                            }
1646
1647                            if (Keyboard.getEventKey() == 20 && Keyboard.isKeyDown(61))
1648                            {
1649                                this.renderEngine.refreshTextures();
1650                                this.renderGlobal.loadRenderers();
1651                            }
1652
1653                            if (Keyboard.getEventKey() == 33 && Keyboard.isKeyDown(61))
1654                            {
1655                                flag = Keyboard.isKeyDown(42) | Keyboard.isKeyDown(54);
1656                                this.gameSettings.setOptionValue(EnumOptions.RENDER_DISTANCE, flag ? -1 : 1);
1657                            }
1658
1659                            if (Keyboard.getEventKey() == 30 && Keyboard.isKeyDown(61))
1660                            {
1661                                this.renderGlobal.loadRenderers();
1662                            }
1663
1664                            if (Keyboard.getEventKey() == 35 && Keyboard.isKeyDown(61))
1665                            {
1666                                this.gameSettings.advancedItemTooltips = !this.gameSettings.advancedItemTooltips;
1667                                this.gameSettings.saveOptions();
1668                            }
1669
1670                            if (Keyboard.getEventKey() == 48 && Keyboard.isKeyDown(61))
1671                            {
1672                                RenderManager.field_85095_o = !RenderManager.field_85095_o;
1673                            }
1674
1675                            if (Keyboard.getEventKey() == 25 && Keyboard.isKeyDown(61))
1676                            {
1677                                this.gameSettings.pauseOnLostFocus = !this.gameSettings.pauseOnLostFocus;
1678                                this.gameSettings.saveOptions();
1679                            }
1680
1681                            if (Keyboard.getEventKey() == 59)
1682                            {
1683                                this.gameSettings.hideGUI = !this.gameSettings.hideGUI;
1684                            }
1685
1686                            if (Keyboard.getEventKey() == 61)
1687                            {
1688                                this.gameSettings.showDebugInfo = !this.gameSettings.showDebugInfo;
1689                                this.gameSettings.showDebugProfilerChart = GuiScreen.isShiftKeyDown();
1690                            }
1691
1692                            if (Keyboard.getEventKey() == 63)
1693                            {
1694                                ++this.gameSettings.thirdPersonView;
1695
1696                                if (this.gameSettings.thirdPersonView > 2)
1697                                {
1698                                    this.gameSettings.thirdPersonView = 0;
1699                                }
1700                            }
1701
1702                            if (Keyboard.getEventKey() == 66)
1703                            {
1704                                this.gameSettings.smoothCamera = !this.gameSettings.smoothCamera;
1705                            }
1706                        }
1707
1708                        int k;
1709
1710                        for (k = 0; k < 9; ++k)
1711                        {
1712                            if (Keyboard.getEventKey() == 2 + k)
1713                            {
1714                                this.thePlayer.inventory.currentItem = k;
1715                            }
1716                        }
1717
1718                        if (this.gameSettings.showDebugInfo && this.gameSettings.showDebugProfilerChart)
1719                        {
1720                            if (Keyboard.getEventKey() == 11)
1721                            {
1722                                this.updateDebugProfilerName(0);
1723                            }
1724
1725                            for (k = 0; k < 9; ++k)
1726                            {
1727                                if (Keyboard.getEventKey() == 2 + k)
1728                                {
1729                                    this.updateDebugProfilerName(k + 1);
1730                                }
1731                            }
1732                        }
1733                    }
1734                }
1735            }
1736
1737            flag = this.gameSettings.chatVisibility != 2;
1738
1739            while (this.gameSettings.keyBindInventory.isPressed())
1740            {
1741                this.displayGuiScreen(new GuiInventory(this.thePlayer));
1742            }
1743
1744            while (this.gameSettings.keyBindDrop.isPressed())
1745            {
1746                this.thePlayer.dropOneItem(GuiScreen.isCtrlKeyDown());
1747            }
1748
1749            while (this.gameSettings.keyBindChat.isPressed() && flag)
1750            {
1751                this.displayGuiScreen(new GuiChat());
1752            }
1753
1754            if (this.currentScreen == null && this.gameSettings.keyBindCommand.isPressed() && flag)
1755            {
1756                this.displayGuiScreen(new GuiChat("/"));
1757            }
1758
1759            if (this.thePlayer.isUsingItem())
1760            {
1761                if (!this.gameSettings.keyBindUseItem.pressed)
1762                {
1763                    this.playerController.onStoppedUsingItem(this.thePlayer);
1764                }
1765
1766                label379:
1767
1768                while (true)
1769                {
1770                    if (!this.gameSettings.keyBindAttack.isPressed())
1771                    {
1772                        while (this.gameSettings.keyBindUseItem.isPressed())
1773                        {
1774                            ;
1775                        }
1776
1777                        while (true)
1778                        {
1779                            if (this.gameSettings.keyBindPickBlock.isPressed())
1780                            {
1781                                continue;
1782                            }
1783
1784                            break label379;
1785                        }
1786                    }
1787                }
1788            }
1789            else
1790            {
1791                while (this.gameSettings.keyBindAttack.isPressed())
1792                {
1793                    this.clickMouse(0);
1794                }
1795
1796                while (this.gameSettings.keyBindUseItem.isPressed())
1797                {
1798                    this.clickMouse(1);
1799                }
1800
1801                while (this.gameSettings.keyBindPickBlock.isPressed())
1802                {
1803                    this.clickMiddleMouseButton();
1804                }
1805            }
1806
1807            if (this.gameSettings.keyBindUseItem.pressed && this.rightClickDelayTimer == 0 && !this.thePlayer.isUsingItem())
1808            {
1809                this.clickMouse(1);
1810            }
1811
1812            this.sendClickBlockToController(0, this.currentScreen == null && this.gameSettings.keyBindAttack.pressed && this.inGameHasFocus);
1813        }
1814
1815        if (this.theWorld != null)
1816        {
1817            if (this.thePlayer != null)
1818            {
1819                ++this.joinPlayerCounter;
1820
1821                if (this.joinPlayerCounter == 30)
1822                {
1823                    this.joinPlayerCounter = 0;
1824                    this.theWorld.joinEntityInSurroundings(this.thePlayer);
1825                }
1826            }
1827
1828            this.mcProfiler.endStartSection("gameRenderer");
1829
1830            if (!this.isGamePaused)
1831            {
1832                this.entityRenderer.updateRenderer();
1833            }
1834
1835            this.mcProfiler.endStartSection("levelRenderer");
1836
1837            if (!this.isGamePaused)
1838            {
1839                this.renderGlobal.updateClouds();
1840            }
1841
1842            this.mcProfiler.endStartSection("level");
1843
1844            if (!this.isGamePaused)
1845            {
1846                if (this.theWorld.lastLightningBolt > 0)
1847                {
1848                    --this.theWorld.lastLightningBolt;
1849                }
1850
1851                this.theWorld.updateEntities();
1852            }
1853
1854            if (!this.isGamePaused)
1855            {
1856                this.theWorld.setAllowedSpawnTypes(this.theWorld.difficultySetting > 0, true);
1857
1858                try
1859                {
1860                    this.theWorld.tick();
1861                }
1862                catch (Throwable throwable3)
1863                {
1864                    crashreport = CrashReport.makeCrashReport(throwable3, "Exception in world tick");
1865
1866                    if (this.theWorld == null)
1867                    {
1868                        crashreportcategory = crashreport.makeCategory("Affected level");
1869                        crashreportcategory.addCrashSection("Problem", "Level is null!");
1870                    }
1871                    else
1872                    {
1873                        this.theWorld.addWorldInfoToCrashReport(crashreport);
1874                    }
1875
1876                    throw new ReportedException(crashreport);
1877                }
1878            }
1879
1880            this.mcProfiler.endStartSection("animateTick");
1881
1882            if (!this.isGamePaused && this.theWorld != null)
1883            {
1884                this.theWorld.func_73029_E(MathHelper.floor_double(this.thePlayer.posX), MathHelper.floor_double(this.thePlayer.posY), MathHelper.floor_double(this.thePlayer.posZ));
1885            }
1886
1887            this.mcProfiler.endStartSection("particles");
1888
1889            if (!this.isGamePaused)
1890            {
1891                this.effectRenderer.updateEffects();
1892            }
1893        }
1894        else if (this.myNetworkManager != null)
1895        {
1896            this.mcProfiler.endStartSection("pendingConnection");
1897            this.myNetworkManager.processReadPackets();
1898        }
1899
1900        FMLCommonHandler.instance().onPostClientTick();
1901
1902        this.mcProfiler.endSection();
1903        this.systemTime = getSystemTime();
1904    }
1905
1906    /**
1907     * Forces a reload of the sound manager and all the resources. Called in game by holding 'F3' and pressing 'S'.
1908     */
1909    private void forceReload()
1910    {
1911        this.getLogAgent().logInfo("FORCING RELOAD!");
1912
1913        if (this.sndManager != null)
1914        {
1915            this.sndManager.stopAllSounds();
1916        }
1917
1918        this.sndManager = new SoundManager();
1919        this.sndManager.loadSoundSettings(this.gameSettings);
1920        this.downloadResourcesThread.reloadResources();
1921    }
1922
1923    /**
1924     * Arguments: World foldername,  World ingame name, WorldSettings
1925     */
1926    public void launchIntegratedServer(String par1Str, String par2Str, WorldSettings par3WorldSettings)
1927    {
1928        this.loadWorld((WorldClient)null);
1929        System.gc();
1930        ISaveHandler isavehandler = this.saveLoader.getSaveLoader(par1Str, false);
1931        WorldInfo worldinfo = isavehandler.loadWorldInfo();
1932
1933        if (worldinfo == null && par3WorldSettings != null)
1934        {
1935            this.statFileWriter.readStat(StatList.createWorldStat, 1);
1936            worldinfo = new WorldInfo(par3WorldSettings, par1Str);
1937            isavehandler.saveWorldInfo(worldinfo);
1938        }
1939
1940        if (par3WorldSettings == null)
1941        {
1942            par3WorldSettings = new WorldSettings(worldinfo);
1943        }
1944
1945        this.statFileWriter.readStat(StatList.startGameStat, 1);
1946
1947        GameData.initializeServerGate(2);
1948
1949        this.theIntegratedServer = new IntegratedServer(this, par1Str, par2Str, par3WorldSettings);
1950        this.theIntegratedServer.startServerThread();
1951
1952        MapDifference<Integer, ItemData> idDifferences = GameData.gateWorldLoadingForValidation();
1953        if (idDifferences!=null)
1954        {
1955            FMLClientHandler.instance().warnIDMismatch(idDifferences, true);
1956        }
1957        else
1958        {
1959            GameData.releaseGate(true);
1960            continueWorldLoading();
1961        }
1962
1963    }
1964
1965    public void continueWorldLoading()
1966    {
1967        this.integratedServerIsRunning = true;
1968        this.loadingScreen.displayProgressMessage(StatCollector.translateToLocal("menu.loadingLevel"));
1969
1970        while (!this.theIntegratedServer.serverIsInRunLoop())
1971        {
1972            String s2 = this.theIntegratedServer.getUserMessage();
1973
1974            if (s2 != null)
1975            {
1976                this.loadingScreen.resetProgresAndWorkingMessage(StatCollector.translateToLocal(s2));
1977            }
1978            else
1979            {
1980                this.loadingScreen.resetProgresAndWorkingMessage("");
1981            }
1982
1983            try
1984            {
1985                Thread.sleep(200L);
1986            }
1987            catch (InterruptedException interruptedexception)
1988            {
1989                ;
1990            }
1991        }
1992
1993        this.displayGuiScreen((GuiScreen)null);
1994
1995        try
1996        {
1997            NetClientHandler netclienthandler = new NetClientHandler(this, this.theIntegratedServer);
1998            this.myNetworkManager = netclienthandler.getNetManager();
1999        }
2000        catch (IOException ioexception)
2001        {
2002            this.displayCrashReport(this.addGraphicsAndWorldToCrashReport(new CrashReport("Connecting to integrated server", ioexception)));
2003        }
2004    }
2005
2006    /**
2007     * unloads the current world first
2008     */
2009    public void loadWorld(WorldClient par1WorldClient)
2010    {
2011        this.loadWorld(par1WorldClient, "");
2012    }
2013
2014    /**
2015     * par2Str is displayed on the loading screen to the user unloads the current world first
2016     */
2017    public void loadWorld(WorldClient par1WorldClient, String par2Str)
2018    {
2019        this.statFileWriter.syncStats();
2020
2021        if (theWorld != null)
2022        {
2023            MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(theWorld));
2024        }
2025
2026        if (par1WorldClient == null)
2027        {
2028            NetClientHandler netclienthandler = this.getNetHandler();
2029
2030            if (netclienthandler != null)
2031            {
2032                netclienthandler.cleanup();
2033            }
2034
2035            if (this.myNetworkManager != null)
2036            {
2037                this.myNetworkManager.closeConnections();
2038            }
2039
2040            if (this.theIntegratedServer != null)
2041            {
2042                this.theIntegratedServer.initiateShutdown();
2043                if (loadingScreen!=null)
2044                {
2045                    this.loadingScreen.resetProgresAndWorkingMessage("Shutting down internal server...");
2046                }
2047                while (!theIntegratedServer.isServerStopped())
2048                {
2049                    try
2050                    {
2051                        Thread.sleep(10);
2052                    }
2053                    catch (InterruptedException ie) {}
2054                }
2055            }
2056
2057            this.theIntegratedServer = null;
2058        }
2059
2060        this.renderViewEntity = null;
2061        this.myNetworkManager = null;
2062
2063        if (this.loadingScreen != null)
2064        {
2065            this.loadingScreen.resetProgressAndMessage(par2Str);
2066            this.loadingScreen.resetProgresAndWorkingMessage("");
2067        }
2068
2069        if (par1WorldClient == null && this.theWorld != null)
2070        {
2071            if (this.texturePackList.getIsDownloading())
2072            {
2073                this.texturePackList.onDownloadFinished();
2074            }
2075
2076            this.setServerData((ServerData)null);
2077            this.integratedServerIsRunning = false;
2078        }
2079
2080        this.sndManager.playStreaming((String)null, 0.0F, 0.0F, 0.0F);
2081        this.sndManager.stopAllSounds();
2082        this.theWorld = par1WorldClient;
2083
2084        if (par1WorldClient != null)
2085        {
2086            if (this.renderGlobal != null)
2087            {
2088                this.renderGlobal.setWorldAndLoadRenderers(par1WorldClient);
2089            }
2090
2091            if (this.effectRenderer != null)
2092            {
2093                this.effectRenderer.clearEffects(par1WorldClient);
2094            }
2095
2096            if (this.thePlayer == null)
2097            {
2098                this.thePlayer = this.playerController.func_78754_a(par1WorldClient);
2099                this.playerController.flipPlayer(this.thePlayer);
2100            }
2101
2102            this.thePlayer.preparePlayerToSpawn();
2103            par1WorldClient.spawnEntityInWorld(this.thePlayer);
2104            this.thePlayer.movementInput = new MovementInputFromOptions(this.gameSettings);
2105            this.playerController.setPlayerCapabilities(this.thePlayer);
2106            this.renderViewEntity = this.thePlayer;
2107        }
2108        else
2109        {
2110            this.saveLoader.flushCache();
2111            this.thePlayer = null;
2112        }
2113
2114        System.gc();
2115        this.systemTime = 0L;
2116    }
2117
2118    /**
2119     * Installs a resource. Currently only sounds are download so this method just adds them to the SoundManager.
2120     */
2121    public void installResource(String par1Str, File par2File)
2122    {
2123        int i = par1Str.indexOf("/");
2124        String s1 = par1Str.substring(0, i);
2125        par1Str = par1Str.substring(i + 1);
2126
2127        if (s1.equalsIgnoreCase("sound3"))
2128        {
2129            this.sndManager.addSound(par1Str, par2File);
2130        }
2131        else if (s1.equalsIgnoreCase("streaming"))
2132        {
2133            this.sndManager.addStreaming(par1Str, par2File);
2134        }
2135        else if (!s1.equalsIgnoreCase("music") && !s1.equalsIgnoreCase("newmusic"))
2136        {
2137            if (s1.equalsIgnoreCase("lang"))
2138            {
2139                StringTranslate.getInstance().func_94519_a(par1Str, par2File);
2140            }
2141        }
2142        else
2143        {
2144            this.sndManager.addMusic(par1Str, par2File);
2145        }
2146    }
2147
2148    /**
2149     * A String of renderGlobal.getDebugInfoRenders
2150     */
2151    public String debugInfoRenders()
2152    {
2153        return this.renderGlobal.getDebugInfoRenders();
2154    }
2155
2156    /**
2157     * Gets the information in the F3 menu about how many entities are infront/around you
2158     */
2159    public String getEntityDebug()
2160    {
2161        return this.renderGlobal.getDebugInfoEntities();
2162    }
2163
2164    /**
2165     * Gets the name of the world's current chunk provider
2166     */
2167    public String getWorldProviderName()
2168    {
2169        return this.theWorld.getProviderName();
2170    }
2171
2172    /**
2173     * A String of how many entities are in the world
2174     */
2175    public String debugInfoEntities()
2176    {
2177        return "P: " + this.effectRenderer.getStatistics() + ". T: " + this.theWorld.getDebugLoadedEntities();
2178    }
2179
2180    public void setDimensionAndSpawnPlayer(int par1)
2181    {
2182        this.theWorld.setSpawnLocation();
2183        this.theWorld.removeAllEntities();
2184        int j = 0;
2185
2186        if (this.thePlayer != null)
2187        {
2188            j = this.thePlayer.entityId;
2189            this.theWorld.removeEntity(this.thePlayer);
2190        }
2191
2192        this.renderViewEntity = null;
2193        this.thePlayer = this.playerController.func_78754_a(this.theWorld);
2194        this.thePlayer.dimension = par1;
2195        this.renderViewEntity = this.thePlayer;
2196        this.thePlayer.preparePlayerToSpawn();
2197        this.theWorld.spawnEntityInWorld(this.thePlayer);
2198        this.playerController.flipPlayer(this.thePlayer);
2199        this.thePlayer.movementInput = new MovementInputFromOptions(this.gameSettings);
2200        this.thePlayer.entityId = j;
2201        this.playerController.setPlayerCapabilities(this.thePlayer);
2202
2203        if (this.currentScreen instanceof GuiGameOver)
2204        {
2205            this.displayGuiScreen((GuiScreen)null);
2206        }
2207    }
2208
2209    /**
2210     * Sets whether this is a demo or not.
2211     */
2212    void setDemo(boolean par1)
2213    {
2214        this.isDemo = par1;
2215    }
2216
2217    /**
2218     * Gets whether this is a demo or not.
2219     */
2220    public final boolean isDemo()
2221    {
2222        return this.isDemo;
2223    }
2224
2225    /**
2226     * Returns the NetClientHandler.
2227     */
2228    public NetClientHandler getNetHandler()
2229    {
2230        return this.thePlayer != null ? this.thePlayer.sendQueue : null;
2231    }
2232
2233    public static void main(String[] par0ArrayOfStr)
2234    {
2235        FMLRelauncher.handleClientRelaunch(new ArgsWrapper(par0ArrayOfStr));
2236    }
2237
2238    public static void fmlReentry(ArgsWrapper wrapper)
2239    {
2240        String[] par0ArrayOfStr = wrapper.args;
2241        HashMap hashmap = new HashMap();
2242        boolean flag = false;
2243        boolean flag1 = true;
2244        boolean flag2 = false;
2245        String s = "Player" + getSystemTime() % 1000L;
2246        String s1 = s;
2247
2248        if (par0ArrayOfStr.length > 0)
2249        {
2250            s1 = par0ArrayOfStr[0];
2251        }
2252
2253        String s2 = "-";
2254
2255        if (par0ArrayOfStr.length > 1)
2256        {
2257            s2 = par0ArrayOfStr[1];
2258        }
2259
2260        ArrayList arraylist = new ArrayList();
2261
2262        for (int i = 2; i < par0ArrayOfStr.length; ++i)
2263        {
2264            String s3 = par0ArrayOfStr[i];
2265            String s4 = i == par0ArrayOfStr.length - 1 ? null : par0ArrayOfStr[i + 1];
2266            boolean flag3 = false;
2267
2268            if (!s3.equals("-demo") && !s3.equals("--demo"))
2269            {
2270                if (s3.equals("--applet"))
2271                {
2272                    flag1 = false;
2273                }
2274                else if (s3.equals("--password") && s4 != null)
2275                {
2276                    String[] astring1 = HttpUtil.loginToMinecraft((ILogAgent)null, s1, s4);
2277
2278                    if (astring1 != null)
2279                    {
2280                        s1 = astring1[0];
2281                        s2 = astring1[1];
2282                        arraylist.add("Logged in insecurely as " + s1);
2283                    }
2284                    else
2285                    {
2286                        arraylist.add("Could not log in as " + s1 + " with given password");
2287                    }
2288
2289                    flag3 = true;
2290                }
2291            }
2292            else
2293            {
2294                flag = true;
2295            }
2296
2297            if (flag3)
2298            {
2299                ++i;
2300            }
2301        }
2302
2303        if (s1.contains("@") && s2.length() <= 1)
2304        {
2305            s1 = s;
2306        }
2307
2308        hashmap.put("demo", "" + flag);
2309        hashmap.put("stand-alone", "" + flag1);
2310        hashmap.put("username", s1);
2311        hashmap.put("fullscreen", "" + flag2);
2312        hashmap.put("sessionid", s2);
2313        Frame frame = new Frame();
2314        frame.setTitle("Minecraft");
2315        frame.setBackground(Color.BLACK);
2316        JPanel jpanel = new JPanel();
2317        frame.setLayout(new BorderLayout());
2318        jpanel.setPreferredSize(new Dimension(854, 480));
2319        frame.add(jpanel, "Center");
2320        frame.pack();
2321        frame.setLocationRelativeTo((Component)null);
2322        frame.setVisible(true);
2323        frame.addWindowListener(new GameWindowListener());
2324        MinecraftFakeLauncher minecraftfakelauncher = new MinecraftFakeLauncher(hashmap);
2325        MinecraftApplet minecraftapplet = new MinecraftApplet();
2326        minecraftapplet.setStub(minecraftfakelauncher);
2327        minecraftfakelauncher.setLayout(new BorderLayout());
2328        minecraftfakelauncher.add(minecraftapplet, "Center");
2329        minecraftfakelauncher.validate();
2330        frame.removeAll();
2331        frame.setLayout(new BorderLayout());
2332        frame.add(minecraftfakelauncher, "Center");
2333        frame.validate();
2334        minecraftapplet.init();
2335        Iterator iterator = arraylist.iterator();
2336
2337        while (iterator.hasNext())
2338        {
2339            String s5 = (String)iterator.next();
2340            getMinecraft().getLogAgent().logInfo(s5);
2341        }
2342
2343        minecraftapplet.start();
2344        Runtime.getRuntime().addShutdownHook(new ThreadShutdown());
2345    }
2346
2347    public static boolean isGuiEnabled()
2348    {
2349        return theMinecraft == null || !theMinecraft.gameSettings.hideGUI;
2350    }
2351
2352    public static boolean isFancyGraphicsEnabled()
2353    {
2354        return theMinecraft != null && theMinecraft.gameSettings.fancyGraphics;
2355    }
2356
2357    /**
2358     * Returns if ambient occlusion is enabled
2359     */
2360    public static boolean isAmbientOcclusionEnabled()
2361    {
2362        return theMinecraft != null && theMinecraft.gameSettings.ambientOcclusion != 0;
2363    }
2364
2365    /**
2366     * Returns true if the message is a client command and should not be sent to the server. However there are no such
2367     * commands at this point in time.
2368     */
2369    public boolean handleClientCommand(String par1Str)
2370    {
2371        return !par1Str.startsWith("/") ? false : false;
2372    }
2373
2374    /**
2375     * Called when the middle mouse button gets clicked
2376     */
2377    private void clickMiddleMouseButton()
2378    {
2379        if (this.objectMouseOver != null)
2380        {
2381            boolean flag = this.thePlayer.capabilities.isCreativeMode;
2382            int k;
2383
2384            if (!ForgeHooks.onPickBlock(this.objectMouseOver, this.thePlayer, this.theWorld))
2385            {
2386                return;
2387            }
2388
2389            if (flag)
2390            {
2391                k = this.thePlayer.inventoryContainer.inventorySlots.size() - 9 + this.thePlayer.inventory.currentItem;
2392                this.playerController.sendSlotPacket(this.thePlayer.inventory.getStackInSlot(this.thePlayer.inventory.currentItem), k);
2393            }
2394        }
2395    }
2396
2397    /**
2398     * adds core server Info (GL version , Texture pack, isModded, type), and the worldInfo to the crash report
2399     */
2400    public CrashReport addGraphicsAndWorldToCrashReport(CrashReport par1CrashReport)
2401    {
2402        par1CrashReport.func_85056_g().addCrashSectionCallable("LWJGL", new CallableLWJGLVersion(this));
2403        par1CrashReport.func_85056_g().addCrashSectionCallable("OpenGL", new CallableGLInfo(this));
2404        par1CrashReport.func_85056_g().addCrashSectionCallable("Is Modded", new CallableModded(this));
2405        par1CrashReport.func_85056_g().addCrashSectionCallable("Type", new CallableType2(this));
2406        par1CrashReport.func_85056_g().addCrashSectionCallable("Texture Pack", new CallableTexturePack(this));
2407        par1CrashReport.func_85056_g().addCrashSectionCallable("Profiler Position", new CallableClientProfiler(this));
2408        par1CrashReport.func_85056_g().addCrashSectionCallable("Vec3 Pool Size", new CallableClientMemoryStats(this));
2409
2410        if (this.theWorld != null)
2411        {
2412            this.theWorld.addWorldInfoToCrashReport(par1CrashReport);
2413        }
2414
2415        return par1CrashReport;
2416    }
2417
2418    /**
2419     * Return the singleton Minecraft instance for the game
2420     */
2421    public static Minecraft getMinecraft()
2422    {
2423        return theMinecraft;
2424    }
2425
2426    /**
2427     * Sets refreshTexturePacksScheduled to true, triggering a texture pack refresh next time the while(running) loop is
2428     * run
2429     */
2430    public void scheduleTexturePackRefresh()
2431    {
2432        this.refreshTexturePacksScheduled = true;
2433    }
2434
2435    public void addServerStatsToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper)
2436    {
2437        par1PlayerUsageSnooper.addData("fps", Integer.valueOf(debugFPS));
2438        par1PlayerUsageSnooper.addData("texpack_name", this.texturePackList.getSelectedTexturePack().getTexturePackFileName());
2439        par1PlayerUsageSnooper.addData("vsync_enabled", Boolean.valueOf(this.gameSettings.enableVsync));
2440        par1PlayerUsageSnooper.addData("display_frequency", Integer.valueOf(Display.getDisplayMode().getFrequency()));
2441        par1PlayerUsageSnooper.addData("display_type", this.fullscreen ? "fullscreen" : "windowed");
2442
2443        if (this.theIntegratedServer != null && this.theIntegratedServer.getPlayerUsageSnooper() != null)
2444        {
2445            par1PlayerUsageSnooper.addData("snooper_partner", this.theIntegratedServer.getPlayerUsageSnooper().getUniqueID());
2446        }
2447    }
2448
2449    public void addServerTypeToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper)
2450    {
2451        par1PlayerUsageSnooper.addData("opengl_version", GL11.glGetString(GL11.GL_VERSION));
2452        par1PlayerUsageSnooper.addData("opengl_vendor", GL11.glGetString(GL11.GL_VENDOR));
2453        par1PlayerUsageSnooper.addData("client_brand", ClientBrandRetriever.getClientModName());
2454        par1PlayerUsageSnooper.addData("applet", Boolean.valueOf(this.hideQuitButton));
2455        ContextCapabilities contextcapabilities = GLContext.getCapabilities();
2456        par1PlayerUsageSnooper.addData("gl_caps[ARB_multitexture]", Boolean.valueOf(contextcapabilities.GL_ARB_multitexture));
2457        par1PlayerUsageSnooper.addData("gl_caps[ARB_multisample]", Boolean.valueOf(contextcapabilities.GL_ARB_multisample));
2458        par1PlayerUsageSnooper.addData("gl_caps[ARB_texture_cube_map]", Boolean.valueOf(contextcapabilities.GL_ARB_texture_cube_map));
2459        par1PlayerUsageSnooper.addData("gl_caps[ARB_vertex_blend]", Boolean.valueOf(contextcapabilities.GL_ARB_vertex_blend));
2460        par1PlayerUsageSnooper.addData("gl_caps[ARB_matrix_palette]", Boolean.valueOf(contextcapabilities.GL_ARB_matrix_palette));
2461        par1PlayerUsageSnooper.addData("gl_caps[ARB_vertex_program]", Boolean.valueOf(contextcapabilities.GL_ARB_vertex_program));
2462        par1PlayerUsageSnooper.addData("gl_caps[ARB_vertex_shader]", Boolean.valueOf(contextcapabilities.GL_ARB_vertex_shader));
2463        par1PlayerUsageSnooper.addData("gl_caps[ARB_fragment_program]", Boolean.valueOf(contextcapabilities.GL_ARB_fragment_program));
2464        par1PlayerUsageSnooper.addData("gl_caps[ARB_fragment_shader]", Boolean.valueOf(contextcapabilities.GL_ARB_fragment_shader));
2465        par1PlayerUsageSnooper.addData("gl_caps[ARB_shader_objects]", Boolean.valueOf(contextcapabilities.GL_ARB_shader_objects));
2466        par1PlayerUsageSnooper.addData("gl_caps[ARB_vertex_buffer_object]", Boolean.valueOf(contextcapabilities.GL_ARB_vertex_buffer_object));
2467        par1PlayerUsageSnooper.addData("gl_caps[ARB_framebuffer_object]", Boolean.valueOf(contextcapabilities.GL_ARB_framebuffer_object));
2468        par1PlayerUsageSnooper.addData("gl_caps[ARB_pixel_buffer_object]", Boolean.valueOf(contextcapabilities.GL_ARB_pixel_buffer_object));
2469        par1PlayerUsageSnooper.addData("gl_caps[ARB_uniform_buffer_object]", Boolean.valueOf(contextcapabilities.GL_ARB_uniform_buffer_object));
2470        par1PlayerUsageSnooper.addData("gl_caps[ARB_texture_non_power_of_two]", Boolean.valueOf(contextcapabilities.GL_ARB_texture_non_power_of_two));
2471        par1PlayerUsageSnooper.addData("gl_caps[gl_max_vertex_uniforms]", Integer.valueOf(GL11.glGetInteger(GL20.GL_MAX_VERTEX_UNIFORM_COMPONENTS)));
2472        par1PlayerUsageSnooper.addData("gl_caps[gl_max_fragment_uniforms]", Integer.valueOf(GL11.glGetInteger(GL20.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS)));
2473        par1PlayerUsageSnooper.addData("gl_max_texture_size", Integer.valueOf(getGLMaximumTextureSize()));
2474    }
2475
2476    //Forge: Adds a optimization to the getGLMaximumTextureSize, only calculate it once.
2477    private static int max_texture_size = -1;
2478    /**
2479     * Used in the usage snooper.
2480     */
2481    public static int getGLMaximumTextureSize()
2482    {
2483        if (max_texture_size != -1)
2484        {
2485            return max_texture_size;
2486        }
2487
2488        for (int i = 16384; i > 0; i >>= 1)
2489        {
2490            GL11.glTexImage2D(GL11.GL_PROXY_TEXTURE_2D, 0, GL11.GL_RGBA, i, i, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer)null);
2491            int j = GL11.glGetTexLevelParameteri(GL11.GL_PROXY_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH);
2492
2493            if (j != 0)
2494            {
2495                max_texture_size = i;
2496                return i;
2497            }
2498        }
2499
2500        return -1;
2501    }
2502
2503    /**
2504     * Returns whether snooping is enabled or not.
2505     */
2506    public boolean isSnooperEnabled()
2507    {
2508        return this.gameSettings.snooperEnabled;
2509    }
2510
2511    /**
2512     * Set the current ServerData instance.
2513     */
2514    public void setServerData(ServerData par1ServerData)
2515    {
2516        this.currentServerData = par1ServerData;
2517    }
2518
2519    /**
2520     * Get the current ServerData instance.
2521     */
2522    public ServerData getServerData()
2523    {
2524        return this.currentServerData;
2525    }
2526
2527    public boolean isIntegratedServerRunning()
2528    {
2529        return this.integratedServerIsRunning;
2530    }
2531
2532    /**
2533     * Returns true if there is only one player playing, and the current server is the integrated one.
2534     */
2535    public boolean isSingleplayer()
2536    {
2537        return this.integratedServerIsRunning && this.theIntegratedServer != null;
2538    }
2539
2540    /**
2541     * Returns the currently running integrated server
2542     */
2543    public IntegratedServer getIntegratedServer()
2544    {
2545        return this.theIntegratedServer;
2546    }
2547
2548    public static void stopIntegratedServer()
2549    {
2550        if (theMinecraft != null)
2551        {
2552            IntegratedServer integratedserver = theMinecraft.getIntegratedServer();
2553
2554            if (integratedserver != null)
2555            {
2556                integratedserver.stopServer();
2557            }
2558        }
2559    }
2560
2561    /**
2562     * Returns the PlayerUsageSnooper instance.
2563     */
2564    public PlayerUsageSnooper getPlayerUsageSnooper()
2565    {
2566        return this.usageSnooper;
2567    }
2568
2569    /**
2570     * Gets the system time in milliseconds.
2571     */
2572    public static long getSystemTime()
2573    {
2574        return Sys.getTime() * 1000L / Sys.getTimerResolution();
2575    }
2576
2577    /**
2578     * Returns whether we're in full screen or not.
2579     */
2580    public boolean isFullScreen()
2581    {
2582        return this.fullscreen;
2583    }
2584
2585    public ILogAgent getLogAgent()
2586    {
2587        return this.field_94139_O;
2588    }
2589}