mirror of
https://github.com/PaperMC/Paper.git
synced 2025-05-18 21:20:24 -07:00
Improvements for Dump paper commands (#12512)
This commit is contained in:
parent
42a2a6c2b5
commit
753cff7c8a
@ -2,12 +2,13 @@ package io.papermc.paper.command.subcommands;
|
||||
|
||||
import com.destroystokyo.paper.util.SneakyThrow;
|
||||
import io.papermc.paper.command.PaperSubcommand;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
@ -16,6 +17,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -23,6 +25,7 @@ import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredListener;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
|
||||
import static net.kyori.adventure.text.Component.newline;
|
||||
@ -35,6 +38,8 @@ import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
|
||||
|
||||
@DefaultQualifier(NonNull.class)
|
||||
public final class DumpListenersCommand implements PaperSubcommand {
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss");
|
||||
private static final String COMMAND_ARGUMENT_TO_FILE = "tofile";
|
||||
private static final MethodHandle EVENT_TYPES_HANDLE;
|
||||
|
||||
static {
|
||||
@ -49,7 +54,7 @@ public final class DumpListenersCommand implements PaperSubcommand {
|
||||
|
||||
@Override
|
||||
public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
if (args.length >= 1 && args[0].equals("tofile")) {
|
||||
if (args.length >= 1 && args[0].equals(COMMAND_ARGUMENT_TO_FILE)) {
|
||||
this.dumpToFile(sender);
|
||||
return true;
|
||||
}
|
||||
@ -58,45 +63,69 @@ public final class DumpListenersCommand implements PaperSubcommand {
|
||||
}
|
||||
|
||||
private void dumpToFile(final CommandSender sender) {
|
||||
final File file = new File("debug/listeners-"
|
||||
+ DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt");
|
||||
file.getParentFile().mkdirs();
|
||||
try (final PrintWriter writer = new PrintWriter(file)) {
|
||||
for (final String eventClass : eventClassNames()) {
|
||||
final HandlerList handlers;
|
||||
try {
|
||||
handlers = (HandlerList) findClass(eventClass).getMethod("getHandlerList").invoke(null);
|
||||
} catch (final ReflectiveOperationException e) {
|
||||
continue;
|
||||
}
|
||||
if (handlers.getRegisteredListeners().length != 0) {
|
||||
writer.println(eventClass);
|
||||
}
|
||||
for (final RegisteredListener registeredListener : handlers.getRegisteredListeners()) {
|
||||
writer.println(" - " + registeredListener);
|
||||
Path parent = Path.of("debug");
|
||||
Path path = parent.resolve("listeners-" + FORMATTER.format(LocalDateTime.now()) + ".txt");
|
||||
sender.sendMessage(
|
||||
text("Writing listeners into directory", GREEN)
|
||||
.appendSpace()
|
||||
.append(
|
||||
text(parent.toString(), WHITE)
|
||||
.hoverEvent(text("Click to copy the full path of debug directory", WHITE))
|
||||
.clickEvent(ClickEvent.copyToClipboard(parent.toAbsolutePath().toString()))
|
||||
)
|
||||
);
|
||||
try {
|
||||
Files.createDirectories(parent);
|
||||
Files.createFile(path);
|
||||
try (final PrintWriter writer = new PrintWriter(path.toFile())){
|
||||
for (final String eventClass : eventClassNames()) {
|
||||
final HandlerList handlers;
|
||||
try {
|
||||
handlers = (HandlerList) findClass(eventClass).getMethod("getHandlerList").invoke(null);
|
||||
} catch (final ReflectiveOperationException e) {
|
||||
continue;
|
||||
}
|
||||
if (handlers.getRegisteredListeners().length != 0) {
|
||||
writer.println(eventClass);
|
||||
}
|
||||
for (final RegisteredListener registeredListener : handlers.getRegisteredListeners()) {
|
||||
writer.println(" - " + registeredListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
sender.sendMessage(text("Failed to write dumped listener! See the console for more info.", RED));
|
||||
MinecraftServer.LOGGER.warn("Error occurred while dumping listeners", ex);
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(text("Dumped listeners to " + file, GREEN));
|
||||
sender.sendMessage(
|
||||
text("Successfully written listeners into", GREEN)
|
||||
.appendSpace()
|
||||
.append(
|
||||
text(path.toString(), WHITE)
|
||||
.hoverEvent(text("Click to copy the full path of the file", WHITE))
|
||||
.clickEvent(ClickEvent.copyToClipboard(path.toAbsolutePath().toString()))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void doDumpListeners(final CommandSender sender, final String[] args) {
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage(text("Usage: /paper dumplisteners tofile|<className>", RED));
|
||||
sender.sendMessage(text("Usage: /paper dumplisteners " + COMMAND_ARGUMENT_TO_FILE + "|<className>", RED));
|
||||
return;
|
||||
}
|
||||
|
||||
final String className = args[0];
|
||||
|
||||
try {
|
||||
final HandlerList handlers = (HandlerList) findClass(args[0]).getMethod("getHandlerList").invoke(null);
|
||||
final HandlerList handlers = (HandlerList) findClass(className).getMethod("getHandlerList").invoke(null);
|
||||
|
||||
if (handlers.getRegisteredListeners().length == 0) {
|
||||
sender.sendMessage(text(args[0] + " does not have any registered listeners."));
|
||||
sender.sendMessage(text(className + " does not have any registered listeners."));
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(text("Listeners for " + args[0] + ":"));
|
||||
sender.sendMessage(text("Listeners for " + className + ":"));
|
||||
|
||||
for (final RegisteredListener listener : handlers.getRegisteredListeners()) {
|
||||
final Component hoverText = text("Priority: " + listener.getPriority().name() + " (" + listener.getPriority().getSlot() + ")", WHITE)
|
||||
@ -115,12 +144,12 @@ public final class DumpListenersCommand implements PaperSubcommand {
|
||||
sender.sendMessage(text("Total listeners: " + handlers.getRegisteredListeners().length));
|
||||
|
||||
} catch (final ClassNotFoundException e) {
|
||||
sender.sendMessage(text("Unable to find a class named '" + args[0] + "'. Make sure to use the fully qualified name.", RED));
|
||||
sender.sendMessage(text("Unable to find a class named '" + className + "'. Make sure to use the fully qualified name.", RED));
|
||||
} catch (final NoSuchMethodException e) {
|
||||
sender.sendMessage(text("Class '" + args[0] + "' does not have a valid getHandlerList method.", RED));
|
||||
sender.sendMessage(text("Class '" + className + "' does not have a valid getHandlerList method.", RED));
|
||||
} catch (final ReflectiveOperationException e) {
|
||||
sender.sendMessage(text("Something went wrong, see the console for more details.", RED));
|
||||
MinecraftServer.LOGGER.warn("Error occurred while dumping listeners for class " + args[0], e);
|
||||
MinecraftServer.LOGGER.warn("Error occurred while dumping listeners for class {}", className, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +166,7 @@ public final class DumpListenersCommand implements PaperSubcommand {
|
||||
|
||||
private static List<String> suggestions() {
|
||||
final List<String> ret = new ArrayList<>();
|
||||
ret.add("tofile");
|
||||
ret.add(COMMAND_ARGUMENT_TO_FILE);
|
||||
ret.addAll(eventClassNames());
|
||||
return ret;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.Strictness;
|
||||
import com.google.gson.internal.Streams;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import io.papermc.paper.command.PaperSubcommand;
|
||||
@ -15,7 +16,6 @@ import io.papermc.paper.plugin.entrypoint.classloader.group.PaperPluginClassLoad
|
||||
import io.papermc.paper.plugin.entrypoint.classloader.group.SimpleListPluginClassLoaderGroup;
|
||||
import io.papermc.paper.plugin.entrypoint.classloader.group.SpigotPluginClassLoaderGroup;
|
||||
import io.papermc.paper.plugin.entrypoint.classloader.group.StaticPluginClassLoaderGroup;
|
||||
import io.papermc.paper.plugin.entrypoint.dependency.GraphDependencyContext;
|
||||
import io.papermc.paper.plugin.entrypoint.dependency.SimpleMetaDependencyTree;
|
||||
import io.papermc.paper.plugin.provider.entrypoint.DependencyContext;
|
||||
import io.papermc.paper.plugin.entrypoint.strategy.modern.ModernPluginLoadingStrategy;
|
||||
@ -27,12 +27,14 @@ import io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage;
|
||||
import io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup;
|
||||
import io.papermc.paper.plugin.storage.ConfiguredProviderStorage;
|
||||
import io.papermc.paper.plugin.storage.ProviderStorage;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -47,6 +49,7 @@ import java.util.Map;
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.GREEN;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.RED;
|
||||
import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
|
||||
|
||||
@DefaultQualifier(NonNull.class)
|
||||
public final class DumpPluginsCommand implements PaperSubcommand {
|
||||
@ -60,24 +63,40 @@ public final class DumpPluginsCommand implements PaperSubcommand {
|
||||
|
||||
private void dumpPlugins(final CommandSender sender, final String[] args) {
|
||||
Path parent = Path.of("debug");
|
||||
Path path = parent.resolve("plugin-info-" + FORMATTER.format(LocalDateTime.now()) + ".txt");
|
||||
Path path = parent.resolve("plugin-info-" + FORMATTER.format(LocalDateTime.now()) + ".json");
|
||||
try {
|
||||
Files.createDirectories(parent);
|
||||
Files.createFile(path);
|
||||
sender.sendMessage(text("Writing plugin information to " + path, GREEN));
|
||||
sender.sendMessage(
|
||||
text("Writing plugin information into directory", GREEN)
|
||||
.appendSpace()
|
||||
.append(
|
||||
text(parent.toString(), WHITE)
|
||||
.hoverEvent(text("Click to copy the full path of debug directory", WHITE))
|
||||
.clickEvent(ClickEvent.copyToClipboard(parent.toAbsolutePath().toString()))
|
||||
)
|
||||
);
|
||||
|
||||
final JsonObject data = this.writeDebug();
|
||||
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
||||
jsonWriter.setIndent(" ");
|
||||
jsonWriter.setLenient(false);
|
||||
jsonWriter.setStrictness(Strictness.STRICT);
|
||||
Streams.write(data, jsonWriter);
|
||||
|
||||
try (PrintStream out = new PrintStream(Files.newOutputStream(path), false, StandardCharsets.UTF_8)) {
|
||||
out.print(stringWriter);
|
||||
}
|
||||
sender.sendMessage(text("Successfully written plugin debug information!", GREEN));
|
||||
sender.sendMessage(
|
||||
text("Successfully written plugin debug information into", GREEN)
|
||||
.appendSpace()
|
||||
.append(
|
||||
text(path.toString(), WHITE)
|
||||
.hoverEvent(text("Click to copy the full path of the file", WHITE))
|
||||
.clickEvent(ClickEvent.copyToClipboard(path.toAbsolutePath().toString()))
|
||||
)
|
||||
);
|
||||
} catch (Throwable e) {
|
||||
sender.sendMessage(text("Failed to write plugin information! See the console for more info.", RED));
|
||||
MinecraftServer.LOGGER.warn("Error occurred while dumping plugin info", e);
|
||||
@ -97,6 +116,7 @@ public final class DumpPluginsCommand implements PaperSubcommand {
|
||||
return root;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void writeProviders(JsonObject root) {
|
||||
JsonObject rootProviders = new JsonObject();
|
||||
root.add("providers", rootProviders);
|
||||
@ -116,7 +136,6 @@ public final class DumpPluginsCommand implements PaperSubcommand {
|
||||
providerObj.addProperty("soft-dependencies", provider.getMeta().getPluginSoftDependencies().toString());
|
||||
providerObj.addProperty("load-before", provider.getMeta().getLoadBeforePlugins().toString());
|
||||
|
||||
|
||||
providers.add(providerObj);
|
||||
pluginProviders.add((PluginProvider<Object>) provider);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user