    001    package net.minecraft.command;
    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.profiler.ProfilerResult;
    011    import net.minecraft.server.MinecraftServer;
    012
    013    public 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    }