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.ProviderStatusHolder;
import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent; import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent;
import io.papermc.paper.plugin.provider.type.spigot.SpigotPluginProvider; 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.Component;
import net.kyori.adventure.text.JoinConfiguration; import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.TextComponent; 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.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jspecify.annotations.NullMarked;
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;
@NullMarked
public class PaperPluginsCommand extends BukkitCommand { public class PaperPluginsCommand extends BukkitCommand {
private static final TextColor INFO_COLOR = TextColor.color(52, 159, 218); 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) private static final Component SERVER_PLUGIN_INFO = Component.text(" What is a server plugin?", INFO_COLOR)
.append(asPlainComponents(""" .append(asPlainComponents("""
Server plugins can add new behavior to your server! Server plugins can add new behavior to your server!
You can find new plugins on Paper's plugin repository, Hangar. You can find new plugins on Paper's plugin repository, Hangar.
<link to hangar> https://hangar.papermc.io/
""")); """));
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.
"""));
private static final Component LEGACY_PLUGIN_INFO = Component.text(" What is a legacy plugin?", INFO_COLOR) private static final Component LEGACY_PLUGIN_INFO = Component.text(" What is a legacy plugin?", INFO_COLOR)
.append(asPlainComponents(""" .append(asPlainComponents("""
A legacy plugin is a plugin that was made on A legacy plugin is a plugin that was made on
very old unsupported versions of the game. very old unsupported versions of the game.
It is encouraged that you replace this plugin, It is encouraged that you replace this plugin,
as they might not work in the future and may cause as they might not work in the future and may cause
performance issues. performance issues.
""")); """));
private static final Component LEGACY_PLUGIN_STAR = Component.text('*', TextColor.color(255, 212, 42)).hoverEvent(LEGACY_PLUGIN_INFO); 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 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 = Component.text("- ", NamedTextColor.DARK_GRAY);
private static final Component PLUGIN_TICK_EMPTY = Component.text(" "); 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(); private static final Type JAVA_PLUGIN_PROVIDER_TYPE = new TypeToken<PluginProvider<JavaPlugin>>() {}.getType();
public PaperPluginsCommand() { public PaperPluginsCommand() {
@ -75,17 +67,17 @@ public class PaperPluginsCommand extends BukkitCommand {
this.description = "Gets a list of plugins running on the server"; this.description = "Gets a list of plugins running on the server";
this.usageMessage = "/plugins"; this.usageMessage = "/plugins";
this.setPermission("bukkit.command.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) { private static <T> List<Component> formatProviders(final TreeMap<String, PluginProvider<T>> plugins) {
List<Component> components = new ArrayList<>(plugins.size()); final List<Component> components = new ArrayList<>(plugins.size());
for (PluginProvider<T> entry : plugins.values()) { for (final PluginProvider<T> entry : plugins.values()) {
components.add(formatProvider(entry)); components.add(formatProvider(entry));
} }
boolean isFirst = true; 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 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 1, Plugin 2, .... Plugin 10,
Plugin 11, Plugin 12 ... Plugin 20, 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(); Component component = Component.space();
if (isFirst) { if (isFirst) {
component = component.append(PLUGIN_TICK); component = component.append(PLUGIN_TICK);
isFirst = false; isFirst = false;
} else { } else {
component = PLUGIN_TICK_EMPTY; 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) { private static Component formatProvider(final PluginProvider<?> provider) {
TextComponent.Builder builder = Component.text(); final TextComponent.Builder builder = Component.text();
if (provider instanceof SpigotPluginProvider spigotPluginProvider && CraftMagicNumbers.isLegacy(spigotPluginProvider.getMeta())) { if (provider instanceof final SpigotPluginProvider spigotPluginProvider && CraftMagicNumbers.isLegacy(spigotPluginProvider.getMeta())) {
builder.append(LEGACY_PLUGIN_STAR); builder.append(LEGACY_PLUGIN_STAR);
} }
String name = provider.getMeta().getName(); final String name = provider.getMeta().getName();
Component pluginName = Component.text(name, fromStatus(provider)) final Component pluginName = Component.text(name, fromStatus(provider))
.clickEvent(ClickEvent.runCommand("/version " + name)); .clickEvent(ClickEvent.runCommand("/version " + name));
builder.append(pluginName); builder.append(pluginName);
@ -124,9 +115,20 @@ public class PaperPluginsCommand extends BukkitCommand {
return builder.build(); return builder.build();
} }
private static Component asPlainComponents(String strings) { private static Component header(final String header, final int color, final int count, final boolean showSize) {
net.kyori.adventure.text.TextComponent.Builder builder = Component.text(); final TextComponent.Builder componentHeader = Component.text().color(TextColor.color(color))
for (String string : strings.split("\n")) { .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.newline());
builder.append(Component.text(string, NamedTextColor.WHITE)); builder.append(Component.text(string, NamedTextColor.WHITE));
} }
@ -134,13 +136,13 @@ public class PaperPluginsCommand extends BukkitCommand {
return builder.build(); return builder.build();
} }
private static TextColor fromStatus(PluginProvider<?> provider) { private static TextColor fromStatus(final PluginProvider<?> provider) {
if (provider instanceof ProviderStatusHolder statusHolder && statusHolder.getLastProvidedStatus() != null) { if (provider instanceof final ProviderStatusHolder statusHolder && statusHolder.getLastProvidedStatus() != null) {
ProviderStatus status = statusHolder.getLastProvidedStatus(); final ProviderStatus status = statusHolder.getLastProvidedStatus();
// Handle enabled/disabled game plugins // Handle enabled/disabled game plugins
if (status == ProviderStatus.INITIALIZED && GenericTypeReflector.isSuperType(JAVA_PLUGIN_PROVIDER_TYPE, provider.getClass())) { 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. // Plugin doesn't exist? Could be due to it being removed.
if (plugin == null) { if (plugin == null) {
return NamedTextColor.RED; return NamedTextColor.RED;
@ -153,7 +155,7 @@ public class PaperPluginsCommand extends BukkitCommand {
case INITIALIZED -> NamedTextColor.GREEN; case INITIALIZED -> NamedTextColor.GREEN;
case ERRORED -> NamedTextColor.RED; 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. // Paper plugins will be skipped if their provider is skipped due to their initializer failing.
// Show them as red // Show them as red
return NamedTextColor.RED; return NamedTextColor.RED;
@ -165,15 +167,14 @@ public class PaperPluginsCommand extends BukkitCommand {
} }
@Override @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; if (!this.testPermission(sender)) return true;
TreeMap<String, PluginProvider<JavaPlugin>> paperPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); final 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>> spigotPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (final PluginProvider<JavaPlugin> provider : LaunchEntryPointHandler.INSTANCE.get(Entrypoint.PLUGIN).getRegisteredProviders()) {
for (PluginProvider<JavaPlugin> provider : LaunchEntryPointHandler.INSTANCE.get(Entrypoint.PLUGIN).getRegisteredProviders()) { final PluginMeta configuration = provider.getMeta();
PluginMeta configuration = provider.getMeta();
if (provider instanceof SpigotPluginProvider) { if (provider instanceof SpigotPluginProvider) {
spigotPlugins.put(configuration.getDisplayName(), provider); 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); final int sizePaperPlugins = paperPlugins.size();
//.append(INFO_ICON_START.hoverEvent(SERVER_PLUGIN_INFO)); TODO: Add docs 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); sender.sendMessage(infoMessage);
if (!paperPlugins.isEmpty()) { 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); sender.sendMessage(component);
} }
if (!spigotPlugins.isEmpty()) { 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); sender.sendMessage(component);
} }
return true; return true;
} }
@NotNull
@Override @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(); return Collections.emptyList();
} }
} }