DebugCommand.java
net.minecraft.server.commands.DebugCommand
信息
- 全限定名:net.minecraft.server.commands.DebugCommand
- 类型:public class
- 包:net.minecraft.server.commands
- 源码路径:src/main/java/net/minecraft/server/commands/DebugCommand.java
- 起始行号:L44
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L45 - 说明:
TODO
- 类型:
-
ERROR_NOT_RUNNING- 类型:
SimpleCommandExceptionType - 修饰符:
private static final - 源码定位:
L46 - 说明:
TODO
- 类型:
-
ERROR_ALREADY_RUNNING- 类型:
SimpleCommandExceptionType - 修饰符:
private static final - 源码定位:
L47 - 说明:
TODO
- 类型:
-
NO_RECURSIVE_TRACES- 类型:
SimpleCommandExceptionType - 修饰符:
private static final - 源码定位:
L50 - 说明:
TODO
- 类型:
-
NO_RETURN_RUN- 类型:
SimpleCommandExceptionType - 修饰符:
private static final - 源码定位:
L53 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.server.commands.DebugCommand.TraceCustomExecutor- 类型:
class - 修饰符:
private static - 源码定位:
L104 - 说明:
TODO
- 类型:
-
net.minecraft.server.commands.DebugCommand.Tracer- 类型:
class - 修饰符:
private static - 源码定位:
L177 - 说明:
TODO
- 类型:
构造器
- 无
方法
下面的方法块按源码顺序生成。
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) @ L57
- 方法名:register
- 源码定位:L57
- 返回类型:void
- 修饰符:public static
参数:
- dispatcher: CommandDispatcher
说明:
TODO
private static int start(CommandSourceStack source) @ L75
- 方法名:start
- 源码定位:L75
- 返回类型:int
- 修饰符:private static
参数:
- source: CommandSourceStack
说明:
TODO
private static int stop(CommandSourceStack source) @ L86
- 方法名:stop
- 源码定位:L86
- 返回类型:int
- 修饰符:private static
参数:
- source: CommandSourceStack
说明:
TODO
代码
public class DebugCommand {
private static final Logger LOGGER = LogUtils.getLogger();
private static final SimpleCommandExceptionType ERROR_NOT_RUNNING = new SimpleCommandExceptionType(Component.translatable("commands.debug.notRunning"));
private static final SimpleCommandExceptionType ERROR_ALREADY_RUNNING = new SimpleCommandExceptionType(
Component.translatable("commands.debug.alreadyRunning")
);
private static final SimpleCommandExceptionType NO_RECURSIVE_TRACES = new SimpleCommandExceptionType(
Component.translatable("commands.debug.function.noRecursion")
);
private static final SimpleCommandExceptionType NO_RETURN_RUN = new SimpleCommandExceptionType(
Component.translatable("commands.debug.function.noReturnRun")
);
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(
Commands.literal("debug")
.requires(Commands.hasPermission(Commands.LEVEL_ADMINS))
.then(Commands.literal("start").executes(c -> start(c.getSource())))
.then(Commands.literal("stop").executes(c -> stop(c.getSource())))
.then(
Commands.literal("function")
.requires(Commands.hasPermission(Commands.LEVEL_ADMINS))
.then(
Commands.argument("name", FunctionArgument.functions())
.suggests(FunctionCommand.SUGGEST_FUNCTION)
.executes(new DebugCommand.TraceCustomExecutor())
)
)
);
}
private static int start(CommandSourceStack source) throws CommandSyntaxException {
MinecraftServer server = source.getServer();
if (server.isTimeProfilerRunning()) {
throw ERROR_ALREADY_RUNNING.create();
} else {
server.startTimeProfiler();
source.sendSuccess(() -> Component.translatable("commands.debug.started"), true);
return 0;
}
}
private static int stop(CommandSourceStack source) throws CommandSyntaxException {
MinecraftServer server = source.getServer();
if (!server.isTimeProfilerRunning()) {
throw ERROR_NOT_RUNNING.create();
} else {
ProfileResults results = server.stopTimeProfiler();
double seconds = (double)results.getNanoDuration() / TimeUtil.NANOSECONDS_PER_SECOND;
double tps = results.getTickDuration() / seconds;
source.sendSuccess(
() -> Component.translatable(
"commands.debug.stopped", String.format(Locale.ROOT, "%.2f", seconds), results.getTickDuration(), String.format(Locale.ROOT, "%.2f", tps)
),
true
);
return (int)tps;
}
}
private static class TraceCustomExecutor
extends CustomCommandExecutor.WithErrorHandling<CommandSourceStack>
implements CustomCommandExecutor.CommandAdapter<CommandSourceStack> {
public void runGuarded(
CommandSourceStack source, ContextChain<CommandSourceStack> currentStep, ChainModifiers modifiers, ExecutionControl<CommandSourceStack> context
) throws CommandSyntaxException {
if (modifiers.isReturn()) {
throw DebugCommand.NO_RETURN_RUN.create();
} else if (context.tracer() != null) {
throw DebugCommand.NO_RECURSIVE_TRACES.create();
} else {
CommandContext<CommandSourceStack> currentContext = currentStep.getTopContext();
Collection<CommandFunction<CommandSourceStack>> functions = FunctionArgument.getFunctions(currentContext, "name");
MinecraftServer server = source.getServer();
String outputName = "debug-trace-" + Util.getFilenameFormattedDateTime() + ".txt";
CommandDispatcher<CommandSourceStack> dispatcher = source.getServer().getFunctions().getDispatcher();
int commandCount = 0;
try {
Path dirPath = server.getFile("debug");
Files.createDirectories(dirPath);
final PrintWriter output = new PrintWriter(Files.newBufferedWriter(dirPath.resolve(outputName), StandardCharsets.UTF_8));
DebugCommand.Tracer tracer = new DebugCommand.Tracer(output);
context.tracer(tracer);
for (final CommandFunction<CommandSourceStack> function : functions) {
try {
CommandSourceStack functionSource = source.withSource(tracer).withMaximumPermission(LevelBasedPermissionSet.GAMEMASTER);
InstantiatedFunction<CommandSourceStack> instantiatedFunction = function.instantiate(null, dispatcher);
context.queueNext((new CallFunction<CommandSourceStack>(instantiatedFunction, CommandResultCallback.EMPTY, false) {
{
Objects.requireNonNull(TraceCustomExecutor.this);
}
public void execute(CommandSourceStack sender, ExecutionContext<CommandSourceStack> contextx, Frame frame) {
output.println(function.id());
super.execute(sender, contextx, frame);
}
}).bind(functionSource));
commandCount += instantiatedFunction.entries().size();
} catch (FunctionInstantiationException var18) {
source.sendFailure(var18.messageComponent());
}
}
} catch (IOException | UncheckedIOException var19) {
DebugCommand.LOGGER.warn("Tracing failed", (Throwable)var19);
source.sendFailure(Component.translatable("commands.debug.function.traceFailed"));
}
int finalCommandCount = commandCount;
context.queueNext(
(c, frame) -> {
if (functions.size() == 1) {
source.sendSuccess(
() -> Component.translatable(
"commands.debug.function.success.single",
finalCommandCount,
Component.translationArg(functions.iterator().next().id()),
outputName
),
true
);
} else {
source.sendSuccess(
() -> Component.translatable("commands.debug.function.success.multiple", finalCommandCount, functions.size(), outputName), true
);
}
}
);
}
}
}
private static class Tracer implements CommandSource, TraceCallbacks {
public static final int INDENT_OFFSET = 1;
private final PrintWriter output;
private int lastIndent;
private boolean waitingForResult;
private Tracer(PrintWriter output) {
this.output = output;
}
private void indentAndSave(int value) {
this.printIndent(value);
this.lastIndent = value;
}
private void printIndent(int value) {
for (int i = 0; i < value + 1; i++) {
this.output.write(" ");
}
}
private void newLine() {
if (this.waitingForResult) {
this.output.println();
this.waitingForResult = false;
}
}
@Override
public void onCommand(int depth, String command) {
this.newLine();
this.indentAndSave(depth);
this.output.print("[C] ");
this.output.print(command);
this.waitingForResult = true;
}
@Override
public void onReturn(int depth, String command, int result) {
if (this.waitingForResult) {
this.output.print(" -> ");
this.output.println(result);
this.waitingForResult = false;
} else {
this.indentAndSave(depth);
this.output.print("[R = ");
this.output.print(result);
this.output.print("] ");
this.output.println(command);
}
}
@Override
public void onCall(int depth, Identifier function, int size) {
this.newLine();
this.indentAndSave(depth);
this.output.print("[F] ");
this.output.print(function);
this.output.print(" size=");
this.output.println(size);
}
@Override
public void onError(String message) {
this.newLine();
this.indentAndSave(this.lastIndent + 1);
this.output.print("[E] ");
this.output.print(message);
}
@Override
public void sendSystemMessage(Component message) {
this.newLine();
this.printIndent(this.lastIndent + 1);
this.output.print("[M] ");
this.output.println(message.getString());
}
@Override
public boolean acceptsSuccess() {
return true;
}
@Override
public boolean acceptsFailure() {
return true;
}
@Override
public boolean shouldInformAdmins() {
return false;
}
@Override
public boolean alwaysAccepts() {
return true;
}
@Override
public void close() {
IOUtils.closeQuietly((Writer)this.output);
}
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Commands.argument(), Commands.hasPermission(), Commands.literal()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
FunctionArgument.functions(), FunctionArgument.getFunctions()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Component.translatable(), Component.translationArg()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Util.getFilenameFormattedDateTime()
- 引用位置: