    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}