Improvement in /plugins command (#12121)

This commit is contained in:
Pedro 2025-02-16 17:10:45 -03:00 committed by GitHub
parent 2a4a115432
commit 06f96dd655
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -11,6 +11,11 @@ import io.papermc.paper.plugin.provider.ProviderStatus;
import io.papermc.paper.plugin.provider.ProviderStatusHolder;
import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent;
import io.papermc.paper.plugin.provider.type.spigot.SpigotPluginProvider;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeMap;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.TextComponent;
@ -23,51 +28,38 @@ import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.TreeMap;
import org.jspecify.annotations.NullMarked;
@NullMarked
public class PaperPluginsCommand extends BukkitCommand {
private static final TextColor INFO_COLOR = TextColor.color(52, 159, 218);
// TODO: LINK?
private static final Component SERVER_PLUGIN_INFO = Component.text(" What is a server plugin?", INFO_COLOR)
.append(asPlainComponents("""
Server plugins can add new behavior to your server!
You can find new plugins on Paper's plugin repository, Hangar.
Server plugins can add new behavior to your server!
You can find new plugins on Paper's plugin repository, Hangar.
<link to hangar>
"""));
private static final Component SERVER_INITIALIZER_INFO = Component.text(" What is a server initializer?", INFO_COLOR)
.append(asPlainComponents("""
Server initializers are ran before your server
starts and are provided by paper plugins.
"""));
https://hangar.papermc.io/
"""));
private static final Component LEGACY_PLUGIN_INFO = Component.text(" What is a legacy plugin?", INFO_COLOR)
.append(asPlainComponents("""
A legacy plugin is a plugin that was made on
very old unsupported versions of the game.
A legacy plugin is a plugin that was made on
very old unsupported versions of the game.
It is encouraged that you replace this plugin,
as they might not work in the future and may cause
performance issues.
"""));
It is encouraged that you replace this plugin,
as they might not work in the future and may cause
performance issues.
"""));
private static final Component LEGACY_PLUGIN_STAR = Component.text('*', TextColor.color(255, 212, 42)).hoverEvent(LEGACY_PLUGIN_INFO);
private static final Component INFO_ICON_START = Component.text(" ", INFO_COLOR);
private static final Component PAPER_HEADER = Component.text("Paper Plugins:", TextColor.color(2, 136, 209));
private static final Component BUKKIT_HEADER = Component.text("Bukkit Plugins:", TextColor.color(237, 129, 6));
private static final Component PLUGIN_TICK = Component.text("- ", NamedTextColor.DARK_GRAY);
private static final Component PLUGIN_TICK_EMPTY = Component.text(" ");
private static final Component INFO_ICON_SERVER_PLUGIN = INFO_ICON_START.hoverEvent(SERVER_PLUGIN_INFO).clickEvent(ClickEvent.openUrl("https://docs.papermc.io/paper/adding-plugins"));
private static final Type JAVA_PLUGIN_PROVIDER_TYPE = new TypeToken<PluginProvider<JavaPlugin>>() {}.getType();
public PaperPluginsCommand() {
@ -75,17 +67,17 @@ public class PaperPluginsCommand extends BukkitCommand {
this.description = "Gets a list of plugins running on the server";
this.usageMessage = "/plugins";
this.setPermission("bukkit.command.plugins");
this.setAliases(Arrays.asList("pl"));
this.setAliases(List.of("pl"));
}
private static <T> List<Component> formatProviders(TreeMap<String, PluginProvider<T>> plugins) {
List<Component> components = new ArrayList<>(plugins.size());
for (PluginProvider<T> entry : plugins.values()) {
private static <T> List<Component> formatProviders(final TreeMap<String, PluginProvider<T>> plugins) {
final List<Component> components = new ArrayList<>(plugins.size());
for (final PluginProvider<T> entry : plugins.values()) {
components.add(formatProvider(entry));
}
boolean isFirst = true;
List<Component> formattedSublists = new ArrayList<>();
final List<Component> formattedSubLists = new ArrayList<>();
/*
Split up the plugin list for each 10 plugins to get size down
@ -93,30 +85,29 @@ public class PaperPluginsCommand extends BukkitCommand {
- Plugin 1, Plugin 2, .... Plugin 10,
Plugin 11, Plugin 12 ... Plugin 20,
*/
for (List<Component> componentSublist : Lists.partition(components, 10)) {
for (final List<Component> componentSublist : Lists.partition(components, 10)) {
Component component = Component.space();
if (isFirst) {
component = component.append(PLUGIN_TICK);
isFirst = false;
} else {
component = PLUGIN_TICK_EMPTY;
//formattedSublists.add(Component.empty()); // Add an empty line, the auto chat wrapping and this makes it quite jarring.
}
formattedSublists.add(component.append(Component.join(JoinConfiguration.commas(true), componentSublist)));
formattedSubLists.add(component.append(Component.join(JoinConfiguration.commas(true), componentSublist)));
}
return formattedSublists;
return formattedSubLists;
}
private static Component formatProvider(PluginProvider<?> provider) {
TextComponent.Builder builder = Component.text();
if (provider instanceof SpigotPluginProvider spigotPluginProvider && CraftMagicNumbers.isLegacy(spigotPluginProvider.getMeta())) {
private static Component formatProvider(final PluginProvider<?> provider) {
final TextComponent.Builder builder = Component.text();
if (provider instanceof final SpigotPluginProvider spigotPluginProvider && CraftMagicNumbers.isLegacy(spigotPluginProvider.getMeta())) {
builder.append(LEGACY_PLUGIN_STAR);
}
String name = provider.getMeta().getName();
Component pluginName = Component.text(name, fromStatus(provider))
final String name = provider.getMeta().getName();
final Component pluginName = Component.text(name, fromStatus(provider))
.clickEvent(ClickEvent.runCommand("/version " + name));
builder.append(pluginName);
@ -124,9 +115,20 @@ public class PaperPluginsCommand extends BukkitCommand {
return builder.build();
}
private static Component asPlainComponents(String strings) {
net.kyori.adventure.text.TextComponent.Builder builder = Component.text();
for (String string : strings.split("\n")) {
private static Component header(final String header, final int color, final int count, final boolean showSize) {
final TextComponent.Builder componentHeader = Component.text().color(TextColor.color(color))
.append(Component.text(header));
if (showSize) {
componentHeader.appendSpace().append(Component.text("(" + count + ")"));
}
return componentHeader.append(Component.text(":")).build();
}
private static Component asPlainComponents(final String strings) {
final net.kyori.adventure.text.TextComponent.Builder builder = Component.text();
for (final String string : strings.split("\n")) {
builder.append(Component.newline());
builder.append(Component.text(string, NamedTextColor.WHITE));
}
@ -134,13 +136,13 @@ public class PaperPluginsCommand extends BukkitCommand {
return builder.build();
}
private static TextColor fromStatus(PluginProvider<?> provider) {
if (provider instanceof ProviderStatusHolder statusHolder && statusHolder.getLastProvidedStatus() != null) {
ProviderStatus status = statusHolder.getLastProvidedStatus();
private static TextColor fromStatus(final PluginProvider<?> provider) {
if (provider instanceof final ProviderStatusHolder statusHolder && statusHolder.getLastProvidedStatus() != null) {
final ProviderStatus status = statusHolder.getLastProvidedStatus();
// Handle enabled/disabled game plugins
if (status == ProviderStatus.INITIALIZED && GenericTypeReflector.isSuperType(JAVA_PLUGIN_PROVIDER_TYPE, provider.getClass())) {
Plugin plugin = Bukkit.getPluginManager().getPlugin(provider.getMeta().getName());
final Plugin plugin = Bukkit.getPluginManager().getPlugin(provider.getMeta().getName());
// Plugin doesn't exist? Could be due to it being removed.
if (plugin == null) {
return NamedTextColor.RED;
@ -153,7 +155,7 @@ public class PaperPluginsCommand extends BukkitCommand {
case INITIALIZED -> NamedTextColor.GREEN;
case ERRORED -> NamedTextColor.RED;
};
} else if (provider instanceof PaperPluginParent.PaperServerPluginProvider serverPluginProvider && serverPluginProvider.shouldSkipCreation()) {
} else if (provider instanceof final PaperPluginParent.PaperServerPluginProvider serverPluginProvider && serverPluginProvider.shouldSkipCreation()) {
// Paper plugins will be skipped if their provider is skipped due to their initializer failing.
// Show them as red
return NamedTextColor.RED;
@ -165,15 +167,14 @@ public class PaperPluginsCommand extends BukkitCommand {
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) {
public boolean execute(final CommandSender sender, final String currentAlias, final String[] args) {
if (!this.testPermission(sender)) return true;
TreeMap<String, PluginProvider<JavaPlugin>> paperPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
TreeMap<String, PluginProvider<JavaPlugin>> spigotPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
final TreeMap<String, PluginProvider<JavaPlugin>> paperPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
final TreeMap<String, PluginProvider<JavaPlugin>> spigotPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (PluginProvider<JavaPlugin> provider : LaunchEntryPointHandler.INSTANCE.get(Entrypoint.PLUGIN).getRegisteredProviders()) {
PluginMeta configuration = provider.getMeta();
for (final PluginProvider<JavaPlugin> provider : LaunchEntryPointHandler.INSTANCE.get(Entrypoint.PLUGIN).getRegisteredProviders()) {
final PluginMeta configuration = provider.getMeta();
if (provider instanceof SpigotPluginProvider) {
spigotPlugins.put(configuration.getDisplayName(), provider);
@ -182,34 +183,36 @@ public class PaperPluginsCommand extends BukkitCommand {
}
}
Component infoMessage = Component.text("Server Plugins (%s):".formatted(paperPlugins.size() + spigotPlugins.size()), NamedTextColor.WHITE);
//.append(INFO_ICON_START.hoverEvent(SERVER_PLUGIN_INFO)); TODO: Add docs
final int sizePaperPlugins = paperPlugins.size();
final int sizeSpigotPlugins = spigotPlugins.size();
final int sizePlugins = sizePaperPlugins + sizeSpigotPlugins;
final boolean hasAllPluginTypes = (sizePaperPlugins > 0 && sizeSpigotPlugins > 0);
final Component infoMessage = Component.text().append(INFO_ICON_SERVER_PLUGIN).append(Component.text("Server Plugins (%s):".formatted(sizePlugins), NamedTextColor.WHITE)).build();
sender.sendMessage(infoMessage);
if (!paperPlugins.isEmpty()) {
sender.sendMessage(PAPER_HEADER);
sender.sendMessage(header("Paper Plugins", 0x0288D1, sizePaperPlugins, hasAllPluginTypes));
}
for (Component component : formatProviders(paperPlugins)) {
for (final Component component : formatProviders(paperPlugins)) {
sender.sendMessage(component);
}
if (!spigotPlugins.isEmpty()) {
sender.sendMessage(BUKKIT_HEADER);
sender.sendMessage(header("Bukkit Plugins", 0xED8106, sizePaperPlugins, hasAllPluginTypes));
}
for (Component component : formatProviders(spigotPlugins)) {
for (final Component component : formatProviders(spigotPlugins)) {
sender.sendMessage(component);
}
return true;
}
@NotNull
@Override
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException {
public List<String> tabComplete(final CommandSender sender, final String alias, final String[] args) throws IllegalArgumentException {
return Collections.emptyList();
}
}