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        /** Time the debugging started in milliseconds. */
015        private long startTime = 0L;
016    
017        /** The number of ticks when debugging started. */
018        private int startTicks = 0;
019    
020        public String getCommandName()
021        {
022            return "debug";
023        }
024    
025        public int func_82362_a()
026        {
027            return 3;
028        }
029    
030        public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr)
031        {
032            if (par2ArrayOfStr.length == 1)
033            {
034                if (par2ArrayOfStr[0].equals("start"))
035                {
036                    notifyAdmins(par1ICommandSender, "commands.debug.start", new Object[0]);
037                    MinecraftServer.getServer().enableProfiling();
038                    this.startTime = System.currentTimeMillis();
039                    this.startTicks = MinecraftServer.getServer().getTickCounter();
040                    return;
041                }
042    
043                if (par2ArrayOfStr[0].equals("stop"))
044                {
045                    if (!MinecraftServer.getServer().theProfiler.profilingEnabled)
046                    {
047                        throw new CommandException("commands.debug.notStarted", new Object[0]);
048                    }
049    
050                    long var3 = System.currentTimeMillis();
051                    int var5 = MinecraftServer.getServer().getTickCounter();
052                    long var6 = var3 - this.startTime;
053                    int var8 = var5 - this.startTicks;
054                    this.saveProfilerResults(var6, var8);
055                    MinecraftServer.getServer().theProfiler.profilingEnabled = false;
056                    notifyAdmins(par1ICommandSender, "commands.debug.stop", new Object[] {Float.valueOf((float)var6 / 1000.0F), Integer.valueOf(var8)});
057                    return;
058                }
059            }
060    
061            throw new WrongUsageException("commands.debug.usage", new Object[0]);
062        }
063    
064        private void saveProfilerResults(long par1, int par3)
065        {
066            File var4 = new File(MinecraftServer.getServer().getFile("debug"), "profile-results-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + ".txt");
067            var4.getParentFile().mkdirs();
068    
069            try
070            {
071                FileWriter var5 = new FileWriter(var4);
072                var5.write(this.getProfilerResults(par1, par3));
073                var5.close();
074            }
075            catch (Throwable var6)
076            {
077                Logger.getLogger("Minecraft").log(Level.SEVERE, "Could not save profiler results to " + var4, var6);
078            }
079        }
080    
081        private String getProfilerResults(long par1, int par3)
082        {
083            StringBuilder var4 = new StringBuilder();
084            var4.append("---- Minecraft Profiler Results ----\n");
085            var4.append("// ");
086            var4.append(getWittyComment());
087            var4.append("\n\n");
088            var4.append("Time span: ").append(par1).append(" ms\n");
089            var4.append("Tick span: ").append(par3).append(" ticks\n");
090            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");
091            var4.append("--- BEGIN PROFILE DUMP ---\n\n");
092            this.getProfileDump(0, "root", var4);
093            var4.append("--- END PROFILE DUMP ---\n\n");
094            return var4.toString();
095        }
096    
097        private void getProfileDump(int par1, String par2Str, StringBuilder par3StringBuilder)
098        {
099            List var4 = MinecraftServer.getServer().theProfiler.getProfilingData(par2Str);
100    
101            if (var4 != null && var4.size() >= 3)
102            {
103                for (int var5 = 1; var5 < var4.size(); ++var5)
104                {
105                    ProfilerResult var6 = (ProfilerResult)var4.get(var5);
106                    par3StringBuilder.append(String.format("[%02d] ", new Object[] {Integer.valueOf(par1)}));
107    
108                    for (int var7 = 0; var7 < par1; ++var7)
109                    {
110                        par3StringBuilder.append(" ");
111                    }
112    
113                    par3StringBuilder.append(var6.field_76331_c);
114                    par3StringBuilder.append(" - ");
115                    par3StringBuilder.append(String.format("%.2f", new Object[] {Double.valueOf(var6.field_76332_a)}));
116                    par3StringBuilder.append("%/");
117                    par3StringBuilder.append(String.format("%.2f", new Object[] {Double.valueOf(var6.field_76330_b)}));
118                    par3StringBuilder.append("%\n");
119    
120                    if (!var6.field_76331_c.equals("unspecified"))
121                    {
122                        try
123                        {
124                            this.getProfileDump(par1 + 1, par2Str + "." + var6.field_76331_c, par3StringBuilder);
125                        }
126                        catch (Exception var8)
127                        {
128                            par3StringBuilder.append("[[ EXCEPTION " + var8 + " ]]");
129                        }
130                    }
131                }
132            }
133        }
134    
135        /**
136         * Returns a random "witty" comment.
137         */
138        private static String getWittyComment()
139        {
140            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."};
141    
142            try
143            {
144                return var0[(int)(System.nanoTime() % (long)var0.length)];
145            }
146            catch (Throwable var2)
147            {
148                return "Witty comment unavailable :(";
149            }
150        }
151    
152        /**
153         * Adds the strings available in this command to the given list of tab completion options.
154         */
155        public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr)
156        {
157            return par2ArrayOfStr.length == 1 ? getListOfStringsMatchingLastWord(par2ArrayOfStr, new String[] {"start", "stop"}): null;
158        }
159    }