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