diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/BukkitContextManager.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/BukkitContextManager.java index 9b419582a..f9735bfa8 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/BukkitContextManager.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/BukkitContextManager.java @@ -25,85 +25,46 @@ package me.lucko.luckperms.bukkit.context; -import com.github.benmanes.caffeine.cache.LoadingCache; import me.lucko.luckperms.bukkit.LPBukkitPlugin; -import me.lucko.luckperms.common.cache.LoadingMap; -import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.context.manager.ContextManager; -import me.lucko.luckperms.common.context.manager.QueryOptionsCache; -import me.lucko.luckperms.common.util.CaffeineFactory; -import net.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.bukkit.inject.permissible.LuckPermsPermissible; +import me.lucko.luckperms.bukkit.inject.permissible.PermissibleInjector; +import me.lucko.luckperms.common.context.manager.DetachedContextManager; +import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier; import net.luckperms.api.query.OptionKey; import net.luckperms.api.query.QueryOptions; import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.Nullable; +import java.util.Objects; import java.util.UUID; -import java.util.concurrent.TimeUnit; -public class BukkitContextManager extends ContextManager { +public class BukkitContextManager extends DetachedContextManager { public static final OptionKey OP_OPTION = OptionKey.of("op", Boolean.class); - // cache the creation of ContextsCache instances for online players with no expiry - private final LoadingMap> onlineSubjectCaches = LoadingMap.of(key -> new QueryOptionsCache<>(key, this)); - - // cache the creation of ContextsCache instances for offline players with a 1m expiry - private final LoadingCache> offlineSubjectCaches = CaffeineFactory.newBuilder() - .expireAfterAccess(1, TimeUnit.MINUTES) - .build(key -> { - QueryOptionsCache cache = this.onlineSubjectCaches.getIfPresent(key); - if (cache != null) { - return cache; - } - return new QueryOptionsCache<>(key, this); - }); - public BukkitContextManager(LPBukkitPlugin plugin) { super(plugin, Player.class, Player.class); } - public void onPlayerQuit(Player player) { - this.onlineSubjectCaches.remove(player); - } - @Override public UUID getUniqueId(Player player) { return player.getUniqueId(); } @Override - public QueryOptionsCache getCacheFor(Player subject) { - if (subject == null) { - throw new NullPointerException("subject"); - } - - if (subject.isOnline()) { - return this.onlineSubjectCaches.get(subject); - } else { - return this.offlineSubjectCaches.get(subject); + public @Nullable QueryOptionsSupplier getQueryOptionsSupplier(Player subject) { + Objects.requireNonNull(subject, "subject"); + LuckPermsPermissible permissible = PermissibleInjector.get(subject); + if (permissible != null) { + return permissible.getQueryOptionsSupplier(); } + return null; } @Override - protected void invalidateCache(Player subject) { - QueryOptionsCache cache = this.onlineSubjectCaches.getIfPresent(subject); - if (cache != null) { - cache.invalidate(); - } - - cache = this.offlineSubjectCaches.getIfPresent(subject); - if (cache != null) { - cache.invalidate(); - } - } - - @Override - public QueryOptions formQueryOptions(Player subject, ImmutableContextSet contextSet) { - QueryOptions.Builder queryOptions = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder(); + public void customizeQueryOptions(Player subject, QueryOptions.Builder builder) { if (subject.isOp()) { - queryOptions.option(OP_OPTION, true); + builder.option(OP_OPTION, true); } - - return queryOptions.context(contextSet).build(); } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LuckPermsPermissible.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LuckPermsPermissible.java index bd5e77063..a8f5848cb 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LuckPermsPermissible.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LuckPermsPermissible.java @@ -32,7 +32,7 @@ import me.lucko.luckperms.bukkit.calculator.OpProcessor; import me.lucko.luckperms.bukkit.calculator.PermissionMapProcessor; import me.lucko.luckperms.common.cacheddata.result.TristateResult; import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.context.manager.QueryOptionsCache; +import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.verbose.event.CheckOrigin; import net.luckperms.api.query.QueryOptions; @@ -68,7 +68,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * "Hot" method calls, (namely #hasPermission) are significantly faster than the base implementation. * * This class is **thread safe**. This means that when LuckPerms is installed on the server, - * is is safe to call Player#hasPermission asynchronously. + * it is safe to call Player#hasPermission asynchronously. */ public class LuckPermsPermissible extends PermissibleBase { @@ -93,7 +93,7 @@ public class LuckPermsPermissible extends PermissibleBase { private final LPBukkitPlugin plugin; // caches context lookups for the player - private final QueryOptionsCache queryOptionsSupplier; + private final QueryOptionsSupplier queryOptionsSupplier; // the players previous permissible. (the one they had before this one was injected) private PermissibleBase oldPermissible = null; @@ -110,7 +110,7 @@ public class LuckPermsPermissible extends PermissibleBase { this.user = Objects.requireNonNull(user, "user"); this.player = Objects.requireNonNull(player, "player"); this.plugin = Objects.requireNonNull(plugin, "plugin"); - this.queryOptionsSupplier = plugin.getContextManager().getCacheFor(player); + this.queryOptionsSupplier = plugin.getContextManager().createQueryOptionsSupplier(player); injectFakeAttachmentsList(); } @@ -293,7 +293,7 @@ public class LuckPermsPermissible extends PermissibleBase { // the query options cache when op status changes. // (#invalidate is a fast call) if (this.queryOptionsSupplier != null) { // this method is called by the super class constructor, before this class has fully initialised - this.queryOptionsSupplier.invalidate(); + this.queryOptionsSupplier.invalidateCache(); } // but we don't need to do anything else in this method, unlike the CB impl. @@ -316,6 +316,10 @@ public class LuckPermsPermissible extends PermissibleBase { return this.plugin; } + public QueryOptionsSupplier getQueryOptionsSupplier() { + return this.queryOptionsSupplier; + } + PermissibleBase getOldPermissible() { return this.oldPermissible; } @@ -409,9 +413,7 @@ public class LuckPermsPermissible extends PermissibleBase { @Override public PermissionAttachment remove(int index) { throw new UnsupportedOperationException(); } @Override public int indexOf(Object o) { throw new UnsupportedOperationException(); } @Override public int lastIndexOf(Object o) { throw new UnsupportedOperationException(); } - @Override - public @NonNull ListIterator listIterator(int index) { throw new UnsupportedOperationException(); } - @Override - public @NonNull List subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); } + @Override public @NonNull ListIterator listIterator(int index) { throw new UnsupportedOperationException(); } + @Override public @NonNull List subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); } } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/PermissibleInjector.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/PermissibleInjector.java index 3902c0ebe..0cdab7d1b 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/PermissibleInjector.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/PermissibleInjector.java @@ -30,6 +30,7 @@ import me.lucko.luckperms.common.plugin.logging.PluginLogger; import org.bukkit.entity.Player; import org.bukkit.permissions.PermissibleBase; import org.bukkit.permissions.PermissionAttachment; +import org.checkerframework.checker.nullness.qual.Nullable; import java.lang.reflect.Field; import java.util.List; @@ -161,6 +162,19 @@ public final class PermissibleInjector { } } + public static @Nullable LuckPermsPermissible get(Player player) { + PermissibleBase permissibleBase; + try { + permissibleBase = (PermissibleBase) HUMAN_ENTITY_PERMISSIBLE_FIELD.get(player); + } catch (IllegalAccessException e) { + return null; + } + if (permissibleBase instanceof LuckPermsPermissible) { + return (LuckPermsPermissible) permissibleBase; + } + return null; + } + public static void checkInjected(Player player, PluginLogger logger) { PermissibleBase permissibleBase; try { diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/listeners/BukkitConnectionListener.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/listeners/BukkitConnectionListener.java index 58e5816ad..3208137e2 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/listeners/BukkitConnectionListener.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/listeners/BukkitConnectionListener.java @@ -253,9 +253,6 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) { player.setOp(false); } - - // remove their contexts cache - this.plugin.getContextManager().onPlayerQuit(player); }, 1L); } diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/context/BungeeContextManager.java b/bungee/src/main/java/me/lucko/luckperms/bungee/context/BungeeContextManager.java index 1529c184d..f1bfc25f5 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/context/BungeeContextManager.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/context/BungeeContextManager.java @@ -26,12 +26,12 @@ package me.lucko.luckperms.bungee.context; import me.lucko.luckperms.bungee.LPBungeePlugin; -import me.lucko.luckperms.common.context.manager.InlineContextManager; +import me.lucko.luckperms.common.context.manager.SimpleContextManager; import net.md_5.bungee.api.connection.ProxiedPlayer; import java.util.UUID; -public class BungeeContextManager extends InlineContextManager { +public class BungeeContextManager extends SimpleContextManager { public BungeeContextManager(LPBungeePlugin plugin) { super(plugin, ProxiedPlayer.class, ProxiedPlayer.class); } diff --git a/common/src/main/java/me/lucko/luckperms/common/context/manager/ContextManager.java b/common/src/main/java/me/lucko/luckperms/common/context/manager/ContextManager.java index 4cc2d7a8b..03880ae93 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/manager/ContextManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/manager/ContextManager.java @@ -46,7 +46,7 @@ import java.util.concurrent.TimeUnit; import java.util.function.Predicate; /** - * Base implementation of {@link ContextManager} which caches content lookups. + * Base implementation of {@link ContextManager}. * * @param the subject type * @param

the player type @@ -78,14 +78,10 @@ public abstract class ContextManager { public abstract UUID getUniqueId(P player); - public abstract QueryOptionsSupplier getCacheFor(S subject); - - public QueryOptions getQueryOptions(S subject) { - return getCacheFor(subject).getQueryOptions(); - } + public abstract QueryOptions getQueryOptions(S subject); public ImmutableContextSet getContext(S subject) { - return getCacheFor(subject).getContextSet(); + return getQueryOptions(subject).context(); } public QueryOptions getStaticQueryOptions() { @@ -96,11 +92,13 @@ public abstract class ContextManager { return getStaticQueryOptions().context(); } - public QueryOptions formQueryOptions(ImmutableContextSet contextSet) { - return this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder().context(contextSet).build(); + public void customizeStaticQueryOptions(QueryOptions.Builder builder) { + // overridden } - public abstract QueryOptions formQueryOptions(S subject, ImmutableContextSet contextSet); + public void customizeQueryOptions(S subject, QueryOptions.Builder builder) { + // overridden + } public void signalContextUpdate(S subject) { if (subject == null) { @@ -114,7 +112,7 @@ public abstract class ContextManager { this.plugin.getEventDispatcher().dispatchContextUpdate(subject); } - protected abstract void invalidateCache(S subject); + public abstract void invalidateCache(S subject); public void registerCalculator(ContextCalculator calculator) { String calculatorClass = calculator.getClass().getName(); @@ -158,7 +156,9 @@ public abstract class ContextManager { callContextCalculator(calculator, subject, consumer); } - return formQueryOptions(subject, accumulator.build()); + QueryOptions.Builder builder = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder().context(accumulator.build()); + customizeQueryOptions(subject, builder); + return builder.build(); } private QueryOptions calculateStatic() { @@ -169,7 +169,9 @@ public abstract class ContextManager { callStaticContextCalculator(calculator, consumer); } - return formQueryOptions(accumulator.build()); + QueryOptions.Builder builder = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder().context(accumulator.build()); + customizeStaticQueryOptions(builder); + return builder.build(); } public ImmutableContextSet getPotentialContexts() { diff --git a/common/src/main/java/me/lucko/luckperms/common/context/manager/DetachedContextManager.java b/common/src/main/java/me/lucko/luckperms/common/context/manager/DetachedContextManager.java new file mode 100644 index 000000000..d887407c2 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/context/manager/DetachedContextManager.java @@ -0,0 +1,73 @@ +/* + * 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.context.manager; + +import com.github.benmanes.caffeine.cache.LoadingCache; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import me.lucko.luckperms.common.util.CaffeineFactory; +import net.luckperms.api.query.QueryOptions; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.concurrent.TimeUnit; + +/** + * Implementation of {@link ContextManager} which utilises 'detached' supplier caches stored alongside the subject instances. + */ +public abstract class DetachedContextManager extends ContextManager { + + private final LoadingCache fallbackContextsCache = CaffeineFactory.newBuilder() + .expireAfterWrite(50, TimeUnit.MILLISECONDS) + .build(this::calculate); + + protected DetachedContextManager(LuckPermsPlugin plugin, Class subjectClass, Class

playerClass) { + super(plugin, subjectClass, playerClass); + } + + @Override + public QueryOptions getQueryOptions(S subject) { + QueryOptionsSupplier supplier = getQueryOptionsSupplier(subject); + if (supplier != null) { + return supplier.getQueryOptions(); + } + return this.fallbackContextsCache.get(subject); + } + + @Override + public void invalidateCache(S subject) { + QueryOptionsSupplier queryOptionsSupplier = getQueryOptionsSupplier(subject); + if (queryOptionsSupplier != null) { + queryOptionsSupplier.invalidateCache(); + } + this.fallbackContextsCache.invalidate(subject); + } + + public QueryOptionsSupplier createQueryOptionsSupplier(S subject) { + return new QueryOptionsCache<>(subject, this); + } + + public abstract @Nullable QueryOptionsSupplier getQueryOptionsSupplier(S subject); + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/context/manager/QueryOptionsCache.java b/common/src/main/java/me/lucko/luckperms/common/context/manager/QueryOptionsCache.java index 385f9ad1f..df4d96828 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/manager/QueryOptionsCache.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/manager/QueryOptionsCache.java @@ -37,11 +37,11 @@ import java.util.concurrent.TimeUnit; * * @param the player type */ -public final class QueryOptionsCache extends ExpiringCache implements QueryOptionsSupplier { +final class QueryOptionsCache extends ExpiringCache implements QueryOptionsSupplier { private final T subject; private final ContextManager contextManager; - public QueryOptionsCache(T subject, ContextManager contextManager) { + QueryOptionsCache(T subject, ContextManager contextManager) { super(50L, TimeUnit.MILLISECONDS); // expire roughly every tick this.subject = subject; this.contextManager = contextManager; @@ -61,4 +61,9 @@ public final class QueryOptionsCache extends ExpiringCache impl public ImmutableContextSet getContextSet() { return get().context(); } + + @Override + public void invalidateCache() { + invalidate(); + } } diff --git a/common/src/main/java/me/lucko/luckperms/common/context/manager/QueryOptionsSupplier.java b/common/src/main/java/me/lucko/luckperms/common/context/manager/QueryOptionsSupplier.java index 7e5af3acc..b44f92446 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/manager/QueryOptionsSupplier.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/manager/QueryOptionsSupplier.java @@ -39,4 +39,6 @@ public interface QueryOptionsSupplier { return getQueryOptions().context(); } + void invalidateCache(); + } diff --git a/common/src/main/java/me/lucko/luckperms/common/context/manager/InlineContextManager.java b/common/src/main/java/me/lucko/luckperms/common/context/manager/SimpleContextManager.java similarity index 58% rename from common/src/main/java/me/lucko/luckperms/common/context/manager/InlineContextManager.java rename to common/src/main/java/me/lucko/luckperms/common/context/manager/SimpleContextManager.java index ced09b136..0c9b56ac7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/manager/InlineContextManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/manager/SimpleContextManager.java @@ -28,63 +28,27 @@ package me.lucko.luckperms.common.context.manager; import com.github.benmanes.caffeine.cache.LoadingCache; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.util.CaffeineFactory; -import net.luckperms.api.context.ImmutableContextSet; import net.luckperms.api.query.QueryOptions; import java.util.concurrent.TimeUnit; -public abstract class InlineContextManager extends ContextManager { +public abstract class SimpleContextManager extends ContextManager { private final LoadingCache contextsCache = CaffeineFactory.newBuilder() .expireAfterWrite(50, TimeUnit.MILLISECONDS) .build(this::calculate); - protected InlineContextManager(LuckPermsPlugin plugin, Class subjectClass, Class

playerClass) { + protected SimpleContextManager(LuckPermsPlugin plugin, Class subjectClass, Class

playerClass) { super(plugin, subjectClass, playerClass); } @Override - public final QueryOptionsSupplier getCacheFor(S subject) { - if (subject == null) { - throw new NullPointerException("subject"); - } - - return new InlineQueryOptionsSupplier<>(subject, this.contextsCache); - } - - // override getContext, getQueryOptions and invalidateCache to skip the QueryOptionsSupplier - @Override - public final ImmutableContextSet getContext(S subject) { - return getQueryOptions(subject).context(); - } - - @Override - public final QueryOptions getQueryOptions(S subject) { + public QueryOptions getQueryOptions(S subject) { return this.contextsCache.get(subject); } @Override - protected final void invalidateCache(S subject) { + public void invalidateCache(S subject) { this.contextsCache.invalidate(subject); } - - @Override - public QueryOptions formQueryOptions(S subject, ImmutableContextSet contextSet) { - return formQueryOptions(contextSet); - } - - private static final class InlineQueryOptionsSupplier implements QueryOptionsSupplier { - private final T key; - private final LoadingCache cache; - - InlineQueryOptionsSupplier(T key, LoadingCache cache) { - this.key = key; - this.cache = cache; - } - - @Override - public QueryOptions getQueryOptions() { - return this.cache.get(this.key); - } - } } diff --git a/fabric/src/main/java/me/lucko/luckperms/fabric/context/FabricContextManager.java b/fabric/src/main/java/me/lucko/luckperms/fabric/context/FabricContextManager.java index 3760e08ab..d6d3143b1 100644 --- a/fabric/src/main/java/me/lucko/luckperms/fabric/context/FabricContextManager.java +++ b/fabric/src/main/java/me/lucko/luckperms/fabric/context/FabricContextManager.java @@ -25,19 +25,19 @@ package me.lucko.luckperms.fabric.context; -import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.context.manager.ContextManager; -import me.lucko.luckperms.common.context.manager.QueryOptionsCache; +import me.lucko.luckperms.common.context.manager.DetachedContextManager; +import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.fabric.model.MixinUser; -import net.luckperms.api.context.ImmutableContextSet; import net.luckperms.api.query.OptionKey; import net.luckperms.api.query.QueryOptions; import net.minecraft.server.network.ServerPlayerEntity; +import org.checkerframework.checker.nullness.qual.Nullable; +import java.util.Objects; import java.util.UUID; -public class FabricContextManager extends ContextManager { +public class FabricContextManager extends DetachedContextManager { public static final OptionKey INTEGRATED_SERVER_OWNER = OptionKey.of("integrated_server_owner", Boolean.class); public FabricContextManager(LuckPermsPlugin plugin) { @@ -49,32 +49,17 @@ public class FabricContextManager extends ContextManager newQueryOptionsCache(ServerPlayerEntity player) { - return new QueryOptionsCache<>(player, this); - } - @Override - public QueryOptionsCache getCacheFor(ServerPlayerEntity subject) { - if (subject == null) { - throw new NullPointerException("subject"); - } - + public @Nullable QueryOptionsSupplier getQueryOptionsSupplier(ServerPlayerEntity subject) { + Objects.requireNonNull(subject, "subject"); return ((MixinUser) subject).luckperms$getQueryOptionsCache(this); } @Override - public void invalidateCache(ServerPlayerEntity subject) { - getCacheFor(subject).invalidate(); - } - - @Override - public QueryOptions formQueryOptions(ServerPlayerEntity subject, ImmutableContextSet contextSet) { - QueryOptions.Builder queryOptions = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder(); + public void customizeQueryOptions(ServerPlayerEntity subject, QueryOptions.Builder builder) { if (subject.getServer().isHost(subject.getGameProfile())) { - queryOptions.option(INTEGRATED_SERVER_OWNER, true); + builder.option(INTEGRATED_SERVER_OWNER, true); } - - return queryOptions.context(contextSet).build(); } } diff --git a/fabric/src/main/java/me/lucko/luckperms/fabric/mixin/ServerPlayerEntityMixin.java b/fabric/src/main/java/me/lucko/luckperms/fabric/mixin/ServerPlayerEntityMixin.java index ce68c2eca..f20b54279 100644 --- a/fabric/src/main/java/me/lucko/luckperms/fabric/mixin/ServerPlayerEntityMixin.java +++ b/fabric/src/main/java/me/lucko/luckperms/fabric/mixin/ServerPlayerEntityMixin.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.fabric.mixin; import me.lucko.luckperms.common.cacheddata.type.MetaCache; import me.lucko.luckperms.common.cacheddata.type.PermissionCache; -import me.lucko.luckperms.common.context.manager.QueryOptionsCache; +import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.verbose.event.CheckOrigin; import me.lucko.luckperms.fabric.context.FabricContextManager; @@ -61,7 +61,7 @@ public abstract class ServerPlayerEntityMixin implements MixinUser { * having to maintain a map of Player->Cache. */ @Unique - private QueryOptionsCache luckperms$queryOptions; + private QueryOptionsSupplier luckperms$queryOptions; // Used by PlayerChangeWorldCallback hook below. @Shadow public abstract ServerWorld getServerWorld(); @@ -72,9 +72,9 @@ public abstract class ServerPlayerEntityMixin implements MixinUser { } @Override - public QueryOptionsCache luckperms$getQueryOptionsCache(FabricContextManager contextManager) { + public QueryOptionsSupplier luckperms$getQueryOptionsCache(FabricContextManager contextManager) { if (this.luckperms$queryOptions == null) { - this.luckperms$queryOptions = contextManager.newQueryOptionsCache((ServerPlayerEntity) (Object) this); + this.luckperms$queryOptions = contextManager.createQueryOptionsSupplier((ServerPlayerEntity) (Object) this); } return this.luckperms$queryOptions; } diff --git a/fabric/src/main/java/me/lucko/luckperms/fabric/model/MixinUser.java b/fabric/src/main/java/me/lucko/luckperms/fabric/model/MixinUser.java index 8b6db8919..6837d0075 100644 --- a/fabric/src/main/java/me/lucko/luckperms/fabric/model/MixinUser.java +++ b/fabric/src/main/java/me/lucko/luckperms/fabric/model/MixinUser.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.fabric.model; -import me.lucko.luckperms.common.context.manager.QueryOptionsCache; +import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.fabric.context.FabricContextManager; import net.luckperms.api.query.QueryOptions; @@ -41,12 +41,12 @@ public interface MixinUser { User luckperms$getUser(); /** - * Gets (or creates using the manager) the objects {@link QueryOptionsCache}. + * Gets (or creates using the manager) the objects {@link QueryOptionsSupplier}. * * @param contextManager the contextManager * @return the cache */ - QueryOptionsCache luckperms$getQueryOptionsCache(FabricContextManager contextManager); + QueryOptionsSupplier luckperms$getQueryOptionsCache(FabricContextManager contextManager); /** * Initialises permissions for this player using the given {@link User}. diff --git a/forge/src/main/java/me/lucko/luckperms/forge/LPForgePlugin.java b/forge/src/main/java/me/lucko/luckperms/forge/LPForgePlugin.java index e45fee008..2f3520c92 100644 --- a/forge/src/main/java/me/lucko/luckperms/forge/LPForgePlugin.java +++ b/forge/src/main/java/me/lucko/luckperms/forge/LPForgePlugin.java @@ -93,7 +93,7 @@ public class LPForgePlugin extends AbstractLuckPermsPlugin { ForgePlatformListener platformListener = new ForgePlatformListener(this); this.bootstrap.registerListeners(platformListener); - UserCapabilityListener userCapabilityListener = new UserCapabilityListener(); + UserCapabilityListener userCapabilityListener = new UserCapabilityListener(this); this.bootstrap.registerListeners(userCapabilityListener); ForgePermissionHandlerListener permissionHandlerListener = new ForgePermissionHandlerListener(this); diff --git a/forge/src/main/java/me/lucko/luckperms/forge/capabilities/UserCapabilityImpl.java b/forge/src/main/java/me/lucko/luckperms/forge/capabilities/UserCapabilityImpl.java index 9fc88f874..4e9ca8f6c 100644 --- a/forge/src/main/java/me/lucko/luckperms/forge/capabilities/UserCapabilityImpl.java +++ b/forge/src/main/java/me/lucko/luckperms/forge/capabilities/UserCapabilityImpl.java @@ -26,11 +26,11 @@ package me.lucko.luckperms.forge.capabilities; import me.lucko.luckperms.common.cacheddata.type.PermissionCache; -import me.lucko.luckperms.common.context.manager.QueryOptionsCache; +import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier; import me.lucko.luckperms.common.locale.TranslationManager; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.verbose.event.CheckOrigin; -import me.lucko.luckperms.forge.context.ForgeContextManager; +import me.lucko.luckperms.forge.LPForgePlugin; import net.luckperms.api.query.QueryOptions; import net.luckperms.api.util.Tristate; import net.minecraft.server.level.ServerPlayer; @@ -77,7 +77,7 @@ public class UserCapabilityImpl implements UserCapability { private boolean initialised = false; private User user; - private QueryOptionsCache queryOptionsCache; + private QueryOptionsSupplier queryOptionsSupplier; private String language; private Locale locale; @@ -85,17 +85,17 @@ public class UserCapabilityImpl implements UserCapability { } - public void initialise(UserCapabilityImpl previous) { + public void initialise(UserCapabilityImpl previous, ServerPlayer player, LPForgePlugin plugin) { this.user = previous.user; - this.queryOptionsCache = previous.queryOptionsCache; + this.queryOptionsSupplier = plugin.getContextManager().createQueryOptionsSupplier(player); this.language = previous.language; this.locale = previous.locale; this.initialised = true; } - public void initialise(User user, ServerPlayer player, ForgeContextManager contextManager) { + public void initialise(User user, ServerPlayer player, LPForgePlugin plugin) { this.user = user; - this.queryOptionsCache = new QueryOptionsCache<>(player, contextManager); + this.queryOptionsSupplier = plugin.getContextManager().createQueryOptionsSupplier(player); this.initialised = true; } @@ -113,7 +113,7 @@ public class UserCapabilityImpl implements UserCapability { throw new NullPointerException("permission"); } - return checkPermission(permission, this.queryOptionsCache.getQueryOptions()); + return checkPermission(permission, this.queryOptionsSupplier.getQueryOptions()); } @Override @@ -139,12 +139,12 @@ public class UserCapabilityImpl implements UserCapability { @Override public QueryOptions getQueryOptions() { - return getQueryOptionsCache().getQueryOptions(); + return getQueryOptionsSupplier().getQueryOptions(); } - public QueryOptionsCache getQueryOptionsCache() { + public QueryOptionsSupplier getQueryOptionsSupplier() { assertInitialised(); - return this.queryOptionsCache; + return this.queryOptionsSupplier; } public Locale getLocale(ServerPlayer player) { diff --git a/forge/src/main/java/me/lucko/luckperms/forge/capabilities/UserCapabilityListener.java b/forge/src/main/java/me/lucko/luckperms/forge/capabilities/UserCapabilityListener.java index a97a69445..7adab8ffd 100644 --- a/forge/src/main/java/me/lucko/luckperms/forge/capabilities/UserCapabilityListener.java +++ b/forge/src/main/java/me/lucko/luckperms/forge/capabilities/UserCapabilityListener.java @@ -25,6 +25,7 @@ package me.lucko.luckperms.forge.capabilities; +import me.lucko.luckperms.forge.LPForgePlugin; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; @@ -41,6 +42,12 @@ import org.jetbrains.annotations.Nullable; public class UserCapabilityListener { + private final LPForgePlugin plugin; + + public UserCapabilityListener(LPForgePlugin plugin) { + this.plugin = plugin; + } + @SubscribeEvent public void onRegisterCapabilities(RegisterCapabilitiesEvent event) { event.register(UserCapabilityImpl.class); @@ -60,13 +67,17 @@ public class UserCapabilityListener { Player previousPlayer = event.getOriginal(); Player currentPlayer = event.getEntity(); + if (!(currentPlayer instanceof ServerPlayer)) { + return; + } + previousPlayer.reviveCaps(); try { UserCapabilityImpl previous = UserCapabilityImpl.get(previousPlayer); UserCapabilityImpl current = UserCapabilityImpl.get(currentPlayer); - current.initialise(previous); - current.getQueryOptionsCache().invalidate(); + current.initialise(previous, ((ServerPlayer) currentPlayer), this.plugin); + current.getQueryOptionsSupplier().invalidateCache(); } catch (IllegalStateException e) { // continue on if we cannot copy original data } finally { diff --git a/forge/src/main/java/me/lucko/luckperms/forge/context/ForgeContextManager.java b/forge/src/main/java/me/lucko/luckperms/forge/context/ForgeContextManager.java index 1e5069079..bb0733df9 100644 --- a/forge/src/main/java/me/lucko/luckperms/forge/context/ForgeContextManager.java +++ b/forge/src/main/java/me/lucko/luckperms/forge/context/ForgeContextManager.java @@ -25,19 +25,19 @@ package me.lucko.luckperms.forge.context; -import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.context.manager.ContextManager; -import me.lucko.luckperms.common.context.manager.QueryOptionsCache; +import me.lucko.luckperms.common.context.manager.DetachedContextManager; +import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier; import me.lucko.luckperms.forge.LPForgePlugin; import me.lucko.luckperms.forge.capabilities.UserCapabilityImpl; -import net.luckperms.api.context.ImmutableContextSet; import net.luckperms.api.query.OptionKey; import net.luckperms.api.query.QueryOptions; import net.minecraft.server.level.ServerPlayer; +import org.checkerframework.checker.nullness.qual.Nullable; +import java.util.Objects; import java.util.UUID; -public class ForgeContextManager extends ContextManager { +public class ForgeContextManager extends DetachedContextManager { public static final OptionKey INTEGRATED_SERVER_OWNER = OptionKey.of("integrated_server_owner", Boolean.class); public ForgeContextManager(LPForgePlugin plugin) { @@ -50,29 +50,19 @@ public class ForgeContextManager extends ContextManager getCacheFor(ServerPlayer subject) { - if (subject == null) { - throw new NullPointerException("subject"); - } - - return UserCapabilityImpl.get(subject).getQueryOptionsCache(); - } - - @Override - public QueryOptions formQueryOptions(ServerPlayer subject, ImmutableContextSet contextSet) { - QueryOptions.Builder builder = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder(); - if (subject.getServer() != null && subject.getServer().isSingleplayerOwner(subject.getGameProfile())) { - builder.option(INTEGRATED_SERVER_OWNER, true); - } - - return builder.context(contextSet).build(); - } - - @Override - public void invalidateCache(ServerPlayer subject) { + public @Nullable QueryOptionsSupplier getQueryOptionsSupplier(ServerPlayer subject) { + Objects.requireNonNull(subject, "subject"); UserCapabilityImpl capability = UserCapabilityImpl.getNullable(subject); if (capability != null) { - capability.getQueryOptionsCache().invalidate(); + return capability.getQueryOptionsSupplier(); + } + return null; + } + + @Override + public void customizeQueryOptions(ServerPlayer subject, QueryOptions.Builder builder) { + if (subject.getServer() != null && subject.getServer().isSingleplayerOwner(subject.getGameProfile())) { + builder.option(INTEGRATED_SERVER_OWNER, true); } } diff --git a/forge/src/main/java/me/lucko/luckperms/forge/listeners/ForgeConnectionListener.java b/forge/src/main/java/me/lucko/luckperms/forge/listeners/ForgeConnectionListener.java index 5c4575e72..7b78846a8 100644 --- a/forge/src/main/java/me/lucko/luckperms/forge/listeners/ForgeConnectionListener.java +++ b/forge/src/main/java/me/lucko/luckperms/forge/listeners/ForgeConnectionListener.java @@ -148,7 +148,7 @@ public class ForgeConnectionListener extends AbstractConnectionListener { // initialise capability UserCapabilityImpl userCapability = UserCapabilityImpl.get(player); - userCapability.initialise(user, player, this.plugin.getContextManager()); + userCapability.initialise(user, player, this.plugin); this.plugin.getContextManager().signalContextUpdate(player); } diff --git a/forge/src/main/java/me/lucko/luckperms/forge/service/ForgePermissionHandler.java b/forge/src/main/java/me/lucko/luckperms/forge/service/ForgePermissionHandler.java index 805d89d2f..06f10e3f8 100644 --- a/forge/src/main/java/me/lucko/luckperms/forge/service/ForgePermissionHandler.java +++ b/forge/src/main/java/me/lucko/luckperms/forge/service/ForgePermissionHandler.java @@ -82,7 +82,7 @@ public class ForgePermissionHandler implements IPermissionHandler { if (capability != null) { User user = capability.getUser(); - QueryOptions queryOptions = capability.getQueryOptionsCache().getQueryOptions(); + QueryOptions queryOptions = capability.getQueryOptionsSupplier().getQueryOptions(); T value = getPermissionValue(user, queryOptions, node, context); if (value != null) { diff --git a/neoforge/src/main/java/me/lucko/luckperms/neoforge/context/NeoForgeContextManager.java b/neoforge/src/main/java/me/lucko/luckperms/neoforge/context/NeoForgeContextManager.java index 41632e229..24d17a000 100644 --- a/neoforge/src/main/java/me/lucko/luckperms/neoforge/context/NeoForgeContextManager.java +++ b/neoforge/src/main/java/me/lucko/luckperms/neoforge/context/NeoForgeContextManager.java @@ -25,17 +25,15 @@ package me.lucko.luckperms.neoforge.context; -import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.context.manager.InlineContextManager; +import me.lucko.luckperms.common.context.manager.SimpleContextManager; import me.lucko.luckperms.neoforge.LPNeoForgePlugin; -import net.luckperms.api.context.ImmutableContextSet; import net.luckperms.api.query.OptionKey; import net.luckperms.api.query.QueryOptions; import net.minecraft.server.level.ServerPlayer; import java.util.UUID; -public class NeoForgeContextManager extends InlineContextManager { +public class NeoForgeContextManager extends SimpleContextManager { public static final OptionKey INTEGRATED_SERVER_OWNER = OptionKey.of("integrated_server_owner", Boolean.class); public NeoForgeContextManager(LPNeoForgePlugin plugin) { @@ -48,12 +46,9 @@ public class NeoForgeContextManager extends InlineContextManager { +public class NukkitContextManager extends DetachedContextManager { public static final OptionKey OP_OPTION = OptionKey.of("op", Boolean.class); - // cache the creation of ContextsCache instances for online players with no expiry - private final LoadingMap> onlineSubjectCaches = LoadingMap.of(key -> new QueryOptionsCache<>(key, this)); - - // cache the creation of ContextsCache instances for offline players with a 1m expiry - private final LoadingCache> offlineSubjectCaches = CaffeineFactory.newBuilder() - .expireAfterAccess(1, TimeUnit.MINUTES) - .build(key -> { - QueryOptionsCache cache = this.onlineSubjectCaches.getIfPresent(key); - if (cache != null) { - return cache; - } - return new QueryOptionsCache<>(key, this); - }); - public NukkitContextManager(LPNukkitPlugin plugin) { super(plugin, Player.class, Player.class); } - public void onPlayerQuit(Player player) { - this.onlineSubjectCaches.remove(player); - } - @Override public UUID getUniqueId(Player player) { return player.getUniqueId(); } @Override - public QueryOptionsCache getCacheFor(Player subject) { - if (subject == null) { - throw new NullPointerException("subject"); - } - - if (subject.isOnline()) { - return this.onlineSubjectCaches.get(subject); - } else { - return this.offlineSubjectCaches.get(subject); + public @Nullable QueryOptionsSupplier getQueryOptionsSupplier(Player subject) { + Objects.requireNonNull(subject, "subject"); + LuckPermsPermissible permissible = PermissibleInjector.get(subject); + if (permissible != null) { + return permissible.getQueryOptionsSupplier(); } + return null; } @Override - protected void invalidateCache(Player subject) { - QueryOptionsCache cache = this.onlineSubjectCaches.getIfPresent(subject); - if (cache != null) { - cache.invalidate(); - } - - cache = this.offlineSubjectCaches.getIfPresent(subject); - if (cache != null) { - cache.invalidate(); - } - } - - @Override - public QueryOptions formQueryOptions(Player subject, ImmutableContextSet contextSet) { - QueryOptions.Builder queryOptions = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder(); + public void customizeQueryOptions(Player subject, QueryOptions.Builder builder) { if (subject.isOp()) { - queryOptions.option(OP_OPTION, true); + builder.option(OP_OPTION, true); } - - return queryOptions.context(contextSet).build(); } } diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LuckPermsPermissible.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LuckPermsPermissible.java index 11f469f2a..f6d8f4455 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LuckPermsPermissible.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LuckPermsPermissible.java @@ -35,7 +35,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import me.lucko.luckperms.common.cacheddata.result.TristateResult; import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.context.manager.QueryOptionsCache; +import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.verbose.event.CheckOrigin; import me.lucko.luckperms.nukkit.LPNukkitPlugin; @@ -93,7 +93,7 @@ public class LuckPermsPermissible extends PermissibleBase { private final LPNukkitPlugin plugin; // caches context lookups for the player - private final QueryOptionsCache queryOptionsSupplier; + private final QueryOptionsSupplier queryOptionsSupplier; // the players previous permissible. (the one they had before this one was injected) private PermissibleBase oldPermissible = null; @@ -110,7 +110,7 @@ public class LuckPermsPermissible extends PermissibleBase { this.user = Objects.requireNonNull(user, "user"); this.player = Objects.requireNonNull(player, "player"); this.plugin = Objects.requireNonNull(plugin, "plugin"); - this.queryOptionsSupplier = plugin.getContextManager().getCacheFor(player); + this.queryOptionsSupplier = plugin.getContextManager().createQueryOptionsSupplier(player); injectFakeAttachmentsList(); } @@ -276,7 +276,7 @@ public class LuckPermsPermissible extends PermissibleBase { // the query options cache when op status changes. // (#invalidate is a fast call) if (this.queryOptionsSupplier != null) { // this method is called by the super class constructor, before this class has fully initialised - this.queryOptionsSupplier.invalidate(); + this.queryOptionsSupplier.invalidateCache(); } // but we don't need to do anything else in this method, unlike the Nukkit impl. @@ -299,6 +299,10 @@ public class LuckPermsPermissible extends PermissibleBase { return this.plugin; } + public QueryOptionsSupplier getQueryOptionsSupplier() { + return this.queryOptionsSupplier; + } + PermissibleBase getOldPermissible() { return this.oldPermissible; } diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/PermissibleInjector.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/PermissibleInjector.java index 346ae83c2..ca1c3f392 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/PermissibleInjector.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/PermissibleInjector.java @@ -28,6 +28,7 @@ package me.lucko.luckperms.nukkit.inject.permissible; import cn.nukkit.Player; import cn.nukkit.permission.PermissibleBase; import cn.nukkit.permission.PermissionAttachment; +import org.checkerframework.checker.nullness.qual.Nullable; import java.lang.reflect.Field; import java.util.Set; @@ -141,4 +142,17 @@ public final class PermissibleInjector { } } + public static @Nullable LuckPermsPermissible get(Player player) { + PermissibleBase permissibleBase; + try { + permissibleBase = (PermissibleBase) PLAYER_PERMISSIBLE_FIELD.get(player); + } catch (IllegalAccessException e) { + return null; + } + if (permissibleBase instanceof LuckPermsPermissible) { + return (LuckPermsPermissible) permissibleBase; + } + return null; + } + } 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 110c46a41..d6fce75e8 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 @@ -215,9 +215,6 @@ public class NukkitConnectionListener extends AbstractConnectionListener impleme if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) { player.setOp(false); } - - // remove their contexts cache - this.plugin.getContextManager().onPlayerQuit(player); }, 1, true); } 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 046b2f478..b2d2fcbc1 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 @@ -25,20 +25,23 @@ package me.lucko.luckperms.sponge.context; -import me.lucko.luckperms.common.context.manager.InlineContextManager; +import me.lucko.luckperms.common.config.ConfigKeys; +import me.lucko.luckperms.common.context.manager.SimpleContextManager; import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.service.model.ContextCalculatorProxy; import me.lucko.luckperms.sponge.service.model.TemporaryCauseHolderSubject; import net.luckperms.api.context.ContextCalculator; import net.luckperms.api.context.ContextConsumer; +import net.luckperms.api.context.ContextSet; import net.luckperms.api.context.StaticContextCalculator; +import net.luckperms.api.query.QueryOptions; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Cause; import org.spongepowered.api.service.permission.Subject; import java.util.UUID; -public class SpongeContextManager extends InlineContextManager { +public class SpongeContextManager extends SimpleContextManager { public SpongeContextManager(LPSpongePlugin plugin) { super(plugin, Subject.class, ServerPlayer.class); @@ -75,4 +78,11 @@ public class SpongeContextManager extends InlineContextManager { - private final QueryOptionsCache singletonCache = new QueryOptionsCache<>(StandaloneUser.INSTANCE, this); - +public class StandaloneContextManager extends SimpleContextManager { public StandaloneContextManager(LPStandalonePlugin plugin) { super(plugin, StandaloneSender.class, StandaloneSender.class); } @@ -47,28 +40,4 @@ public class StandaloneContextManager extends ContextManager getCacheFor(StandaloneSender subject) { - if (subject == null) { - throw new NullPointerException("subject"); - } - if (subject == StandaloneUser.INSTANCE) { - return this.singletonCache; - } - - // just return a new one every time - not optimal but this case should only be hit using unit tests anyway - return new QueryOptionsCache<>(subject, this); - } - - @Override - protected void invalidateCache(StandaloneSender subject) { - this.singletonCache.invalidate(); - } - - @Override - public QueryOptions formQueryOptions(StandaloneSender subject, ImmutableContextSet contextSet) { - QueryOptions.Builder queryOptions = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder(); - return queryOptions.context(contextSet).build(); - } } 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 50bbc15b5..da7412542 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 @@ -26,12 +26,12 @@ package me.lucko.luckperms.velocity.context; import com.velocitypowered.api.proxy.Player; -import me.lucko.luckperms.common.context.manager.InlineContextManager; +import me.lucko.luckperms.common.context.manager.SimpleContextManager; import me.lucko.luckperms.velocity.LPVelocityPlugin; import java.util.UUID; -public class VelocityContextManager extends InlineContextManager { +public class VelocityContextManager extends SimpleContextManager { public VelocityContextManager(LPVelocityPlugin plugin) { super(plugin, Player.class, Player.class); } diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/VelocityConnectionListener.java b/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/VelocityConnectionListener.java index ee92eab25..98d7c5ead 100644 --- a/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/VelocityConnectionListener.java +++ b/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/VelocityConnectionListener.java @@ -38,6 +38,7 @@ import me.lucko.luckperms.common.locale.TranslationManager; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.plugin.util.AbstractConnectionListener; import me.lucko.luckperms.velocity.LPVelocityPlugin; +import me.lucko.luckperms.velocity.context.VelocityContextManager; import me.lucko.luckperms.velocity.service.PlayerPermissionProvider; import me.lucko.luckperms.velocity.util.AdventureCompat; @@ -90,7 +91,8 @@ public class VelocityConnectionListener extends AbstractConnectionListener { try { User user = loadUser(p.getUniqueId(), p.getUsername()); recordConnection(p.getUniqueId()); - e.setProvider(new PlayerPermissionProvider(p, user, this.plugin.getContextManager().getCacheFor(p))); + VelocityContextManager contextManager = this.plugin.getContextManager(); + e.setProvider(new PlayerPermissionProvider(p, user, contextManager::getQueryOptions)); this.plugin.getEventDispatcher().dispatchPlayerLoginProcess(p.getUniqueId(), p.getUsername(), user); } catch (Exception ex) { this.plugin.getLogger().severe("Exception occurred whilst loading data for " + p.getUniqueId() + " - " + p.getUsername(), ex); diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/service/PlayerPermissionProvider.java b/velocity/src/main/java/me/lucko/luckperms/velocity/service/PlayerPermissionProvider.java index 2c872e2e0..3e967d3d2 100644 --- a/velocity/src/main/java/me/lucko/luckperms/velocity/service/PlayerPermissionProvider.java +++ b/velocity/src/main/java/me/lucko/luckperms/velocity/service/PlayerPermissionProvider.java @@ -25,23 +25,24 @@ package me.lucko.luckperms.velocity.service; +import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.velocitypowered.api.permission.PermissionFunction; import com.velocitypowered.api.permission.PermissionProvider; import com.velocitypowered.api.permission.PermissionSubject; import com.velocitypowered.api.permission.Tristate; import com.velocitypowered.api.proxy.Player; -import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.verbose.event.CheckOrigin; +import net.luckperms.api.query.QueryOptions; import org.checkerframework.checker.nullness.qual.NonNull; public class PlayerPermissionProvider implements PermissionProvider, PermissionFunction { private final Player player; private final User user; - private final QueryOptionsSupplier queryOptionsSupplier; + private final Function queryOptionsSupplier; - public PlayerPermissionProvider(Player player, User user, QueryOptionsSupplier queryOptionsSupplier) { + public PlayerPermissionProvider(Player player, User user, Function queryOptionsSupplier) { this.player = player; this.user = user; this.queryOptionsSupplier = queryOptionsSupplier; @@ -55,6 +56,7 @@ public class PlayerPermissionProvider implements PermissionProvider, PermissionF @Override public @NonNull Tristate getPermissionValue(@NonNull String permission) { - return CompatibilityUtil.convertTristate(this.user.getCachedData().getPermissionData(this.queryOptionsSupplier.getQueryOptions()).checkPermission(permission, CheckOrigin.PLATFORM_API_HAS_PERMISSION).result()); + QueryOptions queryOptions = this.queryOptionsSupplier.apply(this.player); + return CompatibilityUtil.convertTristate(this.user.getCachedData().getPermissionData(queryOptions).checkPermission(permission, CheckOrigin.PLATFORM_API_HAS_PERMISSION).result()); } }