Add extra parameter to EventBus#subscribe which allows a handler to be bound to a plugin

This commit is contained in:
Luck
2018-04-02 17:26:02 +01:00
Unverified
parent c13b01da01
commit 7684ac5d3a
18 changed files with 488 additions and 41 deletions
@@ -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<P> implements EventBus, AutoCloseable {
/**
* The plugin instance
@@ -77,7 +78,7 @@ public class LuckPermsEventBus implements EventBus {
private final LoadingCache<Class<? extends LuckPermsEvent>, List<LuckPermsEventHandler<?>>> handlerCache = Caffeine.newBuilder()
.build(eventClass -> {
ImmutableList.Builder<LuckPermsEventHandler<?>> 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 <T extends LuckPermsEvent> EventHandler<T> subscribe(@Nonnull Class<T> eventClass, @Nonnull Consumer<T> handler) {
public <T extends LuckPermsEvent> EventHandler<T> subscribe(@Nonnull Class<T> eventClass, @Nonnull Consumer<? super T> 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<T> eventHandler = new LuckPermsEventHandler<>(this, eventClass, handler);
this.handlerMap.put(eventClass, eventHandler);
this.handlerCache.invalidateAll();
return eventHandler;
@Nonnull
@Override
public <T extends LuckPermsEvent> EventHandler<T> subscribe(Object plugin, @Nonnull Class<T> eventClass, @Nonnull Consumer<? super T> 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 <T> the event type
* @return the resultant handler
*/
private <T extends LuckPermsEvent> EventHandler<T> registerSubscription(Class<T> eventClass, Consumer<? super T> 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<T> 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<LuckPermsEventHandler<?>> 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<LuckPermsEventHandler<?>> 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;
}
}
@@ -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;
}
@@ -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 <T> the event type
*/
public class LuckPermsEventHandler<T extends LuckPermsEvent> implements EventHandler<T> {
private final LuckPermsEventBus eventBus;
/**
* The event bus which created this handler
*/
private final AbstractEventBus<?> eventBus;
/**
* The event class
*/
private final Class<T> eventClass;
private final Consumer<T> consumer;
/**
* The delegate "event handler"
*/
private final Consumer<? super T> 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<T> eventClass, Consumer<T> consumer) {
public LuckPermsEventHandler(AbstractEventBus<?> eventBus, Class<T> eventClass, Consumer<? super T> consumer, @Nullable Object plugin) {
this.eventBus = eventBus;
this.eventClass = eventClass;
this.consumer = consumer;
this.plugin = plugin;
}
@Override
@@ -91,7 +121,12 @@ public class LuckPermsEventHandler<T extends LuckPermsEvent> implements EventHan
@Nonnull
@Override
public Consumer<T> getConsumer() {
public Consumer<? super T> getConsumer() {
return this.consumer;
}
@Nullable
public Object getPlugin() {
return this.plugin;
}
}
@@ -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();