mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-27 06:50:12 +01:00
785 lines
39 KiB
Diff
785 lines
39 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
|
Date: Tue, 18 Jul 2023 17:49:38 -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/PluginBootstrapContextImpl.java b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrapContextImpl.java
|
|
index 30b50e6294c6eaade5e17cfaf34600d122e6251c..0bb7694188d5fb75bb756ce75d0060ea980027ee 100644
|
|
--- a/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrapContextImpl.java
|
|
+++ b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrapContextImpl.java
|
|
@@ -1,6 +1,8 @@
|
|
package io.papermc.paper.plugin.bootstrap;
|
|
|
|
import io.papermc.paper.plugin.configuration.PluginMeta;
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
|
|
+import io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEventManager;
|
|
import io.papermc.paper.plugin.provider.PluginProvider;
|
|
import java.nio.file.Path;
|
|
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
|
@@ -12,6 +14,10 @@ public final class PluginBootstrapContextImpl implements BootstrapContext {
|
|
private final Path dataFolder;
|
|
private final ComponentLogger logger;
|
|
private final Path pluginSource;
|
|
+ // Paper start - lifecycle events
|
|
+ private boolean allowsLifecycleRegistration = true;
|
|
+ private final PaperLifecycleEventManager<BootstrapContext> lifecycleEventManager = new PaperLifecycleEventManager<>(this, () -> this.allowsLifecycleRegistration); // Paper - lifecycle events
|
|
+ // Paper end - lifecycle events
|
|
|
|
public PluginBootstrapContextImpl(PluginMeta config, Path dataFolder, ComponentLogger logger, Path pluginSource) {
|
|
this.config = config;
|
|
@@ -45,4 +51,20 @@ public final class PluginBootstrapContextImpl implements BootstrapContext {
|
|
public @NotNull Path getPluginSource() {
|
|
return this.pluginSource;
|
|
}
|
|
+
|
|
+ // Paper start - lifecycle event system
|
|
+ @Override
|
|
+ public @NotNull PluginMeta getPluginMeta() {
|
|
+ return this.config;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public LifecycleEventManager<BootstrapContext> getLifecycleManager() {
|
|
+ return this.lifecycleEventManager;
|
|
+ }
|
|
+
|
|
+ public void lockLifecycleEventRegistration() {
|
|
+ this.allowsLifecycleRegistration = false;
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..ce808520d639581696689a2ab85de00d85aa0ee3
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/LifecycleEventRunner.java
|
|
@@ -0,0 +1,100 @@
|
|
+package io.papermc.paper.plugin.lifecycle.event;
|
|
+
|
|
+import io.papermc.paper.plugin.lifecycle.event.registrar.PaperRegistrar;
|
|
+import io.papermc.paper.plugin.lifecycle.event.registrar.RegistrarEvent;
|
|
+import io.papermc.paper.plugin.lifecycle.event.registrar.RegistrarEventImpl;
|
|
+import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
|
|
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
|
+import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
|
|
+import io.papermc.paper.plugin.lifecycle.event.types.OwnerAwareLifecycleEvent;
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+import java.util.function.Predicate;
|
|
+import org.bukkit.plugin.Plugin;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class LifecycleEventRunner {
|
|
+
|
|
+ public static final LifecycleEventRunner INSTANCE = new LifecycleEventRunner();
|
|
+
|
|
+ private final List<LifecycleEventType<?, ?, ?>> lifecycleEventTypes = new ArrayList<>();
|
|
+ private boolean blockPluginReloading = false;
|
|
+
|
|
+ public <O extends LifecycleEventOwner> void checkRegisteredHandler(final O owner, final AbstractLifecycleEventType<O, ?, ?> eventType) {
|
|
+ /*
|
|
+ Lifecycle event handlers for reloadable events that are registered from the BootstrapContext prevent
|
|
+ the server from reloading plugins. This is because reloading plugins requires disabling all the plugins,
|
|
+ running the reload logic (which would include places where these events should fire) and then re-enabling plugins.
|
|
+ */
|
|
+ if (eventType.blocksReloading(owner)) {
|
|
+ this.blockPluginReloading = true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean blocksPluginReloading() {
|
|
+ return this.blockPluginReloading;
|
|
+ }
|
|
+
|
|
+ public <O extends LifecycleEventOwner, E extends LifecycleEvent, ET extends LifecycleEventType<O, E, ?>> void addEventType(final ET eventType) {
|
|
+ this.lifecycleEventTypes.add(eventType);
|
|
+ }
|
|
+
|
|
+ public <O extends LifecycleEventOwner, E extends PaperLifecycleEvent> void callEvent(final LifecycleEventType<O, ? super E, ?> eventType, final E event) {
|
|
+ this.callEvent(eventType, event, $ -> true);
|
|
+ }
|
|
+
|
|
+ public <O extends LifecycleEventOwner, E extends PaperLifecycleEvent> void callEvent(final LifecycleEventType<O, ? super E, ?> eventType, final E event, final Predicate<? super O> ownerPredicate) {
|
|
+ final AbstractLifecycleEventType<O, ? super E, ?> lifecycleEventType = (AbstractLifecycleEventType<O, ? super E, ?>) eventType;
|
|
+ lifecycleEventType.forEachHandler(event, registeredHandler -> {
|
|
+ try {
|
|
+ if (event instanceof final OwnerAwareLifecycleEvent<?> ownerAwareEvent) {
|
|
+ ownerAwareGenericHelper(ownerAwareEvent, registeredHandler.owner());
|
|
+ }
|
|
+ registeredHandler.lifecycleEventHandler().run(event);
|
|
+ } catch (final Throwable ex) {
|
|
+ throw new RuntimeException("Could not run '%s' lifecycle event handler from %s".formatted(lifecycleEventType.name(), registeredHandler.owner().getPluginMeta().getDisplayName()), ex);
|
|
+ } finally {
|
|
+ if (event instanceof final OwnerAwareLifecycleEvent<?> ownerAwareEvent) {
|
|
+ ownerAwareEvent.setOwner(null);
|
|
+ }
|
|
+ }
|
|
+ }, handler -> ownerPredicate.test(handler.owner()));
|
|
+ event.invalidate();
|
|
+ }
|
|
+
|
|
+ private static <O extends LifecycleEventOwner> void ownerAwareGenericHelper(final OwnerAwareLifecycleEvent<O> event, final LifecycleEventOwner possibleOwner) {
|
|
+ final @Nullable O owner = event.castOwner(possibleOwner);
|
|
+ if (owner != null) {
|
|
+ event.setOwner(owner);
|
|
+ } else {
|
|
+ throw new IllegalStateException("Found invalid owner " + possibleOwner + " for event " + event);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public void unregisterAllEventHandlersFor(final Plugin plugin) {
|
|
+ for (final LifecycleEventType<?, ?, ?> lifecycleEventType : this.lifecycleEventTypes) {
|
|
+ this.removeEventHandlersOwnedBy(lifecycleEventType, plugin);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private <O extends LifecycleEventOwner> void removeEventHandlersOwnedBy(final LifecycleEventType<O, ?, ?> eventType, final Plugin possibleOwner) {
|
|
+ final AbstractLifecycleEventType<O, ?, ?> lifecycleEventType = (AbstractLifecycleEventType<O, ?, ?>) eventType;
|
|
+ lifecycleEventType.removeMatching(registeredHandler -> registeredHandler.owner().getPluginMeta().getName().equals(possibleOwner.getPluginMeta().getName()));
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public <O extends LifecycleEventOwner, R extends PaperRegistrar<? super O>> void callStaticRegistrarEvent(final LifecycleEventType<O, ? extends RegistrarEvent<? super R>, ?> lifecycleEventType, final R registrar, final Class<? extends O> ownerClass) {
|
|
+ this.callEvent((LifecycleEventType<O, RegistrarEvent<? super R>, ?>) lifecycleEventType, new RegistrarEventImpl<>(registrar, ownerClass), ownerClass::isInstance);
|
|
+ }
|
|
+
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public <O extends LifecycleEventOwner, R extends PaperRegistrar<? super O>> void callReloadableRegistrarEvent(final LifecycleEventType<O, ? extends ReloadableRegistrarEvent<? super R>, ?> lifecycleEventType, final R registrar, final Class<? extends O> ownerClass, final ReloadableRegistrarEvent.Cause cause) {
|
|
+ this.callEvent((LifecycleEventType<O, ReloadableRegistrarEvent<? super R>, ?>) lifecycleEventType, new RegistrarEventImpl.ReloadableImpl<>(registrar, ownerClass, cause), ownerClass::isInstance);
|
|
+ }
|
|
+
|
|
+ private LifecycleEventRunner() {
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEvent.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEvent.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..e941405269a773e8a77e26ffd1afd84f53fadff5
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEvent.java
|
|
@@ -0,0 +1,10 @@
|
|
+package io.papermc.paper.plugin.lifecycle.event;
|
|
+
|
|
+public interface PaperLifecycleEvent extends LifecycleEvent {
|
|
+
|
|
+ // called after all handlers have been run. Can be
|
|
+ // used to invalid various contexts to plugins can't
|
|
+ // try to re-use them by storing them from the event
|
|
+ default void invalidate() {
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEventManager.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEventManager.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..d05334016bd01201c755dea04c0cea56b6dfcb50
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/PaperLifecycleEventManager.java
|
|
@@ -0,0 +1,26 @@
|
|
+package io.papermc.paper.plugin.lifecycle.event;
|
|
+
|
|
+import com.google.common.base.Preconditions;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.AbstractLifecycleEventHandlerConfiguration;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.LifecycleEventHandlerConfiguration;
|
|
+import java.util.function.BooleanSupplier;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public final class PaperLifecycleEventManager<O extends LifecycleEventOwner> implements LifecycleEventManager<O> {
|
|
+
|
|
+ private final O owner;
|
|
+ public final BooleanSupplier registrationCheck;
|
|
+
|
|
+ public PaperLifecycleEventManager(final O owner, final BooleanSupplier registrationCheck) {
|
|
+ this.owner = owner;
|
|
+ this.registrationCheck = registrationCheck;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void registerEventHandler(final LifecycleEventHandlerConfiguration<? super O> handlerConfiguration) {
|
|
+ Preconditions.checkState(this.registrationCheck.getAsBoolean(), "Cannot register lifecycle event handlers");
|
|
+ ((AbstractLifecycleEventHandlerConfiguration<? super O, ?>) handlerConfiguration).registerFrom(this.owner);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/AbstractLifecycleEventHandlerConfiguration.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/AbstractLifecycleEventHandlerConfiguration.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..fa216e6fd804859293385ed43c53dfca057f317f
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/AbstractLifecycleEventHandlerConfiguration.java
|
|
@@ -0,0 +1,28 @@
|
|
+package io.papermc.paper.plugin.lifecycle.event.handler.configuration;
|
|
+
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
|
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public abstract class AbstractLifecycleEventHandlerConfiguration<O extends LifecycleEventOwner, E extends LifecycleEvent> implements LifecycleEventHandlerConfiguration<O> {
|
|
+
|
|
+ private final LifecycleEventHandler<? super E> handler;
|
|
+ private final AbstractLifecycleEventType<O, E, ?> type;
|
|
+
|
|
+ protected AbstractLifecycleEventHandlerConfiguration(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?> type) {
|
|
+ this.handler = handler;
|
|
+ this.type = type;
|
|
+ }
|
|
+
|
|
+ public final void registerFrom(final O owner) {
|
|
+ this.type.tryRegister(owner, this);
|
|
+ }
|
|
+
|
|
+ public LifecycleEventHandler<? super E> handler() {
|
|
+ return this.handler;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfigurationImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfigurationImpl.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..ab444d60d72bd692843052df5d7b24fbb5621cf7
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/MonitorLifecycleEventHandlerConfigurationImpl.java
|
|
@@ -0,0 +1,28 @@
|
|
+package io.papermc.paper.plugin.lifecycle.event.handler.configuration;
|
|
+
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
|
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class MonitorLifecycleEventHandlerConfigurationImpl<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventHandlerConfiguration<O, E> implements MonitorLifecycleEventHandlerConfiguration<O> {
|
|
+
|
|
+ private boolean monitor = false;
|
|
+
|
|
+ public MonitorLifecycleEventHandlerConfigurationImpl(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?> eventType) {
|
|
+ super(handler, eventType);
|
|
+ }
|
|
+
|
|
+ public boolean isMonitor() {
|
|
+ return this.monitor;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public MonitorLifecycleEventHandlerConfiguration<O> monitor() {
|
|
+ this.monitor = true;
|
|
+ return this;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfigurationImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfigurationImpl.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..ccdad31717bf12b844cbeaf11a49247485ec77f1
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/handler/configuration/PrioritizedLifecycleEventHandlerConfigurationImpl.java
|
|
@@ -0,0 +1,40 @@
|
|
+package io.papermc.paper.plugin.lifecycle.event.handler.configuration;
|
|
+
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
|
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
|
+import java.util.OptionalInt;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class PrioritizedLifecycleEventHandlerConfigurationImpl<O extends LifecycleEventOwner, E extends LifecycleEvent>
|
|
+ extends AbstractLifecycleEventHandlerConfiguration<O, E>
|
|
+ implements PrioritizedLifecycleEventHandlerConfiguration<O> {
|
|
+
|
|
+ private static final OptionalInt DEFAULT_PRIORITY = OptionalInt.of(0);
|
|
+ private static final OptionalInt MONITOR_PRIORITY = OptionalInt.empty();
|
|
+
|
|
+ private OptionalInt priority = DEFAULT_PRIORITY;
|
|
+
|
|
+ public PrioritizedLifecycleEventHandlerConfigurationImpl(final LifecycleEventHandler<? super E> handler, final AbstractLifecycleEventType<O, E, ?> eventType) {
|
|
+ super(handler, eventType);
|
|
+ }
|
|
+
|
|
+ public OptionalInt priority() {
|
|
+ return this.priority;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public PrioritizedLifecycleEventHandlerConfiguration<O> priority(final int priority) {
|
|
+ this.priority = OptionalInt.of(priority);
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public PrioritizedLifecycleEventHandlerConfiguration<O> monitor() {
|
|
+ this.priority = MONITOR_PRIORITY;
|
|
+ return this;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/PaperRegistrar.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/PaperRegistrar.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b2586c881988fbabe07eef1b43eb1b55f2d3fa52
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/PaperRegistrar.java
|
|
@@ -0,0 +1,15 @@
|
|
+package io.papermc.paper.plugin.lifecycle.event.registrar;
|
|
+
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public interface PaperRegistrar<O extends LifecycleEventOwner> extends Registrar {
|
|
+
|
|
+ void setCurrentContext(@Nullable O owner);
|
|
+
|
|
+ default void invalidate() {
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEventImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEventImpl.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..6d530c52aaf0dc2cdfe3bd56af557274a7f44256
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/registrar/RegistrarEventImpl.java
|
|
@@ -0,0 +1,70 @@
|
|
+package io.papermc.paper.plugin.lifecycle.event.registrar;
|
|
+
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
|
|
+import io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEvent;
|
|
+import io.papermc.paper.plugin.lifecycle.event.types.OwnerAwareLifecycleEvent;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class RegistrarEventImpl<R extends PaperRegistrar<? super O>, O extends LifecycleEventOwner> implements PaperLifecycleEvent, OwnerAwareLifecycleEvent<O>, RegistrarEvent<R> {
|
|
+
|
|
+ private final R registrar;
|
|
+ private final Class<? extends O> ownerClass;
|
|
+
|
|
+ public RegistrarEventImpl(final R registrar, final Class<? extends O> ownerClass) {
|
|
+ this.registrar = registrar;
|
|
+ this.ownerClass = ownerClass;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public R registrar() {
|
|
+ return this.registrar;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public final void setOwner(final @Nullable O owner) {
|
|
+ this.registrar.setCurrentContext(owner);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public final @Nullable O castOwner(final LifecycleEventOwner owner) {
|
|
+ return this.ownerClass.isInstance(owner) ? this.ownerClass.cast(owner) : null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void invalidate() {
|
|
+ this.registrar.invalidate();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "RegistrarEventImpl{" +
|
|
+ "registrar=" + this.registrar +
|
|
+ ", ownerClass=" + this.ownerClass +
|
|
+ '}';
|
|
+ }
|
|
+
|
|
+ public static class ReloadableImpl<R extends PaperRegistrar<? super O>, O extends LifecycleEventOwner> extends RegistrarEventImpl<R, O> implements ReloadableRegistrarEvent<R> {
|
|
+
|
|
+ private final ReloadableRegistrarEvent.Cause cause;
|
|
+
|
|
+ public ReloadableImpl(final R registrar, final Class<? extends O> ownerClass, final Cause cause) {
|
|
+ super(registrar, ownerClass);
|
|
+ this.cause = cause;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Cause cause() {
|
|
+ return this.cause;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "ReloadableImpl{" +
|
|
+ "cause=" + this.cause +
|
|
+ "} " + super.toString();
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/AbstractLifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/AbstractLifecycleEventType.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..01a4e9a36a9970f30ed9f9236fc5a4a1cf71844e
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/AbstractLifecycleEventType.java
|
|
@@ -0,0 +1,62 @@
|
|
+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.LifecycleEventOwner;
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.AbstractLifecycleEventHandlerConfiguration;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.LifecycleEventHandlerConfiguration;
|
|
+import java.util.function.Consumer;
|
|
+import java.util.function.Predicate;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public abstract class AbstractLifecycleEventType<O extends LifecycleEventOwner, E extends LifecycleEvent, C extends LifecycleEventHandlerConfiguration<O>> implements LifecycleEventType<O, E, C> {
|
|
+
|
|
+ private final String name;
|
|
+ private final Class<? extends O> ownerType;
|
|
+
|
|
+ protected AbstractLifecycleEventType(final String name, final Class<? extends O> ownerType) {
|
|
+ this.name = name;
|
|
+ this.ownerType = ownerType;
|
|
+ LifecycleEventRunner.INSTANCE.addEventType(this);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String name() {
|
|
+ return this.name;
|
|
+ }
|
|
+
|
|
+ private void verifyOwner(final O owner) {
|
|
+ if (!this.ownerType.isInstance(owner)) {
|
|
+ throw new IllegalArgumentException("You cannot register the lifecycle event '" + this.name + "' on " + owner);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean blocksReloading(final O eventOwner) {
|
|
+ return eventOwner instanceof BootstrapContext;
|
|
+ }
|
|
+
|
|
+ public abstract boolean hasHandlers();
|
|
+
|
|
+ public abstract void forEachHandler(E event, Consumer<RegisteredHandler<O, E>> consumer, Predicate<RegisteredHandler<O, E>> predicate);
|
|
+
|
|
+ public abstract void removeMatching(Predicate<RegisteredHandler<O, E>> predicate);
|
|
+
|
|
+ protected abstract void register(O owner, AbstractLifecycleEventHandlerConfiguration<O, E> config);
|
|
+
|
|
+ public final void tryRegister(final O owner, final AbstractLifecycleEventHandlerConfiguration<O, E> config) {
|
|
+ this.verifyOwner(owner);
|
|
+ LifecycleEventRunner.INSTANCE.checkRegisteredHandler(owner, this);
|
|
+ this.register(owner, config);
|
|
+ }
|
|
+
|
|
+ public record RegisteredHandler<O extends LifecycleEventOwner, E extends LifecycleEvent>(O owner, AbstractLifecycleEventHandlerConfiguration<O, E> config) {
|
|
+
|
|
+ public LifecycleEventHandler<? super E> lifecycleEventHandler() {
|
|
+ return this.config().handler();
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b11346e04bb16c3238f32deb87dbd680e261d4d2
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java
|
|
@@ -0,0 +1,25 @@
|
|
+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 io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public final class LifecycleEventTypeProviderImpl implements LifecycleEventTypeProvider {
|
|
+
|
|
+ public static LifecycleEventTypeProviderImpl instance() {
|
|
+ return (LifecycleEventTypeProviderImpl) LifecycleEventTypeProvider.provider();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Monitorable<O, E> monitor(final String name, final Class<? extends O> ownerType) {
|
|
+ return new MonitorableLifecycleEventType<>(name, ownerType);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Prioritizable<O, E> prioritized(final String name, final Class<? extends O> ownerType) {
|
|
+ return new PrioritizableLifecycleEventType.Simple<>(name, ownerType);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/MonitorableLifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/MonitorableLifecycleEventType.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..abb969cf6ed967fe7720c56d3b3157bd1b74700d
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/MonitorableLifecycleEventType.java
|
|
@@ -0,0 +1,63 @@
|
|
+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 io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.AbstractLifecycleEventHandlerConfiguration;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.MonitorLifecycleEventHandlerConfiguration;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.MonitorLifecycleEventHandlerConfigurationImpl;
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+import java.util.function.Consumer;
|
|
+import java.util.function.Predicate;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public class MonitorableLifecycleEventType<O extends LifecycleEventOwner, E extends LifecycleEvent> extends AbstractLifecycleEventType<O, E, MonitorLifecycleEventHandlerConfiguration<O>> implements LifecycleEventType.Monitorable<O, E> {
|
|
+
|
|
+ final List<RegisteredHandler<O, E>> handlers = new ArrayList<>();
|
|
+ int nonMonitorIdx = 0;
|
|
+
|
|
+ public MonitorableLifecycleEventType(final String name, final Class<? extends O> ownerType) {
|
|
+ super(name, ownerType);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasHandlers() {
|
|
+ return !this.handlers.isEmpty();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public MonitorLifecycleEventHandlerConfigurationImpl<O, E> newHandler(final LifecycleEventHandler<? super E> handler) {
|
|
+ return new MonitorLifecycleEventHandlerConfigurationImpl<>(handler, this);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void register(final O owner, final AbstractLifecycleEventHandlerConfiguration<O, E> config) {
|
|
+ if (!(config instanceof final MonitorLifecycleEventHandlerConfigurationImpl<?,?> monitor)) {
|
|
+ throw new IllegalArgumentException("Configuration must be a MonitorLifecycleEventHandlerConfiguration");
|
|
+ }
|
|
+ final RegisteredHandler<O, E> registeredHandler = new RegisteredHandler<>(owner, config);
|
|
+ if (!monitor.isMonitor()) {
|
|
+ this.handlers.add(this.nonMonitorIdx, registeredHandler);
|
|
+ this.nonMonitorIdx++;
|
|
+ } else {
|
|
+ this.handlers.add(registeredHandler);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void forEachHandler(final E event, final Consumer<RegisteredHandler<O, E>> consumer, final Predicate<RegisteredHandler<O, E>> predicate) {
|
|
+ for (final RegisteredHandler<O, E> handler : this.handlers) {
|
|
+ if (predicate.test(handler)) {
|
|
+ consumer.accept(handler);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void removeMatching(final Predicate<RegisteredHandler<O, E>> predicate) {
|
|
+ this.handlers.removeIf(predicate);
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/OwnerAwareLifecycleEvent.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/OwnerAwareLifecycleEvent.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..3e7e7474f301c0725fa2bcd6e19e476fc35f2d5a
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/OwnerAwareLifecycleEvent.java
|
|
@@ -0,0 +1,15 @@
|
|
+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 org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public interface OwnerAwareLifecycleEvent<O extends LifecycleEventOwner> extends LifecycleEvent {
|
|
+
|
|
+ void setOwner(@Nullable O owner);
|
|
+
|
|
+ @Nullable O castOwner(LifecycleEventOwner owner);
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PrioritizableLifecycleEventType.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PrioritizableLifecycleEventType.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..2ed622a61ddc37b11888867770b513909b9a2ecc
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PrioritizableLifecycleEventType.java
|
|
@@ -0,0 +1,79 @@
|
|
+package io.papermc.paper.plugin.lifecycle.event.types;
|
|
+
|
|
+import com.google.common.base.Preconditions;
|
|
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
|
|
+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.AbstractLifecycleEventHandlerConfiguration;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfiguration;
|
|
+import io.papermc.paper.plugin.lifecycle.event.handler.configuration.PrioritizedLifecycleEventHandlerConfigurationImpl;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Comparator;
|
|
+import java.util.List;
|
|
+import java.util.function.Consumer;
|
|
+import java.util.function.Predicate;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public abstract class PrioritizableLifecycleEventType<
|
|
+ O extends LifecycleEventOwner,
|
|
+ E extends LifecycleEvent,
|
|
+ C extends PrioritizedLifecycleEventHandlerConfiguration<O>
|
|
+> extends AbstractLifecycleEventType<O, E, C> {
|
|
+
|
|
+ private static final Comparator<RegisteredHandler<?, ?>> COMPARATOR = Comparator.comparing(handler -> ((PrioritizedLifecycleEventHandlerConfigurationImpl<?, ?>) handler.config()).priority(), (o1, o2) -> {
|
|
+ if (o1.equals(o2)) {
|
|
+ return 0;
|
|
+ } else if (o1.isEmpty()) {
|
|
+ return 1;
|
|
+ } else if (o2.isEmpty()) {
|
|
+ return -1;
|
|
+ } else {
|
|
+ return Integer.compare(o1.getAsInt(), o2.getAsInt());
|
|
+ }
|
|
+ });
|
|
+
|
|
+ private final List<RegisteredHandler<O, E>> handlers = new ArrayList<>();
|
|
+
|
|
+ public PrioritizableLifecycleEventType(final String name, final Class<? extends O> ownerType) {
|
|
+ super(name, ownerType);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasHandlers() {
|
|
+ return !this.handlers.isEmpty();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void register(final O owner, final AbstractLifecycleEventHandlerConfiguration<O, E> config) {
|
|
+ Preconditions.checkArgument(config instanceof PrioritizedLifecycleEventHandlerConfigurationImpl<?, ?>, "Configuration must be a PrioritizedLifecycleEventHandlerConfiguration");
|
|
+ this.handlers.add(new RegisteredHandler<>(owner, config));
|
|
+ this.handlers.sort(COMPARATOR);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void forEachHandler(final E event, final Consumer<RegisteredHandler<O, E>> consumer, final Predicate<RegisteredHandler<O, E>> predicate) {
|
|
+ for (final RegisteredHandler<O, E> handler : this.handlers) {
|
|
+ if (predicate.test(handler)) {
|
|
+ consumer.accept(handler);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void removeMatching(final Predicate<RegisteredHandler<O, E>> predicate) {
|
|
+ this.handlers.removeIf(predicate);
|
|
+ }
|
|
+
|
|
+ public static class Simple<O extends LifecycleEventOwner, E extends LifecycleEvent> extends PrioritizableLifecycleEventType<O, E, PrioritizedLifecycleEventHandlerConfiguration<O>> implements LifecycleEventType.Prioritizable<O, E> {
|
|
+ public Simple(final String name, final Class<? extends O> ownerType) {
|
|
+ super(name, ownerType);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public PrioritizedLifecycleEventHandlerConfiguration<O> newHandler(final LifecycleEventHandler<? super E> handler) {
|
|
+ return new PrioritizedLifecycleEventHandlerConfigurationImpl<>(handler, this);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java
|
|
index 834b85f24df023642f8abf7213fe578ac8c17a3e..3e82ea07ca4194844c5528446e2c4a46ff4acee5 100644
|
|
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java
|
|
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java
|
|
@@ -293,6 +293,15 @@ class PaperPluginInstanceManager {
|
|
+ pluginName + " (Is it up to date?)", ex, plugin); // Paper
|
|
}
|
|
|
|
+ // Paper start - lifecycle event system
|
|
+ try {
|
|
+ io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.unregisterAllEventHandlersFor(plugin);
|
|
+ } catch (Throwable ex) {
|
|
+ this.handlePluginException("Error occurred (in the plugin loader) while unregistering lifecycle event handlers for "
|
|
+ + pluginName + " (Is it up to date?)", ex, plugin);
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
try {
|
|
this.server.getMessenger().unregisterIncomingPluginChannel(plugin);
|
|
this.server.getMessenger().unregisterOutgoingPluginChannel(plugin);
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java b/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java
|
|
index 2e96308696e131f3f013469a395e5ddda2c5d529..65a66e484c1c39c5f41d97db52f31c67b4479d20 100644
|
|
--- a/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java
|
|
+++ b/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java
|
|
@@ -32,8 +32,9 @@ public class BootstrapProviderStorage extends SimpleProviderStorage<PluginBootst
|
|
@Override
|
|
public boolean load(PluginProvider<PluginBootstrap> provider, PluginBootstrap provided) {
|
|
try {
|
|
- BootstrapContext context = PluginBootstrapContextImpl.create(provider, PluginInitializerManager.instance().pluginDirectoryPath());
|
|
+ PluginBootstrapContextImpl context = PluginBootstrapContextImpl.create(provider, PluginInitializerManager.instance().pluginDirectoryPath()); // Paper - lifecycle events
|
|
provided.bootstrap(context);
|
|
+ context.lockLifecycleEventRegistration(); // Paper - lifecycle events
|
|
return true;
|
|
} catch (Throwable e) {
|
|
LOGGER.error("Failed to run bootstrapper for %s. This plugin will not be loaded.".formatted(provider.getSource()), e);
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
index eaea08530ca864158a2fa15dca38ca0c25a49bde..b4a823a62d7088262b7f799c977aec71f8778ff5 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
@@ -1062,6 +1062,11 @@ public final class CraftServer implements Server {
|
|
|
|
@Override
|
|
public void reload() {
|
|
+ // Paper start - lifecycle events
|
|
+ if (io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.blocksPluginReloading()) {
|
|
+ throw new IllegalStateException("A lifecycle event handler has been registered which makes reloading plugins not possible");
|
|
+ }
|
|
+ // Paper end - lifecycle events
|
|
org.spigotmc.WatchdogThread.hasStarted = false; // Paper - Disable watchdog early timeout on reload
|
|
this.reloadCount++;
|
|
this.configuration = YamlConfiguration.loadConfiguration(this.getConfigFile());
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
|
index 44abd5742f2682b6224d6de90d52312000d20429..0debfd0f95c063566280556dbd755c717e3aa266 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
|
@@ -649,6 +649,13 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
|
}
|
|
// Paper end - spawn egg color visibility
|
|
|
|
+ // Paper start - lifecycle event API
|
|
+ @Override
|
|
+ public io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager<org.bukkit.plugin.Plugin> createPluginLifecycleEventManager(final org.bukkit.plugin.java.JavaPlugin plugin, final java.util.function.BooleanSupplier registrationCheck) {
|
|
+ return new io.papermc.paper.plugin.lifecycle.event.PaperLifecycleEventManager<>(plugin, registrationCheck);
|
|
+ }
|
|
+ // Paper end - lifecycle event API
|
|
+
|
|
/**
|
|
* This helper class represents the different NBT Tags.
|
|
* <p>
|
|
diff --git a/src/main/resources/META-INF/services/io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventTypeProvider b/src/main/resources/META-INF/services/io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventTypeProvider
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..808b1192b60348ad05f0bfbdeda6f94df4876743
|
|
--- /dev/null
|
|
+++ b/src/main/resources/META-INF/services/io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventTypeProvider
|
|
@@ -0,0 +1 @@
|
|
+io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventTypeProviderImpl
|
|
diff --git a/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java b/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java
|
|
index 1d14f530ef888102e47eeeaf0d1a6076e51871c4..90cf0c702ca2ff9de64d9718ecba5f2d128953a6 100644
|
|
--- a/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java
|
|
+++ b/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java
|
|
@@ -143,4 +143,11 @@ public class PaperTestPlugin extends PluginBase {
|
|
public List<String> 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<org.bukkit.plugin.Plugin> getLifecycleManager() {
|
|
+ throw new UnsupportedOperationException("Not supported.");
|
|
+ }
|
|
+ // Paper end - lifecycle events
|
|
}
|