From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Tue, 18 Jul 2023 14:47:02 -0700 Subject: [PATCH] Add Lifecycle Event system This event system is separate from Bukkit's event system and is meant for managing resources across reloads and from points in the PluginBootstrap. diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java b/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java index 08f2050356acaf74e3210416760e3873c2dafd2c..37dfdcfcbd14947e0550e7528aca68f452e53eb6 100644 --- a/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java +++ b/src/main/java/io/papermc/paper/plugin/bootstrap/BootstrapContext.java @@ -1,6 +1,9 @@ package io.papermc.paper.plugin.bootstrap; +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; /** * Represents the context provided to a {@link PluginBootstrap} during both the bootstrapping and plugin @@ -10,5 +13,13 @@ import org.jetbrains.annotations.ApiStatus; */ @ApiStatus.Experimental @ApiStatus.NonExtendable -public interface BootstrapContext extends PluginProviderContext { +public interface BootstrapContext extends PluginProviderContext, LifecycleEventOwner { + + /** + * Get the lifecycle event manager for registering handlers + * for lifecycle events allowed on the {@link BootstrapContext}. + * + * @return the lifecycle event manager + */ + @NotNull LifecycleEventManager getLifecycleManager(); } diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEvent.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..0b8eafd3e79494d4a750cd9182387fbaead24011 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEvent.java @@ -0,0 +1,17 @@ +package io.papermc.paper.plugin.lifecycle.event; + +import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; +import org.jetbrains.annotations.ApiStatus; + +/** + * Base type for all Lifecycle Events. + *

+ * Lifecycle events are generally fired when the older + * event system is not available, like during early + * server initialization. + * @see LifecycleEvents + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface LifecycleEvent { +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventManager.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventManager.java new file mode 100644 index 0000000000000000000000000000000000000000..3626ce3da17f20ec44f0c15baa13f40e1dc2bc9c --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventManager.java @@ -0,0 +1,52 @@ +package io.papermc.paper.plugin.lifecycle.event; + +import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler; +import io.papermc.paper.plugin.lifecycle.event.handler.configuration.LifecycleEventHandlerConfiguration; +import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Manages a plugin's lifecycle events. Can be obtained + * from {@link org.bukkit.plugin.Plugin} or {@link io.papermc.paper.plugin.bootstrap.BootstrapContext}. + * + * @param the owning type, {@link org.bukkit.plugin.Plugin} or {@link io.papermc.paper.plugin.bootstrap.BootstrapContext} + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface LifecycleEventManager { + + /** + * Registers an event handler for a specific event type. + *

+ * This is shorthand for creating a new {@link LifecycleEventHandlerConfiguration} and + * just passing in the {@link LifecycleEventHandler}. + *

{@code
+     * LifecycleEventHandler> handler = new Handler();
+     * manager.registerEventHandler(LifecycleEvents.COMMANDS, handler);
+     * }
+ * is equivalent to + *
{@code
+     * LifecycleEventHandler> handler = new Handler();
+     * manager.registerEventHandler(LifecycleEvents.COMMANDS.newHandler(handler));
+     * }
+ * + * @param eventType the event type to listen to + * @param eventHandler the handler for that event + * @param the type of the event object + */ + default void registerEventHandler(final @NotNull LifecycleEventType eventType, final @NotNull LifecycleEventHandler eventHandler) { + this.registerEventHandler(eventType.newHandler(eventHandler)); + } + + /** + * Registers an event handler configuration. + *

+ * Configurations are created via {@link LifecycleEventType#newHandler(LifecycleEventHandler)}. + * Event types may have different configurations options available on the builder-like object + * returned by {@link LifecycleEventType#newHandler(LifecycleEventHandler)}. + * + * @param handlerConfiguration the handler configuration to register + */ + void registerEventHandler(@NotNull LifecycleEventHandlerConfiguration handlerConfiguration); +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventOwner.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventOwner.java new file mode 100644 index 0000000000000000000000000000000000000000..1160474f94476b580426cec29756c4699e163bf7 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventOwner.java @@ -0,0 +1,24 @@ +package io.papermc.paper.plugin.lifecycle.event; + +import io.papermc.paper.plugin.configuration.PluginMeta; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Implemented by types that are considered owners + * of registered handlers for lifecycle events. Generally + * the types that implement this interface also provide + * a {@link LifecycleEventManager} where you can register + * event handlers. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface LifecycleEventOwner { + + /** + * Get the plugin meta for this plugin. + * + * @return the plugin meta + */ + @NotNull PluginMeta getPluginMeta(); +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/LifecycleEventHandler.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/LifecycleEventHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..8239ba3c0147c0e8e8d28987d3f543a67641892a --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/LifecycleEventHandler.java @@ -0,0 +1,18 @@ +package io.papermc.paper.plugin.lifecycle.event.handler; + +import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * A handler for a specific event. Can be implemented + * in a concrete class or as a lambda. + * + * @param the event + */ +@ApiStatus.Experimental +@FunctionalInterface +public interface LifecycleEventHandler { + + void run(@NotNull E event); +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/LifecycleEventHandlerConfiguration.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/LifecycleEventHandlerConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..0831794fad1f6eb8960225909d40f4a3b20a2a3b --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/LifecycleEventHandlerConfiguration.java @@ -0,0 +1,18 @@ +package io.papermc.paper.plugin.lifecycle.event.handler.configuration; + +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; +import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler; +import org.jetbrains.annotations.ApiStatus; + +/** + * Base type for constructing configured event handlers for + * lifecycle events. Usually created via {@link io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType#newHandler(LifecycleEventHandler)} + * from event types in {@link io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents} + * + * @param + */ +@SuppressWarnings("unused") +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface LifecycleEventHandlerConfiguration { +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfiguration.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..d307ede51a66279f2eeef4e5b41c71779503f0d4 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfiguration.java @@ -0,0 +1,25 @@ +package io.papermc.paper.plugin.lifecycle.event.handler.configuration; + +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; + +/** + * Handler configuration for event types that allow "monitor" handlers. + * + * @param the required owner type + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface MonitorLifecycleEventHandlerConfiguration extends LifecycleEventHandlerConfiguration { + + /** + * Sets this handler configuration to be considered a "monitor". + * These handlers will run last and should only be used by plugins + * to observe changes from previously run handlers. + * + * @return this configuration for chaining + */ + @Contract("-> this") + MonitorLifecycleEventHandlerConfiguration monitor(); +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfiguration.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..1c404df0be359ceac7fb52fec03027c771395e07 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfiguration.java @@ -0,0 +1,39 @@ +package io.papermc.paper.plugin.lifecycle.event.handler.configuration; + +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; + +/** + * Handler configuration that allows both "monitor" and prioritized handlers. + * The default priority is 0. + * + * @param the required owner type + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface PrioritizedLifecycleEventHandlerConfiguration extends LifecycleEventHandlerConfiguration { + + /** + * Sets the priority for this handler. Resets + * all previous calls to {@link #monitor()}. A + * lower numeric value correlates to the handler + * being run earlier. + * + * @param priority the numerical priority + * @return this configuration for chaining + */ + @Contract("_ -> this") + PrioritizedLifecycleEventHandlerConfiguration priority(int priority); + + /** + * Sets this handler configuration to be considered a "monitor". + * These handlers will run last and should only be used by plugins + * to observe any changes from previously ran handlers. + * + * @return this configuration for chaining + */ + @Contract("-> this") + PrioritizedLifecycleEventHandlerConfiguration monitor(); + +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/Registrar.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/Registrar.java new file mode 100644 index 0000000000000000000000000000000000000000..fd9c3605a8f5e6bdd31e42f18a45154d4074eb67 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/Registrar.java @@ -0,0 +1,12 @@ +package io.papermc.paper.plugin.lifecycle.event.registrar; + +import org.jetbrains.annotations.ApiStatus; + +/** + * To be implemented by types that provide ways to register types + * either on server start or during a reload + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface Registrar { +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEvent.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..2e5758d1af6215f33f89b12984a5594df592147f --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEvent.java @@ -0,0 +1,27 @@ +package io.papermc.paper.plugin.lifecycle.event.registrar; + +import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +/** + * A lifecycle event that exposes a {@link Registrar} of some kind + * to allow management of various things. Look at implementations of + * {@link Registrar} for an idea of what uses this event. + * + * @param registrar type + * @see ReloadableRegistrarEvent + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface RegistrarEvent extends LifecycleEvent { + + /** + * Get the registrar related to this event. + * + * @return the registrar + */ + @Contract(pure = true) + @NotNull R registrar(); +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/ReloadableRegistrarEvent.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/ReloadableRegistrarEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..b8b439bdad2e47c7c715fe30e0c1e69aa25374dd --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/ReloadableRegistrarEvent.java @@ -0,0 +1,38 @@ +package io.papermc.paper.plugin.lifecycle.event.registrar; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +/** + * A lifecycle event that exposes a {@link Registrar} that is + * reloadable. + * + * @param the registrar type + * @see RegistrarEvent + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface ReloadableRegistrarEvent extends RegistrarEvent { + + /** + * Get the cause of this reload. + * + * @return the cause + */ + @Contract(pure = true) + @NotNull Cause cause(); + + @ApiStatus.Experimental + enum Cause { + /** + * The initial load of the server. + */ + INITIAL, + /** + * A reload, triggered via one of the various mechanisms like + * the bukkit or minecraft reload commands. + */ + RELOAD + } +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventType.java new file mode 100644 index 0000000000000000000000000000000000000000..92ea0374079a228ccc59c00fcf58abff2f6c46fe --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventType.java @@ -0,0 +1,73 @@ +package io.papermc.paper.plugin.lifecycle.event.types; + +import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; +import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler; +import io.papermc.paper.plugin.lifecycle.event.handler.configuration.LifecycleEventHandlerConfiguration; +import io.papermc.paper.plugin.lifecycle.event.handler.configuration.MonitorLifecycleEventHandlerConfiguration; +import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfiguration; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +/** + * Base type for all types of lifecycle events. Differs from + * {@link LifecycleEvent} which is the actual event object, whereas + * this is an object representing the type of the event. Used + * to construct subtypes of {@link LifecycleEventHandlerConfiguration} for + * use in {@link LifecycleEventManager} + * + * @param the required owner type + * @param the event object type + * @param the configuration type + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface LifecycleEventType> { + + /** + * Gets the name of the lifecycle event. + * + * @return the name + */ + @Contract(pure = true) + @NotNull String name(); + + /** + * Create a configuration for this event with the specified + * handler. + * + * @param handler the event handler + * @return a new configuration + * @see LifecycleEventManager#registerEventHandler(LifecycleEventHandlerConfiguration) + */ + @Contract("_ -> new") + @NotNull C newHandler(@NotNull LifecycleEventHandler handler); + + /** + * Lifecycle event type that supports separate registration + * of handlers as "monitors" that are run last. Useful + * if a plugin wants to only observe the changes other handlers + * made. + * + * @param the required owner type + * @param the event object type + */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Monitorable extends LifecycleEventType> { + } + + /** + * Lifecycle event type that supports both {@link Monitorable "monitors"} and + * specific numeric-based priorities. + * + * @param the required owner type + * @param the event object type + */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Prioritizable extends LifecycleEventType> { + } +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..1588f6943a909bed053a952e650e043c44028c2d --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProvider.java @@ -0,0 +1,18 @@ +package io.papermc.paper.plugin.lifecycle.event.types; + +import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; +import java.util.ServiceLoader; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Internal +interface LifecycleEventTypeProvider { + + LifecycleEventTypeProvider PROVIDER = ServiceLoader.load(LifecycleEventTypeProvider.class) + .findFirst() + .orElseThrow(); + + LifecycleEventType.Monitorable monitor(String name, Class ownerType); + + LifecycleEventType.Prioritizable prioritized(String name, Class ownerType); +} diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java new file mode 100644 index 0000000000000000000000000000000000000000..304f978e40e1759bb19704cc5cec399500905195 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEvents.java @@ -0,0 +1,52 @@ +package io.papermc.paper.plugin.lifecycle.event.types; + +import io.papermc.paper.plugin.bootstrap.BootstrapContext; +import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.ApiStatus; + +/** + * Holds various types of lifecycle events for + * use when creating event handler configurations + * in {@link LifecycleEventManager}. + */ +@ApiStatus.Experimental +public final class LifecycleEvents { + + // + @ApiStatus.Internal + private static LifecycleEventType.Monitorable plugin(final String name) { + return monitor(name, Plugin.class); + } + + @ApiStatus.Internal + private static LifecycleEventType.Prioritizable pluginPrioritized(final String name) { + return prioritized(name, Plugin.class); + } + + @ApiStatus.Internal + private static LifecycleEventType.Monitorable bootstrap(final String name) { + return monitor(name, BootstrapContext.class); + } + + @ApiStatus.Internal + private static LifecycleEventType.Prioritizable bootstrapPrioritized(final String name) { + return prioritized(name, BootstrapContext.class); + } + + @ApiStatus.Internal + private static LifecycleEventType.Monitorable monitor(final String name, final Class ownerType) { + return LifecycleEventTypeProvider.PROVIDER.monitor(name, ownerType); + } + + @ApiStatus.Internal + private static LifecycleEventType.Prioritizable prioritized(final String name, final Class ownerType) { + return LifecycleEventTypeProvider.PROVIDER.prioritized(name, ownerType); + } + // + + private LifecycleEvents() { + } +} diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java index 1887cc2882ea197481b39693cc48aa16ccde5782..c8c966feade4881f7a741ce059803f089e96107c 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java @@ -269,4 +269,12 @@ public interface UnsafeValues { */ @Nullable org.bukkit.Color getSpawnEggLayerColor(org.bukkit.entity.EntityType entityType, int layer); // Paper end - spawn egg color visibility + + // Paper start - lifecycle event API + /** + * @hidden + */ + @org.jetbrains.annotations.ApiStatus.Internal + io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager createPluginLifecycleEventManager(final org.bukkit.plugin.java.JavaPlugin plugin, final java.util.function.BooleanSupplier registrationCheck); + // Paper end - lifecycle event API } diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java index 46fc37a36403c8fbc4c0c9f863d4d57eb3896bd4..0ff8b53f900092dc419d61a8ede0a7cd72a2e1e1 100644 --- a/src/main/java/org/bukkit/plugin/Plugin.java +++ b/src/main/java/org/bukkit/plugin/Plugin.java @@ -16,7 +16,7 @@ import org.jetbrains.annotations.Nullable; *

* The use of {@link PluginBase} is recommended for actual Implementation */ -public interface Plugin extends TabExecutor { +public interface Plugin extends TabExecutor, io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner { // Paper /** * Returns the folder that the plugin data files are located in. The * folder may not yet exist. @@ -224,4 +224,14 @@ public interface Plugin extends TabExecutor { */ @NotNull public String getName(); + + // Paper start - lifecycle events + /** + * Get the lifecycle event manager for registering handlers + * for lifecycle events allowed on the {@link Plugin}. + * + * @return the lifecycle event manager + */ + io.papermc.paper.plugin.lifecycle.event.@NotNull LifecycleEventManager getLifecycleManager(); + // Paper end - lifecycle events } diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java index 2d64fc065d53dcd8c01d05215c3e63aaf4428177..e0203f199700c397961a0667a79792497da7f796 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java @@ -48,6 +48,11 @@ public abstract class JavaPlugin extends PluginBase { private FileConfiguration newConfig = null; private File configFile = null; private Logger logger = null; // Paper - PluginLogger -> Logger + // Paper start - lifecycle events + @SuppressWarnings("deprecation") + private final io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager lifecycleEventManager = org.bukkit.Bukkit.getUnsafe().createPluginLifecycleEventManager(this, () -> this.allowsLifecycleRegistration); + private boolean allowsLifecycleRegistration = true; + // Paper end public JavaPlugin() { // Paper start @@ -279,7 +284,9 @@ public abstract class JavaPlugin extends PluginBase { isEnabled = enabled; if (isEnabled) { + try { // Paper - lifecycle events onEnable(); + } finally { this.allowsLifecycleRegistration = false; } // Paper - lifecycle events } else { onDisable(); } @@ -457,4 +464,11 @@ public abstract class JavaPlugin extends PluginBase { } return plugin; } + + // Paper start - lifecycle events + @Override + public final io.papermc.paper.plugin.lifecycle.event.@NotNull LifecycleEventManager getLifecycleManager() { + return this.lifecycleEventManager; + } + // Paper end - lifecycle events } diff --git a/src/test/java/org/bukkit/plugin/TestPlugin.java b/src/test/java/org/bukkit/plugin/TestPlugin.java index 43b58e920e739bb949ac0673e9ef73ba7b500dc9..affe88cf8e98a787e197936f5fc443464a2343c6 100644 --- a/src/test/java/org/bukkit/plugin/TestPlugin.java +++ b/src/test/java/org/bukkit/plugin/TestPlugin.java @@ -133,4 +133,11 @@ public class TestPlugin extends PluginBase { public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { throw new UnsupportedOperationException("Not supported."); } + + // Paper start - lifecycle events + @Override + public io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager getLifecycleManager() { + throw new UnsupportedOperationException("Not supported."); + } + // Paper end - lifecycle events }