From 7684ac5d3a666abc6f937507547409956b70ade5 Mon Sep 17 00:00:00 2001 From: Luck Date: Mon, 2 Apr 2018 17:26:02 +0100 Subject: [PATCH] Add extra parameter to EventBus#subscribe which allows a handler to be bound to a plugin --- .../lucko/luckperms/api/event/EventBus.java | 33 +++++- .../luckperms/api/event/EventHandler.java | 4 +- .../bukkit/BukkitCommandExecutor.java | 2 +- .../luckperms/bukkit/BukkitEventBus.java | 60 ++++++++++ .../luckperms/bukkit/LPBukkitPlugin.java | 7 ++ .../bungee/BungeeCommandExecutor.java | 2 +- .../luckperms/bungee/BungeeEventBus.java | 97 +++++++++++++++ .../luckperms/bungee/LPBungeePlugin.java | 7 ++ ...rmsEventBus.java => AbstractEventBus.java} | 111 ++++++++++++++---- .../luckperms/common/event/EventFactory.java | 10 +- .../common/event/LuckPermsEventHandler.java | 43 ++++++- .../plugin/AbstractLuckPermsPlugin.java | 4 +- .../luckperms/nukkit/LPNukkitPlugin.java | 7 ++ .../nukkit/NukkitCommandExecutor.java | 2 +- .../luckperms/nukkit/NukkitEventBus.java | 60 ++++++++++ .../luckperms/sponge/LPSpongePlugin.java | 7 ++ .../sponge/SpongeCommandExecutor.java | 2 +- .../luckperms/sponge/SpongeEventBus.java | 71 +++++++++++ 18 files changed, 488 insertions(+), 41 deletions(-) create mode 100644 bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitEventBus.java create mode 100644 bungee/src/main/java/me/lucko/luckperms/bungee/BungeeEventBus.java rename common/src/main/java/me/lucko/luckperms/common/event/{LuckPermsEventBus.java => AbstractEventBus.java} (66%) create mode 100644 nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitEventBus.java create mode 100644 sponge/src/main/java/me/lucko/luckperms/sponge/SpongeEventBus.java diff --git a/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java b/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java index a0b5470da..5550e1a31 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java @@ -31,16 +31,20 @@ import java.util.function.Consumer; import javax.annotation.Nonnull; /** - * The internal LuckPerms event bus. + * The LuckPerms event bus. * - *

LuckPerms events are posted to any listeners registered with the bus.

+ *

Used to subscribe (or "listen") to LuckPerms events.

* * @since 3.0 */ public interface EventBus { /** - * Subscribes to an event. + * Registers a new subscription to the given event. + * + *

The returned {@link EventHandler} instance encapsulates the subscription state. It has + * methods which can be used to terminate the subscription, or view stats about the nature of + * the subscription.

* * @param eventClass the event class * @param handler the event handler @@ -48,7 +52,28 @@ public interface EventBus { * @return an event handler instance representing this subscription */ @Nonnull - EventHandler subscribe(@Nonnull Class eventClass, @Nonnull Consumer handler); + EventHandler subscribe(@Nonnull Class eventClass, @Nonnull Consumer handler); + + /** + * Registers a new subscription to the given event. + * + *

The returned {@link EventHandler} instance encapsulates the subscription state. It has + * methods which can be used to terminate the subscription, or view stats about the nature of + * the subscription.

+ * + *

Unlike {@link #subscribe(Class, Consumer)}, this method accepts an additional parameter + * for {@code plugin}. This object must be a "plugin" instance on the platform, and is used to + * automatically {@link EventHandler#unregister() unregister} the subscription when the + * corresponding plugin is disabled.

+ * + * @param the event class + * @param plugin a plugin instance to bind the subscription to. + * @param eventClass the event class + * @param handler the event handler + * @return an event handler instance representing this subscription + */ + @Nonnull + EventHandler subscribe(Object plugin, @Nonnull Class eventClass, @Nonnull Consumer handler); /** * Gets a set of all registered handlers for a given event. diff --git a/api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java b/api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java index 11daf89c8..6d6389f95 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java @@ -30,7 +30,7 @@ import java.util.function.Consumer; import javax.annotation.Nonnull; /** - * Represents a handler for a LuckPerms event + * Represents a subscription to a {@link LuckPermsEvent}. * * @param the event class */ @@ -64,7 +64,7 @@ public interface EventHandler extends AutoCloseable { * @return the event consumer */ @Nonnull - Consumer getConsumer(); + Consumer getConsumer(); /** * Gets the number of times this handler has been called diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitCommandExecutor.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitCommandExecutor.java index 8aa68d018..9a2d3509e 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitCommandExecutor.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitCommandExecutor.java @@ -45,7 +45,7 @@ public class BukkitCommandExecutor extends CommandManager implements CommandExec private final LPBukkitPlugin plugin; - BukkitCommandExecutor(LPBukkitPlugin plugin) { + public BukkitCommandExecutor(LPBukkitPlugin plugin) { super(plugin); this.plugin = plugin; } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitEventBus.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitEventBus.java new file mode 100644 index 000000000..cb6219c4a --- /dev/null +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitEventBus.java @@ -0,0 +1,60 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.bukkit; + +import me.lucko.luckperms.common.api.LuckPermsApiProvider; +import me.lucko.luckperms.common.event.AbstractEventBus; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.plugin.Plugin; + +public class BukkitEventBus extends AbstractEventBus implements Listener { + public BukkitEventBus(LPBukkitPlugin plugin, LuckPermsApiProvider apiProvider) { + super(plugin, apiProvider); + + // register listener + LPBukkitBootstrap bootstrap = plugin.getBootstrap(); + bootstrap.getServer().getPluginManager().registerEvents(this, bootstrap); + } + + @Override + protected Plugin checkPlugin(Object plugin) throws IllegalArgumentException { + if (plugin instanceof Plugin) { + return (Plugin) plugin; + } + + throw new IllegalArgumentException("Object " + plugin + " (" + plugin.getClass().getName() + ") is not a plugin."); + } + + @EventHandler + public void onPluginDisable(PluginDisableEvent e) { + Plugin plugin = e.getPlugin(); + unregisterHandlers(plugin); + } + +} diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java index e44d44d78..49cbf5ad8 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java @@ -43,11 +43,13 @@ import me.lucko.luckperms.bukkit.model.server.LPDefaultsMap; import me.lucko.luckperms.bukkit.model.server.LPPermissionMap; import me.lucko.luckperms.bukkit.model.server.LPSubscriptionMap; import me.lucko.luckperms.bukkit.vault.VaultHookManager; +import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory; import me.lucko.luckperms.common.command.access.CommandPermission; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter; import me.lucko.luckperms.common.contexts.ContextManager; +import me.lucko.luckperms.common.event.AbstractEventBus; import me.lucko.luckperms.common.listener.ConnectionListener; import me.lucko.luckperms.common.managers.group.StandardGroupManager; import me.lucko.luckperms.common.managers.track.StandardTrackManager; @@ -171,6 +173,11 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin { tryVaultHook(false); } + @Override + protected AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider) { + return new BukkitEventBus(this, apiProvider); + } + public void tryVaultHook(boolean force) { if (this.vaultHookManager != null) { return; // already hooked diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeCommandExecutor.java b/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeCommandExecutor.java index 3c04f98ee..d6d08ae7c 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeCommandExecutor.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeCommandExecutor.java @@ -45,7 +45,7 @@ public class BungeeCommandExecutor extends Command implements TabExecutor { private final LPBungeePlugin plugin; private final CommandManager manager; - BungeeCommandExecutor(LPBungeePlugin plugin, CommandManager manager) { + public BungeeCommandExecutor(LPBungeePlugin plugin, CommandManager manager) { super("luckpermsbungee", null, "lpb", "bperm", "bperms", "bpermission", "bpermissions"); this.plugin = plugin; this.manager = manager; diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeEventBus.java b/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeEventBus.java new file mode 100644 index 000000000..e7ba49caf --- /dev/null +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeEventBus.java @@ -0,0 +1,97 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.bungee; + +import me.lucko.luckperms.common.api.LuckPermsApiProvider; +import me.lucko.luckperms.common.event.AbstractEventBus; + +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.api.plugin.Plugin; + +import java.util.logging.Handler; +import java.util.logging.LogRecord; + +public class BungeeEventBus extends AbstractEventBus implements Listener { + private final LPBungeeBootstrap bootstrap; + + public BungeeEventBus(LPBungeePlugin plugin, LuckPermsApiProvider apiProvider) { + super(plugin, apiProvider); + this.bootstrap = plugin.getBootstrap(); + } + + @Override + protected Plugin checkPlugin(Object plugin) throws IllegalArgumentException { + if (plugin instanceof Plugin) { + Plugin bungeePlugin = (Plugin) plugin; + + // add a custom log handler to effectively listen for the plugin being disabled. + // BungeeCord doesn't really support enabling/disabling plugins at runtime, and as + // such doesn't have a PluginDisableEvent. However, some plugins do exist to reload + // plugins at runtime. We rely on these plugins following the BungeeCord behaviour, + // and #close ing the plugins logger, so we can unregister the listeners. :) + Handler[] handlers = bungeePlugin.getLogger().getHandlers(); + for (Handler handler : handlers) { + if (handler instanceof UnloadHookLoggerHandler) { + return bungeePlugin; + } + } + + bungeePlugin.getLogger().addHandler(new UnloadHookLoggerHandler(bungeePlugin)); + return bungeePlugin; + } + + throw new IllegalArgumentException("Object " + plugin + " (" + plugin.getClass().getName() + ") is not a plugin."); + } + + @Override + public void close() { + for (Plugin plugin : this.bootstrap.getProxy().getPluginManager().getPlugins()) { + for (Handler handler : plugin.getLogger().getHandlers()) { + if (handler instanceof UnloadHookLoggerHandler) { + plugin.getLogger().removeHandler(handler); + } + } + } + + super.close(); + } + + private final class UnloadHookLoggerHandler extends Handler { + private final Plugin plugin; + + private UnloadHookLoggerHandler(Plugin plugin) { + this.plugin = plugin; + } + + @Override + public void close() { + unregisterHandlers(this.plugin); + } + + @Override public void publish(LogRecord record) {} + @Override public void flush() {} + } +} diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java index 1a7086d6b..6905b6ae0 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java @@ -34,10 +34,12 @@ import me.lucko.luckperms.bungee.contexts.RedisBungeeCalculator; import me.lucko.luckperms.bungee.listeners.BungeeConnectionListener; import me.lucko.luckperms.bungee.listeners.BungeePermissionCheckListener; import me.lucko.luckperms.bungee.messaging.BungeeMessagingFactory; +import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory; import me.lucko.luckperms.common.command.CommandManager; import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter; import me.lucko.luckperms.common.contexts.ContextManager; +import me.lucko.luckperms.common.event.AbstractEventBus; import me.lucko.luckperms.common.listener.ConnectionListener; import me.lucko.luckperms.common.managers.group.StandardGroupManager; import me.lucko.luckperms.common.managers.track.StandardTrackManager; @@ -139,6 +141,11 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin { } + @Override + protected AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider) { + return new BungeeEventBus(this, apiProvider); + } + @Override protected void registerApiOnPlatform(LuckPermsApi api) { // BungeeCord doesn't have a services manager diff --git a/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventBus.java b/common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java similarity index 66% rename from common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventBus.java rename to common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java index bd79f389f..2b67690a0 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventBus.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java @@ -39,6 +39,7 @@ import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; @@ -51,7 +52,7 @@ import javax.annotation.Nonnull; /** * Simple implementation of EventBus. */ -public class LuckPermsEventBus implements EventBus { +public abstract class AbstractEventBus

implements EventBus, AutoCloseable { /** * The plugin instance @@ -77,7 +78,7 @@ public class LuckPermsEventBus implements EventBus { private final LoadingCache, List>> handlerCache = Caffeine.newBuilder() .build(eventClass -> { ImmutableList.Builder> matched = ImmutableList.builder(); - LuckPermsEventBus.this.handlerMap.asMap().forEach((clazz, handlers) -> { + AbstractEventBus.this.handlerMap.asMap().forEach((clazz, handlers) -> { if (clazz.isAssignableFrom(eventClass)) { matched.addAll(handlers); } @@ -85,29 +86,30 @@ public class LuckPermsEventBus implements EventBus { return matched.build(); }); - public LuckPermsEventBus(LuckPermsPlugin plugin, LuckPermsApiProvider apiProvider) { + protected AbstractEventBus(LuckPermsPlugin plugin, LuckPermsApiProvider apiProvider) { this.plugin = plugin; this.apiProvider = apiProvider; } + public LuckPermsPlugin getPlugin() { + return this.plugin; + } + @Nonnull @Override - public EventHandler subscribe(@Nonnull Class eventClass, @Nonnull Consumer handler) { + public EventHandler subscribe(@Nonnull Class eventClass, @Nonnull Consumer handler) { Objects.requireNonNull(eventClass, "eventClass"); Objects.requireNonNull(handler, "handler"); + return registerSubscription(eventClass, handler, null); + } - if (!eventClass.isInterface()) { - throw new IllegalArgumentException("class " + eventClass + " is not an interface"); - } - if (!LuckPermsEvent.class.isAssignableFrom(eventClass)) { - throw new IllegalArgumentException("class " + eventClass.getName() + " does not implement LuckPermsEvent"); - } - - LuckPermsEventHandler eventHandler = new LuckPermsEventHandler<>(this, eventClass, handler); - this.handlerMap.put(eventClass, eventHandler); - this.handlerCache.invalidateAll(); - - return eventHandler; + @Nonnull + @Override + public EventHandler subscribe(Object plugin, @Nonnull Class eventClass, @Nonnull Consumer handler) { + Objects.requireNonNull(plugin, "plugin"); + Objects.requireNonNull(eventClass, "eventClass"); + Objects.requireNonNull(handler, "handler"); + return registerSubscription(eventClass, handler, checkPlugin(plugin)); } @Nonnull @@ -122,11 +124,79 @@ public class LuckPermsEventBus implements EventBus { return ret.build(); } + /** + * Checks that the given plugin object is a valid plugin instance for the platform + * + * @param plugin the object + * @return a plugin + * @throws IllegalArgumentException if the plugin is invalid + */ + protected abstract P checkPlugin(Object plugin) throws IllegalArgumentException; + + /** + * Registers a subscription for the given class, handler and plugin + * + * @param eventClass the event class + * @param handler the handler + * @param plugin the plugin, nullable + * @param the event type + * @return the resultant handler + */ + private EventHandler registerSubscription(Class eventClass, Consumer handler, Object plugin) { + if (!eventClass.isInterface()) { + throw new IllegalArgumentException("class " + eventClass + " is not an interface"); + } + if (!LuckPermsEvent.class.isAssignableFrom(eventClass)) { + throw new IllegalArgumentException("class " + eventClass.getName() + " does not implement LuckPermsEvent"); + } + + LuckPermsEventHandler eventHandler = new LuckPermsEventHandler<>(this, eventClass, handler, plugin); + this.handlerMap.put(eventClass, eventHandler); + this.handlerCache.invalidateAll(); + + return eventHandler; + } + + /** + * Removes a specific handler from the bus + * + * @param handler the handler to remove + */ public void unregisterHandler(LuckPermsEventHandler handler) { this.handlerMap.remove(handler.getEventClass(), handler); this.handlerCache.invalidateAll(); } + /** + * Removes all handlers for a specific plugin + * + * @param plugin the plugin + */ + protected void unregisterHandlers(P plugin) { + List> handlers = new ArrayList<>(this.handlerMap.values()); + for (LuckPermsEventHandler handler : handlers) { + if (handler.getPlugin() == plugin) { + handler.unregister(); + } + } + } + + /** + * Unregisters all handlers in this event bus + */ + @Override + public void close() { + List> handlers = new ArrayList<>(this.handlerMap.values()); + for (LuckPermsEventHandler handler : handlers) { + handler.unregister(); + } + } + + /** + * Fires the given event to all registered handlers in this event bus + * + * @param event the event to fire + */ public void fireEvent(LuckPermsEvent event) { if (event instanceof AbstractEvent) { ((AbstractEvent) event).setApi(this.apiProvider); @@ -142,14 +212,15 @@ public class LuckPermsEventBus implements EventBus { } } + /** + * Fires the given event asynchronously to all registered handlers in this event bus + * + * @param event the event to fire + */ public void fireEventAsync(LuckPermsEvent event) { if (event instanceof Cancellable) { throw new IllegalArgumentException("cannot call Cancellable event async"); } this.plugin.getBootstrap().getScheduler().doAsync(() -> fireEvent(event)); } - - public LuckPermsPlugin getPlugin() { - return this.plugin; - } } diff --git a/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java b/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java index a0236e965..a76cb481c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java @@ -37,7 +37,6 @@ import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.api.event.cause.DeletionCause; import me.lucko.luckperms.api.event.log.LogBroadcastEvent; import me.lucko.luckperms.api.event.log.LogNotifyEvent; -import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.api.delegates.model.ApiPermissionHolder; import me.lucko.luckperms.common.api.delegates.model.ApiUser; import me.lucko.luckperms.common.event.impl.EventConfigReload; @@ -78,7 +77,6 @@ import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.User; -import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import java.util.Collection; @@ -87,13 +85,13 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; public final class EventFactory { - private final LuckPermsEventBus eventBus; + private final AbstractEventBus eventBus; - public EventFactory(LuckPermsPlugin plugin, LuckPermsApiProvider apiProvider) { - this.eventBus = new LuckPermsEventBus(plugin, apiProvider); + public EventFactory(AbstractEventBus eventBus) { + this.eventBus = eventBus; } - public LuckPermsEventBus getEventBus() { + public AbstractEventBus getEventBus() { return this.eventBus; } diff --git a/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventHandler.java b/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventHandler.java index 9de555b52..aa7b94259 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventHandler.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventHandler.java @@ -33,21 +33,51 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +/** + * Simple implementation of {@link EventHandler}. + * + * @param the event type + */ public class LuckPermsEventHandler implements EventHandler { - private final LuckPermsEventBus eventBus; + /** + * The event bus which created this handler + */ + private final AbstractEventBus eventBus; + + /** + * The event class + */ private final Class eventClass; - private final Consumer consumer; + /** + * The delegate "event handler" + */ + private final Consumer consumer; + /** + * The plugin which "owns" this handler + */ + @Nullable + private final Object plugin; + + /** + * If this handler is active + */ private final AtomicBoolean active = new AtomicBoolean(true); + + /** + * How many times this handler has been called + */ private final AtomicInteger callCount = new AtomicInteger(0); - public LuckPermsEventHandler(LuckPermsEventBus eventBus, Class eventClass, Consumer consumer) { + public LuckPermsEventHandler(AbstractEventBus eventBus, Class eventClass, Consumer consumer, @Nullable Object plugin) { this.eventBus = eventBus; this.eventClass = eventClass; this.consumer = consumer; + this.plugin = plugin; } @Override @@ -91,7 +121,12 @@ public class LuckPermsEventHandler implements EventHan @Nonnull @Override - public Consumer getConsumer() { + public Consumer getConsumer() { return this.consumer; } + + @Nullable + public Object getPlugin() { + return this.plugin; + } } diff --git a/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java b/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java index fd9ddac95..7130d23d8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java +++ b/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java @@ -41,6 +41,7 @@ import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter; import me.lucko.luckperms.common.contexts.LuckPermsCalculator; import me.lucko.luckperms.common.dependencies.DependencyManager; import me.lucko.luckperms.common.dependencies.DependencyRegistry; +import me.lucko.luckperms.common.event.AbstractEventBus; import me.lucko.luckperms.common.event.EventFactory; import me.lucko.luckperms.common.inheritance.InheritanceHandler; import me.lucko.luckperms.common.locale.LocaleManager; @@ -160,7 +161,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin { // register with the LP API this.apiProvider = new LuckPermsApiProvider(this); - this.eventFactory = new EventFactory(this, this.apiProvider); + this.eventFactory = new EventFactory(provideEventBus(this.apiProvider)); ApiRegistrationUtil.registerProvider(this.apiProvider); registerApiOnPlatform(this.apiProvider); @@ -234,6 +235,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin { protected abstract PlatformCalculatorFactory provideCalculatorFactory(); protected abstract void setupContextManager(); protected abstract void setupPlatformHooks(); + protected abstract AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider); protected abstract void registerApiOnPlatform(LuckPermsApi api); protected abstract void registerHousekeepingTasks(); protected abstract void performFinalSetup(); diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitPlugin.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitPlugin.java index 792450aee..36239a3b4 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitPlugin.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitPlugin.java @@ -27,11 +27,13 @@ package me.lucko.luckperms.nukkit; import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory; import me.lucko.luckperms.common.command.access.CommandPermission; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter; import me.lucko.luckperms.common.contexts.ContextManager; +import me.lucko.luckperms.common.event.AbstractEventBus; import me.lucko.luckperms.common.listener.ConnectionListener; import me.lucko.luckperms.common.managers.group.StandardGroupManager; import me.lucko.luckperms.common.managers.track.StandardTrackManager; @@ -162,6 +164,11 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin { } } + @Override + protected AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider) { + return new NukkitEventBus(this, apiProvider); + } + @Override protected void registerApiOnPlatform(LuckPermsApi api) { this.bootstrap.getServer().getServiceManager().register(LuckPermsApi.class, api, this.bootstrap, ServicePriority.NORMAL); diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitCommandExecutor.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitCommandExecutor.java index 06f99c3bc..84e94b187 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitCommandExecutor.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitCommandExecutor.java @@ -38,7 +38,7 @@ import java.util.Arrays; public class NukkitCommandExecutor extends CommandManager implements CommandExecutor { private final LPNukkitPlugin plugin; - NukkitCommandExecutor(LPNukkitPlugin plugin) { + public NukkitCommandExecutor(LPNukkitPlugin plugin) { super(plugin); this.plugin = plugin; } diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitEventBus.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitEventBus.java new file mode 100644 index 000000000..f072d7645 --- /dev/null +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitEventBus.java @@ -0,0 +1,60 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.nukkit; + +import me.lucko.luckperms.common.api.LuckPermsApiProvider; +import me.lucko.luckperms.common.event.AbstractEventBus; + +import cn.nukkit.event.EventHandler; +import cn.nukkit.event.Listener; +import cn.nukkit.event.plugin.PluginDisableEvent; +import cn.nukkit.plugin.Plugin; + +public class NukkitEventBus extends AbstractEventBus implements Listener { + public NukkitEventBus(LPNukkitPlugin plugin, LuckPermsApiProvider apiProvider) { + super(plugin, apiProvider); + + // register listener + LPNukkitBootstrap bootstrap = plugin.getBootstrap(); + bootstrap.getServer().getPluginManager().registerEvents(this, bootstrap); + } + + @Override + protected Plugin checkPlugin(Object plugin) throws IllegalArgumentException { + if (plugin instanceof Plugin) { + return (Plugin) plugin; + } + + throw new IllegalArgumentException("Object " + plugin + " (" + plugin.getClass().getName() + ") is not a plugin."); + } + + @EventHandler + public void onPluginDisable(PluginDisableEvent e) { + Plugin plugin = e.getPlugin(); + unregisterHandlers(plugin); + } + +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java index beec94289..2f6b5ff84 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java @@ -27,12 +27,14 @@ package me.lucko.luckperms.sponge; import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory; import me.lucko.luckperms.common.command.CommandManager; import me.lucko.luckperms.common.command.abstraction.Command; import me.lucko.luckperms.common.command.access.CommandPermission; import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter; import me.lucko.luckperms.common.contexts.ContextManager; +import me.lucko.luckperms.common.event.AbstractEventBus; import me.lucko.luckperms.common.managers.track.StandardTrackManager; import me.lucko.luckperms.common.messaging.MessagingFactory; import me.lucko.luckperms.common.model.User; @@ -159,6 +161,11 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin { } } + @Override + protected AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider) { + return new SpongeEventBus(this, apiProvider); + } + @Override protected void registerApiOnPlatform(LuckPermsApi api) { this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, LuckPermsApi.class, api); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCommandExecutor.java b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCommandExecutor.java index 249b3b301..1d118402b 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCommandExecutor.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCommandExecutor.java @@ -52,7 +52,7 @@ public class SpongeCommandExecutor extends CommandManager implements CommandCall private final LPSpongePlugin plugin; - SpongeCommandExecutor(LPSpongePlugin plugin) { + public SpongeCommandExecutor(LPSpongePlugin plugin) { super(plugin); this.plugin = plugin; } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeEventBus.java b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeEventBus.java new file mode 100644 index 000000000..63b71613d --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeEventBus.java @@ -0,0 +1,71 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.sponge; + +import me.lucko.luckperms.common.api.LuckPermsApiProvider; +import me.lucko.luckperms.common.event.AbstractEventBus; + +import org.spongepowered.api.Sponge; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.cause.EventContextKeys; +import org.spongepowered.api.event.game.GameReloadEvent; +import org.spongepowered.api.plugin.PluginContainer; + +public class SpongeEventBus extends AbstractEventBus { + public SpongeEventBus(LPSpongePlugin plugin, LuckPermsApiProvider apiProvider) { + super(plugin, apiProvider); + + // register listener + LPSpongeBootstrap bootstrap = plugin.getBootstrap(); + bootstrap.getGame().getEventManager().registerListeners(bootstrap, this); + } + + @Override + protected PluginContainer checkPlugin(Object plugin) throws IllegalArgumentException { + if (plugin instanceof PluginContainer) { + return (PluginContainer) plugin; + } + + PluginContainer pluginContainer = Sponge.getPluginManager().fromInstance(plugin).orElse(null); + if (pluginContainer != null) { + return pluginContainer; + } + + throw new IllegalArgumentException("Object " + plugin + " (" + plugin.getClass().getName() + ") is not a plugin."); + } + + @Listener + public void onReload(GameReloadEvent e) { + // sponge doesn't really support unloading of plugins at runtime. + // this probably won't ever work/be useful, but I suppose it's worth a try. + PluginContainer pluginContainer = e.getContext().get(EventContextKeys.PLUGIN).orElse(null); + if (pluginContainer == null) { + return; + } + unregisterHandlers(pluginContainer); + } + +}