mirror of
https://github.com/lucko/LuckPerms.git
synced 2025-08-31 01:59:48 +02:00
Improve context manager caching (#4050)
This commit is contained in:
@@ -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<Player, Player> {
|
||||
public class BukkitContextManager extends DetachedContextManager<Player, Player> {
|
||||
|
||||
public static final OptionKey<Boolean> OP_OPTION = OptionKey.of("op", Boolean.class);
|
||||
|
||||
// cache the creation of ContextsCache instances for online players with no expiry
|
||||
private final LoadingMap<Player, QueryOptionsCache<Player>> onlineSubjectCaches = LoadingMap.of(key -> new QueryOptionsCache<>(key, this));
|
||||
|
||||
// cache the creation of ContextsCache instances for offline players with a 1m expiry
|
||||
private final LoadingCache<Player, QueryOptionsCache<Player>> offlineSubjectCaches = CaffeineFactory.newBuilder()
|
||||
.expireAfterAccess(1, TimeUnit.MINUTES)
|
||||
.build(key -> {
|
||||
QueryOptionsCache<Player> 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<Player> 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<Player> 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();
|
||||
}
|
||||
}
|
||||
|
@@ -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<Player> 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<PermissionAttachment> listIterator(int index) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public @NonNull List<PermissionAttachment> subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); }
|
||||
@Override public @NonNull ListIterator<PermissionAttachment> listIterator(int index) { throw new UnsupportedOperationException(); }
|
||||
@Override public @NonNull List<PermissionAttachment> subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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<ProxiedPlayer, ProxiedPlayer> {
|
||||
public class BungeeContextManager extends SimpleContextManager<ProxiedPlayer, ProxiedPlayer> {
|
||||
public BungeeContextManager(LPBungeePlugin plugin) {
|
||||
super(plugin, ProxiedPlayer.class, ProxiedPlayer.class);
|
||||
}
|
||||
|
@@ -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 <S> the subject type
|
||||
* @param <P> the player type
|
||||
@@ -78,14 +78,10 @@ public abstract class ContextManager<S, P extends S> {
|
||||
|
||||
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<S, P extends S> {
|
||||
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<S, P extends S> {
|
||||
this.plugin.getEventDispatcher().dispatchContextUpdate(subject);
|
||||
}
|
||||
|
||||
protected abstract void invalidateCache(S subject);
|
||||
public abstract void invalidateCache(S subject);
|
||||
|
||||
public void registerCalculator(ContextCalculator<? super S> calculator) {
|
||||
String calculatorClass = calculator.getClass().getName();
|
||||
@@ -158,7 +156,9 @@ public abstract class ContextManager<S, P extends S> {
|
||||
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<S, P extends S> {
|
||||
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() {
|
||||
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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<S, P extends S> extends ContextManager<S, P> {
|
||||
|
||||
private final LoadingCache<S, QueryOptions> fallbackContextsCache = CaffeineFactory.newBuilder()
|
||||
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
|
||||
.build(this::calculate);
|
||||
|
||||
protected DetachedContextManager(LuckPermsPlugin plugin, Class<S> subjectClass, Class<P> 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);
|
||||
|
||||
}
|
@@ -37,11 +37,11 @@ import java.util.concurrent.TimeUnit;
|
||||
*
|
||||
* @param <T> the player type
|
||||
*/
|
||||
public final class QueryOptionsCache<T> extends ExpiringCache<QueryOptions> implements QueryOptionsSupplier {
|
||||
final class QueryOptionsCache<T> extends ExpiringCache<QueryOptions> implements QueryOptionsSupplier {
|
||||
private final T subject;
|
||||
private final ContextManager<T, ?> contextManager;
|
||||
|
||||
public QueryOptionsCache(T subject, ContextManager<T, ?> contextManager) {
|
||||
QueryOptionsCache(T subject, ContextManager<T, ?> contextManager) {
|
||||
super(50L, TimeUnit.MILLISECONDS); // expire roughly every tick
|
||||
this.subject = subject;
|
||||
this.contextManager = contextManager;
|
||||
@@ -61,4 +61,9 @@ public final class QueryOptionsCache<T> extends ExpiringCache<QueryOptions> impl
|
||||
public ImmutableContextSet getContextSet() {
|
||||
return get().context();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateCache() {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
@@ -39,4 +39,6 @@ public interface QueryOptionsSupplier {
|
||||
return getQueryOptions().context();
|
||||
}
|
||||
|
||||
void invalidateCache();
|
||||
|
||||
}
|
||||
|
@@ -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<S, P extends S> extends ContextManager<S, P> {
|
||||
public abstract class SimpleContextManager<S, P extends S> extends ContextManager<S, P> {
|
||||
|
||||
private final LoadingCache<S, QueryOptions> contextsCache = CaffeineFactory.newBuilder()
|
||||
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
|
||||
.build(this::calculate);
|
||||
|
||||
protected InlineContextManager(LuckPermsPlugin plugin, Class<S> subjectClass, Class<P> playerClass) {
|
||||
protected SimpleContextManager(LuckPermsPlugin plugin, Class<S> subjectClass, Class<P> 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<T> implements QueryOptionsSupplier {
|
||||
private final T key;
|
||||
private final LoadingCache<T, QueryOptions> cache;
|
||||
|
||||
InlineQueryOptionsSupplier(T key, LoadingCache<T, QueryOptions> cache) {
|
||||
this.key = key;
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptions getQueryOptions() {
|
||||
return this.cache.get(this.key);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<ServerPlayerEntity, ServerPlayerEntity> {
|
||||
public class FabricContextManager extends DetachedContextManager<ServerPlayerEntity, ServerPlayerEntity> {
|
||||
public static final OptionKey<Boolean> INTEGRATED_SERVER_OWNER = OptionKey.of("integrated_server_owner", Boolean.class);
|
||||
|
||||
public FabricContextManager(LuckPermsPlugin plugin) {
|
||||
@@ -49,32 +49,17 @@ public class FabricContextManager extends ContextManager<ServerPlayerEntity, Ser
|
||||
return player.getUuid();
|
||||
}
|
||||
|
||||
public QueryOptionsCache<ServerPlayerEntity> newQueryOptionsCache(ServerPlayerEntity player) {
|
||||
return new QueryOptionsCache<>(player, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptionsCache<ServerPlayerEntity> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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<ServerPlayerEntity> 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<ServerPlayerEntity> 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;
|
||||
}
|
||||
|
@@ -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<ServerPlayerEntity> luckperms$getQueryOptionsCache(FabricContextManager contextManager);
|
||||
QueryOptionsSupplier luckperms$getQueryOptionsCache(FabricContextManager contextManager);
|
||||
|
||||
/**
|
||||
* Initialises permissions for this player using the given {@link User}.
|
||||
|
@@ -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);
|
||||
|
@@ -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<ServerPlayer> 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<ServerPlayer> getQueryOptionsCache() {
|
||||
public QueryOptionsSupplier getQueryOptionsSupplier() {
|
||||
assertInitialised();
|
||||
return this.queryOptionsCache;
|
||||
return this.queryOptionsSupplier;
|
||||
}
|
||||
|
||||
public Locale getLocale(ServerPlayer player) {
|
||||
|
@@ -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 {
|
||||
|
@@ -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<ServerPlayer, ServerPlayer> {
|
||||
public class ForgeContextManager extends DetachedContextManager<ServerPlayer, ServerPlayer> {
|
||||
public static final OptionKey<Boolean> INTEGRATED_SERVER_OWNER = OptionKey.of("integrated_server_owner", Boolean.class);
|
||||
|
||||
public ForgeContextManager(LPForgePlugin plugin) {
|
||||
@@ -50,29 +50,19 @@ public class ForgeContextManager extends ContextManager<ServerPlayer, ServerPlay
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptionsCache<ServerPlayer> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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<ServerPlayer, ServerPlayer> {
|
||||
public class NeoForgeContextManager extends SimpleContextManager<ServerPlayer, ServerPlayer> {
|
||||
public static final OptionKey<Boolean> INTEGRATED_SERVER_OWNER = OptionKey.of("integrated_server_owner", Boolean.class);
|
||||
|
||||
public NeoForgeContextManager(LPNeoForgePlugin plugin) {
|
||||
@@ -48,12 +46,9 @@ public class NeoForgeContextManager extends InlineContextManager<ServerPlayer, S
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptions formQueryOptions(ServerPlayer subject, ImmutableContextSet contextSet) {
|
||||
QueryOptions.Builder builder = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder();
|
||||
public void customizeQueryOptions(ServerPlayer subject, QueryOptions.Builder builder) {
|
||||
if (subject.getServer() != null && subject.getServer().isSingleplayerOwner(subject.getGameProfile())) {
|
||||
builder.option(INTEGRATED_SERVER_OWNER, true);
|
||||
}
|
||||
|
||||
return builder.context(contextSet).build();
|
||||
}
|
||||
}
|
||||
|
@@ -26,84 +26,45 @@
|
||||
package me.lucko.luckperms.nukkit.context;
|
||||
|
||||
import cn.nukkit.Player;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
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 me.lucko.luckperms.common.context.manager.DetachedContextManager;
|
||||
import me.lucko.luckperms.common.context.manager.QueryOptionsSupplier;
|
||||
import me.lucko.luckperms.nukkit.LPNukkitPlugin;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.nukkit.inject.permissible.LuckPermsPermissible;
|
||||
import me.lucko.luckperms.nukkit.inject.permissible.PermissibleInjector;
|
||||
import net.luckperms.api.query.OptionKey;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class NukkitContextManager extends ContextManager<Player, Player> {
|
||||
public class NukkitContextManager extends DetachedContextManager<Player, Player> {
|
||||
|
||||
public static final OptionKey<Boolean> OP_OPTION = OptionKey.of("op", Boolean.class);
|
||||
|
||||
// cache the creation of ContextsCache instances for online players with no expiry
|
||||
private final LoadingMap<Player, QueryOptionsCache<Player>> onlineSubjectCaches = LoadingMap.of(key -> new QueryOptionsCache<>(key, this));
|
||||
|
||||
// cache the creation of ContextsCache instances for offline players with a 1m expiry
|
||||
private final LoadingCache<Player, QueryOptionsCache<Player>> offlineSubjectCaches = CaffeineFactory.newBuilder()
|
||||
.expireAfterAccess(1, TimeUnit.MINUTES)
|
||||
.build(key -> {
|
||||
QueryOptionsCache<Player> 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<Player> 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<Player> 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();
|
||||
}
|
||||
}
|
||||
|
@@ -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<Player> 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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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<Subject, ServerPlayer> {
|
||||
public class SpongeContextManager extends SimpleContextManager<Subject, ServerPlayer> {
|
||||
|
||||
public SpongeContextManager(LPSpongePlugin plugin) {
|
||||
super(plugin, Subject.class, ServerPlayer.class);
|
||||
@@ -75,4 +78,11 @@ public class SpongeContextManager extends InlineContextManager<Subject, ServerPl
|
||||
public UUID getUniqueId(ServerPlayer player) {
|
||||
return player.uniqueId();
|
||||
}
|
||||
|
||||
public QueryOptions formQueryOptions(ContextSet contexts) {
|
||||
QueryOptions.Builder builder = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS).toBuilder().context(contexts);
|
||||
customizeStaticQueryOptions(builder);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -25,20 +25,13 @@
|
||||
|
||||
package me.lucko.luckperms.standalone.stub;
|
||||
|
||||
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.SimpleContextManager;
|
||||
import me.lucko.luckperms.standalone.LPStandalonePlugin;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneSender;
|
||||
import me.lucko.luckperms.standalone.app.integration.StandaloneUser;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class StandaloneContextManager extends ContextManager<StandaloneSender, StandaloneSender> {
|
||||
private final QueryOptionsCache<StandaloneSender> singletonCache = new QueryOptionsCache<>(StandaloneUser.INSTANCE, this);
|
||||
|
||||
public class StandaloneContextManager extends SimpleContextManager<StandaloneSender, StandaloneSender> {
|
||||
public StandaloneContextManager(LPStandalonePlugin plugin) {
|
||||
super(plugin, StandaloneSender.class, StandaloneSender.class);
|
||||
}
|
||||
@@ -47,28 +40,4 @@ public class StandaloneContextManager extends ContextManager<StandaloneSender, S
|
||||
public UUID getUniqueId(StandaloneSender player) {
|
||||
return player.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptionsCache<StandaloneSender> 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();
|
||||
}
|
||||
}
|
||||
|
@@ -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<Player, Player> {
|
||||
public class VelocityContextManager extends SimpleContextManager<Player, Player> {
|
||||
public VelocityContextManager(LPVelocityPlugin plugin) {
|
||||
super(plugin, Player.class, Player.class);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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<Player, QueryOptions> queryOptionsSupplier;
|
||||
|
||||
public PlayerPermissionProvider(Player player, User user, QueryOptionsSupplier queryOptionsSupplier) {
|
||||
public PlayerPermissionProvider(Player player, User user, Function<Player, QueryOptions> 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());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user