Disallow calling JavaPlugin#getCommand during onEnable for Paper plugins (#11914)

Co-authored-by: leguan <longboard.noah@gmail.com>
This commit is contained in:
Noah van der Aa
2025-01-11 22:46:36 +01:00
committed by GitHub
parent c2f24e1567
commit ed75b0e54b

View File

@@ -26,7 +26,6 @@ import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.PluginBase; import org.bukkit.plugin.PluginBase;
import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginLoader; import org.bukkit.plugin.PluginLoader;
import org.bukkit.plugin.PluginLogger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -41,30 +40,27 @@ public abstract class JavaPlugin extends PluginBase {
private Server server = null; private Server server = null;
private File file = null; private File file = null;
private PluginDescriptionFile description = null; private PluginDescriptionFile description = null;
private io.papermc.paper.plugin.configuration.PluginMeta pluginMeta = null; // Paper private io.papermc.paper.plugin.configuration.PluginMeta pluginMeta = null;
private File dataFolder = null; private File dataFolder = null;
private ClassLoader classLoader = null; private ClassLoader classLoader = null;
private boolean naggable = true; private boolean naggable = true;
private FileConfiguration newConfig = null; private FileConfiguration newConfig = null;
private File configFile = null; private File configFile = null;
private Logger logger = null; // Paper - PluginLogger -> Logger private Logger logger = null;
// Paper start - lifecycle events
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private final io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager<org.bukkit.plugin.Plugin> lifecycleEventManager = org.bukkit.Bukkit.getUnsafe().createPluginLifecycleEventManager(this, () -> this.allowsLifecycleRegistration); private final io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager<org.bukkit.plugin.Plugin> lifecycleEventManager = org.bukkit.Bukkit.getUnsafe().createPluginLifecycleEventManager(this, () -> this.allowsLifecycleRegistration);
private boolean allowsLifecycleRegistration = true; private boolean allowsLifecycleRegistration = true;
// Paper end private boolean isBeingEnabled = false;
public JavaPlugin() { public JavaPlugin() {
// Paper start
if (this.getClass().getClassLoader() instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader) { if (this.getClass().getClassLoader() instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader) {
configuredPluginClassLoader.init(this); configuredPluginClassLoader.init(this);
} else { } else {
throw new IllegalStateException("JavaPlugin requires to be created by a valid classloader."); throw new IllegalStateException("JavaPlugin requires to be created by a valid classloader.");
} }
// Paper end
} }
@Deprecated(forRemoval = true) // Paper @Deprecated(forRemoval = true)
protected JavaPlugin(@NotNull final JavaPluginLoader loader, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file) { protected JavaPlugin(@NotNull final JavaPluginLoader loader, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file) {
final ClassLoader classLoader = this.getClass().getClassLoader(); final ClassLoader classLoader = this.getClass().getClassLoader();
if (classLoader instanceof PluginClassLoader) { if (classLoader instanceof PluginClassLoader) {
@@ -94,7 +90,7 @@ public abstract class JavaPlugin extends PluginBase {
*/ */
@NotNull @NotNull
@Override @Override
@Deprecated(forRemoval = true) // Paper @Deprecated(forRemoval = true)
public final PluginLoader getPluginLoader() { public final PluginLoader getPluginLoader() {
return loader; return loader;
} }
@@ -111,8 +107,7 @@ public abstract class JavaPlugin extends PluginBase {
} }
/** /**
* Returns a value indicating whether or not this plugin is currently * Returns a value indicating whether this plugin is currently enabled
* enabled
* *
* @return true if this plugin is enabled, otherwise false * @return true if this plugin is enabled, otherwise false
*/ */
@@ -278,22 +273,25 @@ public abstract class JavaPlugin extends PluginBase {
* *
* @param enabled true if enabled, otherwise false * @param enabled true if enabled, otherwise false
*/ */
@org.jetbrains.annotations.ApiStatus.Internal // Paper @org.jetbrains.annotations.ApiStatus.Internal
public final void setEnabled(final boolean enabled) { // Paper public final void setEnabled(final boolean enabled) {
if (isEnabled != enabled) { if (isEnabled != enabled) {
isEnabled = enabled; isEnabled = enabled;
if (isEnabled) { if (isEnabled) {
try { // Paper - lifecycle events this.isBeingEnabled = true;
onEnable(); try {
} finally { this.allowsLifecycleRegistration = false; } // Paper - lifecycle events onEnable();
} finally {
this.allowsLifecycleRegistration = false;
this.isBeingEnabled = false;
}
} else { } else {
onDisable(); onDisable();
} }
} }
} }
// Paper start
private static class DummyPluginLoaderImplHolder { private static class DummyPluginLoaderImplHolder {
private static final PluginLoader INSTANCE = net.kyori.adventure.util.Services.service(PluginLoader.class) private static final PluginLoader INSTANCE = net.kyori.adventure.util.Services.service(PluginLoader.class)
.orElseThrow(); .orElseThrow();
@@ -303,16 +301,15 @@ public abstract class JavaPlugin extends PluginBase {
this.pluginMeta = description; this.pluginMeta = description;
} }
public final void init(@NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader, @Nullable io.papermc.paper.plugin.configuration.PluginMeta configuration, @NotNull Logger logger) { public final void init(@NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader, @Nullable io.papermc.paper.plugin.configuration.PluginMeta configuration, @NotNull Logger logger) {
// Paper end this.loader = DummyPluginLoaderImplHolder.INSTANCE;
this.loader = DummyPluginLoaderImplHolder.INSTANCE; // Paper
this.server = server; this.server = server;
this.file = file; this.file = file;
this.description = description; this.description = description;
this.dataFolder = dataFolder; this.dataFolder = dataFolder;
this.classLoader = classLoader; this.classLoader = classLoader;
this.configFile = new File(dataFolder, "config.yml"); this.configFile = new File(dataFolder, "config.yml");
this.pluginMeta = configuration; // Paper this.pluginMeta = configuration;
this.logger = logger; // Paper this.logger = logger;
} }
/** /**
@@ -339,9 +336,18 @@ public abstract class JavaPlugin extends PluginBase {
* *
* @param name name or alias of the command * @param name name or alias of the command
* @return the plugin command if found, otherwise null * @return the plugin command if found, otherwise null
* @throws UnsupportedOperationException if this plugin is a paper plugin and the method is called in {@link #onEnable()}
*/ */
@Nullable @Nullable
public PluginCommand getCommand(@NotNull String name) { public PluginCommand getCommand(@NotNull String name) {
if (this.isBeingEnabled && !(pluginMeta instanceof PluginDescriptionFile)) {
throw new UnsupportedOperationException("""
You are trying to call JavaPlugin#getCommand on a Paper plugin during startup:
you are probably trying to get a command you tried to define in paper-plugin.yml.
Paper plugins do not support YAML-based command declarations!
Please check the documentation for more information on how to define commands in Paper plugins: https://docs.papermc.io/paper/dev/getting-started/paper-plugins#commands
""");
}
String alias = name.toLowerCase(Locale.ROOT); String alias = name.toLowerCase(Locale.ROOT);
PluginCommand command = getServer().getPluginCommand(alias); PluginCommand command = getServer().getPluginCommand(alias);
@@ -429,10 +435,10 @@ public abstract class JavaPlugin extends PluginBase {
throw new IllegalArgumentException(clazz + " does not extend " + JavaPlugin.class); throw new IllegalArgumentException(clazz + " does not extend " + JavaPlugin.class);
} }
final ClassLoader cl = clazz.getClassLoader(); final ClassLoader cl = clazz.getClassLoader();
if (!(cl instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader)) { // Paper if (!(cl instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader)) {
throw new IllegalArgumentException(clazz + " is not initialized by a " + io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader.class); // Paper throw new IllegalArgumentException(clazz + " is not initialized by a " + io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader.class);
} }
JavaPlugin plugin = configuredPluginClassLoader.getPlugin(); // Paper JavaPlugin plugin = configuredPluginClassLoader.getPlugin();
if (plugin == null) { if (plugin == null) {
throw new IllegalStateException("Cannot get plugin for " + clazz + " from a static initializer"); throw new IllegalStateException("Cannot get plugin for " + clazz + " from a static initializer");
} }
@@ -455,20 +461,18 @@ public abstract class JavaPlugin extends PluginBase {
public static JavaPlugin getProvidingPlugin(@NotNull Class<?> clazz) { public static JavaPlugin getProvidingPlugin(@NotNull Class<?> clazz) {
Preconditions.checkArgument(clazz != null, "Null class cannot have a plugin"); Preconditions.checkArgument(clazz != null, "Null class cannot have a plugin");
final ClassLoader cl = clazz.getClassLoader(); final ClassLoader cl = clazz.getClassLoader();
if (!(cl instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader)) { // Paper if (!(cl instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader)) {
throw new IllegalArgumentException(clazz + " is not provided by a " + io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader.class); // Paper throw new IllegalArgumentException(clazz + " is not provided by a " + io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader.class);
} }
JavaPlugin plugin = configuredPluginClassLoader.getPlugin(); // Paper JavaPlugin plugin = configuredPluginClassLoader.getPlugin();
if (plugin == null) { if (plugin == null) {
throw new IllegalStateException("Cannot get plugin for " + clazz + " from a static initializer"); throw new IllegalStateException("Cannot get plugin for " + clazz + " from a static initializer");
} }
return plugin; return plugin;
} }
// Paper start - lifecycle events
@Override @Override
public final io.papermc.paper.plugin.lifecycle.event.@NotNull LifecycleEventManager<org.bukkit.plugin.Plugin> getLifecycleManager() { public final io.papermc.paper.plugin.lifecycle.event.@NotNull LifecycleEventManager<org.bukkit.plugin.Plugin> getLifecycleManager() {
return this.lifecycleEventManager; return this.lifecycleEventManager;
} }
// Paper end - lifecycle events
} }