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 }