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