001    package net.minecraft.src;
002    
003    import java.io.File;
004    import java.io.FileWriter;
005    import java.text.SimpleDateFormat;
006    import java.util.Date;
007    import java.util.List;
008    import java.util.logging.Level;
009    import java.util.logging.Logger;
010    import net.minecraft.server.MinecraftServer;
011    
012    public class CommandDebug extends CommandBase
013    {
014        private long field_71551_a = 0L;
015        private int field_71550_b = 0;
016    
017        public String getCommandName()
018        {
019            return "debug";
020        }
021    
022        public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr)
023        {
024            if (par2ArrayOfStr.length == 1)
025            {
026                if (par2ArrayOfStr[0].equals("start"))
027                {
028                    notifyAdmins(par1ICommandSender, "commands.debug.start", new Object[0]);
029                    MinecraftServer.getServer().enableProfiling();
030                    this.field_71551_a = System.currentTimeMillis();
031                    this.field_71550_b = MinecraftServer.getServer().getTickCounter();
032                    return;
033                }
034    
035                if (par2ArrayOfStr[0].equals("stop"))
036                {
037                    if (!MinecraftServer.getServer().theProfiler.profilingEnabled)
038                    {
039                        throw new CommandException("commands.debug.notStarted", new Object[0]);
040                    }
041    
042                    long var3 = System.currentTimeMillis();
043                    int var5 = MinecraftServer.getServer().getTickCounter();
044                    long var6 = var3 - this.field_71551_a;
045                    int var8 = var5 - this.field_71550_b;
046                    this.func_71548_a(var6, var8);
047                    MinecraftServer.getServer().theProfiler.profilingEnabled = false;
048                    notifyAdmins(par1ICommandSender, "commands.debug.stop", new Object[] {Float.valueOf((float)var6 / 1000.0F), Integer.valueOf(var8)});
049                    return;
050                }
051            }
052    
053            throw new WrongUsageException("commands.debug.usage", new Object[0]);
054        }
055    
056        private void func_71548_a(long par1, int par3)
057        {
058            File var4 = new File(MinecraftServer.getServer().getFile("debug"), "profile-results-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + ".txt");
059            var4.getParentFile().mkdirs();
060    
061            try
062            {
063                FileWriter var5 = new FileWriter(var4);
064                var5.write(this.func_71547_b(par1, par3));
065                var5.close();
066            }
067            catch (Throwable var6)
068            {
069                Logger.getLogger("Minecraft").log(Level.SEVERE, "Could not save profiler results to " + var4, var6);
070            }
071        }
072    
073        private String func_71547_b(long par1, int par3)
074        {
075            StringBuilder var4 = new StringBuilder();
076            var4.append("---- Minecraft Profiler Results ----\n");
077            var4.append("// ");
078            var4.append(getWittyComment());
079            var4.append("\n\n");
080            var4.append("Time span: ").append(par1).append(" ms\n");
081            var4.append("Tick span: ").append(par3).append(" ticks\n");
082            var4.append("// This is approximately ").append(String.format("%.2f", new Object[] {Float.valueOf((float)par3 / ((float)par1 / 1000.0F))})).append(" ticks per second. It should be ").append(20).append(" ticks per second\n\n");
083            var4.append("--- BEGIN PROFILE DUMP ---\n\n");
084            this.func_71546_a(0, "root", var4);
085            var4.append("--- END PROFILE DUMP ---\n\n");
086            return var4.toString();
087        }
088    
089        private void func_71546_a(int par1, String par2Str, StringBuilder par3StringBuilder)
090        {
091            List var4 = MinecraftServer.getServer().theProfiler.getProfilingData(par2Str);
092    
093            if (var4 != null && var4.size() >= 3)
094            {
095                for (int var5 = 1; var5 < var4.size(); ++var5)
096                {
097                    ProfilerResult var6 = (ProfilerResult)var4.get(var5);
098                    par3StringBuilder.append(String.format("[%02d] ", new Object[] {Integer.valueOf(par1)}));
099    
100                    for (int var7 = 0; var7 < par1; ++var7)
101                    {
102                        par3StringBuilder.append(" ");
103                    }
104    
105                    par3StringBuilder.append(var6.field_76331_c);
106                    par3StringBuilder.append(" - ");
107                    par3StringBuilder.append(String.format("%.2f", new Object[] {Double.valueOf(var6.field_76332_a)}));
108                    par3StringBuilder.append("%/");
109                    par3StringBuilder.append(String.format("%.2f", new Object[] {Double.valueOf(var6.field_76330_b)}));
110                    par3StringBuilder.append("%\n");
111    
112                    if (!var6.field_76331_c.equals("unspecified"))
113                    {
114                        try
115                        {
116                            this.func_71546_a(par1 + 1, par2Str + "." + var6.field_76331_c, par3StringBuilder);
117                        }
118                        catch (Exception var8)
119                        {
120                            par3StringBuilder.append("[[ EXCEPTION " + var8 + " ]]");
121                        }
122                    }
123                }
124            }
125        }
126    
127        /**
128         * Returns a random "witty" comment.
129         */
130        private static String getWittyComment()
131        {
132            String[] var0 = new String[] {"Shiny numbers!", "Am I not running fast enough? :(", "I\'m working as hard as I can!", "Will I ever be good enough for you? :(", "Speedy. Zoooooom!", "Hello world", "40% better than a crash report.", "Now with extra numbers", "Now with less numbers", "Now with the same numbers", "You should add flames to things, it makes them go faster!", "Do you feel the need for... optimization?", "*cracks redstone whip*", "Maybe if you treated it better then it\'ll have more motivation to work faster! Poor server."};
133    
134            try
135            {
136                return var0[(int)(System.nanoTime() % (long)var0.length)];
137            }
138            catch (Throwable var2)
139            {
140                return "Witty comment unavailable :(";
141            }
142        }
143    
144        /**
145         * Adds the strings available in this command to the given list of tab completion options.
146         */
147        public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr)
148        {
149            return par2ArrayOfStr.length == 1 ? getListOfStringsMatchingLastWord(par2ArrayOfStr, new String[] {"start", "stop"}): null;
150        }
151    }