diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/contexts/BukkitContextManager.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/contexts/BukkitContextManager.java index 8ea816a4..f620c3db 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/contexts/BukkitContextManager.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/contexts/BukkitContextManager.java @@ -31,12 +31,12 @@ import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.bukkit.LPBukkitPlugin; import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.contexts.ContextManager; +import me.lucko.luckperms.common.contexts.AbstractContextManager; import org.bukkit.entity.Player; @RequiredArgsConstructor -public class BukkitContextManager extends ContextManager { +public class BukkitContextManager extends AbstractContextManager { private final LPBukkitPlugin plugin; @Override diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/contexts/BungeeContextManager.java b/bungee/src/main/java/me/lucko/luckperms/bungee/contexts/BungeeContextManager.java index b8fdff5a..784a5bbd 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/contexts/BungeeContextManager.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/contexts/BungeeContextManager.java @@ -31,12 +31,12 @@ import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.bungee.LPBungeePlugin; import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.contexts.ContextManager; +import me.lucko.luckperms.common.contexts.AbstractContextManager; import net.md_5.bungee.api.connection.ProxiedPlayer; @RequiredArgsConstructor -public class BungeeContextManager extends ContextManager { +public class BungeeContextManager extends AbstractContextManager { private final LPBungeePlugin plugin; @Override diff --git a/common/src/main/java/me/lucko/luckperms/common/contexts/AbstractContextManager.java b/common/src/main/java/me/lucko/luckperms/common/contexts/AbstractContextManager.java new file mode 100644 index 00000000..22809a2c --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/contexts/AbstractContextManager.java @@ -0,0 +1,127 @@ +/* + * 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.contexts; + +import lombok.NonNull; + +import com.github.benmanes.caffeine.cache.CacheLoader; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; + +import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.context.ContextCalculator; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.context.MutableContextSet; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; + +/** + * An abstract implementation of {@link ContextManager} which caches content lookups. + * + * @param the calculator type + */ +public abstract class AbstractContextManager implements ContextManager { + + private final List> calculators = new CopyOnWriteArrayList<>(); + private final List> staticCalculators = new CopyOnWriteArrayList<>(); + + // caches context lookups + private final LoadingCache lookupCache = Caffeine.newBuilder() + .weakKeys() + .expireAfterWrite(50L, TimeUnit.MILLISECONDS) // expire roughly every tick + .build(new Loader()); + + @Override + public ImmutableContextSet getApplicableContext(@NonNull T subject) { + // this is actually already immutable, but the Contexts method signature returns the interface. + return getApplicableContexts(subject).getContexts().makeImmutable(); + } + + @Override + public Contexts getApplicableContexts(@NonNull T subject) { + return lookupCache.get(subject); + } + + @Override + public void registerCalculator(ContextCalculator calculator) { + registerCalculator(calculator, false); + } + + @Override + public void registerCalculator(ContextCalculator calculator, boolean isStatic) { + // calculators registered first should have priority (and be checked last.) + calculators.add(0, calculator); + + if (isStatic) { + staticCalculators.add(0, calculator); + } + } + + @Override + public ImmutableContextSet getStaticContexts() { + MutableContextSet accumulator = MutableContextSet.create(); + for (ContextCalculator calculator : staticCalculators) { + calculator.giveApplicableContext(null, accumulator); + } + return accumulator.makeImmutable(); + } + + @Override + public void invalidateCache(@NonNull T subject){ + lookupCache.invalidate(subject); + } + + @Override + public int getCalculatorsSize() { + return calculators.size(); + } + + // iterates the calculators in this manager and accumulates contexts from them all. + private void calculateApplicableContext(T subject, MutableContextSet accumulator) { + for (ContextCalculator calculator : calculators) { + try { + calculator.giveApplicableContext(subject, accumulator); + } catch (Exception e) { + new RuntimeException("Exception thrown by ContextCalculator: " + calculator.getClass().getName(), e).printStackTrace(); + } + } + } + + private final class Loader implements CacheLoader { + + @Override + public Contexts load(T subject) { + MutableContextSet accumulator = MutableContextSet.create(); + calculateApplicableContext(subject, accumulator); + + ImmutableContextSet ret = accumulator.makeImmutable(); + return formContexts(subject, ret); + } + } + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java b/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java index ff63beac..985beed2 100644 --- a/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java @@ -27,17 +27,9 @@ package me.lucko.luckperms.common.contexts; import lombok.NonNull; -import com.github.benmanes.caffeine.cache.Caffeine; -import com.github.benmanes.caffeine.cache.LoadingCache; - import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ContextCalculator; import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.api.context.MutableContextSet; - -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.TimeUnit; /** * Manages {@link ContextCalculator}s, and calculates applicable contexts for a @@ -45,23 +37,7 @@ import java.util.concurrent.TimeUnit; * * @param the calculator type */ -public abstract class ContextManager { - - private final List> calculators = new CopyOnWriteArrayList<>(); - private final List> staticCalculators = new CopyOnWriteArrayList<>(); - - // caches context lookups - private final LoadingCache lookupCache = Caffeine.newBuilder() - .weakKeys() - .expireAfterWrite(50L, TimeUnit.MILLISECONDS) // expire roughly every tick - .build(subject -> { - MutableContextSet accumulator = MutableContextSet.create(); - calculateApplicableContext(subject, accumulator); - - ImmutableContextSet ret = accumulator.makeImmutable(); - return formContexts(subject, ret); - }); - +public interface ContextManager { /** * Queries the ContextManager for current context values for the subject. @@ -69,10 +45,7 @@ public abstract class ContextManager { * @param subject the subject * @return the applicable context for the subject */ - public ImmutableContextSet getApplicableContext(@NonNull T subject) { - // this is actually already immutable, but the Contexts method signature returns the interface. - return getApplicableContexts(subject).getContexts().makeImmutable(); - } + ImmutableContextSet getApplicableContext(@NonNull T subject); /** * Queries the ContextManager for current context values for the subject. @@ -80,9 +53,7 @@ public abstract class ContextManager { * @param subject the subject * @return the applicable context for the subject */ - public Contexts getApplicableContexts(@NonNull T subject) { - return lookupCache.get(subject); - } + Contexts getApplicableContexts(@NonNull T subject); /** * Forms a {@link Contexts} instance from an {@link ImmutableContextSet}. @@ -91,16 +62,14 @@ public abstract class ContextManager { * @param contextSet the context set * @return a contexts instance */ - public abstract Contexts formContexts(T subject, ImmutableContextSet contextSet); + Contexts formContexts(T subject, ImmutableContextSet contextSet); /** * Registers a context calculator with the manager. * * @param calculator the calculator */ - public void registerCalculator(ContextCalculator calculator) { - registerCalculator(calculator, false); - } + void registerCalculator(ContextCalculator calculator); /** * Registers a context calculator with the manager. @@ -108,56 +77,27 @@ public abstract class ContextManager { * @param calculator the calculator * @param isStatic if the calculator is static. (if it allows a null subject parameter) */ - public void registerCalculator(ContextCalculator calculator, boolean isStatic) { - // calculators registered first should have priority (and be checked last.) - calculators.add(0, calculator); - - if (isStatic) { - staticCalculators.add(0, calculator); - } - } + void registerCalculator(ContextCalculator calculator, boolean isStatic); /** * Gets the contexts from the static calculators in this manager. * * @return the current active static contexts */ - public ImmutableContextSet getStaticContexts() { - MutableContextSet accumulator = MutableContextSet.create(); - for (ContextCalculator calculator : staticCalculators) { - calculator.giveApplicableContext(null, accumulator); - } - return accumulator.makeImmutable(); - } + ImmutableContextSet getStaticContexts(); /** * Invalidates the lookup cache for a given subject * * @param subject the subject */ - public void invalidateCache(@NonNull T subject){ - lookupCache.invalidate(subject); - } + void invalidateCache(@NonNull T subject); /** * Gets the number of calculators registered with the manager. * * @return the number of calculators registered */ - public int getCalculatorsSize() { - return calculators.size(); - } - - // iterates the calculators in this manager and accumulates contexts from them all. - private void calculateApplicableContext(T subject, MutableContextSet accumulator) { - for (ContextCalculator calculator : calculators) { - try { - calculator.giveApplicableContext(subject, accumulator); - } catch (Exception e) { - new RuntimeException("Exception thrown by ContextCalculator: " + calculator.getClass().getName(), e).printStackTrace(); - } - - } - } + int getCalculatorsSize(); } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeContextManager.java b/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeContextManager.java index 8ee6217e..d21a9ae5 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeContextManager.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeContextManager.java @@ -30,13 +30,13 @@ import lombok.RequiredArgsConstructor; import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.contexts.ContextManager; +import me.lucko.luckperms.common.contexts.AbstractContextManager; import me.lucko.luckperms.sponge.LPSpongePlugin; import org.spongepowered.api.service.permission.Subject; @RequiredArgsConstructor -public class SpongeContextManager extends ContextManager { +public class SpongeContextManager extends AbstractContextManager { private final LPSpongePlugin plugin; @Override