getEventBus() {
return this.plugin.getEventDispatcher().getEventBus();
}
diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextManager.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextManager.java
index 0bd646c93..58d7bf3d0 100644
--- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextManager.java
+++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextManager.java
@@ -116,8 +116,8 @@ public class ApiContextManager implements net.luckperms.api.context.ContextManag
}
@Override
- public void invalidateCache(@NonNull Object subject) {
+ public void signalContextUpdate(@NonNull Object subject) {
Objects.requireNonNull(subject, "subject");
- this.handle.invalidateCache(checkType(subject));
+ this.handle.signalContextUpdate(checkType(subject));
}
}
diff --git a/common/src/main/java/me/lucko/luckperms/common/context/ContextManager.java b/common/src/main/java/me/lucko/luckperms/common/context/ContextManager.java
index b9de1f4fc..dd806c8c9 100644
--- a/common/src/main/java/me/lucko/luckperms/common/context/ContextManager.java
+++ b/common/src/main/java/me/lucko/luckperms/common/context/ContextManager.java
@@ -100,7 +100,19 @@ public abstract class ContextManager {
public abstract QueryOptions formQueryOptions(S subject, ImmutableContextSet contextSet);
- public abstract void invalidateCache(S subject);
+ public void signalContextUpdate(S subject) {
+ if (subject == null) {
+ throw new NullPointerException("subject");
+ }
+
+ // invalidate their cache
+ invalidateCache(subject);
+
+ // call event
+ this.plugin.getEventDispatcher().dispatchContextUpdate(subject);
+ }
+
+ protected abstract void invalidateCache(S subject);
public void registerCalculator(ContextCalculator super S> calculator) {
// calculators registered first should have priority (and be checked last.)
diff --git a/common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java b/common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java
index 8876763f0..9ecb810f6 100644
--- a/common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java
+++ b/common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java
@@ -88,6 +88,10 @@ public abstract class AbstractEventBus implements EventBus, AutoCloseable {
return this.bus.hasSubscribers(eventClass);
}
+ public void subscribe(LuckPermsEventListener listener) {
+ listener.bind(this);
+ }
+
@Override
public @NonNull EventSubscription subscribe(@NonNull Class eventClass, @NonNull Consumer super T> handler) {
Objects.requireNonNull(eventClass, "eventClass");
diff --git a/common/src/main/java/me/lucko/luckperms/common/event/EventDispatcher.java b/common/src/main/java/me/lucko/luckperms/common/event/EventDispatcher.java
index 08e98fc2e..deca7003c 100644
--- a/common/src/main/java/me/lucko/luckperms/common/event/EventDispatcher.java
+++ b/common/src/main/java/me/lucko/luckperms/common/event/EventDispatcher.java
@@ -46,6 +46,7 @@ import net.luckperms.api.actionlog.Action;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.cause.CreationCause;
import net.luckperms.api.event.cause.DeletionCause;
+import net.luckperms.api.event.context.ContextUpdateEvent;
import net.luckperms.api.event.extension.ExtensionLoadEvent;
import net.luckperms.api.event.group.GroupCacheLoadEvent;
import net.luckperms.api.event.group.GroupCreateEvent;
@@ -138,6 +139,14 @@ public final class EventDispatcher {
}
}
+ public void dispatchContextUpdate(Object subject) {
+ if (!shouldPost(ContextUpdateEvent.class)) {
+ return;
+ }
+
+ post(generate(ContextUpdateEvent.class, subject));
+ }
+
public void dispatchExtensionLoad(Extension extension) {
post(ExtensionLoadEvent.class, () -> generate(ExtensionLoadEvent.class, extension));
}
diff --git a/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventListener.java b/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventListener.java
new file mode 100644
index 000000000..4f4ec512c
--- /dev/null
+++ b/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventListener.java
@@ -0,0 +1,38 @@
+/*
+ * 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.common.event;
+
+import net.luckperms.api.event.EventBus;
+import net.luckperms.api.event.LuckPermsEvent;
+
+/**
+ * Defines a class which listens to {@link LuckPermsEvent}s.
+ */
+public interface LuckPermsEventListener {
+
+ void bind(EventBus bus);
+
+}
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 0fb8a0d08..eade58ed1 100644
--- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitPlugin.java
+++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitPlugin.java
@@ -26,7 +26,6 @@
package me.lucko.luckperms.nukkit;
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
-import me.lucko.luckperms.common.api.implementation.ApiUser;
import me.lucko.luckperms.common.calculator.CalculatorFactory;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.config.ConfigKeys;
@@ -55,11 +54,11 @@ import me.lucko.luckperms.nukkit.inject.server.InjectorSubscriptionMap;
import me.lucko.luckperms.nukkit.inject.server.LuckPermsDefaultsMap;
import me.lucko.luckperms.nukkit.inject.server.LuckPermsPermissionMap;
import me.lucko.luckperms.nukkit.inject.server.LuckPermsSubscriptionMap;
+import me.lucko.luckperms.nukkit.listeners.NukkitAutoOpListener;
import me.lucko.luckperms.nukkit.listeners.NukkitConnectionListener;
import me.lucko.luckperms.nukkit.listeners.NukkitPlatformListener;
import net.luckperms.api.LuckPerms;
-import net.luckperms.api.event.user.UserDataRecalculateEvent;
import net.luckperms.api.query.QueryOptions;
import cn.nukkit.Player;
@@ -145,7 +144,10 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
@Override
protected void setupContextManager() {
this.contextManager = new NukkitContextManager(this);
- this.contextManager.registerCalculator(new WorldCalculator(this));
+
+ WorldCalculator worldCalculator = new WorldCalculator(this);
+ this.bootstrap.getServer().getPluginManager().registerEvents(worldCalculator, this.bootstrap);
+ this.contextManager.registerCalculator(worldCalculator);
}
@Override
@@ -205,11 +207,7 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
// register autoop listener
if (getConfiguration().get(ConfigKeys.AUTO_OP)) {
- getApiProvider().getEventBus().subscribe(UserDataRecalculateEvent.class, event -> {
- User user = ApiUser.cast(event.getUser());
- Optional player = getBootstrap().getPlayer(user.getUniqueId());
- player.ifPresent(this::refreshAutoOp);
- });
+ getApiProvider().getEventBus().subscribe(new NukkitAutoOpListener(this));
}
// Load any online users (in the case of a reload)
diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/NukkitContextManager.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/NukkitContextManager.java
index 420050523..9514862af 100644
--- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/NukkitContextManager.java
+++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/NukkitContextManager.java
@@ -88,11 +88,7 @@ public class NukkitContextManager extends ContextManager {
}
@Override
- public void invalidateCache(Player subject) {
- if (subject == null) {
- throw new NullPointerException("subject");
- }
-
+ protected void invalidateCache(Player subject) {
QueryOptionsCache cache = this.onlineSubjectCaches.getIfPresent(subject);
if (cache != null) {
cache.invalidate();
diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/WorldCalculator.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/WorldCalculator.java
index 6e8ab6015..9fd23cc63 100644
--- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/WorldCalculator.java
+++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/WorldCalculator.java
@@ -38,13 +38,17 @@ import net.luckperms.api.context.ImmutableContextSet;
import org.checkerframework.checker.nullness.qual.NonNull;
import cn.nukkit.Player;
+import cn.nukkit.event.EventHandler;
+import cn.nukkit.event.EventPriority;
+import cn.nukkit.event.Listener;
+import cn.nukkit.event.entity.EntityLevelChangeEvent;
import cn.nukkit.level.Level;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
-public class WorldCalculator implements ContextCalculator {
+public class WorldCalculator implements ContextCalculator, Listener {
private final LPNukkitPlugin plugin;
public WorldCalculator(LPNukkitPlugin plugin) {
@@ -70,4 +74,12 @@ public class WorldCalculator implements ContextCalculator {
}
return builder.build();
}
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onWorldChange(EntityLevelChangeEvent e) {
+ if (e.getEntity() instanceof Player) {
+ Player player = (Player) e.getEntity();
+ this.plugin.getContextManager().signalContextUpdate(player);
+ }
+ }
}
diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitAutoOpListener.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitAutoOpListener.java
new file mode 100644
index 000000000..50ee3ffce
--- /dev/null
+++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitAutoOpListener.java
@@ -0,0 +1,84 @@
+/*
+ * 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.listeners;
+
+import me.lucko.luckperms.common.api.implementation.ApiUser;
+import me.lucko.luckperms.common.event.LuckPermsEventListener;
+import me.lucko.luckperms.common.model.User;
+import me.lucko.luckperms.nukkit.LPNukkitPlugin;
+
+import net.luckperms.api.event.EventBus;
+import net.luckperms.api.event.context.ContextUpdateEvent;
+import net.luckperms.api.event.user.UserDataRecalculateEvent;
+import net.luckperms.api.query.QueryOptions;
+
+import cn.nukkit.Player;
+
+import java.util.Map;
+
+/**
+ * Implements the LuckPerms auto op feature.
+ */
+public class NukkitAutoOpListener implements LuckPermsEventListener {
+ private static final String NODE = "luckperms.autoop";
+
+ private final LPNukkitPlugin plugin;
+
+ public NukkitAutoOpListener(LPNukkitPlugin plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public void bind(EventBus bus) {
+ bus.subscribe(UserDataRecalculateEvent.class, this::onUserDataRecalculate);
+ bus.subscribe(ContextUpdateEvent.class, this::onContextUpdate);
+ }
+
+ private void onUserDataRecalculate(UserDataRecalculateEvent e) {
+ User user = ApiUser.cast(e.getUser());
+ this.plugin.getBootstrap().getPlayer(user.getUniqueId()).ifPresent(this::refreshAutoOp);
+ }
+
+ private void onContextUpdate(ContextUpdateEvent e) {
+ e.getSubject(Player.class).ifPresent(this::refreshAutoOp);
+ }
+
+ private void refreshAutoOp(Player player) {
+ User user = plugin.getUserManager().getIfLoaded(player.getUniqueId());
+ boolean value;
+
+ if (user != null) {
+ QueryOptions queryOptions = this.plugin.getContextManager().getQueryOptions(player);
+ Map permData = user.getCachedData().getPermissionData(queryOptions).getPermissionMap();
+ value = permData.getOrDefault(NODE, false);
+ } else {
+ value = false;
+ }
+
+ player.setOp(value);
+ }
+
+}
diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitConnectionListener.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitConnectionListener.java
index 2f6f7aac4..cf3d38dff 100644
--- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitConnectionListener.java
+++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitConnectionListener.java
@@ -166,7 +166,7 @@ public class NukkitConnectionListener extends AbstractConnectionListener impleme
return;
}
- this.plugin.refreshAutoOp(player);
+ this.plugin.getContextManager().signalContextUpdate(player);
}
@EventHandler(priority = EventPriority.MONITOR)
diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitPlatformListener.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitPlatformListener.java
index 4b1770463..9dc6302be 100644
--- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitPlatformListener.java
+++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/listeners/NukkitPlatformListener.java
@@ -29,13 +29,10 @@ import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.nukkit.LPNukkitPlugin;
-import cn.nukkit.Player;
import cn.nukkit.command.CommandSender;
import cn.nukkit.event.Cancellable;
import cn.nukkit.event.EventHandler;
-import cn.nukkit.event.EventPriority;
import cn.nukkit.event.Listener;
-import cn.nukkit.event.entity.EntityLevelChangeEvent;
import cn.nukkit.event.player.PlayerCommandPreprocessEvent;
import cn.nukkit.event.server.RemoteServerCommandEvent;
import cn.nukkit.event.server.ServerCommandEvent;
@@ -85,13 +82,4 @@ public class NukkitPlatformListener implements Listener {
}
}
- @EventHandler(priority = EventPriority.LOWEST)
- public void onWorldChange(EntityLevelChangeEvent e) {
- if (e.getEntity() instanceof Player) {
- Player player = (Player) e.getEntity();
- this.plugin.getContextManager().invalidateCache(player);
- this.plugin.refreshAutoOp(player);
- }
- }
-
}
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 5cc296478..6e6789224 100644
--- a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java
+++ b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java
@@ -156,7 +156,10 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin {
@Override
protected void setupContextManager() {
this.contextManager = new SpongeContextManager(this);
- this.contextManager.registerCalculator(new WorldCalculator(this));
+
+ WorldCalculator worldCalculator = new WorldCalculator(this);
+ this.bootstrap.getGame().getEventManager().registerListeners(this.bootstrap, worldCalculator);
+ this.contextManager.registerCalculator(worldCalculator);
}
@Override
diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/context/SpongeContextManager.java b/sponge/src/main/java/me/lucko/luckperms/sponge/context/SpongeContextManager.java
index b3518b32e..90b415837 100644
--- a/sponge/src/main/java/me/lucko/luckperms/sponge/context/SpongeContextManager.java
+++ b/sponge/src/main/java/me/lucko/luckperms/sponge/context/SpongeContextManager.java
@@ -67,11 +67,7 @@ public class SpongeContextManager extends ContextManager {
}
@Override
- public void invalidateCache(Subject subject) {
- if (subject == null) {
- throw new NullPointerException("subject");
- }
-
+ protected void invalidateCache(Subject subject) {
QueryOptionsCache cache = this.subjectCaches.getIfPresent(subject);
if (cache != null) {
cache.invalidate();
diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/context/WorldCalculator.java b/sponge/src/main/java/me/lucko/luckperms/sponge/context/WorldCalculator.java
index d1024becb..129305092 100644
--- a/sponge/src/main/java/me/lucko/luckperms/sponge/context/WorldCalculator.java
+++ b/sponge/src/main/java/me/lucko/luckperms/sponge/context/WorldCalculator.java
@@ -38,7 +38,11 @@ import net.luckperms.api.context.ImmutableContextSet;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.spongepowered.api.Game;
import org.spongepowered.api.command.CommandSource;
+import org.spongepowered.api.entity.Entity;
import org.spongepowered.api.entity.living.player.Player;
+import org.spongepowered.api.event.Listener;
+import org.spongepowered.api.event.Order;
+import org.spongepowered.api.event.entity.MoveEntityEvent;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.world.World;
@@ -84,4 +88,19 @@ public class WorldCalculator implements ContextCalculator {
}
return builder.build();
}
+
+ @Listener(order = Order.LAST)
+ public void onWorldChange(MoveEntityEvent.Teleport e) {
+ Entity targetEntity = e.getTargetEntity();
+ if (!(targetEntity instanceof Player)) {
+ return;
+ }
+
+ if (e.getFromTransform().getExtent().equals(e.getToTransform().getExtent())) {
+ return;
+ }
+
+ Player player = (Player) targetEntity;
+ this.plugin.getContextManager().signalContextUpdate(player);
+ }
}
diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/ContextCalculatorProxy.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/ContextCalculatorProxy.java
index 221cf4ea1..9fd13f63c 100644
--- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/ContextCalculatorProxy.java
+++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/ContextCalculatorProxy.java
@@ -64,7 +64,8 @@ public class ContextCalculatorProxy implements ForwardingContextCalculator {
}
return builder.build();
}
+
+ @Subscribe
+ public void onServerConnect(ServerConnectedEvent e) {
+ this.plugin.getContextManager().signalContextUpdate(e.getPlayer());
+ }
}
diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/context/VelocityContextManager.java b/velocity/src/main/java/me/lucko/luckperms/velocity/context/VelocityContextManager.java
index b619da2ed..ee76620ff 100644
--- a/velocity/src/main/java/me/lucko/luckperms/velocity/context/VelocityContextManager.java
+++ b/velocity/src/main/java/me/lucko/luckperms/velocity/context/VelocityContextManager.java
@@ -65,11 +65,7 @@ public class VelocityContextManager extends ContextManager {
}
@Override
- public void invalidateCache(Player subject) {
- if (subject == null) {
- throw new NullPointerException("subject");
- }
-
+ protected void invalidateCache(Player subject) {
QueryOptionsCache cache = this.subjectCaches.getIfPresent(subject);
if (cache != null) {
cache.invalidate();