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