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 }