diff --git a/api/build.gradle b/api/build.gradle index 2917e7ba1..d15207a4c 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -1,7 +1,6 @@ -project.version = '4.4' +project.version = '5.0' dependencies { - compileOnly 'com.google.guava:guava:19.0' compileOnly 'org.checkerframework:checker-qual:2.5.5' } @@ -14,7 +13,6 @@ if (project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePass options.encoding = 'UTF-8' options.charSet = 'UTF-8' options.links( - 'https://google.github.io/guava/releases/21.0/api/docs/', 'https://docs.oracle.com/javase/8/docs/api/' ) options.addStringOption('Xdoclint:none', '-quiet') diff --git a/api/src/main/java/me/lucko/luckperms/api/ChatMetaType.java b/api/src/main/java/me/lucko/luckperms/api/ChatMetaType.java deleted file mode 100644 index e276bdc7f..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/ChatMetaType.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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.api; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -/** - * Represents a type of chat meta - * - * @since 3.2 - */ -public enum ChatMetaType { - - /** - * Represents a prefix - */ - PREFIX("prefix") { - @Override - public boolean matches(@NonNull Node node) { - return Objects.requireNonNull(node, "node").isPrefix(); - } - - @Override - public Map.@NonNull Entry getEntry(@NonNull Node node) { - return Objects.requireNonNull(node, "node").getPrefix(); - } - }, - - /** - * Represents a suffix - */ - SUFFIX("suffix") { - @Override - public boolean matches(@NonNull Node node) { - return Objects.requireNonNull(node, "node").isSuffix(); - } - - @Override - public Map.@NonNull Entry getEntry(@NonNull Node node) { - return Objects.requireNonNull(node, "node").getSuffix(); - } - }; - - private final String str; - - ChatMetaType(String str) { - this.str = str; - } - - /** - * Returns if the passed node matches the type - * - * @param node the node to test - * @return true if the node has the same type - */ - public abstract boolean matches(@NonNull Node node); - - /** - * Returns if the passed node should be ignored when searching for meta of this type - * - * @param node the node to test - * @return true if the node does not share the same type - */ - public boolean shouldIgnore(@NonNull Node node) { - return !matches(node); - } - - /** - * Maps the corresponding entry from the given node - * - * @param node the node to retrieve the entry from - * @return the entry - * @throws IllegalStateException if the node does not share the same type - */ - public abstract Map.@NonNull Entry getEntry(@NonNull Node node); - - @Override - public String toString() { - return this.str; - } - - /** - * Parses a ChatMetaType from the given node. - * - * @param node the node - * @return the parsed chat meta type - * @since 3.4 - */ - public static @NonNull Optional ofNode(@NonNull Node node) { - if (node.isPrefix()) { - return Optional.of(PREFIX); - } else if (node.isSuffix()) { - return Optional.of(SUFFIX); - } else { - return Optional.empty(); - } - } - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/Contexts.java b/api/src/main/java/me/lucko/luckperms/api/Contexts.java deleted file mode 100644 index adf38f46d..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/Contexts.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * 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.api; - -import me.lucko.luckperms.api.context.ContextSet; -import me.lucko.luckperms.api.context.ImmutableContextSet; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Objects; -import java.util.Set; - -/** - * Encapsulates the {@link ContextSet contexts} and {@link LookupSetting settings} for - * a permission or meta lookup. - * - *

This class is immutable.

- * - * @since 2.11 - */ -public class Contexts { - - /** - * The context key used to denote the subjects server - */ - public static final String SERVER_KEY = "server"; - - /** - * The context key used to denote the subjects world - */ - public static final String WORLD_KEY = "world"; - - /** - * The default {@link LookupSetting}s as a flag. - */ - private static final byte DEFAULT_SETTINGS_FLAG = LookupSetting.createFlag( - LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER, - LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD, - LookupSetting.RESOLVE_INHERITANCE, - LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER, - LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD - ); - - /** - * A 'global' or default contexts instance. - * - *

Formed of an empty {@link ContextSet} and all inclusion and - * inheritance {@link LookupSetting}s applied.

- */ - private static final Contexts GLOBAL = new Contexts(ImmutableContextSet.empty(), DEFAULT_SETTINGS_FLAG); - - /** - * Gets the {@link FullySatisfiedContexts} instance. - * - * @return a context that will satisfy all contextual requirements. - */ - public static @NonNull Contexts allowAll() { - return FullySatisfiedContexts.getInstance(); - } - - /** - * Returns a 'global' or default contexts instance. - * - *

Formed of an empty {@link ContextSet} and all inclusion and - * inheritance {@link LookupSetting}s applied.

- * - * @return the global contexts - * @since 3.3 - */ - public static @NonNull Contexts global() { - return GLOBAL; - } - - /** - * Creates a new {@link Contexts} instance. - * - * @param contextSet the context set - * @param includeNodesSetWithoutServer the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER} - * @param includeNodesSetWithoutWorld the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD} - * @param resolveInheritance the value of {@link LookupSetting#RESOLVE_INHERITANCE} - * @param applyParentsWithoutServer the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER} - * @param applyParentsWithoutWorld the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD} - * @param isOp the value of {@link LookupSetting#IS_OP} - * @return a new instance - */ - public static @NonNull Contexts of(@NonNull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) { - Objects.requireNonNull(contextSet, "contextSet"); - byte settingsFlag = LookupSetting.createFlag( - includeNodesSetWithoutServer, - includeNodesSetWithoutWorld, - resolveInheritance, - applyParentsWithoutServer, - applyParentsWithoutWorld, - isOp - ); - if (contextSet.isEmpty() && DEFAULT_SETTINGS_FLAG == settingsFlag) { - return GLOBAL; - } - return new Contexts(contextSet.makeImmutable(), settingsFlag); - } - - /** - * Creates a new {@link Contexts} instance. - * - * @param contextSet the context set - * @param settings the settings - * @return a new instance - */ - public static Contexts of(@NonNull ContextSet contextSet, @NonNull Set settings) { - Objects.requireNonNull(contextSet, "contextSet"); - Objects.requireNonNull(settings, "settings"); - - byte settingsFlag = LookupSetting.createFlag(settings); - if (contextSet.isEmpty() && DEFAULT_SETTINGS_FLAG == settingsFlag) { - return GLOBAL; - } - - return new Contexts(contextSet.makeImmutable(), settingsFlag); - } - - /** - * The contexts that apply for this lookup - */ - private final ImmutableContextSet contextSet; - - /** - * The settings for this lookup - */ - private final byte settingsFlag; - - // cache hashcode - this class is immutable, and is used as an index in the permission cache. - private final int hashCode; - - /** - * Creates a new {@link Contexts} instance. - * - * @param contextSet the context set - * @param includeNodesSetWithoutServer the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER} - * @param includeNodesSetWithoutWorld the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD} - * @param resolveInheritance the value of {@link LookupSetting#RESOLVE_INHERITANCE} - * @param applyParentsWithoutServer the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER} - * @param applyParentsWithoutWorld the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD} - * @param isOp the value of {@link LookupSetting#IS_OP} - * @deprecated in favour of {@link #of(ContextSet, boolean, boolean, boolean, boolean, boolean, boolean)} - */ - @Deprecated - public Contexts(@NonNull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) { - this.contextSet = Objects.requireNonNull(contextSet, "contextSet").makeImmutable(); - this.settingsFlag = LookupSetting.createFlag( - includeNodesSetWithoutServer, - includeNodesSetWithoutWorld, - resolveInheritance, - applyParentsWithoutServer, - applyParentsWithoutWorld, - isOp - ); - this.hashCode = calculateHashCode(); - } - - protected Contexts(@NonNull ImmutableContextSet contextSet, byte settingsFlag) { - this.contextSet = contextSet; - this.settingsFlag = settingsFlag; - this.hashCode = calculateHashCode(); - } - - /** - * Gets the {@link ContextSet set of context pairs} for this {@link Contexts} instance. - * - * @return an immutable context from this instance - * @since 2.13 - */ - public @NonNull ContextSet getContexts() { - return this.contextSet; - } - - /** - * Gets the set of {@link LookupSetting}s for this {@link Contexts} instance. - * - * @return the settings - * @since 4.2 - */ - public @NonNull Set getSettings() { - return LookupSetting.createSetFromFlag(this.settingsFlag); - } - - /** - * Creates a copy of this {@link Contexts} instance, but with the - * {@link ContextSet set of context pairs} replaced by the given set. - * - * @param contextSet the context set - * @return a new contexts instance representing the new settings - * @since 4.4 - */ - public @NonNull Contexts setContexts(@NonNull ContextSet contextSet) { - ImmutableContextSet cs = Objects.requireNonNull(contextSet, "contextSet").makeImmutable(); - if (this.contextSet.equals(cs)) { - return this; - } - return new Contexts(cs, this.settingsFlag); - } - - /** - * Creates a copy of this {@link Contexts} instance, but with the - * {@link LookupSetting}s replaced by the given settings. - * - * @param settings the lookup settings - * @return a new contexts instance representing the new settings - * @since 4.4 - */ - public @NonNull Contexts setSettings(@NonNull Set settings) { - Objects.requireNonNull(settings, "settings"); - - byte settingsFlag = LookupSetting.createFlag(settings); - if (this.settingsFlag == settingsFlag) { - return this; - } - if (DEFAULT_SETTINGS_FLAG == settingsFlag && this.contextSet.isEmpty()) { - return GLOBAL; - } - - return new Contexts(this.contextSet, settingsFlag); - } - - /** - * Gets if the given {@link LookupSetting} is set. - * - * @param setting the setting - * @return the value - * @since 4.2 - */ - public boolean hasSetting(@NonNull LookupSetting setting) { - return LookupSetting.isSet(this.settingsFlag, setting); - } - - /** - * Gets the value of {@link LookupSetting#IS_OP}. - * - * @return the value - * @see LookupSetting#IS_OP - * @deprecated in favour of {@link #hasSetting(LookupSetting)} - */ - @Deprecated - public boolean isOp() { - return hasSetting(LookupSetting.IS_OP); - } - - /** - * Gets the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER}. - * - * @return the value - * @see LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER - * @deprecated in favour of {@link #hasSetting(LookupSetting)} - */ - @Deprecated - public boolean isIncludeGlobal() { - return hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER); - } - - /** - * Gets the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD}. - * - * @return the value - * @see LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD - * @deprecated in favour of {@link #hasSetting(LookupSetting)} - */ - @Deprecated - public boolean isIncludeGlobalWorld() { - return hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD); - } - - /** - * Gets the value of {@link LookupSetting#RESOLVE_INHERITANCE}. - * - * @return the value - * @see LookupSetting#RESOLVE_INHERITANCE - * @deprecated in favour of {@link #hasSetting(LookupSetting)} - */ - @Deprecated - public boolean isApplyGroups() { - return hasSetting(LookupSetting.RESOLVE_INHERITANCE); - } - - /** - * Gets the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER}. - * - * @return the value - * @see LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER - * @deprecated in favour of {@link #hasSetting(LookupSetting)} - */ - @Deprecated - public boolean isApplyGlobalGroups() { - return hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER); - } - - /** - * Gets the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD}. - * - * @return the value - * @see LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD - * @deprecated in favour of {@link #hasSetting(LookupSetting)} - */ - @Deprecated - public boolean isApplyGlobalWorldGroups() { - return hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD); - } - - @Override - public @NonNull String toString() { - return "Contexts(contextSet=" + this.contextSet + ", settings=" + LookupSetting.createSetFromFlag(this.settingsFlag) + ")"; - } - - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (o == allowAll()) return false; - if (!(o instanceof Contexts)) return false; - final Contexts that = (Contexts) o; - return this.contextSet.equals(that.contextSet) && this.settingsFlag == that.settingsFlag; - } - - private int calculateHashCode() { - final int PRIME = 59; - int result = 1; - result = result * PRIME + this.contextSet.hashCode(); - result = result * PRIME + this.settingsFlag; - return result; - } - - @Override - public int hashCode() { - return this.hashCode; - } - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java b/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java deleted file mode 100644 index d7e897fb7..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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.api; - -import me.lucko.luckperms.api.caching.CachedData; -import me.lucko.luckperms.api.caching.MetaContexts; -import me.lucko.luckperms.api.context.ImmutableContextSet; - -import org.checkerframework.checker.nullness.qual.NonNull; - -/** - * A special instance of {@link Contexts}, which when passed to: - * - *

- *
    - *
  • {@link CachedData#getPermissionData(Contexts)}
  • - *
  • {@link CachedData#getMetaData(Contexts)}
  • - *
  • {@link CachedData#getMetaData(MetaContexts)}
  • - *
- * - *

... will always satisfy all contextual requirements.

- * - *

This effectively allows you to do lookups which ignore context.

- * - * @since 3.3 - */ -public final class FullySatisfiedContexts extends Contexts { - - // singleton - private static final FullySatisfiedContexts INSTANCE = new FullySatisfiedContexts(); - - public static @NonNull Contexts getInstance() { - return INSTANCE; - } - - private FullySatisfiedContexts() { - super(ImmutableContextSet.empty(), LookupSetting.createFlag(Contexts.global().getSettings())); - } - - @Override - public @NonNull String toString() { - return "FullySatisfiedContexts()"; - } - - @Override - public boolean equals(Object o) { - // this class is a singleton, so we can use object comparison to check equality. - return o == this; - } - - @Override - public int hashCode() { - // just use the system hashcode - we need to override the hashcode impl in super - return System.identityHashCode(this); - } -} diff --git a/api/src/main/java/me/lucko/luckperms/api/LPConfiguration.java b/api/src/main/java/me/lucko/luckperms/api/LPConfiguration.java deleted file mode 100644 index 124efcc7d..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/LPConfiguration.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.api; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Map; - -/** - * Wrapper around parts of the LuckPerms configuration file - */ -public interface LPConfiguration { - - /** - * Gets the name of this server - * - * @return the name of this server - */ - @NonNull String getServer(); - - /** - * Gets if the users on this server will have their global permissions applied - * - * @return if the users on this server will have their global permissions applied - */ - boolean getIncludeGlobalPerms(); - - /** - * Gets if the users on this server will have their global world permissions applied - * - * @return if the users on this server will have their global world permissions applied - * @since 2.9 - */ - boolean getIncludeGlobalWorldPerms(); - - /** - * Gets if the platform is applying global groups - * - * @return true if the platform is applying global groups - * @since 2.9 - */ - boolean getApplyGlobalGroups(); - - /** - * Gets if the platform is applying global world groups - * - * @return true if the platform is applying global world groups - * @since 2.9 - */ - boolean getApplyGlobalWorldGroups(); - - /** - * Gets the storage method string from the configuration - * - * @return the storage method string from the configuration - */ - @NonNull String getStorageMethod(); - - /** - * Gets true if split storage is enabled - * - * @return true if split storage is enabled - * @since 2.7 - */ - boolean getSplitStorage(); - - /** - * Gets a map of split storage options - * - * @return a map of split storage options, where the key is the storage section, and the value is the storage - * method. For example: key = user, value = json - * @since 2.7 - */ - @NonNull Map getSplitStorageOptions(); - - @NonNull Unsafe unsafe(); - - interface Unsafe { - - /** - * Gets an Object from the config. - * - *

This method is nested under {@link Unsafe} because the keys - * and return types may change between versions without warning.

- * - * @param key the key, as defined as a field name in - * the "ConfigKeys" class. - * @return the corresponding object, if one is present - * @throws IllegalArgumentException if the key isn't known - */ - @NonNull Object getObject(String key); - } - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/LookupSetting.java b/api/src/main/java/me/lucko/luckperms/api/LookupSetting.java deleted file mode 100644 index 740a72d91..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/LookupSetting.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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.api; - -import java.util.EnumSet; -import java.util.Set; - -/** - * The various lookup setting flags for {@link Contexts}. - * - * @since 4.2 - */ -public enum LookupSetting { - - /** - * If the target subject is OP - */ - IS_OP, - - /** - * If global or non-server-specific nodes should be applied - */ - INCLUDE_NODES_SET_WITHOUT_SERVER, - - /** - * If global or non-world-specific nodes should be applied - */ - INCLUDE_NODES_SET_WITHOUT_WORLD, - - /** - * If parent groups should be resolved - */ - RESOLVE_INHERITANCE, - - /** - * If global or non-server-specific group memberships should be applied - */ - APPLY_PARENTS_SET_WITHOUT_SERVER, - - /** - * If global or non-world-specific group memberships should be applied - */ - APPLY_PARENTS_SET_WITHOUT_WORLD; - - - - /* bitwise utility methods */ - - static boolean isSet(byte b, LookupSetting setting) { - return ((b >> setting.ordinal()) & 1) == 1; - } - - static byte createFlag(LookupSetting... settings) { - byte b = 0; - for (LookupSetting setting : settings) { - b |= (1 << setting.ordinal()); - } - return b; - } - - static byte createFlag(Set settings) { - byte b = 0; - for (LookupSetting setting : settings) { - b |= (1 << setting.ordinal()); - } - return b; - } - - static Set createSetFromFlag(byte b) { - EnumSet settings = EnumSet.noneOf(LookupSetting.class); - for (LookupSetting setting : LookupSetting.values()) { - if (((b >> setting.ordinal()) & 1) == 1) { - settings.add(setting); - } - } - return settings; - } - - static byte createFlag(boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) { - byte b = 0; - if (includeNodesSetWithoutServer) { - b |= (1 << LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER.ordinal()); - } - if (includeNodesSetWithoutWorld) { - b |= (1 << LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD.ordinal()); - } - if (resolveInheritance) { - b |= (1 << LookupSetting.RESOLVE_INHERITANCE.ordinal()); - } - if (applyParentsWithoutServer) { - b |= (1 << LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER.ordinal()); - } - if (applyParentsWithoutWorld) { - b |= (1 << LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD.ordinal()); - } - if (isOp) { - b |= (1 << LookupSetting.IS_OP.ordinal()); - } - return b; - } -} diff --git a/api/src/main/java/me/lucko/luckperms/api/LuckPerms.java b/api/src/main/java/me/lucko/luckperms/api/LuckPerms.java new file mode 100644 index 000000000..e5d511c01 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/LuckPerms.java @@ -0,0 +1,217 @@ +/* + * 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.api; + +import me.lucko.luckperms.api.actionlog.ActionLogger; +import me.lucko.luckperms.api.context.ContextCalculator; +import me.lucko.luckperms.api.context.ContextManager; +import me.lucko.luckperms.api.event.EventBus; +import me.lucko.luckperms.api.messaging.MessagingService; +import me.lucko.luckperms.api.messenger.MessengerProvider; +import me.lucko.luckperms.api.metastacking.MetaStackDefinition; +import me.lucko.luckperms.api.metastacking.MetaStackElement; +import me.lucko.luckperms.api.metastacking.MetaStackFactory; +import me.lucko.luckperms.api.model.group.Group; +import me.lucko.luckperms.api.model.group.GroupManager; +import me.lucko.luckperms.api.model.user.User; +import me.lucko.luckperms.api.model.user.UserManager; +import me.lucko.luckperms.api.node.NodeBuilderRegistry; +import me.lucko.luckperms.api.platform.Platform; +import me.lucko.luckperms.api.platform.PluginMetadata; +import me.lucko.luckperms.api.track.Track; +import me.lucko.luckperms.api.track.TrackManager; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Collection; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +/** + * The LuckPerms API. + * + *

The API allows other plugins on the server to read and modify LuckPerms + * data, change behaviour of the plugin, listen to certain events, and integrate + * LuckPerms into other plugins and systems.

+ * + *

This interface represents the base of the API package. All functions are + * accessed via this interface.

+ * + *

To start using the API, you need to obtain an instance of this interface. + * These are registered by the LuckPerms plugin to the platforms Services + * Manager. This is the preferred method for obtaining an instance.

+ * + *

For ease of use, and for platforms without a Service Manager, an instance + * can also be obtained from the static singleton accessor in + * {@link LuckPermsProvider}.

+ */ +public interface LuckPerms { + + /** + * Gets the name of this server. + * + *

This is defined in the LuckPerms configuration file, and is used for + * server specific permission handling.

+ * + *

The default server name is "global".

+ * + * @return the server name + */ + @NonNull String getServerName(); + + /** + * Gets the {@link UserManager}, responsible for managing + * {@link User} instances. + * + *

This manager can be used to retrieve instances of {@link User} by uuid + * or name, or query all loaded users.

+ * + * @return the user manager + */ + @NonNull UserManager getUserManager(); + + /** + * Gets the {@link GroupManager}, responsible for managing + * {@link Group} instances. + * + *

This manager can be used to retrieve instances of {@link Group} by + * name, or query all loaded groups.

+ * + * @return the group manager + */ + @NonNull GroupManager getGroupManager(); + + /** + * Gets the {@link TrackManager}, responsible for managing + * {@link Track} instances. + * + *

This manager can be used to retrieve instances of {@link Track} by + * name, or query all loaded tracks.

+ * + * @return the track manager + */ + @NonNull TrackManager getTrackManager(); + + /** + * Gets the {@link Platform}, which represents the server platform the + * plugin is running on. + * + * @return the platform + */ + @NonNull Platform getPlatform(); + + /** + * Gets the {@link PluginMetadata}, responsible for providing metadata about + * the LuckPerms plugin currently running. + * + * @return the plugin metadata + */ + @NonNull PluginMetadata getPluginMetadata(); + + /** + * Gets the {@link EventBus}, used for subscribing to internal LuckPerms + * events. + * + * @return the event bus + */ + @NonNull EventBus getEventBus(); + + /** + * Gets the {@link MessagingService}, used to dispatch updates throughout a + * network of servers running the plugin. + * + *

Not all instances of LuckPerms will have a messaging service setup and + * configured.

+ * + * @return the messaging service instance, if present. + */ + @NonNull Optional getMessagingService(); + + /** + * Gets the {@link ActionLogger}, responsible for saving and broadcasting + * defined actions occurring on the platform. + * + * @return the action logger + */ + @NonNull ActionLogger getActionLogger(); + + /** + * Gets the {@link ContextManager}, responsible for managing + * {@link ContextCalculator}s, and calculating applicable contexts.

+ * + * @return the context manager + */ + @NonNull ContextManager getContextManager(); + + /** + * Gets the {@link NodeBuilderRegistry}. + * + * @return the node builder registry + */ + @NonNull NodeBuilderRegistry getNodeBuilderRegistry(); + + /** + * Gets the {@link MetaStackFactory}. + * + *

The metastack factory provides methods for retrieving + * {@link MetaStackElement}s and constructing + * {@link MetaStackDefinition}s.

+ * + * @return the meta stack factory + */ + @NonNull MetaStackFactory getMetaStackFactory(); + + /** + * Schedules the execution of an update task, and returns an encapsulation + * of the task as a {@link CompletableFuture}. + * + *

The exact actions performed in an update task remains an + * implementation detail of the plugin, however, as a minimum, it is + * expected to perform a full reload of user, group and track data, and + * ensure that any changes are fully applied and propagated.

+ * + * @return a future + */ + @NonNull CompletableFuture runUpdateTask(); + + /** + * Registers a {@link MessengerProvider} for use by the platform. + * + *

Note that the mere action of registering a provider doesn't + * necessarily mean that it will be used.

+ * + * @param messengerProvider the messenger provider. + */ + void registerMessengerProvider(@NonNull MessengerProvider messengerProvider); + + /** + * Gets a {@link Collection} of all known permission strings. + * + * @return a collection of the known permissions + */ + @NonNull Collection getKnownPermissions(); + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/LuckPermsApi.java b/api/src/main/java/me/lucko/luckperms/api/LuckPermsApi.java deleted file mode 100644 index 1599b9cb3..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/LuckPermsApi.java +++ /dev/null @@ -1,473 +0,0 @@ -/* - * 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.api; - -import me.lucko.luckperms.LuckPerms; -import me.lucko.luckperms.api.caching.CachedData; -import me.lucko.luckperms.api.context.ContextCalculator; -import me.lucko.luckperms.api.context.ContextManager; -import me.lucko.luckperms.api.context.ContextSet; -import me.lucko.luckperms.api.event.EventBus; -import me.lucko.luckperms.api.manager.CachedDataManager; -import me.lucko.luckperms.api.manager.GroupManager; -import me.lucko.luckperms.api.manager.TrackManager; -import me.lucko.luckperms.api.manager.UserManager; -import me.lucko.luckperms.api.messenger.MessengerProvider; -import me.lucko.luckperms.api.metastacking.MetaStackFactory; -import me.lucko.luckperms.api.platform.PlatformInfo; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.util.Collection; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -/** - * The LuckPerms API. - * - *

This interface is the base of the entire API package. All API functions - * are accessed via this interface.

- * - *

An instance can be obtained via {@link LuckPerms#getApi()}, or the platforms - * Services Manager.

- */ -public interface LuckPermsApi { - - /** - * Gets information about the platform LuckPerms is running on. - * - * @return the platform info - * @since 4.0 - */ - @NonNull PlatformInfo getPlatformInfo(); - - /** - * Gets the {@link UserManager}, responsible for managing - * {@link User} instances. - * - *

This manager can be used to retrieve instances of {@link User} by uuid - * or name, or query all loaded users.

- * - *

The {@link #getStorage() storage} instance should be used to - * load/create/save users.

- * - * @return the user manager - * @since 4.0 - */ - @NonNull UserManager getUserManager(); - - /** - * Gets the {@link GroupManager}, responsible for managing - * {@link Group} instances. - * - *

This manager can be used to retrieve instances of {@link Group} by - * name, or query all loaded groups.

- * - *

The {@link #getStorage() storage} instance should be used to - * load/create/save/delete groups.

- * - * @return the group manager - * @since 4.0 - */ - @NonNull GroupManager getGroupManager(); - - /** - * Gets the {@link TrackManager}, responsible for managing - * {@link Track} instances. - * - *

This manager can be used to retrieve instances of {@link Track} by - * name, or query all loaded tracks.

- * - *

The {@link #getStorage() storage} instance should be used to - * load/create/save/delete tracks.

- * - * @return the track manager - * @since 4.0 - */ - @NonNull TrackManager getTrackManager(); - - /** - * Gets the {@link CachedDataManager}, responsible for managing - * {@link CachedData} instances. - * - * @return the cached data manager - * @since 4.5 - */ - @NonNull CachedDataManager getCachedDataManager(); - - /** - * Schedules the execution of an update task, and returns an encapsulation - * of the task as a {@link CompletableFuture}. - * - *

The exact actions performed in an update task remains an - * implementation detail of the plugin, however, as a minimum, it is - * expected to perform a full reload of user, group and track data, and - * ensure that any changes are fully applied and propagated.

- * - * @return a future - * @since 4.0 - */ - @NonNull CompletableFuture runUpdateTask(); - - /** - * Gets the {@link EventBus}, used for subscribing to internal LuckPerms - * events. - * - * @return the event bus - * @since 3.0 - */ - @NonNull EventBus getEventBus(); - - /** - * Gets a representation of the plugins configuration - * - * @return the configuration - */ - @NonNull LPConfiguration getConfiguration(); - - /** - * Gets the {@link MessagingService}, if present. - * - *

The MessagingService is used to dispatch updates throughout a network - * of servers running the plugin.

- * - *

Not all instances of LuckPerms will have a messaging service setup and - * configured, but it is recommended that all users of the API account for - * and make use of this.

- * - * @return the messaging service instance, if present. - */ - @NonNull Optional getMessagingService(); - - /** - * Registers a {@link MessengerProvider} for use by the platform. - * - *

Note that the mere action of registering a provider doesn't - * necessarily mean that it will be used.

- * - * @param messengerProvider the messenger provider. - * @since 4.1 - */ - void registerMessengerProvider(@NonNull MessengerProvider messengerProvider); - - /** - * Gets the {@link ActionLogger}. - * - *

The action logger is responsible for saving and broadcasting defined - * actions occurring on the platform.

- * - * @return the action logger - * @since 4.1 - */ - @NonNull ActionLogger getActionLogger(); - - /** - * Gets the {@link ContextManager}. - * - *

The context manager manages {@link ContextCalculator}s, and calculates - * applicable contexts for a given type.

- * - * @return the context manager - * @since 4.0 - */ - @NonNull ContextManager getContextManager(); - - /** - * Gets a {@link Collection} of all known permission strings. - * - * @return a collection of the known permissions - * @since 4.4 - */ - @NonNull Collection getKnownPermissions(); - - /** - * Gets the {@link NodeFactory}. - * - *

The node factory provides methods for building {@link Node} instances.

- * - * @return the node factory - */ - @NonNull NodeFactory getNodeFactory(); - - /** - * Gets the {@link MetaStackFactory}. - * - *

The metastack factory provides methods for retrieving - * {@link me.lucko.luckperms.api.metastacking.MetaStackElement}s and constructing - * {@link me.lucko.luckperms.api.metastacking.MetaStackDefinition}s.

- * - * @return the meta stack factory - * @since 3.2 - */ - @NonNull MetaStackFactory getMetaStackFactory(); - - - - - /* - * The following methods are provided only for convenience, and offer no - * additional functionality. - * - * They are implemented as "default" methods, using the manager and factory - * instances provided by the methods above. - */ - - - - /** - * Gets a wrapped user object from the user storage - * - * @param uuid the uuid of the user to get - * @return a {@link User} object, if one matching the uuid is loaded, or null if not - * @throws NullPointerException if the uuid is null - */ - default @Nullable User getUser(@NonNull UUID uuid) { - return getUserManager().getUser(uuid); - } - - /** - * Gets a wrapped user object from the user storage. - * - * @param uuid the uuid of the user to get - * @return an optional {@link User} object - * @throws NullPointerException if the uuid is null - */ - default @NonNull Optional getUserSafe(@NonNull UUID uuid) { - return getUserManager().getUserOpt(uuid); - } - - /** - * Gets a wrapped user object from the user storage - * - * @param name the username of the user to get - * @return a {@link User} object, if one matching the uuid is loaded, or null if not - * @throws NullPointerException if the name is null - */ - default @Nullable User getUser(@NonNull String name) { - return getUserManager().getUser(name); - } - - /** - * Gets a wrapped user object from the user storage. - * - * @param name the username of the user to get - * @return an optional {@link User} object - * @throws NullPointerException if the name is null - */ - default @NonNull Optional getUserSafe(@NonNull String name) { - return getUserManager().getUserOpt(name); - } - - /** - * Gets a set of all loaded users. - * - * @return a {@link Set} of {@link User} objects - */ - default @NonNull Set getUsers() { - return getUserManager().getLoadedUsers(); - } - - /** - * Check if a user is loaded in memory - * - * @param uuid the uuid to check for - * @return true if the user is loaded - * @throws NullPointerException if the uuid is null - */ - default boolean isUserLoaded(@NonNull UUID uuid) { - return getUserManager().isLoaded(uuid); - } - - /** - * Unload a user from the internal storage, if they're not currently online. - * - * @param user the user to unload - * @throws NullPointerException if the user is null - */ - default void cleanupUser(@NonNull User user) { - getUserManager().cleanupUser(user); - } - - /** - * Gets a wrapped group object from the group storage - * - * @param name the name of the group to get - * @return a {@link Group} object, if one matching the name exists, or null if not - * @throws NullPointerException if the name is null - */ - default @Nullable Group getGroup(@NonNull String name) { - return getGroupManager().getGroup(name); - } - - /** - * Gets a wrapped group object from the group storage. - * - *

This method does not return null, unlike {@link #getGroup}

- * - * @param name the name of the group to get - * @return an optional {@link Group} object - * @throws NullPointerException if the name is null - */ - default @NonNull Optional getGroupSafe(@NonNull String name) { - return getGroupManager().getGroupOpt(name); - } - - /** - * Gets a set of all loaded groups. - * - * @return a {@link Set} of {@link Group} objects - */ - default @NonNull Set getGroups() { - return getGroupManager().getLoadedGroups(); - } - - /** - * Check if a group is loaded in memory - * - * @param name the name to check for - * @return true if the group is loaded - * @throws NullPointerException if the name is null - */ - default boolean isGroupLoaded(@NonNull String name) { - return getGroupManager().isLoaded(name); - } - - /** - * Gets a wrapped track object from the track storage - * - * @param name the name of the track to get - * @return a {@link Track} object, if one matching the name exists, or null - * if not - * @throws NullPointerException if the name is null - */ - default @Nullable Track getTrack(@NonNull String name) { - return getTrackManager().getTrack(name); - } - - /** - * Gets a wrapped track object from the track storage. - * - *

This method does not return null, unlike {@link #getTrack}

- * - * @param name the name of the track to get - * @return an optional {@link Track} object - * @throws NullPointerException if the name is null - */ - default @NonNull Optional getTrackSafe(@NonNull String name) { - return getTrackManager().getTrackOpt(name); - } - - /** - * Gets a set of all loaded tracks. - * - * @return a {@link Set} of {@link Track} objects - */ - default @NonNull Set getTracks() { - return getTrackManager().getLoadedTracks(); - } - - /** - * Check if a track is loaded in memory - * - * @param name the name to check for - * @return true if the track is loaded - * @throws NullPointerException if the name is null - */ - default boolean isTrackLoaded(@NonNull String name) { - return getTrackManager().isLoaded(name); - } - - /** - * Returns a new LogEntry Builder instance - * - * @return a new builder - * @since 4.0 - */ - default LogEntry.@NonNull Builder newLogEntryBuilder() { - return getActionLogger().newEntryBuilder(); - } - - /** - * Returns a permission builder instance - * - * @param permission the main permission node to build - * @return a {@link Node.Builder} instance - * @throws IllegalArgumentException if the permission is invalid - * @throws NullPointerException if the permission is null - * @since 2.6 - */ - default Node.@NonNull Builder buildNode(@NonNull String permission) throws IllegalArgumentException { - return getNodeFactory().newBuilder(permission); - } - - /** - * Register a custom context calculator to the server - * - * @param calculator the context calculator to register. The type MUST be the player class of the platform. - * @throws ClassCastException if the type is not the player class of the platform. - */ - default void registerContextCalculator(@NonNull ContextCalculator calculator) { - getContextManager().registerCalculator(calculator); - } - - /** - * Gets a calculated context instance for the user using the rules of the platform. - * - *

These values are calculated using the options in the configuration, and the provided calculators. - * - * @param user the user to get contexts for - * @return an optional containing contexts. Will return empty if the user is not online. - */ - default @NonNull Optional getContextForUser(@NonNull User user) { - return getContextManager().lookupApplicableContexts(user); - } - - /** - * Gets set of contexts applicable to a player using the platforms {@link ContextCalculator}s. - * - * @param player the player to calculate for. Must be the player instance for the platform. - * @return a set of contexts. - * @since 2.17 - */ - default @NonNull ContextSet getContextForPlayer(@NonNull Object player) { - return getContextManager().getApplicableContext(player); - } - - /** - * Gets a Contexts instance for the player using the platforms {@link ContextCalculator}s. - * - * @param player the player to calculate for. Must be the player instance for the platform. - * @return a set of contexts. - * @since 3.3 - */ - default @NonNull Contexts getContextsForPlayer(@NonNull Object player) { - return getContextManager().getApplicableContexts(player); - } - -} diff --git a/api/src/main/java/me/lucko/luckperms/LuckPerms.java b/api/src/main/java/me/lucko/luckperms/api/LuckPermsProvider.java similarity index 57% rename from api/src/main/java/me/lucko/luckperms/LuckPerms.java rename to api/src/main/java/me/lucko/luckperms/api/LuckPermsProvider.java index a3f806075..6a5cef019 100644 --- a/api/src/main/java/me/lucko/luckperms/LuckPerms.java +++ b/api/src/main/java/me/lucko/luckperms/api/LuckPermsProvider.java @@ -23,25 +23,21 @@ * SOFTWARE. */ -package me.lucko.luckperms; - -import me.lucko.luckperms.api.LuckPermsApi; +package me.lucko.luckperms.api; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.Optional; - /** - * Provides static access to the {@link LuckPermsApi}. + * Provides static access to the {@link LuckPerms} service. * - *

Ideally, the ServiceManager for the platform should be used to obtain an instance, - * however, this provider can be used if you need static access.

+ *

Ideally, the ServiceManager for the platform should be used to obtain an + * instance, however, this provider can be used if you need static access.

*/ -public final class LuckPerms { - private static LuckPermsApi instance = null; +public final class LuckPermsProvider { + private static LuckPerms instance = null; /** - * Gets an instance of the {@link LuckPermsApi}, + * Gets an instance of the {@link LuckPerms} service, * throwing {@link IllegalStateException} if an instance is not yet loaded. * *

Will never return null.

@@ -49,43 +45,22 @@ public final class LuckPerms { * @return an api instance * @throws IllegalStateException if the api is not loaded */ - public static @NonNull LuckPermsApi getApi() { + public static @NonNull LuckPerms get() { if (instance == null) { - throw new IllegalStateException("API is not loaded."); + throw new IllegalStateException("The LuckPerms API is not loaded."); } return instance; } - /** - * Gets an instance of {@link LuckPermsApi}, if it is loaded. - * - *

Unlike {@link LuckPerms#getApi}, this method will not throw an - * {@link IllegalStateException} if an instance is not yet loaded, rather return - * an empty {@link Optional}. - * - * @return an optional api instance - */ - public static @NonNull Optional getApiSafe() { - return Optional.ofNullable(instance); + static void register(LuckPerms instance) { + LuckPermsProvider.instance = instance; } - /** - * Registers an instance of the {@link LuckPermsApi} with this provider. - * - * @param instance the instance - */ - static void registerProvider(LuckPermsApi instance) { - LuckPerms.instance = instance; + static void unregister() { + LuckPermsProvider.instance = null; } - /** - * Removes the current instance from this provider. - */ - static void unregisterProvider() { - LuckPerms.instance = null; - } - - private LuckPerms() { + private LuckPermsProvider() { throw new UnsupportedOperationException("This class cannot be instantiated."); } diff --git a/api/src/main/java/me/lucko/luckperms/api/MutateResult.java b/api/src/main/java/me/lucko/luckperms/api/MutateResult.java deleted file mode 100644 index e2ca32e1c..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/MutateResult.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.api; - -/** - * Represents the result to a "mutation" on an object. - * - * @since 4.2 - */ -public interface MutateResult { - - /** - * Instance of {@link MutateResult} which always reports success. - */ - MutateResult GENERIC_SUCCESS = () -> true; - - /** - * Instance of {@link MutateResult} which always reports failure. - */ - MutateResult GENERIC_FAILURE = () -> false; - - /** - * Gets if the operation which produced this result completed successfully. - * - * @return if the result indicates a success - */ - boolean wasSuccess(); - - /** - * Gets if the operation which produced this result failed. - * - * @return if the result indicates a failure - */ - default boolean wasFailure() { - return !wasSuccess(); - } - - /** - * Gets a boolean representation of the result. - * - *

A value of true marks that the operation {@link #wasSuccess() was a success} - * and a value of false marks that the operation - * {@link #wasFailure() was a failure}.

- * - * @return a boolean representation - */ - default boolean asBoolean() { - return wasSuccess(); - } - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/Node.java b/api/src/main/java/me/lucko/luckperms/api/Node.java deleted file mode 100644 index 5339bbe78..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/Node.java +++ /dev/null @@ -1,670 +0,0 @@ -/* - * 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.api; - -import com.google.common.base.Preconditions; - -import me.lucko.luckperms.api.context.ContextSet; -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; -import me.lucko.luckperms.api.nodetype.types.DisplayNameType; -import me.lucko.luckperms.api.nodetype.types.InheritanceType; -import me.lucko.luckperms.api.nodetype.types.MetaType; -import me.lucko.luckperms.api.nodetype.types.PrefixType; -import me.lucko.luckperms.api.nodetype.types.SuffixType; -import me.lucko.luckperms.api.nodetype.types.WeightType; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; - -/** - * Represents a LuckPerms "node". - * - *

The {@link Node} class encapsulates more than just permission assignments. - * Nodes are used to store data about inherited groups, as well as assigned - * prefixes, suffixes and meta values.

- * - *

Combining these various states into one object (a "node") means that a - * holder only has to have one type of data set (a set of nodes) in order to - * take on various properties.

- * - *

It is recommended that users of the API make use of {@link Stream}s - * to manipulate data and obtain the required information.

- * - *

This interface provides a number of methods to read the attributes of the - * node, as well as methods to query and extract additional state and properties - * from these settings.

- * - *

Nodes have the following attributes:

- *

- *
    - *
  • {@link #getPermission() permission} - the actual permission string
  • - *
  • {@link #getValue() value} - the value of the node (false for negated)
  • - *
  • {@link #isOverride() override} - if the node is marked as having special priority over other nodes
  • - *
  • {@link #getServer() server} - the specific server where this node should apply
  • - *
  • {@link #getWorld() world} - the specific world where this node should apply
  • - *
  • {@link #getContexts() context} - the additional contexts required for this node to apply
  • - *
  • {@link #getExpiry() expiry} - the time when this node should expire
  • - *
- * - *

The 'permission' property of a {@link Node} is also used in some cases to represent state - * beyond a granted permission. This state is encapsulated by extra {@link NodeType} data which - * can be obtained from this instance using {@link #getTypeData(NodeTypeKey)}.

- * - *

Type data is mapped by {@link NodeTypeKey}s, which are usually stored as static members of the - * corresponding {@link NodeType} class under the KEY field.

- * - *

The current types are:

- *

- *
    - *
  • normal - just a regular permission
  • - *
  • {@link InheritanceType} - an "inheritance node" marks that the holder should inherit data from another group
  • - *
  • {@link PrefixType} - represents an assigned prefix
  • - *
  • {@link SuffixType} - represents an assigned suffix
  • - *
  • {@link MetaType} - represents an assigned meta option
  • - *
  • {@link WeightType} - marks the weight of the object holding this node
  • - *
  • {@link DisplayNameType} - marks the display name of the object holding this node
  • - *
- * - *

The core node state must be immutable in all implementations.

- * - * @see NodeFactory for obtaining and constructing instances. - * @since 2.6 - */ -public interface Node { - - /** - * Gets the permission string this node encapsulates. - * - *

The exact value of this string may vary for nodes which aren't regular - * permission settings.

- * - * @return the actual permission node - */ - @NonNull String getPermission(); - - /** - * Gets the value of the node. - * - *

A negated setting would result in a value of false.

- * - * @return the nodes value - */ - boolean getValue(); - - /** - * Gets the value of this node as a {@link Tristate}. - * - * @return the value of this node as a Tristate - */ - default @NonNull Tristate getTristate() { - return Tristate.fromBoolean(getValue()); - } - - /** - * Gets if the node is negated. - * - *

This is the inverse of the {@link #getValue() value}.

- * - * @return true if the node is negated - */ - default boolean isNegated() { - return !getValue(); - } - - /** - * Gets if this node is set to override explicitly. - * - *

This value does not persist across saves, and is therefore only - * useful for transient nodes.

- * - * @return true if this node is set to override explicitly - */ - boolean isOverride(); - - /** - * Gets the server this node applies on, if the node is server specific. - * - * @return an {@link Optional} containing the server, if one is defined - */ - @NonNull Optional getServer(); - - /** - * Gets the world this node applies on, if the node is world specific. - * - * @return an {@link Optional} containing the world, if one is defined - */ - @NonNull Optional getWorld(); - - /** - * Gets if this node is server specific. - * - * @return true if this node is server specific - */ - boolean isServerSpecific(); - - /** - * Gets if this node is server specific. - * - * @return true if this node is server specific - */ - boolean isWorldSpecific(); - - /** - * Gets if this node applies globally, and therefore has no specific context. - * - * @return true if this node applies globally, and has no specific context - * @since 3.1 - */ - boolean appliesGlobally(); - - /** - * Gets if this node has any specific context in order for it to apply. - * - * @return true if this node has specific context - * @since 3.1 - */ - boolean hasSpecificContext(); - - /** - * Gets if this node should apply in the given context - * - * @param contextSet the context set - * @return true if the node should apply - * @since 2.13 - */ - boolean shouldApplyWithContext(@NonNull ContextSet contextSet); - - /** - * Resolves any shorthand parts of this node and returns the full list of - * resolved nodes. - * - *

The list will not contain the exact permission itself.

- * - * @return a list of full nodes - */ - @NonNull List resolveShorthand(); - - /** - * Gets if this node is assigned temporarily. - * - * @return true if this node will expire in the future - */ - boolean isTemporary(); - - /** - * Gets if this node is permanent (will not expire). - * - * @return true if this node will not expire - */ - default boolean isPermanent() { - return !isTemporary(); - } - - /** - * Gets the unix timestamp (in seconds) when this node will expire. - * - * @return the time in Unix time when this node will expire - * @throws IllegalStateException if the node is not temporary - */ - long getExpiryUnixTime() throws IllegalStateException; - - /** - * Gets the date when this node will expire. - * - * @return the {@link Date} when this node will expire - * @throws IllegalStateException if the node is not temporary - */ - @NonNull Date getExpiry() throws IllegalStateException; - - /** - * Gets the number of seconds until this permission will expire. - * - *

Will return a negative value if the node has already expired.

- * - * @return the number of seconds until this permission will expire - * @throws IllegalStateException if the node is not temporary - */ - long getSecondsTilExpiry() throws IllegalStateException; - - /** - * Gets if the node has expired. - * - *

This returns false if the node is not temporary.

- * - * @return true if this node has expired - */ - boolean hasExpired(); - - /** - * Gets the extra contexts required for this node to apply. - * - * @return the extra contexts required for this node to apply - * @since 2.13 - */ - @NonNull ContextSet getContexts(); - - /** - * The same as {@link #getContexts()}, but also includes context pairs for - * "server" and "world" keys if present. - * - * @return the full contexts required for this node to apply - * @see Contexts#SERVER_KEY - * @see Contexts#WORLD_KEY - * @since 3.1 - */ - @NonNull ContextSet getFullContexts(); - - /** - * Gets if this node is a wildcard permission. - * - * @return true if this node is a wildcard permission - */ - boolean isWildcard(); - - /** - * Gets the level of this wildcard. - * - *

The node luckperms.* has a wildcard level of 1.

- *

The node luckperms.user.permission.* has a wildcard level of 3.

- * - *

Nodes with a higher wildcard level are more specific and have priority over - * less specific nodes (nodes with a lower wildcard level).

- * - * @return the wildcard level - * @throws IllegalStateException if this is not a wildcard - */ - int getWildcardLevel() throws IllegalStateException; - - /** - * Gets if this node has any extra {@link NodeType} data attached to it. - * - * @return if this node has any type data - * @since 4.2 - */ - boolean hasTypeData(); - - /** - * Gets the type data corresponding to the given key, if present. - * - * @param key the key - * @param the {@link NodeType} type - * @return the data, if present - * @since 4.2 - */ - Optional getTypeData(NodeTypeKey key); - - /** - * Gets the type data corresponding to the given key, throwing an exception - * if no data is present. - * - * @param key the key - * @param the {@link NodeType} type - * @return the data - * @throws IllegalStateException if data isn't present - * @since 4.2 - */ - default T typeData(NodeTypeKey key) throws IllegalStateException { - return getTypeData(key).orElseThrow(() -> new IllegalStateException("Node '" + getPermission() + "' does not have the '" + key.getTypeName() + "' type.")); - } - - /** - * Gets if this node has {@link InheritanceType} type data. - * - * @return true if this is a inheritance (group) node. - */ - default boolean isGroupNode() { - return getTypeData(InheritanceType.KEY).isPresent(); - } - - /** - * Gets the name of the inherited group if this node has {@link InheritanceType} type data, - * throwing an exception if the data is not present. - * - * @return the name of the group - * @throws IllegalStateException if this node doesn't have {@link InheritanceType} data - */ - default @NonNull String getGroupName() throws IllegalStateException { - return typeData(InheritanceType.KEY).getGroupName(); - } - - /** - * Gets if this node has {@link MetaType} type data. - * - * @return true if this is a meta node. - */ - default boolean isMeta() { - return getTypeData(MetaType.KEY).isPresent(); - } - - /** - * Gets the meta entry if this node has {@link MetaType} type data, - * throwing an exception if the data is not present. - * - * @return the meta entry - * @throws IllegalStateException if this node doesn't have {@link MetaType} data - */ - default Map.@NonNull Entry getMeta() throws IllegalStateException { - return typeData(MetaType.KEY); - } - - /** - * Gets if this node has {@link PrefixType} type data. - * - * @return true if this node is a prefix node - */ - default boolean isPrefix() { - return getTypeData(PrefixType.KEY).isPresent(); - } - - /** - * Gets the prefix entry if this node has {@link PrefixType} type data, - * throwing an exception if the data is not present. - * - * @return the meta entry - * @throws IllegalStateException if this node doesn't have {@link PrefixType} data - */ - default Map.@NonNull Entry getPrefix() throws IllegalStateException { - return typeData(PrefixType.KEY).getAsEntry(); - } - - /** - * Gets if this node has {@link SuffixType} type data. - * - * @return true if this node is a suffix node - */ - default boolean isSuffix() { - return getTypeData(SuffixType.KEY).isPresent(); - } - - /** - * Gets the suffix entry if this node has {@link SuffixType} type data, - * throwing an exception if the data is not present. - * - * @return the meta entry - * @throws IllegalStateException if this node doesn't have {@link SuffixType} data - */ - default Map.@NonNull Entry getSuffix() throws IllegalStateException { - return typeData(SuffixType.KEY).getAsEntry(); - } - - /** - * Gets if this Node is equal to another node. - * - * @param obj the other node - * @return true if this node is equal to the other provided - * @see StandardNodeEquality#EXACT - */ - @Override - boolean equals(Object obj); - - /** - * Gets if this Node is equal to another node as defined by the given - * {@link NodeEqualityPredicate}. - * - * @param other the other node - * @param equalityPredicate the predicate - * @return true if this node is considered equal - * @since 4.1 - */ - boolean equals(Node other, NodeEqualityPredicate equalityPredicate); - - /** - * Similar to {@link Node#equals(Object)}, except doesn't take note of the - * value. - * - * @param other the other node - * @return true if the two nodes are almost equal - * @see StandardNodeEquality#IGNORE_VALUE - * @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)} - */ - @Deprecated - default boolean equalsIgnoringValue(@NonNull Node other) { - return equals(other, StandardNodeEquality.IGNORE_VALUE); - } - - /** - * Similar to {@link Node#equals(Object)}, except doesn't take note of the - * expiry time or value. - * - * @param other the other node - * @return true if the two nodes are almost equal - * @see StandardNodeEquality#IGNORE_EXPIRY_TIME_AND_VALUE - * @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)} - */ - @Deprecated - default boolean almostEquals(@NonNull Node other) { - return equals(other, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE); - } - - /** - * Similar to {@link Node#equals(Object)}, except doesn't take note of the - * value or if the node is temporary. - * - * @param other the other node - * @return true if the two nodes are almost equal - * @see StandardNodeEquality#IGNORE_VALUE_OR_IF_TEMPORARY - * @since 2.8 - * @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)} - */ - @Deprecated - default boolean equalsIgnoringValueOrTemp(@NonNull Node other) { - return equals(other, StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY); - } - - /** - * Constructs a new builder initially containing the current properties of - * this node. - * - * @return a new builder - * @since 4.1 - */ - Builder toBuilder(); - - /** - * Builds a Node instance - */ - interface Builder { - - /** - * Copies the attributes from the given node and applies them to this - * builder. - * - *

Note that this copies all attributes except the - * permission itself.

- * - * @param node the node to copy from - * @return the builder - * @since 4.2 - */ - Builder copyFrom(@NonNull Node node); - - /** - * Sets the value of negated for the node. - * - * @param negated the value - * @return the builder - * @see Node#isNegated() - */ - @NonNull Builder setNegated(boolean negated); - - /** - * Sets the value of the node. - * - * @param value the value - * @return the builder - * @see Node#getValue() - */ - @NonNull Builder setValue(boolean value); - - /** - * Sets the override property for the node. - * - *

Warning: this value does not persist, and disappears when the holder is re-loaded. - * It is therefore only useful for transient nodes.

- * - * @param override the override state - * @return the builder - * @see Node#isOverride() - */ - @NonNull Builder setOverride(boolean override); - - /** - * Sets the time when the node should expire. - * - *

The parameter passed to this method must be the unix timestamp - * (in seconds) when the node should expire.

- * - * @param expiryUnixTimestamp the expiry timestamp (unix seconds) - * @return the builder - * @see Node#getExpiryUnixTime() - */ - @NonNull Builder setExpiry(long expiryUnixTimestamp); - - /** - * Sets the time when the node should expire. - * - *

The expiry timestamp is calculated relative to the current - * system time.

- * - * @param duration how long the node should be added for - * @param unit the unit duration is measured in - * @return the builder - * @since 4.2 - */ - default @NonNull Builder setExpiry(long duration, TimeUnit unit) { - Preconditions.checkArgument(duration > 0, "duration must be positive"); - long seconds = Objects.requireNonNull(unit, "unit").toSeconds(duration); - long timeNow = System.currentTimeMillis() / 1000L; - return setExpiry(timeNow + seconds); - } - - /** - * Marks that the node being built should never expire. - * - * @return the builder - * @since 4.2 - */ - @NonNull Builder clearExpiry(); - - /** - * Sets the world value for the node. - * - * @param world the world value - * @return the builder - * @see Node#getWorld() - */ - @NonNull Builder setWorld(@Nullable String world); - - /** - * Sets the server value for the node. - * - * @param server the world value - * @return the builder - * @see Node#getServer() - */ - @NonNull Builder setServer(@Nullable String server); - - /** - * Appends an extra context onto the node. - * - * @param key the context key - * @param value the context value - * @return the builder - * @see ContextSet - * @see Node#getContexts() - */ - @NonNull Builder withExtraContext(@NonNull String key, @NonNull String value); - - /** - * Appends extra contexts onto the node. - * - * @param map a map of contexts - * @return the builder - * @see ContextSet - * @see Node#getContexts() - */ - @NonNull Builder withExtraContext(@NonNull Map map); - - /** - * Appends extra contexts onto the node. - * - * @param context a set of contexts - * @return the builder - * @see ContextSet - * @see Node#getContexts() - */ - @NonNull Builder withExtraContext(@NonNull Set> context); - - /** - * Appends an extra context onto the node. - * - * @param entry the context - * @return the builder - * @see ContextSet - * @see Node#getContexts() - */ - @NonNull Builder withExtraContext(Map.@NonNull Entry entry); - - /** - * Appends extra contexts onto the node. - * - * @param contextSet a context set - * @return the builder - * @see ContextSet - * @see Node#getContexts() - */ - @NonNull Builder withExtraContext(@NonNull ContextSet contextSet); - - /** - * Sets the extra contexts for the node. - * - * @param contextSet a context set - * @return the builder - * @see ContextSet - * @see Node#getContexts() - * @since 4.2 - */ - @NonNull Builder setExtraContext(@NonNull ContextSet contextSet); - - /** - * Creates a {@link Node} instance from the builder. - * - * @return a new node instance - */ - @NonNull Node build(); - } - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/NodeEqualityPredicate.java b/api/src/main/java/me/lucko/luckperms/api/NodeEqualityPredicate.java deleted file mode 100644 index 428fdcea4..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/NodeEqualityPredicate.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.api; - -import org.checkerframework.checker.nullness.qual.NonNull; - -/** - * A rule for determining if two nodes are equal. - * - *

Generally, individual instances of this interface should fulfil the same - * requirements as the {@link Object#equals(Object)} contract.

- * - *

Some standard implementations are provided by {@link StandardNodeEquality}.

- * - * @since 4.1 - */ -@FunctionalInterface -public interface NodeEqualityPredicate { - - /** - * Returns if the two nodes are equal. - * - *

This method should avoid making calls to {@link Node#equals(Node, NodeEqualityPredicate)} - * with {@code this} as the second argument, directly or otherwise.

- * - * @param o1 the first node - * @param o2 the second node - * @return true if equal - */ - boolean areEqual(@NonNull Node o1, @NonNull Node o2); - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/NodeFactory.java b/api/src/main/java/me/lucko/luckperms/api/NodeFactory.java deleted file mode 100644 index 226eeca82..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/NodeFactory.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.api; - -import org.checkerframework.checker.nullness.qual.NonNull; - -/** - * Assists with constructing {@link Node} instances. - * - * @since 2.17 - */ -public interface NodeFactory { - - /** - * Creates a new node builder from a given base permission string - * - * @param permission the permission - * @return a node builder instance - * @throws NullPointerException if the permission is null - */ - Node.@NonNull Builder newBuilder(@NonNull String permission); - - /** - * Creates a node builder instance from an existing node - * - * @param other the other node - * @return a node builder instance - * @throws NullPointerException if the other node is null - */ - Node.@NonNull Builder newBuilderFromExisting(@NonNull Node other); - - - /** - * Creates a node builder from a group - * - * @param group the group - * @return a node builder instance - * @throws NullPointerException if the group is null - * @throws IllegalStateException if the group instance was not obtained from LuckPerms. - * @since 3.1 - */ - Node.@NonNull Builder makeGroupNode(@NonNull Group group); - - /** - * Creates a node builder from a group - * - * @param groupName the name of the group - * @return a node builder instance - * @throws NullPointerException if the groupName is null - * @since 4.0 - */ - Node.@NonNull Builder makeGroupNode(@NonNull String groupName); - - /** - * Creates a node builder from a key value pair - * - * @param key the key - * @param value the value - * @return a node builder instance - * @throws NullPointerException if the key or value is null - */ - Node.@NonNull Builder makeMetaNode(@NonNull String key, @NonNull String value); - - /** - * Creates a node builder for the given chat meta type - * - * @param type the type - * @param priority the priority - * @param value the value for the prefix/suffix - * @return a node builder instance - * @throws NullPointerException if the type or value is null - * @since 3.2 - */ - Node.@NonNull Builder makeChatMetaNode(@NonNull ChatMetaType type, int priority, @NonNull String value); - - /** - * Creates a node builder from a prefix string and priority - * - * @param priority the priority - * @param prefix the prefix string - * @return a node builder instance - * @throws NullPointerException if the prefix is null - */ - Node.@NonNull Builder makePrefixNode(int priority, @NonNull String prefix); - - /** - * Creates a node builder from a prefix string and priority - * - * @param priority the priority - * @param suffix the suffix string - * @return a node builder instance - * @throws NullPointerException if the suffix is null - */ - Node.@NonNull Builder makeSuffixNode(int priority, @NonNull String suffix); - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/PermissionHolder.java b/api/src/main/java/me/lucko/luckperms/api/PermissionHolder.java deleted file mode 100644 index 48d1c11b2..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/PermissionHolder.java +++ /dev/null @@ -1,777 +0,0 @@ -/* - * 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.api; - -import com.google.common.collect.ImmutableSetMultimap; -import com.google.common.collect.Multimap; - -import me.lucko.luckperms.api.caching.CachedData; -import me.lucko.luckperms.api.context.ContextSet; -import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.api.manager.GroupManager; -import me.lucko.luckperms.api.manager.UserManager; -import me.lucko.luckperms.api.nodetype.types.MetaType; -import me.lucko.luckperms.api.nodetype.types.PrefixType; -import me.lucko.luckperms.api.nodetype.types.SuffixType; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.function.Predicate; - -/** - * Generic superinterface for an object which holds permissions. - */ -public interface PermissionHolder { - - /** - * Gets the objects generic name. - * - *

The result of this method is guaranteed to be a unique identifier for distinct instances - * of the same type of object.

- * - *

For {@link User}s, this method returns a {@link UUID#toString() string} representation of - * the users {@link User#getUuid() unique id}.

- * - *

For {@link Group}s, this method returns the {@link Group#getName() group name}.

- * - *

The {@link User#getUuid()}, {@link User#getName()} and {@link Group#getName()} methods - * define a "tighter" specification for obtaining object identifiers.

- * - * @return the identifier for this object. Either a uuid string or name. - */ - @NonNull String getObjectName(); - - /** - * Gets a friendly name for this holder, to be displayed in command output, etc. - * - *

This will always return a value, eventually falling back to - * {@link #getObjectName()} if no other "friendlier" identifiers are present.

- * - *

For {@link User}s, this method will attempt to return the {@link User#getName() username}, - * before falling back to {@link #getObjectName()}.

- * - *

For {@link Group}s, this method will attempt to return the groups display name, before - * falling back to {@link #getObjectName()}.

- * - * @return a friendly identifier for this holder - * @since 3.2 - */ - @NonNull String getFriendlyName(); - - /** - * Gets the holders {@link CachedData} cache. - * - * @return the holders cached data. - * @since 3.2 - */ - @NonNull CachedData getCachedData(); - - /** - * Refreshes and applies any changes to the cached holder data. - * - *

Calling this method is unnecessary in most cases. Cache updates are handled - * behind the scenes by the implementation.

- * - * @return the task future - * @since 4.0 - */ - @NonNull CompletableFuture refreshCachedData(); - - /** - * Gets the backing multimap containing every permission this holder has. - * - *

This method does not resolve inheritance rules, and returns a - * view of what's 'in the file'.

- * - * @return the holders own permissions - * @since 3.3 - */ - @NonNull ImmutableSetMultimap getNodes(); - - /** - * Gets the backing multimap containing every transient permission this holder has. - * - *

This method does not resolve inheritance rules.

- * - *

Transient permissions only exist for the duration of the session.

- * - * @return the holders own permissions - * @since 3.3 - */ - @NonNull ImmutableSetMultimap getTransientNodes(); - - /** - * Gets a flattened/squashed view of the holders permissions. - * - *

This list is constructed using the {@link Multimap#values()} method - * of both the transient and enduring backing multimaps.

- * - *

This means that it may contain duplicate entries.

- * - *

Use {@link #getPermissions()} for a view without duplicates.

- * - *

This method does not resolve inheritance rules.

- * - * @return a list of the holders own nodes. - * @since 3.3 - */ - @NonNull List getOwnNodes(); - - /** - * Gets a sorted set of all held permissions. - * - *

Effectively a sorted version of {@link #getOwnNodes()}, without duplicates. Use the - * aforementioned method if you don't require either of these attributes.

- * - *

This method does not resolve inheritance rules.

- * - *

Although this method is named getPermissions, it will actually return all types of node.

- * - * @return an immutable set of permissions in priority order - * @since 2.6 - */ - @NonNull SortedSet getPermissions(); - - /** - * Similar to {@link #getPermissions()}, except only including permissions from the enduring - * node map. (See {@link #getNodes()}) - * - *

Unlike transient permissions, enduring permissions will be saved to storage, and exist - * after the session.

- * - *

This method does not resolve inheritance rules.

- * - *

Although this method is named getEnduringPermissions, it will actually return all types - * of node.

- * - * @return a set of nodes - * @since 2.6 - */ - @NonNull Set getEnduringPermissions(); - - /** - * Similar to {@link #getPermissions()}, except only including permissions from the enduring - * node map. (See {@link #getTransientNodes()}) - * - *

Transient permissions only exist for the duration of the session.

- * - *

This method does not resolve inheritance rules.

- * - *

Although this method is named getTransientPermissions, it will actually return all types - * of node.

- * - * @return a set of nodes - * @since 2.6 - */ - @NonNull Set getTransientPermissions(); - - /** - * A filtered view of this holders nodes, only including permanent entries. - * - *

Data is sourced from {@link #getOwnNodes()}, filtered, and then collected to a set.

- * - *

This method does not resolve inheritance rules.

- * - *

Although this method is named getPermanentPermissionNodes, it will actually return all types - * of node.

- * - * @return a set of permanent nodes - * @since 2.6 - */ - @NonNull Set getPermanentPermissionNodes(); - - /** - * A filtered view of this holders nodes, only including temporary entries. - * - *

Data is sourced from {@link #getOwnNodes()}, filtered, and then collected to a set.

- * - *

This method does not resolve inheritance rules.

- * - *

Although this method is named getTemporaryPermissionNodes, it will actually return all types - * of node.

- * - * @return a set of temporary nodes - * @since 2.6 - */ - @NonNull Set getTemporaryPermissionNodes(); - - /** - * Recursively resolves this holders permissions. - * - *

The returned list will contain every inherited - * node the holder has, in the order that they were inherited in.

- * - *

This means the list will contain duplicates.

- * - *

Inheritance is performed according to the platforms rules, and the order will vary - * depending on the accumulation order. By default, the holders own nodes are first in the list, - * with the entries from the end of the inheritance tree appearing last.

- * - * @param contexts the contexts for the lookup - * @return a list of nodes - * @since 3.3 - */ - @NonNull List resolveInheritances(@NonNull Contexts contexts); - - /** - * Recursively resolves this holders permissions. - * - *

The returned list will contain every inherited - * node the holder has, in the order that they were inherited in.

- * - *

This means the list will contain duplicates.

- * - *

Unlike {@link #resolveInheritances(Contexts)}, this method does not - * filter by context, at all.

- * - *

Inheritance is performed according to the platforms rules, and the order will vary - * depending on the accumulation order. By default, the holders own nodes are first in the list, - * with the entries from the end of the inheritance tree appearing last.

- * - * @return a list of nodes - * @since 3.3 - */ - @NonNull List resolveInheritances(); - - /** - * Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context - * - *

Unlike {@link #getAllNodesFiltered(Contexts)}, this method will not filter individual - * nodes by context. The context is only used to determine which groups should apply.

- * - *

Nodes are sorted into priority order. The order of inheritance is only important during - * the process of flattening inherited entries.

- * - * @param contexts the context for the lookup - * @return an immutable sorted set of permissions - * @throws NullPointerException if the context is null - * @since 2.11 - */ - @NonNull SortedSet getAllNodes(@NonNull Contexts contexts); - - /** - * Gets a mutable sorted set of the nodes that this object has and inherits. - * - *

Unlike {@link #getAllNodes(Contexts)}, this method does not filter by context, at all.

- * - *

Nodes are sorted into priority order. The order of inheritance is only important during - * the process of flattening inherited entries.

- * - * @return an immutable sorted set of permissions - * @throws NullPointerException if the context is null - * @since 3.3 - */ - @NonNull SortedSet getAllNodes(); - - /** - * Gets a mutable set of the nodes that this object has and inherits, filtered by context. - * - *

Unlike {@link #getAllNodes(Contexts)}, this method WILL filter individual nodes, - * and only return ones that fully meet the context provided.

- * - * @param contexts the context for the lookup - * @return a mutable set of permissions - * @throws NullPointerException if the context is null - * @since 2.11 - */ - @NonNull Set getAllNodesFiltered(@NonNull Contexts contexts); - - /** - * Converts the output of {@link #getAllNodesFiltered(Contexts)} into string and boolean form, - * and expands shorthand permissions. - * - * @param contexts the context for the lookup - * @param convertToLowercase if the keys should be made lowercase whilst being exported - * @return a mutable map of permissions - */ - @NonNull Map exportNodes(@NonNull Contexts contexts, boolean convertToLowercase); - - /** - * Removes any temporary permissions that have expired. - * - *

This method is called periodically by the platform, so it is only necessary to run - * if you want to guarentee that the current data is totally up-to-date.

- */ - void auditTemporaryPermissions(); - - /** - * Checks to see if the object has a certain permission. - * - *

Although this method is named hasPermission, it can be used for all node types.

- * - * @param node the node to check for - * @param equalityPredicate how to determine if a node matches - * @return a Tristate for the holders permission status for the node - * @throws NullPointerException if the node is null - * @since 4.1 - */ - @NonNull Tristate hasPermission(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate); - - /** - * Checks to see if the object has a certain permission. - * - *

Although this method is named hasTransientPermission, it can be used for all node types.

- * - * @param node the node to check for - * @param equalityPredicate how to determine if a node matches - * @return a Tristate for the holders permission status for the node - * @throws NullPointerException if the node is null - * @since 4.1 - */ - @NonNull Tristate hasTransientPermission(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate); - - /** - * Checks to see if the object inherits a certain permission. - * - *

Although this method is named inheritsPermission, it can be used for all node types.

- * - * @param node the node to check for - * @param equalityPredicate how to determine if a node matches - * @return a Tristate for the holders inheritance status for the node - * @throws NullPointerException if the node is null - * @since 4.1 - */ - @NonNull Tristate inheritsPermission(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate); - - /** - * Checks to see if the object has a certain permission. - * - *

Although this method is named hasPermission, it can be used for all node types.

- * - * @param node the node to check for - * @return a Tristate for the holders permission status for the node - * @throws NullPointerException if the node is null - * @since 2.6 - */ - @NonNull Tristate hasPermission(@NonNull Node node); - - /** - * Checks to see if the object has a certain permission. - * - *

Although this method is named hasTransientPermission, it can be used for all node types.

- * - * @param node the node to check for - * @return a Tristate for the holders permission status for the node - * @throws NullPointerException if the node is null - * @since 2.6 - */ - @NonNull Tristate hasTransientPermission(@NonNull Node node); - - /** - * Checks to see if the object inherits a certain permission. - * - *

Although this method is named inheritsPermission, it can be used for all node types.

- * - * @param node the node to check for - * @return a Tristate for the holders inheritance status for the node - * @throws NullPointerException if the node is null - * @since 2.6 - */ - @NonNull Tristate inheritsPermission(@NonNull Node node); - - /** - * Check to see if this holder inherits another group in the global context. - * - *

"Global context" simply means an empty context set.

- * - *

This method only checks for direct inheritance - one hop up the inheritance tree.

- * - * @param group The group to check membership of - * @return true if the group inherits the other group - * @throws NullPointerException if the group is null - * @throws IllegalStateException if the group instance was not obtained from LuckPerms. - * @since 4.0 - */ - boolean inheritsGroup(@NonNull Group group); - - /** - * Check to see if this holder inherits another group. - * - *

This method only checks for direct inheritance - one hop up the inheritance tree.

- * - * @param group The group to check membership of - * @param contextSet the context set to filter by - * @return true if the group inherits the other group - * @throws NullPointerException if the group is null - * @throws IllegalStateException if the group instance was not obtained from LuckPerms. - * @since 4.0 - */ - boolean inheritsGroup(@NonNull Group group, @NonNull ContextSet contextSet); - - /** - * Sets a permission node for the permission holder. - * - *

Although this method is named setPermission, it can be used for all node types.

- * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @param node The node to be set - * @return the result of the operation - * @throws NullPointerException if the node is null - * @since 4.0 - */ - @NonNull DataMutateResult setPermission(@NonNull Node node); - - /** - * Sets a permission node for the permission holder. - * - *

Although this method is named setPermission, it can be used for all node types.

- * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @param node The node to be set - * @param temporaryMergeBehaviour The behaviour used to merge temporary permission entries - * @return the result of the operation - * @throws NullPointerException if the node is null - * @since 4.3 - */ - @NonNull TemporaryDataMutateResult setPermission(@NonNull Node node, @NonNull TemporaryMergeBehaviour temporaryMergeBehaviour); - - /** - * Sets a transient permission for the permission holder. - * - *

A transient node is a permission that does not persist. - * Whenever a user logs out of the server, or the server restarts, this permission will - * disappear. It is never saved to the datastore, and therefore will not apply on other - * servers.

- * - *

This is useful if you want to temporarily set a permission for a user while they're - * online, but don't want it to persist, and have to worry about removing it when they log - * out.

- * - *

For unsetting a transient permission, see {@link #unsetTransientPermission(Node)}.

- * - *

Although this method is named setTransientPermission, it can be used for all node types.

- * - * @param node The node to be set - * @return the result of the operation - * @throws NullPointerException if the node is null - * @since 4.0 - */ - @NonNull DataMutateResult setTransientPermission(@NonNull Node node); - - /** - * Sets a transient permission for the permission holder. - * - *

A transient node is a permission that does not persist. - * Whenever a user logs out of the server, or the server restarts, this permission will - * disappear. It is never saved to the datastore, and therefore will not apply on other - * servers.

- * - *

This is useful if you want to temporarily set a permission for a user while they're - * online, but don't want it to persist, and have to worry about removing it when they log - * out.

- * - *

For unsetting a transient permission, see {@link #unsetTransientPermission(Node)}.

- * - *

Although this method is named setTransientPermission, it can be used for all node types.

- * - * @param node The node to be se - * @param temporaryMergeBehaviour The behaviour used to merge temporary permission entries - * @return the result of the operation - * @throws NullPointerException if the node is null - * @since 4.3 - */ - @NonNull TemporaryDataMutateResult setTransientPermission(@NonNull Node node, @NonNull TemporaryMergeBehaviour temporaryMergeBehaviour); - - /** - * Unsets a permission for the permission holder. - * - *

Although this method is named unsetPermission, it can be used for all node types.

- * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @param node The node to be unset - * @return the result of the operation - * @throws NullPointerException if the node is null - * @since 4.0 - */ - @NonNull DataMutateResult unsetPermission(@NonNull Node node); - - /** - * Unsets a transient permission for the permission holder. - * - *

Although this method is named unsetTransientPermission, it can be used for all node types.

- * - * @param node The node to be unset - * @return the result of the operation - * @throws NullPointerException if the node is null - * @since 4.0 - */ - @NonNull DataMutateResult unsetTransientPermission(@NonNull Node node); - - /** - * Clears any nodes from the holder which pass the predicate. - * - *

This method only targets enduring data.

- * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @param test the predicate to test for nodes which should be removed - * @since 3.2 - */ - void clearMatching(@NonNull Predicate test); - - /** - * Clears any transient nodes from the holder which pass the predicate. - * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @param test the predicate to test for nodes which should be removed - * @since 3.2 - */ - void clearMatchingTransient(@NonNull Predicate test); - - /** - * Clears all nodes held by the permission holder. - * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @since 2.17 - */ - void clearNodes(); - - /** - * Clears all nodes held by the permission holder in a specific context. - * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @param contextSet the contexts to filter by - * @since 3.2 - */ - void clearNodes(@NonNull ContextSet contextSet); - - /** - * Clears all parent groups. - * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @since 2.17 - */ - void clearParents(); - - /** - * Clears all parent groups in a specific context. - * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @param contextSet the contexts to filter by - * @since 3.2 - */ - void clearParents(@NonNull ContextSet contextSet); - - /** - * Clears all meta held by the permission holder. - * - *

Meta nodes in this case, are any nodes which have a {@link MetaType}, {@link PrefixType} - * or {@link SuffixType} type.

- * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @since 2.17 - */ - void clearMeta(); - - /** - * Clears all meta held by the permission holder in a specific context. - * - *

Meta nodes in this case, are any nodes which have a {@link MetaType}, {@link PrefixType} - * or {@link SuffixType} type.

- * - *

The effect of this mutate operation will not persist in storage unless changes are - * explicitly saved. If changes are not saved, the effect will only be observed until the next - * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved - * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved - * using {@link GroupManager#saveGroup(Group)}.

- * - *

Before making changes to a user or group, it may be a good idea to load a fresh copy of - * the backing data from the storage if you haven't done so already, to avoid overwriting changes - * made already. This can be done via {@link UserManager#loadUser(UUID)} or - * {@link GroupManager#loadGroup(String)} respectively.

- * - * @param contextSet the contexts to filter by - * @since 3.2 - */ - void clearMeta(@NonNull ContextSet contextSet); - - /** - * Clears all transient nodes the permission holder has. - */ - void clearTransientNodes(); - - /** - * Sets a permission for the permission holder. - * - * @param node The node to be set - * @return the result of the operation - * @throws NullPointerException if the node is null - * @since 3.1 - * @deprecated now forwards to {@link #setPermission(Node)}. - */ - @Deprecated - default @NonNull DataMutateResult setPermissionUnchecked(@NonNull Node node) { - return setPermission(node); - } - - /** - * Sets a transient permission for the permission holder. - * - * @param node The node to be set - * @return the result of the operation - * @throws NullPointerException if the node is null - * @since 3.1 - * @deprecated now forwards to {@link #setTransientPermission(Node)} - */ - @Deprecated - default @NonNull DataMutateResult setTransientPermissionUnchecked(@NonNull Node node) { - return setTransientPermission(node); - } - - /** - * Unsets a permission for the permission holder. - * - * @param node The node to be unset - * @return the result of the operation - * @throws NullPointerException if the node is null - * @since 3.1 - * @deprecated now forwards to {@link #unsetPermission(Node)} - */ - @Deprecated - default @NonNull DataMutateResult unsetPermissionUnchecked(@NonNull Node node) { - return unsetPermission(node); - } - - /** - * Unsets a transient permission for the permission holder. - * - * @param node The node to be unset - * @return the result of the operation - * @throws NullPointerException if the node is null - * @since 3.1 - * @deprecated now forwards to {@link #unsetTransientPermission(Node)} - */ - @Deprecated - default @NonNull DataMutateResult unsetTransientPermissionUnchecked(@NonNull Node node) { - return unsetTransientPermission(node); - } - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/LogEntry.java b/api/src/main/java/me/lucko/luckperms/api/actionlog/Action.java similarity index 83% rename from api/src/main/java/me/lucko/luckperms/api/LogEntry.java rename to api/src/main/java/me/lucko/luckperms/api/actionlog/Action.java index 1502aa759..2631da02c 100644 --- a/api/src/main/java/me/lucko/luckperms/api/LogEntry.java +++ b/api/src/main/java/me/lucko/luckperms/api/actionlog/Action.java @@ -23,7 +23,9 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.actionlog; + +import me.lucko.luckperms.api.LuckPermsProvider; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -33,10 +35,17 @@ import java.util.UUID; /** * Represents a logged action. - * - * @see ActionLogger#newEntryBuilder() for creating an instance */ -public interface LogEntry extends Comparable { +public interface Action extends Comparable { + + /** + * Gets a {@link Action.Builder} + * + * @return a new builder + */ + static @NonNull Builder builder() { + return LuckPermsProvider.get().getActionLogger().actionBuilder(); + } /** * Gets the time in unix seconds when the action occurred. @@ -95,9 +104,7 @@ public interface LogEntry extends Comparable { @NonNull String getAction(); /** - * Represents the type of a {@link LogEntry}. - * - * @since 3.3 + * Represents the type of a {@link Action}. */ enum Type { USER('U'), GROUP('G'), TRACK('T'); @@ -108,7 +115,6 @@ public interface LogEntry extends Comparable { * @param type the string * @return a type * @throws IllegalArgumentException if a type could not be parsed - * @since 4.4 */ public static @NonNull Type parse(String type) { try { @@ -168,70 +174,70 @@ public interface LogEntry extends Comparable { * * @param timestamp the timestamp * @return the builder - * @see LogEntry#getTimestamp() + * @see Action#getTimestamp() */ - @NonNull Builder setTimestamp(long timestamp); + @NonNull Builder timestamp(long timestamp); /** * Sets the actor of the entry. * * @param actor the actor * @return the builder - * @see LogEntry#getActor() + * @see Action#getActor() */ - @NonNull Builder setActor(@NonNull UUID actor); + @NonNull Builder actor(@NonNull UUID actor); /** * Sets the actor name of the entry. * * @param actorName the actor name * @return the builder - * @see LogEntry#getActorName() + * @see Action#getActorName() */ - @NonNull Builder setActorName(@NonNull String actorName); + @NonNull Builder actorName(@NonNull String actorName); /** * Sets the type of the entry. * * @param type the type * @return the builder - * @see LogEntry#getType() + * @see Action#getType() */ - @NonNull Builder setType(@NonNull Type type); + @NonNull Builder type(@NonNull Type type); /** * Sets the acted object for the entry. * * @param acted the acted object * @return the builder - * @see LogEntry#getActed() + * @see Action#getActed() */ - @NonNull Builder setActed(@Nullable UUID acted); + @NonNull Builder acted(@Nullable UUID acted); /** * Sets the acted name for the entry. * * @param actedName the acted name * @return the builder - * @see LogEntry#getActedName() + * @see Action#getActedName() */ - @NonNull Builder setActedName(@NonNull String actedName); + @NonNull Builder actedName(@NonNull String actedName); /** * Sets the action of the entry. * * @param action the action * @return the builder - * @see LogEntry#getAction() + * @see Action#getAction() */ - @NonNull Builder setAction(@NonNull String action); + @NonNull Builder action(@NonNull String action); /** - * Creates a {@link LogEntry} instance from the builder. + * Creates a {@link Action} instance from the builder. * * @return a new log entry instance */ - @NonNull LogEntry build(); + @NonNull Action build(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/Log.java b/api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLog.java similarity index 81% rename from api/src/main/java/me/lucko/luckperms/api/Log.java rename to api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLog.java index 3171f0062..84c90d1b5 100644 --- a/api/src/main/java/me/lucko/luckperms/api/Log.java +++ b/api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLog.java @@ -23,7 +23,7 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.actionlog; import org.checkerframework.checker.nullness.qual.NonNull; @@ -36,18 +36,18 @@ import java.util.UUID; *

The returned instance provides a copy of the data at the time of retrieval.

* *

Any changes made to log entries will only apply to this instance of the log. - * You can add to the log using the {@link Storage}, and then request an updated copy.

+ * You can add to the log using the {@link ActionLogger}, and then request an updated copy.

* *

All methods are thread safe, and return immutable and thread safe collections.

*/ -public interface Log { +public interface ActionLog { /** - * Gets the {@link LogEntry}s that make up this log. + * Gets the {@link Action}s that make up this log. * * @return the content */ - @NonNull SortedSet getContent(); + @NonNull SortedSet getContent(); /** * Gets the entries in the log performed by the given actor. @@ -55,7 +55,7 @@ public interface Log { * @param actor the uuid of the actor to filter by * @return the content for the given actor */ - @NonNull SortedSet getContent(@NonNull UUID actor); + @NonNull SortedSet getContent(@NonNull UUID actor); /** * Gets the log content for a given user @@ -63,7 +63,7 @@ public interface Log { * @param uuid the uuid to filter by * @return all content in this log where the user = uuid */ - @NonNull SortedSet getUserHistory(@NonNull UUID uuid); + @NonNull SortedSet getUserHistory(@NonNull UUID uuid); /** * Gets the log content for a given group @@ -71,7 +71,7 @@ public interface Log { * @param name the name to filter by * @return all content in this log where the group = name */ - @NonNull SortedSet getGroupHistory(@NonNull String name); + @NonNull SortedSet getGroupHistory(@NonNull String name); /** * Gets the log content for a given track @@ -79,6 +79,6 @@ public interface Log { * @param name the name to filter by * @return all content in this log where the track = name */ - @NonNull SortedSet getTrackHistory(@NonNull String name); + @NonNull SortedSet getTrackHistory(@NonNull String name); } diff --git a/api/src/main/java/me/lucko/luckperms/api/ActionLogger.java b/api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLogger.java similarity index 79% rename from api/src/main/java/me/lucko/luckperms/api/ActionLogger.java rename to api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLogger.java index fe4aa8455..22c0c797e 100644 --- a/api/src/main/java/me/lucko/luckperms/api/ActionLogger.java +++ b/api/src/main/java/me/lucko/luckperms/api/actionlog/ActionLogger.java @@ -23,7 +23,9 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.actionlog; + +import me.lucko.luckperms.api.messaging.MessagingService; import org.checkerframework.checker.nullness.qual.NonNull; @@ -31,25 +33,22 @@ import java.util.concurrent.CompletableFuture; /** * Represents the object responsible for handling action logging. - * - * @since 4.1 */ public interface ActionLogger { /** - * Returns a new {@link LogEntry.Builder} instance + * Returns a new {@link Action.Builder} instance * * @return a new builder */ - LogEntry.@NonNull Builder newEntryBuilder(); + Action.@NonNull Builder actionBuilder(); /** - * Gets a {@link Log} instance from the plugin storage. + * Gets a {@link ActionLog} instance from the plugin storage. * * @return a log instance - * @see Storage#getLog() */ - @NonNull CompletableFuture getLog(); + @NonNull CompletableFuture getLog(); /** * Submits a log entry to the plugin to be handled. @@ -58,7 +57,7 @@ public interface ActionLogger { * it.

* *

It is therefore roughly equivalent to calling - * {@link #submitToStorage(LogEntry)} and {@link #broadcastAction(LogEntry)}, + * {@link #submitToStorage(Action)} and {@link #broadcastAction(Action)}, * however, using this method is preferred to making the calls individually.

* *

If you want to submit a log entry but don't know which method to pick, @@ -67,17 +66,15 @@ public interface ActionLogger { * @param entry the entry to submit * @return a future which will complete when the action is done */ - @NonNull CompletableFuture submit(@NonNull LogEntry entry); + @NonNull CompletableFuture submit(@NonNull Action entry); /** * Submits a log entry to the plugins storage handler. * - *

Performs the same action as {@link Storage#logAction(LogEntry)}.

- * * @param entry the entry to submit * @return a future which will complete when the action is done */ - @NonNull CompletableFuture submitToStorage(@NonNull LogEntry entry); + @NonNull CompletableFuture submitToStorage(@NonNull Action entry); /** * Submits a log entry to the plugins log broadcasting handler. @@ -88,6 +85,6 @@ public interface ActionLogger { * @param entry the entry to submit * @return a future which will complete when the action is done */ - @NonNull CompletableFuture broadcastAction(@NonNull LogEntry entry); + @NonNull CompletableFuture broadcastAction(@NonNull Action entry); } diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/CachedDataContainer.java b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedData.java similarity index 79% rename from api/src/main/java/me/lucko/luckperms/api/caching/CachedDataContainer.java rename to api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedData.java index d9aa4b04f..fb829b558 100644 --- a/api/src/main/java/me/lucko/luckperms/api/caching/CachedDataContainer.java +++ b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedData.java @@ -23,24 +23,22 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.caching; +package me.lucko.luckperms.api.cacheddata; -import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.query.QueryOptions; import org.checkerframework.checker.nullness.qual.NonNull; /** - * Holds cached lookup data in a specific set of contexts. - * - * @since 4.1 + * Holds cached lookup data for a given set of query options. */ -public interface CachedDataContainer { +public interface CachedData { /** - * Gets the contexts this container is holding data for. + * Gets the query options this container is holding data for. * - * @return the contexts this container is caching + * @return the query options this container is caching */ - @NonNull Contexts getContexts(); + @NonNull QueryOptions getQueryOptions(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedDataManager.java b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedDataManager.java new file mode 100644 index 000000000..7922b94d2 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedDataManager.java @@ -0,0 +1,212 @@ +/* + * 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.api.cacheddata; + +import me.lucko.luckperms.api.model.PermissionHolder; +import me.lucko.luckperms.api.query.QueryOptions; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.concurrent.CompletableFuture; + +/** + * Holds cached permission and meta lookup data for a {@link PermissionHolder}. + * + *

All calls will account for inheritance, as well as any default data + * provided by the platform. This calls are heavily cached and are therefore + * fast.

+ */ +public interface CachedDataManager { + + /** + * Gets the manager for {@link CachedPermissionData}. + * + * @return the permission data manager + */ + @NonNull Container permissionData(); + + /** + * Gets the manager for {@link CachedMetaData}. + * + * @return the meta data manager + */ + @NonNull Container metaData(); + + /** + * Gets PermissionData from the cache, given a specified context. + * + * @param queryOptions the query options + * @return a permission data instance + * @throws NullPointerException if contexts is null + */ + @NonNull CachedPermissionData getPermissionData(@NonNull QueryOptions queryOptions); + + /** + * Gets MetaData from the cache, given a specified context. + * + * @param queryOptions the query options + * @return a meta data instance + * @throws NullPointerException if contexts is null + */ + @NonNull CachedMetaData getMetaData(@NonNull QueryOptions queryOptions); + + /** + * Invalidates all cached {@link CachedPermissionData} and {@link CachedMetaData} + * instances. + */ + void invalidate(); + + /** + * Invalidates all of the underlying Permission calculators. + * + *

Can be called to allow for an update in defaults.

+ */ + void invalidatePermissionCalculators(); + + /** + * Manages a specific type of {@link CachedData cached data} within + * a {@link CachedDataManager} instance. + * + * @param the data type + */ + interface Container { + + /** + * Gets {@link T data} from the cache. + * + * @param queryOptions the query options + * @return a data instance + * @throws NullPointerException if contexts is null + */ + @NonNull T get(@NonNull QueryOptions queryOptions); + + /** + * Calculates {@link T data}, bypassing the cache. + * + *

The result of this operation is calculated each time the method is called. + * The result is not added to the internal cache.

+ * + *

It is therefore highly recommended to use {@link #get(QueryOptions)} instead.

+ * + *

The use cases of this method are more around constructing one-time + * instances of {@link T data}, without adding the result to the cache.

+ * + * @param queryOptions the query options + * @return a data instance + * @throws NullPointerException if contexts is null + */ + @NonNull T calculate(@NonNull QueryOptions queryOptions); + + /** + * (Re)calculates data for a given context. + * + *

This method returns immediately in all cases. The (re)calculation is + * performed asynchronously and applied to the cache in the background.

+ * + *

If there was a previous data instance associated with + * the given {@link QueryOptions}, then that instance will continue to be returned by + * {@link #get(QueryOptions)} until the recalculation is completed.

+ * + *

If there was no value calculated and cached prior to the call of this + * method, then one will be calculated.

+ * + * @param queryOptions the query options + * @throws NullPointerException if contexts is null + */ + void recalculate(@NonNull QueryOptions queryOptions); + + /** + * (Re)loads permission data for a given context. + * + *

Unlike {@link #recalculate(QueryOptions)}, this method immediately + * invalidates any previous data values contained within the cache, + * and then schedules a task to reload a new data instance to + * replace the one which was invalidated.

+ * + *

The invalidation happens immediately during the execution of this method. + * The result of the re-computation encapsulated by the future.

+ * + *

Subsequent calls to {@link #get(QueryOptions)} will block until + * the result of this operation is complete.

+ * + *

If there was no value calculated and cached prior to the call of this + * method, then one will be calculated.

+ * + *

This method returns a Future so users can optionally choose to wait + * until the recalculation has been performed.

+ * + * @param queryOptions the query options. + * @return a future + * @throws NullPointerException if contexts is null + */ + @NonNull CompletableFuture reload(@NonNull QueryOptions queryOptions); + + /** + * Recalculates data for all known contexts. + * + *

This method returns immediately. The recalculation is performed + * asynchronously and applied to the cache in the background.

+ * + *

The previous data instances will continue to be returned + * by {@link #get(QueryOptions)} until the recalculation is completed.

+ */ + void recalculate(); + + /** + * Reloads permission data for all known contexts. + * + *

Unlike {@link #recalculate()}, this method immediately + * invalidates all previous data values contained within the cache, + * and then schedules a task to reload new data instances to + * replace the ones which were invalidated.

+ * + *

The invalidation happens immediately during the execution of this method. + * The result of the re-computation encapsulated by the future.

+ * + *

Subsequent calls to {@link #get(QueryOptions)} will block until + * the result of this operation is complete.

+ * + *

This method returns a Future so users can optionally choose to wait + * until the recalculation has been performed.

+ * + * @return a future + */ + @NonNull CompletableFuture reload(); + + /** + * Invalidates any cached data instances mapped to the given context. + * + * @param queryOptions the queryOptions to invalidate for + */ + void invalidate(@NonNull QueryOptions queryOptions); + + /** + * Invalidates all cached data instances. + */ + void invalidate(); + } + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/MetaData.java b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedMetaData.java similarity index 72% rename from api/src/main/java/me/lucko/luckperms/api/caching/MetaData.java rename to api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedMetaData.java index ead912adb..c24984736 100644 --- a/api/src/main/java/me/lucko/luckperms/api/caching/MetaData.java +++ b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedMetaData.java @@ -23,55 +23,50 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.caching; - -import com.google.common.collect.ListMultimap; +package me.lucko.luckperms.api.cacheddata; import me.lucko.luckperms.api.metastacking.MetaStackDefinition; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import java.util.List; import java.util.Map; import java.util.SortedMap; /** * Holds cached meta lookup data for a specific set of contexts. - * - * @since 2.13 */ -public interface MetaData extends CachedDataContainer { +public interface CachedMetaData extends CachedData { /** - * Gets the contexts this container is holding data for. + * Gets a value for the given meta key. * - * @return the contexts this container is caching + * @param key the key + * @return the value */ - @NonNull MetaContexts getMetaContexts(); + @Nullable String getMetaValue(String key); + + /** + * Gets the user's highest priority prefix, or null if the user has no prefixes + * + * @return a prefix string, or null + */ + @Nullable String getPrefix(); + + /** + * Gets the user's highest priority suffix, or null if the user has no suffixes + * + * @return a suffix string, or null + */ + @Nullable String getSuffix(); /** * Gets an immutable copy of the meta this user has. * - *

A list multimap is used because when inherited values are included, each key can be - * mapped to multiple values.

- * - *

The first value to be accumulated (and used to represent the key in {@link #getMeta()} is at index 0 - * in the list. Any additional values are stored in order of accumulation.

- * - * @return an immutable multimap of meta - * @since 3.3 - */ - @NonNull ListMultimap getMetaMultimap(); - - /** - * Gets an immutable copy of the meta this user has. - * - *

This map is formed by taking the entries in {@link #getMetaMultimap()}, and mapping each key - * to the value at index 0 in the corresponding list.

- * * @return an immutable map of meta */ - @NonNull Map getMeta(); + @NonNull Map> getMeta(); /** * Gets an immutable sorted map of all of the prefixes the user has, whereby the first value is the highest priority @@ -89,25 +84,10 @@ public interface MetaData extends CachedDataContainer { */ @NonNull SortedMap getSuffixes(); - /** - * Gets the user's highest priority prefix, or null if the user has no prefixes - * - * @return a prefix string, or null - */ - @Nullable String getPrefix(); - - /** - * Gets the user's highest priority suffix, or null if the user has no suffixes - * - * @return a suffix string, or null - */ - @Nullable String getSuffix(); - /** * Gets the definition used for the prefix stack * * @return the definition used for the prefix stack - * @since 3.2 */ @NonNull MetaStackDefinition getPrefixStackDefinition(); @@ -115,7 +95,6 @@ public interface MetaData extends CachedDataContainer { * Gets the definition used for the suffix stack * * @return the definition used for the suffix stack - * @since 3.2 */ @NonNull MetaStackDefinition getSuffixStackDefinition(); diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/PermissionData.java b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedPermissionData.java similarity index 87% rename from api/src/main/java/me/lucko/luckperms/api/caching/PermissionData.java rename to api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedPermissionData.java index ac1460de8..94233e763 100644 --- a/api/src/main/java/me/lucko/luckperms/api/caching/PermissionData.java +++ b/api/src/main/java/me/lucko/luckperms/api/cacheddata/CachedPermissionData.java @@ -23,9 +23,9 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.caching; +package me.lucko.luckperms.api.cacheddata; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import org.checkerframework.checker.nullness.qual.NonNull; @@ -33,10 +33,8 @@ import java.util.Map; /** * Holds cached permission lookup data for a specific set of contexts. - * - * @since 2.13 */ -public interface PermissionData extends CachedDataContainer { +public interface CachedPermissionData extends CachedData { /** * Gets a permission check result for the given permission node. @@ -45,7 +43,7 @@ public interface PermissionData extends CachedDataContainer { * @return a tristate result * @throws NullPointerException if permission is null */ - @NonNull Tristate getPermissionValue(@NonNull String permission); + @NonNull Tristate checkPermission(@NonNull String permission); /** * Invalidates the underlying permission calculator cache. @@ -59,6 +57,6 @@ public interface PermissionData extends CachedDataContainer { * * @return an immutable set of permissions */ - @NonNull Map getImmutableBacking(); + @NonNull Map getPermissionMap(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/CachedData.java b/api/src/main/java/me/lucko/luckperms/api/caching/CachedData.java deleted file mode 100644 index 1a5e143c8..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/caching/CachedData.java +++ /dev/null @@ -1,430 +0,0 @@ -/* - * 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.api.caching; - -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.PermissionHolder; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; - -/** - * Holds cached permission and meta lookup data for a {@link PermissionHolder}. - * - *

All calls will account for inheritance, as well as any default data - * provided by the platform. This calls are heavily cached and are therefore - * fast.

- * - *

For meta, both methods accepting {@link Contexts} and {@link MetaContexts} - * are provided. The only difference is that the latter allows you to define - * how the meta stack should be structured internally. Where {@link Contexts} - * are passed, the values from the configuration are used.

- * - * @since 4.0 - */ -public interface CachedData { - - /** - * Gets PermissionData from the cache, given a specified context. - * - * @param contexts the contexts to get the permission data in - * @return a permission data instance - * @throws NullPointerException if contexts is null - */ - @NonNull PermissionData getPermissionData(@NonNull Contexts contexts); - - /** - * Gets MetaData from the cache, given a specified context. - * - * @param contexts the contexts to get the permission data in - * @return a meta data instance - * @throws NullPointerException if contexts is null - * @since 3.2 - */ - @NonNull MetaData getMetaData(@NonNull MetaContexts contexts); - - /** - * Gets MetaData from the cache, given a specified context. - * - * @param contexts the contexts to get the permission data in - * @return a meta data instance - * @throws NullPointerException if contexts is null - */ - @NonNull MetaData getMetaData(@NonNull Contexts contexts); - - /** - * Calculates permission data, bypassing the cache. - * - *

The result of this operation is calculated each time the method is called. - * The result is not added to the internal cache.

- * - *

It is therefore highly recommended to use {@link #getPermissionData(Contexts)} instead.

- * - *

The use cases of this method are more around constructing one-time - * instances of {@link PermissionData}, without adding the result to the cache.

- * - * @param contexts the contexts to get permission data in - * @return a permission data instance - * @throws NullPointerException if contexts is null - */ - @NonNull PermissionData calculatePermissions(@NonNull Contexts contexts); - - /** - * Calculates meta data, bypassing the cache. - * - *

The result of this operation is calculated each time the method is called. - * The result is not added to the internal cache.

- * - *

It is therefore highly recommended to use {@link #getMetaData(MetaContexts)} instead.

- * - *

The use cases of this method are more around constructing one-time - * instances of {@link MetaData}, without adding the result to the cache.

- * - * @param contexts the contexts to get meta data in - * @return a meta data instance - * @throws NullPointerException if contexts is null - * @since 3.2 - */ - @NonNull MetaData calculateMeta(@NonNull MetaContexts contexts); - - /** - * Calculates meta data, bypassing the cache. - * - *

The result of this operation is calculated each time the method is called. - * The result is not added to the internal cache.

- * - *

It is therefore highly recommended to use {@link #getMetaData(Contexts)} instead.

- * - *

The use cases of this method are more around constructing one-time - * instances of {@link MetaData}, without adding the result to the cache.

- * - * @param contexts the contexts to get meta data in - * @return a meta data instance - * @throws NullPointerException if contexts is null - */ - @NonNull MetaData calculateMeta(@NonNull Contexts contexts); - - /** - * (Re)calculates permission data for a given context. - * - *

This method returns immediately in all cases. The (re)calculation is - * performed asynchronously and applied to the cache in the background.

- * - *

If there was a previous {@link PermissionData} instance associated with - * the given {@link Contexts}, then that instance will continue to be returned by - * {@link #getPermissionData(Contexts)} until the recalculation is completed.

- * - *

If there was no value calculated and cached prior to the call of this - * method, then one will be calculated.

- * - * @param contexts the contexts to recalculate in. - * @throws NullPointerException if contexts is null - */ - void recalculatePermissions(@NonNull Contexts contexts); - - /** - * (Re)calculates meta data for a given context. - * - *

This method returns immediately in all cases. The (re)calculation is - * performed asynchronously and applied to the cache in the background.

- * - *

If there was a previous {@link MetaData} instance associated with - * the given {@link MetaContexts}, then that instance will continue to be returned by - * {@link #getMetaData(MetaContexts)} until the recalculation is completed.

- * - *

If there was no value calculated and cached prior to the call of this - * method, then one will be calculated.

- * - * @param contexts the contexts to recalculate in. - * @throws NullPointerException if contexts is null - * @since 3.2 - */ - void recalculateMeta(@NonNull MetaContexts contexts); - - /** - * (Re)calculates meta data for a given context. - * - *

This method returns immediately in all cases. The (re)calculation is - * performed asynchronously and applied to the cache in the background.

- * - *

If there was a previous {@link MetaData} instance associated with - * the given {@link Contexts}, then that instance will continue to be returned by - * {@link #getMetaData(Contexts)} until the recalculation is completed.

- * - *

If there was no value calculated and cached prior to the call of this - * method, then one will be calculated.

- * - * @param contexts the contexts to recalculate in. - * @throws NullPointerException if contexts is null - */ - void recalculateMeta(@NonNull Contexts contexts); - - /** - * (Re)loads permission data for a given context. - * - *

Unlike {@link #recalculatePermissions(Contexts)}, this method immediately - * invalidates any previous {@link PermissionData} values contained within the cache, - * and then schedules a task to reload a new {@link PermissionData} instance to - * replace the one which was invalidated.

- * - *

The invalidation happens immediately during the execution of this method. - * The result of the re-computation encapsulated by the future.

- * - *

Subsequent calls to {@link #getPermissionData(Contexts)} will block until - * the result of this operation is complete.

- * - *

If there was no value calculated and cached prior to the call of this - * method, then one will be calculated.

- * - *

This method returns a Future so users can optionally choose to wait - * until the recalculation has been performed.

- * - * @param contexts the contexts to reload in. - * @return a future - * @throws NullPointerException if contexts is null - * @since 4.0 - */ - @NonNull CompletableFuture reloadPermissions(@NonNull Contexts contexts); - - /** - * (Re)loads meta data for a given context. - * - *

Unlike {@link #recalculateMeta(MetaContexts)}, this method immediately - * invalidates any previous {@link MetaData} values contained within the cache, - * and then schedules a task to reload a new {@link MetaData} instance to - * replace the one which was invalidated.

- * - *

The invalidation happens immediately during the execution of this method. - * The result of the re-computation encapsulated by the future.

- * - *

Subsequent calls to {@link #getMetaData(MetaContexts)} will block until - * the result of this operation is complete.

- * - *

If there was no value calculated and cached prior to the call of this - * method, then one will be calculated.

- * - *

This method returns a Future so users can optionally choose to wait - * until the recalculation has been performed.

- * - * @param contexts the contexts to reload in. - * @return a future - * @throws NullPointerException if contexts is null - * @since 4.0 - */ - @NonNull CompletableFuture reloadMeta(@NonNull MetaContexts contexts); - - /** - * (Re)loads meta data for a given context. - * - *

Unlike {@link #recalculateMeta(Contexts)}, this method immediately - * invalidates any previous {@link MetaData} values contained within the cache, - * and then schedules a task to reload a new {@link MetaData} instance to - * replace the one which was invalidated.

- * - *

The invalidation happens immediately during the execution of this method. - * The result of the re-computation encapsulated by the future.

- * - *

Subsequent calls to {@link #getMetaData(Contexts)} will block until - * the result of this operation is complete.

- * - *

If there was no value calculated and cached prior to the call of this - * method, then one will be calculated.

- * - *

This method returns a Future so users can optionally choose to wait - * until the recalculation has been performed.

- * - * @param contexts the contexts to reload in. - * @return a future - * @throws NullPointerException if contexts is null - * @since 4.0 - */ - @NonNull CompletableFuture reloadMeta(@NonNull Contexts contexts); - - /** - * Recalculates permission data for all known contexts. - * - *

This method returns immediately. The recalculation is performed - * asynchronously and applied to the cache in the background.

- * - *

The previous {@link PermissionData} instances will continue to be returned - * by {@link #getPermissionData(Contexts)} until the recalculation is completed.

- */ - void recalculatePermissions(); - - /** - * Recalculates meta data for all known contexts. - * - *

This method returns immediately. The recalculation is performed - * asynchronously and applied to the cache in the background.

- * - *

The previous {@link MetaData} instances will continue to be returned - * by {@link #getMetaData(MetaContexts)} and {@link #getMetaData(Contexts)} - * until the recalculation is completed.

- */ - void recalculateMeta(); - - /** - * Reloads permission data for all known contexts. - * - *

Unlike {@link #recalculatePermissions()}, this method immediately - * invalidates all previous {@link PermissionData} values contained within the cache, - * and then schedules a task to reload a new {@link PermissionData} instances to - * replace the ones which were invalidated.

- * - *

The invalidation happens immediately during the execution of this method. - * The result of the re-computation encapsulated by the future.

- * - *

Subsequent calls to {@link #getPermissionData(Contexts)} will block until - * the result of this operation is complete.

- * - *

This method returns a Future so users can optionally choose to wait - * until the recalculation has been performed.

- * - * @return a future - * @since 4.0 - */ - @NonNull CompletableFuture reloadPermissions(); - - /** - * Reloads meta data for all known contexts. - * - *

Unlike {@link #recalculateMeta()}, this method immediately - * invalidates all previous {@link MetaData} values contained within the cache, - * and then schedules a task to reload a new {@link MetaData} instances to - * replace the ones which were invalidated.

- * - *

The invalidation happens immediately during the execution of this method. - * The result of the re-computation encapsulated by the future.

- * - *

Subsequent calls to {@link #getMetaData(MetaContexts)} and - * {@link #getMetaData(Contexts)} will block until the result of this operation - * is complete.

- * - *

This method returns a Future so users can optionally choose to wait - * until the recalculation has been performed.

- * - * @return a future - * @since 4.0 - */ - @NonNull CompletableFuture reloadMeta(); - - /** - * Pre-calculates and caches {@link PermissionData} and {@link MetaData} - * instances for the given contexts. - * - *

If the cache already contains a value for the given context, - * no action is taken.

- * - *

This method blocks until the calculation is completed.

- * - * @param contexts a set of contexts - * @throws NullPointerException if contexts is null - */ - default void preCalculate(@NonNull Set contexts) { - contexts.forEach(this::preCalculate); - } - - /** - * Pre-calculates and caches {@link PermissionData} and {@link MetaData} - * instances for a given context. - * - *

If the cache already contains a value for the given context, - * no action is taken.

- * - *

This method blocks until the calculation is completed.

- * - * @param contexts the contexts to pre-calculate for - * @throws NullPointerException if contexts is null - */ - default void preCalculate(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - - // pre-calculate just by requesting the data from this cache. - // if the data isn't already loaded, it will be calculated. - getPermissionData(contexts); - getMetaData(contexts); - } - - /** - * Invalidates any cached {@link PermissionData} instances mapped to the given - * {@link Contexts}. - * - * @param contexts the contexts to invalidate for - * @since 4.0 - */ - void invalidatePermissions(@NonNull Contexts contexts); - - /** - * Invalidates any cached {@link MetaData} instances mapped to the given - * {@link MetaContexts}. - * - * @param contexts the contexts to invalidate for - * @since 4.0 - */ - void invalidateMeta(@NonNull MetaContexts contexts); - - /** - * Invalidates any cached {@link MetaData} instances mapped to the given - * {@link Contexts}. - * - * @param contexts the contexts to invalidate for - * @since 4.0 - */ - void invalidateMeta(@NonNull Contexts contexts); - - /** - * Invalidates all cached {@link PermissionData} instances. - * - * @since 4.2 - */ - void invalidatePermissions(); - - /** - * Invalidates all cached {@link MetaData} instances. - * - * @since 4.2 - */ - void invalidateMeta(); - - /** - * Invalidates all cached {@link PermissionData} and {@link MetaData} - * instances. - * - * @since 4.5 - */ - void invalidate(); - - /** - * Invalidates all of the underlying Permission calculators. - * - *

Can be called to allow for an update in defaults.

- */ - void invalidatePermissionCalculators(); - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/GroupData.java b/api/src/main/java/me/lucko/luckperms/api/caching/GroupData.java deleted file mode 100644 index 968189c4a..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/caching/GroupData.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.api.caching; - -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Group; - -/** - * Holds cached permission and meta lookup data for a {@link Group}. - * - *

All calls will account for inheritance, as well as any default data provided - * by the platform. This calls are heavily cached and are therefore fast.

- * - *

For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that - * the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the - * values from the configuration are used.

- * - * @since 4.0 - */ -public interface GroupData extends CachedData { - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/MetaContexts.java b/api/src/main/java/me/lucko/luckperms/api/caching/MetaContexts.java deleted file mode 100644 index 1c30a46a4..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/caching/MetaContexts.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.api.caching; - -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.metastacking.MetaStackDefinition; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Objects; - -/** - * Encapsulates the options and settings for a meta lookup. - * - *

Consists of a standard {@link Contexts} element, plus options to define how - * the meta stack should be constructed.

- * - * @since 3.2 - */ -public final class MetaContexts { - - /** - * Creates a new meta contexts instance - * - * @param contexts the standard contexts for the query - * @param prefixStackDefinition the prefix stack definition to be used - * @param suffixStackDefinition the suffix stack definition to be used - * @return the new instance - */ - public static MetaContexts of(@NonNull Contexts contexts, @NonNull MetaStackDefinition prefixStackDefinition, @NonNull MetaStackDefinition suffixStackDefinition) { - return new MetaContexts(contexts, prefixStackDefinition, suffixStackDefinition); - } - - private final Contexts contexts; - private final MetaStackDefinition prefixStackDefinition; - private final MetaStackDefinition suffixStackDefinition; - - // cache hashcode - this class is immutable, and is used as an index in the permission cache. - private final int hashCode; - - /** - * Creates a new meta contexts instance - * - * @param contexts the standard contexts for the query - * @param prefixStackDefinition the prefix stack definition to be used - * @param suffixStackDefinition the suffix stack definition to be used - */ - public MetaContexts(@NonNull Contexts contexts, @NonNull MetaStackDefinition prefixStackDefinition, @NonNull MetaStackDefinition suffixStackDefinition) { - this.contexts = Objects.requireNonNull(contexts, "contexts"); - this.prefixStackDefinition = Objects.requireNonNull(prefixStackDefinition, "prefixStackDefinition"); - this.suffixStackDefinition = Objects.requireNonNull(suffixStackDefinition, "suffixStackDefinition"); - this.hashCode = calculateHashCode(); - } - - public @NonNull Contexts getContexts() { - return this.contexts; - } - - public @NonNull MetaStackDefinition getPrefixStackDefinition() { - return this.prefixStackDefinition; - } - - public @NonNull MetaStackDefinition getSuffixStackDefinition() { - return this.suffixStackDefinition; - } - - @Override - public @NonNull String toString() { - return "MetaContexts(" + - "contexts=" + this.getContexts() + ", " + - "prefixStackDefinition=" + this.getPrefixStackDefinition() + ", " + - "suffixStackDefinition=" + this.getSuffixStackDefinition() + - ")"; - } - - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof MetaContexts)) return false; - final MetaContexts that = (MetaContexts) o; - return this.contexts.equals(that.contexts) && - this.prefixStackDefinition.equals(that.prefixStackDefinition) && - this.suffixStackDefinition.equals(that.suffixStackDefinition); - } - - private int calculateHashCode() { - return Objects.hash(this.contexts, this.prefixStackDefinition, this.suffixStackDefinition); - } - - @Override - public int hashCode() { - return this.hashCode; - } -} diff --git a/api/src/main/java/me/lucko/luckperms/api/caching/UserData.java b/api/src/main/java/me/lucko/luckperms/api/caching/UserData.java deleted file mode 100644 index 8de86dcb7..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/caching/UserData.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.api.caching; - -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.User; - -/** - * Holds cached permission and meta lookup data for a {@link User}. - * - *

All calls will account for inheritance, as well as any default data provided by - * the platform. This calls are heavily cached and are therefore fast.

- * - *

For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that - * the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the - * values from the configuration are used.

- * - * @since 2.13 - */ -public interface UserData extends CachedData { - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/context/ContextCalculator.java b/api/src/main/java/me/lucko/luckperms/api/context/ContextCalculator.java index ec7b61790..86761cb58 100644 --- a/api/src/main/java/me/lucko/luckperms/api/context/ContextCalculator.java +++ b/api/src/main/java/me/lucko/luckperms/api/context/ContextCalculator.java @@ -27,23 +27,71 @@ package me.lucko.luckperms.api.context; import org.checkerframework.checker.nullness.qual.NonNull; +import java.util.Objects; +import java.util.function.Function; + /** - * Calculates whether contexts are applicable to a {@link T subject}. + * Calculates the contexts applicable for a contextual subject. * - * @param the subject type. Is ALWAYS the player class of the platform. - * @since 2.13 + *

Implementations of this interface should satisfy the following + * requirements:

+ *
    + *
  • Context lookups should be fast: lookup methods are likely to + * be invoked frequently, and should therefore be fast to execute. If + * determining the current contexts involves a particularly time consuming + * lookup (database queries, network requests, etc), then such results + * should be cached ahead of time.
  • + * + *
  • Context lookups should be thread-safe: lookups will sometimes + * be performed from "async" threads, and therefore should not access any + * part of the server only safe for access from a sync context. If + * necessary, such results should be determined ahead of time and stored in + * a thread-safe collection for retrieval later.
  • + * + *
  • Context lookups should not query active contexts: doing so is + * likely to result in a stack overflow, or thread deadlock. Care should be + * taken to avoid (indirect) calls to the same calculator.
  • + *
+ *

+ * + *

Calculators should be registered using + * {@link ContextManager#registerCalculator(ContextCalculator)}.

*/ @FunctionalInterface public interface ContextCalculator { /** - * Gives the subject all of the applicable contexts they meet + * Creates a new {@link ContextCalculator} that provides a single context. * - * @param subject the subject to add contexts to - * @param accumulator a map of contexts to add to - * @return the map - * @since 2.13 + * @param key the key of the context provided by the calculator + * @param valueFunction the function used to compute the corresponding value + * for each query. A context will not be "accumulated" + * if the value returned is null. + * @param the contextual type + * @return the resultant calculator */ - @NonNull MutableContextSet giveApplicableContext(@NonNull T subject, @NonNull MutableContextSet accumulator); + static @NonNull ContextCalculator forSingleContext(@NonNull String key, @NonNull Function valueFunction) { + Objects.requireNonNull(key, "key"); + Objects.requireNonNull(valueFunction, "valueFunction"); + return (target, consumer) -> { + String value = valueFunction.apply(target); + if (value != null) { + consumer.accept(key, value); + } + }; + } + + /** + * Submits any contexts this calculator determines to be applicable to + * the {@code target} contextual subject. + * + *

Care should be taken to ensure implementations of this method meet the + * general requirements for {@link ContextCalculator}, defined in the class + * doc.

+ * + * @param target the target contextual subject for this operation + * @param consumer the {@link ContextConsumer} to submit contexts to + */ + void giveApplicableContext(@NonNull T target, @NonNull ContextConsumer consumer); } diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/DisplayNameType.java b/api/src/main/java/me/lucko/luckperms/api/context/ContextConsumer.java similarity index 69% rename from api/src/main/java/me/lucko/luckperms/api/nodetype/types/DisplayNameType.java rename to api/src/main/java/me/lucko/luckperms/api/context/ContextConsumer.java index 73995d6b5..83ce5c9fb 100644 --- a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/DisplayNameType.java +++ b/api/src/main/java/me/lucko/luckperms/api/context/ContextConsumer.java @@ -23,31 +23,35 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.nodetype.types; - -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; +package me.lucko.luckperms.api.context; import org.checkerframework.checker.nullness.qual.NonNull; +import java.util.Map; + /** - * A sub-type of {@link Node} used to mark the display name of the node's holder. - * - * @since 4.2 + * Functional interface that accepts context key value pairs. */ -public interface DisplayNameType extends NodeType { +@FunctionalInterface +public interface ContextConsumer { /** - * The key for this type. - */ - NodeTypeKey KEY = new NodeTypeKey(){}; - - /** - * Gets the display name. + * Accepts a context pair. * - * @return the display name + * @param key the key + * @param value the value */ - @NonNull String getDisplayName(); + void accept(@NonNull String key, @NonNull String value); + + /** + * Accepts a context set. + * + * @param contextSet the context set + */ + default void accept(@NonNull ContextSet contextSet) { + for (Map.Entry entry : contextSet) { + accept(entry.getKey(), entry.getValue()); + } + } } diff --git a/api/src/main/java/me/lucko/luckperms/api/context/ContextManager.java b/api/src/main/java/me/lucko/luckperms/api/context/ContextManager.java index 74a4167f9..d6351227a 100644 --- a/api/src/main/java/me/lucko/luckperms/api/context/ContextManager.java +++ b/api/src/main/java/me/lucko/luckperms/api/context/ContextManager.java @@ -25,8 +25,9 @@ package me.lucko.luckperms.api.context; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.User; +import me.lucko.luckperms.api.model.user.User; +import me.lucko.luckperms.api.query.QueryMode; +import me.lucko.luckperms.api.query.QueryOptions; import org.checkerframework.checker.nullness.qual.NonNull; @@ -50,8 +51,6 @@ import java.util.Optional; *
  • {@code cn.nukkit.Player}
  • *
  • {@code com.velocitypowered.api.proxy.Player}
  • * - * - * @since 4.0 */ public interface ContextManager { @@ -61,15 +60,7 @@ public interface ContextManager { * @param subject the subject * @return the applicable context for the subject */ - @NonNull ImmutableContextSet getApplicableContext(@NonNull Object subject); - - /** - * Queries the ContextManager for current context values for the subject. - * - * @param subject the subject - * @return the applicable context for the subject - */ - @NonNull Contexts getApplicableContexts(@NonNull Object subject); + @NonNull ImmutableContextSet getContext(@NonNull Object subject); /** * Queries the ContextManager for current context values for the given User. @@ -77,27 +68,14 @@ public interface ContextManager { *

    This will only return a value if the player corresponding to the * {@link User} is online.

    * - *

    If you need to be a {@link Contexts} instance regardless, you should - * initially try this method, and then fallback on {@link #getStaticContext()}.

    + *

    If you need to obtain a {@link ImmutableContextSet} instance + * regardless, you should initially try this method, and then fallback on + * {@link #getStaticContext()}.

    * * @param user the user * @return the applicable context for the subject */ - @NonNull Optional lookupApplicableContext(@NonNull User user); - - /** - * Queries the ContextManager for current context values for the given User. - * - *

    This will only return a value if the player corresponding to the - * {@link User} is online.

    - * - *

    If you need to be a {@link Contexts} instance regardless, you should - * initially try this method, and then fallback on {@link #getStaticContexts()}.

    - * - * @param user the user - * @return the applicable context for the subject - */ - @NonNull Optional lookupApplicableContexts(@NonNull User user); + @NonNull Optional lookupContext(@NonNull User user); /** * Gets the contexts from the static calculators in this manager. @@ -110,37 +88,64 @@ public interface ContextManager { @NonNull ImmutableContextSet getStaticContext(); /** - * Gets the contexts from the static calculators in this manager. + * Creates a new {@link QueryOptions.Builder}. * - *

    Static calculators provide the same context for all subjects, and are - * marked as such when registered.

    - * - * @return the current active static contexts + * @param mode the mode + * @return a new query options builder */ - @NonNull Contexts getStaticContexts(); + QueryOptions.@NonNull Builder queryOptionsBuilder(@NonNull QueryMode mode); /** - * Forms a {@link Contexts} instance from an {@link ImmutableContextSet}. + * Obtains current {@link QueryOptions} for the subject. + * + * @param subject the subject + * @return the query options for the subject + */ + @NonNull QueryOptions getQueryOptions(@NonNull Object subject); + + /** + * Obtains current {@link QueryOptions} for the given User. + * + *

    This will only return a value if the player corresponding to the + * {@link User} is online.

    + * + *

    If you need to obtain a {@link QueryOptions} instance regardless, you should + * initially try this method, and then fallback on {@link #getStaticQueryOptions()}.

    + * + * @param user the user + * @return the query options for the subject + */ + @NonNull Optional lookupQueryOptions(@NonNull User user); + + /** + * Gets the static query options, using the registered static context calculators. + * + * @return the current static query options + */ + @NonNull QueryOptions getStaticQueryOptions(); + + /** + * Forms a {@link QueryOptions} instance from an {@link ImmutableContextSet}. * *

    This method relies on the plugins configuration to form the - * {@link Contexts} instance.

    + * {@link QueryOptions} instance.

    * * @param subject the reference subject * @param contextSet the context set - * @return a contexts instance + * @return a options instance */ - @NonNull Contexts formContexts(@NonNull Object subject, @NonNull ImmutableContextSet contextSet); + @NonNull QueryOptions formQueryOptions(@NonNull Object subject, @NonNull ImmutableContextSet contextSet); /** - * Forms a {@link Contexts} instance from an {@link ImmutableContextSet}. + * Forms a {@link QueryOptions} instance from an {@link ImmutableContextSet}. * *

    This method relies on the plugins configuration to form the - * {@link Contexts} instance.

    + * {@link QueryOptions} instance.

    * * @param contextSet the context set - * @return a contexts instance + * @return a options instance */ - @NonNull Contexts formContexts(@NonNull ImmutableContextSet contextSet); + @NonNull QueryOptions formQueryOptions(@NonNull ImmutableContextSet contextSet); /** * Registers a context calculator with the manager. @@ -153,10 +158,17 @@ public interface ContextManager { * Unregisters a context calculator with the manager. * * @param calculator the calculator - * @since 4.4 */ void unregisterCalculator(@NonNull ContextCalculator calculator); + /** + * Gets the {@link ContextSetFactory}, responsible for creating + * {@link ContextSet} instances. + * + * @return the context set factory + */ + @NonNull ContextSetFactory getContextSetFactory(); + /** * Invalidates the lookup cache for a given subject * diff --git a/api/src/main/java/me/lucko/luckperms/api/context/ContextSet.java b/api/src/main/java/me/lucko/luckperms/api/context/ContextSet.java index 81f3fd8b3..03d69b55b 100644 --- a/api/src/main/java/me/lucko/luckperms/api/context/ContextSet.java +++ b/api/src/main/java/me/lucko/luckperms/api/context/ContextSet.java @@ -25,8 +25,6 @@ package me.lucko.luckperms.api.context; -import com.google.common.collect.Multimap; - import org.checkerframework.checker.nullness.qual.NonNull; import java.util.Iterator; @@ -58,94 +56,9 @@ import java.util.Set; *

    Two default ContextSet implementations are provided. * {@link MutableContextSet} allows the addition and removal of context keys * after construction, and {@link ImmutableContextSet} does not.

    - * - * @since 2.13 */ public interface ContextSet extends Iterable> { - /** - * Creates an {@link ImmutableContextSet} from a context pair. - * - * @param key the key - * @param value the value - * @return a new ImmutableContextSet containing one context pair - * @throws NullPointerException if key or value is null - */ - static @NonNull ImmutableContextSet singleton(@NonNull String key, @NonNull String value) { - return ImmutableContextSet.singleton(key, value); - } - - /** - * Creates an {@link ImmutableContextSet} from two context pairs. - * - * @param key1 the first key - * @param value1 the first value - * @param key2 the second key - * @param value2 the second value - * @return a new ImmutableContextSet containing the two pairs - * @throws NullPointerException if any of the keys or values are null - * @since 3.1 - */ - static @NonNull ImmutableContextSet of(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) { - return ImmutableContextSet.of(key1, value1, key2, value2); - } - - /** - * Creates an {@link ImmutableContextSet} from an existing {@link Iterable} of {@link Map.Entry}s. - * - * @param iterable the iterable to copy from - * @return a new ImmutableContextSet representing the pairs in the iterable - * @throws NullPointerException if the iterable is null - */ - static @NonNull ImmutableContextSet fromEntries(@NonNull Iterable> iterable) { - return ImmutableContextSet.fromEntries(iterable); - } - - /** - * Creates an {@link ImmutableContextSet} from an existing {@link Map}. - * - * @param map the map to copy from - * @return a new ImmutableContextSet representing the pairs from the map - * @throws NullPointerException if the map is null - */ - static @NonNull ImmutableContextSet fromMap(@NonNull Map map) { - return ImmutableContextSet.fromMap(map); - } - - /** - * Creates an {@link ImmutableContextSet} from an existing {@link Multimap}. - * - * @param multimap the multimap to copy from - * @return a new ImmutableContextSet representing the pairs in the multimap - * @throws NullPointerException if the multimap is null - * @since 2.16 - */ - static @NonNull ImmutableContextSet fromMultimap(@NonNull Multimap multimap) { - return ImmutableContextSet.fromMultimap(multimap); - } - - /** - * Creates an new {@link ImmutableContextSet} from an existing {@link Set}. - * - *

    Only really useful for converting between mutable and immutable types.

    - * - * @param contextSet the context set to copy from - * @return a new ImmutableContextSet with the same content and the one provided - * @throws NullPointerException if contextSet is null - */ - static @NonNull ImmutableContextSet fromSet(@NonNull ContextSet contextSet) { - return ImmutableContextSet.fromSet(contextSet); - } - - /** - * Returns an empty {@link ImmutableContextSet}. - * - * @return an empty ImmutableContextSet - */ - static @NonNull ImmutableContextSet empty() { - return ImmutableContextSet.empty(); - } - /** * Gets if this {@link ContextSet} is immutable. * @@ -163,7 +76,7 @@ public interface ContextSet extends Iterable> { * * @return an immutable representation of this set */ - @NonNull ImmutableContextSet makeImmutable(); + @NonNull ImmutableContextSet immutableCopy(); /** * Creates a mutable copy of this {@link ContextSet}. @@ -172,7 +85,6 @@ public interface ContextSet extends Iterable> { * {@link #isImmutable() mutability} of this set.

    * * @return a mutable ContextSet - * @since 2.16 */ @NonNull MutableContextSet mutableCopy(); @@ -187,6 +99,17 @@ public interface ContextSet extends Iterable> { */ @NonNull Set> toSet(); + /** + * Returns a {@link Map} representing the current state of this + * {@link ContextSet}. + * + *

    The returned set is immutable, and is a copy of the current set. + * (will not update live)

    + * + * @return a map + */ + @NonNull Map> toMap(); + /** * Returns a {@link Map} loosely representing the current state of * this {@link ContextSet}. @@ -197,27 +120,11 @@ public interface ContextSet extends Iterable> { *

    As a single context key can be mapped to multiple values, this method * may not be a true representation of the set.

    * - *

    If you need a representation of the set in a Java collection instance, - * use {@link #toSet()} or {@link #toMultimap()} followed by - * {@link Multimap#asMap()}.

    - * * @return an immutable map * @deprecated because the resultant map may not contain all data in the ContextSet */ @Deprecated - @NonNull Map toMap(); - - /** - * Returns a {@link Multimap} representing the current state of this - * {@link ContextSet}. - * - *

    The returned multimap is immutable, and is a copy of the current set. - * (will not update live)

    - * - * @return a multimap - * @since 2.16 - */ - @NonNull Multimap toMultimap(); + @NonNull Map toFlattenedMap(); /** * Returns an {@link Iterator} over each of the context pairs in this set. @@ -262,7 +169,6 @@ public interface ContextSet extends Iterable> { * * @param key the key to find values for * @return an optional containing any match - * @since 3.1 */ default @NonNull Optional getAnyValue(@NonNull String key) { return getValues(key).stream().findAny(); @@ -276,7 +182,7 @@ public interface ContextSet extends Iterable> { * @return true if the set contains the context pair * @throws NullPointerException if the key or value is null */ - boolean has(@NonNull String key, @NonNull String value); + boolean contains(@NonNull String key, @NonNull String value); /** * Returns if the {@link ContextSet} contains a given context pairing. @@ -285,9 +191,9 @@ public interface ContextSet extends Iterable> { * @return true if the set contains the context pair * @throws NullPointerException if the key or value is null */ - default boolean has(Map.@NonNull Entry entry) { + default boolean contains(Map.@NonNull Entry entry) { Objects.requireNonNull(entry, "entry"); - return has(entry.getKey(), entry.getValue()); + return contains(entry.getKey(), entry.getValue()); } /** @@ -300,7 +206,6 @@ public interface ContextSet extends Iterable> { * * @param other the other set to check * @return true if all entries in this set are also in the other set - * @since 3.1 */ default boolean isSatisfiedBy(@NonNull ContextSet other) { if (this == other) { @@ -320,7 +225,7 @@ public interface ContextSet extends Iterable> { } else { // neither are empty, we need to compare the individual entries for (Map.Entry context : toSet()) { - if (!other.has(context)) { + if (!other.contains(context)) { return false; } } diff --git a/api/src/main/java/me/lucko/luckperms/api/context/ContextSetFactory.java b/api/src/main/java/me/lucko/luckperms/api/context/ContextSetFactory.java new file mode 100644 index 000000000..b30a5cf91 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/context/ContextSetFactory.java @@ -0,0 +1,45 @@ +/* + * 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.api.context; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * A factory for creating {@link ContextSet}s. + */ +public interface ContextSetFactory { + + ImmutableContextSet.@NonNull Builder immutableBuilder(); + + @NonNull ImmutableContextSet immutableOf(@NonNull String key, @NonNull String value); + + @NonNull ImmutableContextSet immutableOf(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2); + + @NonNull ImmutableContextSet immutableEmpty(); + + @NonNull MutableContextSet mutable(); + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/context/DefaultContextKeys.java b/api/src/main/java/me/lucko/luckperms/api/context/DefaultContextKeys.java new file mode 100644 index 000000000..16506a6c1 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/context/DefaultContextKeys.java @@ -0,0 +1,44 @@ +/* + * 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.api.context; + +/** + * Some default context keys used by the plugin. + */ +public enum DefaultContextKeys { + ; + + /** + * The context key used to denote the subjects server. + */ + public static final String SERVER_KEY = "server"; + + /** + * The context key used to denote the subjects world. + */ + public static final String WORLD_KEY = "world"; + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/context/ImmutableContextSet.java b/api/src/main/java/me/lucko/luckperms/api/context/ImmutableContextSet.java index f1ee27967..35d8306a4 100644 --- a/api/src/main/java/me/lucko/luckperms/api/context/ImmutableContextSet.java +++ b/api/src/main/java/me/lucko/luckperms/api/context/ImmutableContextSet.java @@ -25,35 +25,26 @@ package me.lucko.luckperms.api.context; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSetMultimap; -import com.google.common.collect.Multimap; -import com.google.common.collect.SetMultimap; +import me.lucko.luckperms.api.LuckPermsProvider; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.Spliterator; /** * An immutable implementation of {@link ContextSet}. - * - * @since 2.16 */ -public final class ImmutableContextSet extends AbstractContextSet implements ContextSet { - private static final ImmutableContextSet EMPTY = new ImmutableContextSet(ImmutableSetMultimap.of()); +public interface ImmutableContextSet extends ContextSet { /** * Creates an {@link ImmutableContextSet.Builder}. * * @return a new ImmutableContextSet builder - * @since 4.1 */ - public static @NonNull Builder builder() { - return new Builder(); + static @NonNull Builder builder() { + return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableBuilder(); } /** @@ -64,8 +55,8 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con * @return a new ImmutableContextSet containing one context pair * @throws NullPointerException if key or value is null */ - public static @NonNull ImmutableContextSet singleton(@NonNull String key, @NonNull String value) { - return new ImmutableContextSet(ImmutableSetMultimap.of(sanitizeKey(key), sanitizeValue(value))); + static @NonNull ImmutableContextSet of(@NonNull String key, @NonNull String value) { + return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableOf(key, value); } /** @@ -77,15 +68,9 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con * @param value2 the second value * @return a new ImmutableContextSet containing the two pairs * @throws NullPointerException if any of the keys or values are null - * @since 3.1 */ - public static @NonNull ImmutableContextSet of(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) { - return new ImmutableContextSet(ImmutableSetMultimap.of( - sanitizeKey(key1), - sanitizeValue(value1), - sanitizeKey(key2), - sanitizeValue(value2) - )); + static @NonNull ImmutableContextSet of(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) { + return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableOf(key1, value1, key2, value2); } /** @@ -95,38 +80,15 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con * @return a new ImmutableContextSet representing the pairs in the iterable * @throws NullPointerException if the iterable is null */ - public static @NonNull ImmutableContextSet fromEntries(@NonNull Iterable> iterable) { + static @NonNull ImmutableContextSet fromEntries(@NonNull Iterable> iterable) { Objects.requireNonNull(iterable, "iterable"); - ImmutableContextSet.Builder builder = builder(); + Builder builder = builder(); for (Map.Entry entry : iterable) { builder.add(entry); } return builder.build(); } - /** - * Creates an {@link ImmutableContextSet} from an existing {@link Map}. - * - * @param map the map to copy from - * @return a new ImmutableContextSet representing the pairs from the map - * @throws NullPointerException if the map is null - */ - public static @NonNull ImmutableContextSet fromMap(@NonNull Map map) { - return fromEntries(Objects.requireNonNull(map, "map").entrySet()); - } - - /** - * Creates an {@link ImmutableContextSet} from an existing {@link Multimap}. - * - * @param multimap the multimap to copy from - * @return a new ImmutableContextSet representing the pairs in the multimap - * @throws NullPointerException if the multimap is null - * @since 2.16 - */ - public static @NonNull ImmutableContextSet fromMultimap(@NonNull Multimap multimap) { - return fromEntries(Objects.requireNonNull(multimap, "multimap").entries()); - } - /** * Creates an new {@link ImmutableContextSet} from an existing {@link Set}. * @@ -136,8 +98,8 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con * @return a new ImmutableContextSet with the same content and the one provided * @throws NullPointerException if contextSet is null */ - public static @NonNull ImmutableContextSet fromSet(@NonNull ContextSet contextSet) { - return Objects.requireNonNull(contextSet, "contextSet").makeImmutable(); + static @NonNull ImmutableContextSet fromSet(@NonNull ContextSet contextSet) { + return Objects.requireNonNull(contextSet, "contextSet").immutableCopy(); } /** @@ -145,128 +107,21 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con * * @return an empty ImmutableContextSet */ - public static @NonNull ImmutableContextSet empty() { - return EMPTY; - } - - private final ImmutableSetMultimap map; - private final int hashCode; - - ImmutableContextSet(ImmutableSetMultimap contexts) { - this.map = contexts; - this.hashCode = this.map.hashCode(); - } - - @Override - protected SetMultimap backing() { - return this.map; - } - - @Override - protected void copyTo(SetMultimap other) { - other.putAll(this.map); - } - - @Override - public boolean isImmutable() { - return true; - } - - @Deprecated - @Override // This set is already immutable! - public @NonNull ImmutableContextSet makeImmutable() { - return this; - } - - @Override - public @NonNull MutableContextSet mutableCopy() { - return MutableContextSet.fromSet(this); - } - - @Override - public @NonNull Set> toSet() { - return this.map.entries(); - } - - @Deprecated - @Override - public @NonNull Map toMap() { - ImmutableMap.Builder m = ImmutableMap.builder(); - for (Map.Entry e : this.map.entries()) { - m.put(e.getKey(), e.getValue()); - } - return m.build(); - } - - @Override - public @NonNull Multimap toMultimap() { - return this.map; - } - - @Override - public @NonNull Iterator> iterator() { - return this.map.entries().iterator(); - } - - @Override - public Spliterator> spliterator() { - return this.map.entries().spliterator(); - } - - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof ContextSet)) return false; - final ContextSet that = (ContextSet) o; - - // fast(er) path for ImmutableContextSet comparisons - if (that instanceof ImmutableContextSet) { - ImmutableContextSet immutableThat = (ImmutableContextSet) that; - if (this.hashCode != immutableThat.hashCode) return false; - } - - final Multimap thatBacking; - if (that instanceof AbstractContextSet) { - thatBacking = ((AbstractContextSet) that).backing(); - } else { - thatBacking = that.toMultimap(); - } - - return backing().equals(thatBacking); - } - - @Override - public int hashCode() { - return this.hashCode; - } - - @Override - public String toString() { - return "ImmutableContextSet(contexts=" + this.map + ")"; + static @NonNull ImmutableContextSet empty() { + return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableEmpty(); } /** - * A builder for {@link ImmutableContextSet}. - * - * @since 4.1 + * @deprecated Already immutable! */ - public static final class Builder { - private ImmutableSetMultimap.Builder builder; + @Override + @Deprecated + @NonNull ImmutableContextSet immutableCopy(); - private Builder() { - - } - - private synchronized ImmutableSetMultimap.Builder builder() { - if (this.builder == null) { - this.builder = ImmutableSetMultimap.builder(); - } - return this.builder; - } - - private void put(String key, String value) { - builder().put(key, value); - } + /** + * A builder for {@link ImmutableContextSet}. + */ + interface Builder { /** * Adds a context to the set. @@ -277,10 +132,7 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con * @throws NullPointerException if the key or value is null * @see MutableContextSet#add(String, String) */ - public @NonNull Builder add(@NonNull String key, @NonNull String value) { - put(sanitizeKey(key), sanitizeValue(value)); - return this; - } + @NonNull Builder add(@NonNull String key, @NonNull String value); /** * Adds a context to the set. @@ -290,7 +142,7 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con * @throws NullPointerException if the entry is null * @see MutableContextSet#add(Map.Entry) */ - public @NonNull Builder add(Map.@NonNull Entry entry) { + default @NonNull Builder add(Map.@NonNull Entry entry) { Objects.requireNonNull(entry, "entry"); add(entry.getKey(), entry.getValue()); return this; @@ -304,40 +156,13 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con * @throws NullPointerException if iterable is null * @see MutableContextSet#addAll(Iterable) */ - public @NonNull Builder addAll(@NonNull Iterable> iterable) { + default @NonNull Builder addAll(@NonNull Iterable> iterable) { for (Map.Entry e : Objects.requireNonNull(iterable, "iterable")) { add(e); } return this; } - /** - * Adds the contexts contained in the given {@link Map} to the set. - * - * @param map the map to add from - * @return the builder - * @throws NullPointerException if the map is null - * @see MutableContextSet#addAll(Map) - */ - public @NonNull Builder addAll(@NonNull Map map) { - addAll(Objects.requireNonNull(map, "map").entrySet()); - return this; - } - - /** - * Adds the contexts contained in the given {@link Multimap} to the set. - * - * @param multimap the multimap to add from - * @return the builder - * @throws NullPointerException if the map is null - * @since 3.4 - * @see MutableContextSet#addAll(Multimap) - */ - public @NonNull Builder addAll(@NonNull Multimap multimap) { - addAll(Objects.requireNonNull(multimap, "multimap").entries()); - return this; - } - /** * Adds of of the contexts in another {@link ContextSet} to the set. * @@ -346,18 +171,7 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con * @throws NullPointerException if the contextSet is null * @see MutableContextSet#addAll(ContextSet) */ - public @NonNull Builder addAll(@NonNull ContextSet contextSet) { - Objects.requireNonNull(contextSet, "contextSet"); - if (contextSet instanceof AbstractContextSet) { - AbstractContextSet other = ((AbstractContextSet) contextSet); - if (!other.isEmpty()) { - builder().putAll(other.backing()); - } - } else { - addAll(contextSet.toMultimap()); - } - return this; - } + @NonNull Builder addAll(@NonNull ContextSet contextSet); /** * Creates a {@link ImmutableContextSet} from the values previously @@ -365,12 +179,6 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con * * @return an {@link ImmutableContextSet} from the builder */ - public @NonNull ImmutableContextSet build() { - if (this.builder == null) { - return empty(); - } else { - return new ImmutableContextSet(this.builder.build()); - } - } + @NonNull ImmutableContextSet build(); } } diff --git a/api/src/main/java/me/lucko/luckperms/api/context/MutableContextSet.java b/api/src/main/java/me/lucko/luckperms/api/context/MutableContextSet.java index 6ec0f415f..851ee4b1d 100644 --- a/api/src/main/java/me/lucko/luckperms/api/context/MutableContextSet.java +++ b/api/src/main/java/me/lucko/luckperms/api/context/MutableContextSet.java @@ -25,28 +25,18 @@ package me.lucko.luckperms.api.context; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSetMultimap; -import com.google.common.collect.Multimap; -import com.google.common.collect.Multimaps; -import com.google.common.collect.SetMultimap; +import me.lucko.luckperms.api.LuckPermsProvider; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.Spliterator; /** * A mutable implementation of {@link ContextSet}. - * - * @since 2.16 */ -public final class MutableContextSet extends AbstractContextSet implements ContextSet { +public interface MutableContextSet extends ContextSet { /** * Creates a {@link MutableContextSet} from a context pair. @@ -56,10 +46,10 @@ public final class MutableContextSet extends AbstractContextSet implements Conte * @return a new MutableContextSet containing one context pair * @throws NullPointerException if key or value is null */ - public static @NonNull MutableContextSet singleton(@NonNull String key, @NonNull String value) { + static @NonNull MutableContextSet of(@NonNull String key, @NonNull String value) { Objects.requireNonNull(key, "key"); Objects.requireNonNull(value, "value"); - MutableContextSet set = MutableContextSet.create(); + MutableContextSet set = create(); set.add(key, value); return set; } @@ -73,9 +63,8 @@ public final class MutableContextSet extends AbstractContextSet implements Conte * @param value2 the second value * @return a new MutableContextSet containing the two pairs * @throws NullPointerException if any of the keys or values are null - * @since 3.1 */ - public static @NonNull MutableContextSet of(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) { + static @NonNull MutableContextSet of(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) { Objects.requireNonNull(key1, "key1"); Objects.requireNonNull(value1, "value1"); Objects.requireNonNull(key2, "key2"); @@ -93,42 +82,13 @@ public final class MutableContextSet extends AbstractContextSet implements Conte * @return a new MutableContextSet representing the pairs in the iterable * @throws NullPointerException if the iterable is null */ - public static @NonNull MutableContextSet fromEntries(@NonNull Iterable> iterable) { + static @NonNull MutableContextSet fromEntries(@NonNull Iterable> iterable) { Objects.requireNonNull(iterable, "iterable"); MutableContextSet set = create(); set.addAll(iterable); return set; } - /** - * Creates a {@link MutableContextSet} from an existing {@link Map}. - * - * @param map the map to copy from - * @return a new MutableContextSet representing the pairs from the map - * @throws NullPointerException if the map is null - */ - public static @NonNull MutableContextSet fromMap(@NonNull Map map) { - Objects.requireNonNull(map, "map"); - MutableContextSet set = create(); - set.addAll(map); - return set; - } - - /** - * Creates a {@link MutableContextSet} from an existing {@link Multimap}. - * - * @param multimap the multimap to copy from - * @return a new MutableContextSet representing the pairs in the multimap - * @throws NullPointerException if the multimap is null - * @since 2.16 - */ - public static @NonNull MutableContextSet fromMultimap(@NonNull Multimap multimap) { - Objects.requireNonNull(multimap, "multimap"); - MutableContextSet set = create(); - set.addAll(multimap); - return set; - } - /** * Creates a new {@link MutableContextSet} from an existing {@link Set}. * @@ -138,19 +98,8 @@ public final class MutableContextSet extends AbstractContextSet implements Conte * @return a new MutableContextSet with the same content and the one provided * @throws NullPointerException if contextSet is null */ - public static @NonNull MutableContextSet fromSet(@NonNull ContextSet contextSet) { - Objects.requireNonNull(contextSet, "contextSet"); - - if (contextSet instanceof ImmutableContextSet) { - SetMultimap map = ((ImmutableContextSet) contextSet).backing(); - return new MutableContextSet(map); - } else if (contextSet instanceof MutableContextSet) { - return contextSet.mutableCopy(); - } else { - MutableContextSet set = create(); - set.addAll(contextSet); - return set; - } + static @NonNull MutableContextSet fromSet(@NonNull ContextSet contextSet) { + return contextSet.mutableCopy(); } /** @@ -158,90 +107,8 @@ public final class MutableContextSet extends AbstractContextSet implements Conte * * @return a new MutableContextSet */ - public static @NonNull MutableContextSet create() { - return new MutableContextSet(); - } - - private final SetMultimap map; - - public MutableContextSet() { - this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create()); - } - - private MutableContextSet(SetMultimap other) { - this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create(other)); - } - - @Override - protected SetMultimap backing() { - return this.map; - } - - @Override - protected void copyTo(SetMultimap other) { - synchronized (this.map) { - other.putAll(this.map); - } - } - - @Override - public boolean isImmutable() { - return false; - } - - @Override - public @NonNull ImmutableContextSet makeImmutable() { - // if the map is empty, don't create a new instance - if (this.map.isEmpty()) { - return ImmutableContextSet.empty(); - } - synchronized (this.map) { - return new ImmutableContextSet(ImmutableSetMultimap.copyOf(this.map)); - } - } - - @Override - public @NonNull MutableContextSet mutableCopy() { - synchronized (this.map) { - return new MutableContextSet(this.map); - } - } - - @Override - public @NonNull Set> toSet() { - synchronized (this.map) { - // map.entries() returns immutable Map.Entry instances, so we can just call copyOf - return ImmutableSet.copyOf(this.map.entries()); - } - } - - @Deprecated - @Override - public @NonNull Map toMap() { - ImmutableMap.Builder m = ImmutableMap.builder(); - synchronized (this.map) { - for (Map.Entry e : this.map.entries()) { - m.put(e.getKey(), e.getValue()); - } - } - return m.build(); - } - - @Override - public @NonNull Multimap toMultimap() { - synchronized (this.map) { - return ImmutableSetMultimap.copyOf(this.map); - } - } - - @Override - public @NonNull Iterator> iterator() { - return toSet().iterator(); - } - - @Override - public Spliterator> spliterator() { - return toSet().spliterator(); + static @NonNull MutableContextSet create() { + return LuckPermsProvider.get().getContextManager().getContextSetFactory().mutable(); } /** @@ -251,9 +118,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte * @param value the value to add * @throws NullPointerException if the key or value is null */ - public void add(@NonNull String key, @NonNull String value) { - this.map.put(sanitizeKey(key), sanitizeValue(value)); - } + void add(@NonNull String key, @NonNull String value); /** * Adds a context to this set. @@ -261,7 +126,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte * @param entry the entry to add * @throws NullPointerException if the entry is null */ - public void add(Map.@NonNull Entry entry) { + default void add(Map.@NonNull Entry entry) { Objects.requireNonNull(entry, "entry"); add(entry.getKey(), entry.getValue()); } @@ -272,50 +137,19 @@ public final class MutableContextSet extends AbstractContextSet implements Conte * @param iterable an iterable of key value context pairs * @throws NullPointerException if iterable is null */ - public void addAll(@NonNull Iterable> iterable) { + default void addAll(@NonNull Iterable> iterable) { for (Map.Entry e : Objects.requireNonNull(iterable, "iterable")) { add(e); } } - /** - * Adds the contexts contained in the given {@link Map} to this set. - * - * @param map the map to add from - * @throws NullPointerException if the map is null - */ - public void addAll(@NonNull Map map) { - addAll(Objects.requireNonNull(map, "map").entrySet()); - } - - /** - * Adds the contexts contained in the given {@link Multimap} to this set. - * - * @param multimap the multimap to add from - * @throws NullPointerException if the map is null - * @since 3.4 - */ - public void addAll(@NonNull Multimap multimap) { - addAll(Objects.requireNonNull(multimap, "multimap").entries()); - } - /** * Adds of of the contexts in another {@link ContextSet} to this set. * * @param contextSet the set to add from * @throws NullPointerException if the contextSet is null */ - public void addAll(@NonNull ContextSet contextSet) { - Objects.requireNonNull(contextSet, "contextSet"); - if (contextSet instanceof AbstractContextSet) { - AbstractContextSet other = ((AbstractContextSet) contextSet); - synchronized (this.map) { - other.copyTo(this.map); - } - } else { - addAll(contextSet.toMultimap()); - } - } + void addAll(@NonNull ContextSet contextSet); /** * Removes a context from this set. @@ -324,9 +158,7 @@ public final class MutableContextSet extends AbstractContextSet implements Conte * @param value the value to remove * @throws NullPointerException if the key or value is null */ - public void remove(@NonNull String key, @NonNull String value) { - this.map.remove(sanitizeKey(key), sanitizeValue(value)); - } + void remove(@NonNull String key, @NonNull String value); /** * Removes all contexts from this set with the given key. @@ -334,35 +166,11 @@ public final class MutableContextSet extends AbstractContextSet implements Conte * @param key the key to remove * @throws NullPointerException if the key is null */ - public void removeAll(@NonNull String key) { - this.map.removeAll(sanitizeKey(key)); - } + void removeAll(@NonNull String key); /** * Removes all contexts from the set. */ - public void clear() { - this.map.clear(); - } + void clear(); - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof ContextSet)) return false; - final ContextSet that = (ContextSet) o; - - final Multimap thatBacking; - if (that instanceof AbstractContextSet) { - thatBacking = ((AbstractContextSet) that).backing(); - } else { - thatBacking = that.toMultimap(); - } - - return backing().equals(thatBacking); - } - - @Override - public String toString() { - return "MutableContextSet(contexts=" + this.map + ")"; - } } diff --git a/api/src/main/java/me/lucko/luckperms/api/context/StaticContextCalculator.java b/api/src/main/java/me/lucko/luckperms/api/context/StaticContextCalculator.java index de4fb8a99..53afa5246 100644 --- a/api/src/main/java/me/lucko/luckperms/api/context/StaticContextCalculator.java +++ b/api/src/main/java/me/lucko/luckperms/api/context/StaticContextCalculator.java @@ -26,36 +26,50 @@ package me.lucko.luckperms.api.context; import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Objects; +import java.util.function.Supplier; /** * Extension of {@link ContextCalculator} which provides the same context * regardless of the subject. - * - * @since 4.0 */ @FunctionalInterface public interface StaticContextCalculator extends ContextCalculator { /** - * Adds this calculators context to the given accumulator. + * Creates a new {@link StaticContextCalculator} that provides a single context. * - * @param accumulator a map of contexts to add to - * @return the map + * @param key the key of the context provided by the calculator + * @param valueFunction the function used to compute the corresponding value + * for each query. A context will not be "accumulated" + * if the value returned is null. + * @return the resultant calculator */ - @NonNull MutableContextSet giveApplicableContext(@NonNull MutableContextSet accumulator); - - /** - * Gives the subject all of the applicable contexts they meet - * - * @param subject the subject to add contexts to - * @param accumulator a map of contexts to add to - * @return the map - */ - @Deprecated - @Override - default @NonNull MutableContextSet giveApplicableContext(@Nullable Object subject, @NonNull MutableContextSet accumulator) { - return giveApplicableContext(accumulator); + static StaticContextCalculator forSingleContext(String key, Supplier valueFunction) { + Objects.requireNonNull(key, "key"); + Objects.requireNonNull(valueFunction, "valueFunction"); + return consumer -> { + String value = valueFunction.get(); + if (value != null) { + consumer.accept(key, value); + } + }; } + /** + * Submits any contexts this calculator determines to be applicable. + * + *

    Care should be taken to ensure implementations of this method meet the + * general requirements for {@link ContextCalculator}, defined in the class + * doc.

    + * + * @param consumer the {@link ContextConsumer} to submit contexts to + */ + void giveApplicableContext(@NonNull ContextConsumer consumer); + + @Override + default void giveApplicableContext(@NonNull Object target, @NonNull ContextConsumer consumer) { + giveApplicableContext(consumer); + } } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/Cancellable.java b/api/src/main/java/me/lucko/luckperms/api/event/Cancellable.java index a63e8e4af..5b8a655c1 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/Cancellable.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/Cancellable.java @@ -39,13 +39,13 @@ public interface Cancellable { * * @return the cancellation */ - @NonNull @Param(-1) AtomicBoolean getCancellationState(); + @Param(-1) + @NonNull AtomicBoolean getCancellationState(); /** * Returns true if the event is currently cancelled. * * @return if the event is cancelled - * @since 4.1 */ default boolean isCancelled() { return getCancellationState().get(); @@ -55,7 +55,6 @@ public interface Cancellable { * Returns true if the event is not currently cancelled. * * @return if the event is not cancelled - * @since 4.1 */ default boolean isNotCancelled() { return !isCancelled(); @@ -66,7 +65,6 @@ public interface Cancellable { * * @param cancelled the new state * @return the previous state - * @since 4.1 */ default boolean setCancelled(boolean cancelled) { return getCancellationState().getAndSet(cancelled); diff --git a/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java b/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java index 0dffe5fe6..4f9578242 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java @@ -34,15 +34,13 @@ import java.util.function.Consumer; * The LuckPerms event bus. * *

    Used to subscribe (or "listen") to LuckPerms events.

    - * - * @since 3.0 */ public interface EventBus { /** * Registers a new subscription to the given event. * - *

    The returned {@link EventHandler} instance encapsulates the subscription state. It has + *

    The returned {@link EventSubscription} instance encapsulates the subscription state. It has * methods which can be used to terminate the subscription, or view stats about the nature of * the subscription.

    * @@ -51,18 +49,18 @@ public interface EventBus { * @param the event class * @return an event handler instance representing this subscription */ - @NonNull EventHandler subscribe(@NonNull Class eventClass, @NonNull Consumer handler); + @NonNull EventSubscription subscribe(@NonNull Class eventClass, @NonNull Consumer handler); /** * Registers a new subscription to the given event. * - *

    The returned {@link EventHandler} instance encapsulates the subscription state. It has + *

    The returned {@link EventSubscription} instance encapsulates the subscription state. It has * methods which can be used to terminate the subscription, or view stats about the nature of * the subscription.

    * *

    Unlike {@link #subscribe(Class, Consumer)}, this method accepts an additional parameter * for {@code plugin}. This object must be a "plugin" instance on the platform, and is used to - * automatically {@link EventHandler#unregister() unregister} the subscription when the + * automatically {@link EventSubscription#close() unregister} the subscription when the * corresponding plugin is disabled.

    * * @param the event class @@ -71,7 +69,7 @@ public interface EventBus { * @param handler the event handler * @return an event handler instance representing this subscription */ - @NonNull EventHandler subscribe(Object plugin, @NonNull Class eventClass, @NonNull Consumer handler); + @NonNull EventSubscription subscribe(Object plugin, @NonNull Class eventClass, @NonNull Consumer handler); /** * Gets a set of all registered handlers for a given event. @@ -80,6 +78,6 @@ public interface EventBus { * @param the event class * @return an immutable set of event handlers */ - @NonNull Set> getHandlers(@NonNull Class eventClass); + @NonNull Set> getSubscriptions(@NonNull Class eventClass); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java b/api/src/main/java/me/lucko/luckperms/api/event/EventSubscription.java similarity index 79% rename from api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java rename to api/src/main/java/me/lucko/luckperms/api/event/EventSubscription.java index 4b77721aa..d6288e22c 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/EventSubscription.java @@ -34,7 +34,7 @@ import java.util.function.Consumer; * * @param the event class */ -public interface EventHandler extends AutoCloseable { +public interface EventSubscription extends AutoCloseable { /** * Gets the class this handler is listening to @@ -51,28 +51,15 @@ public interface EventHandler extends AutoCloseable { boolean isActive(); /** - * Unregisters this handler from the event bus - * - * @return true if the handler wasn't already unregistered + * Unregisters this handler from the event bus. */ - boolean unregister(); + @Override + void close(); /** * Gets the event consumer responsible for handling the event * * @return the event consumer */ - @NonNull Consumer getConsumer(); - - /** - * Gets the number of times this handler has been called - * - * @return the number of times this handler has been called - */ - int getCallCount(); - - @Override - default void close() { - unregister(); - } + @NonNull Consumer getHandler(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/LuckPermsEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/LuckPermsEvent.java index 638871c4f..77f0ed714 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/LuckPermsEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/LuckPermsEvent.java @@ -25,14 +25,12 @@ package me.lucko.luckperms.api.event; -import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.LuckPerms; import org.checkerframework.checker.nullness.qual.NonNull; /** * A superinterface for all LuckPerms events. - * - * @since 3.0 */ public interface LuckPermsEvent { @@ -41,13 +39,12 @@ public interface LuckPermsEvent { * * @return the api instance */ - @NonNull LuckPermsApi getApi(); + @NonNull LuckPerms getLuckPerms(); /** * Gets the type of the event. * * @return the type of the event - * @since 4.4 */ @NonNull Class getEventType(); diff --git a/api/src/main/java/me/lucko/luckperms/api/event/Sourced.java b/api/src/main/java/me/lucko/luckperms/api/event/Sourced.java index 921167360..ab7ae04f7 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/Sourced.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/Sourced.java @@ -31,8 +31,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; /** * Represents an event with a {@link Source}. - * - * @since 4.1 */ public interface Sourced { diff --git a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCacheLoadEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCacheLoadEvent.java index e4055736f..b30ca3a25 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCacheLoadEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCacheLoadEvent.java @@ -25,17 +25,15 @@ package me.lucko.luckperms.api.event.group; -import me.lucko.luckperms.api.Group; -import me.lucko.luckperms.api.caching.GroupData; +import me.lucko.luckperms.api.cacheddata.CachedDataManager; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.model.group.Group; import org.checkerframework.checker.nullness.qual.NonNull; /** - * Called when a groups {@link GroupData} is loaded. - * - * @since 4.0 + * Called when a groups {@link CachedDataManager} is loaded. */ public interface GroupCacheLoadEvent extends LuckPermsEvent { @@ -44,13 +42,15 @@ public interface GroupCacheLoadEvent extends LuckPermsEvent { * * @return the group */ - @NonNull @Param(0) Group getGroup(); + @Param(0) + @NonNull Group getGroup(); /** * Gets the data that was loaded * * @return the loaded data */ - @NonNull @Param(1) GroupData getLoadedData(); + @Param(1) + @NonNull CachedDataManager getLoadedData(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCreateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCreateEvent.java index 11015d2f6..d70d3f679 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCreateEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupCreateEvent.java @@ -25,10 +25,10 @@ package me.lucko.luckperms.api.event.group; -import me.lucko.luckperms.api.Group; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; import me.lucko.luckperms.api.event.cause.CreationCause; +import me.lucko.luckperms.api.model.group.Group; import org.checkerframework.checker.nullness.qual.NonNull; @@ -42,13 +42,15 @@ public interface GroupCreateEvent extends LuckPermsEvent { * * @return the new group */ - @NonNull @Param(0) Group getGroup(); + @Param(0) + @NonNull Group getGroup(); /** * Gets the cause of the creation * * @return the cause of the creation */ - @NonNull @Param(1) CreationCause getCause(); + @Param(1) + @NonNull CreationCause getCause(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDataRecalculateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDataRecalculateEvent.java index f402f2d72..c018b2b1c 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDataRecalculateEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDataRecalculateEvent.java @@ -25,17 +25,15 @@ package me.lucko.luckperms.api.event.group; -import me.lucko.luckperms.api.Group; -import me.lucko.luckperms.api.caching.GroupData; +import me.lucko.luckperms.api.cacheddata.CachedDataManager; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.model.group.Group; import org.checkerframework.checker.nullness.qual.NonNull; /** * Called when a groups cached data is refreshed - * - * @since 4.0 */ public interface GroupDataRecalculateEvent extends LuckPermsEvent { @@ -44,13 +42,15 @@ public interface GroupDataRecalculateEvent extends LuckPermsEvent { * * @return the group */ - @NonNull @Param(0) Group getGroup(); + @Param(0) + @NonNull Group getGroup(); /** * Gets the data that was recalculated * * @return the data */ - @NonNull @Param(1) GroupData getData(); + @Param(1) + @NonNull CachedDataManager getData(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDeleteEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDeleteEvent.java index 2f99dee79..047f8dad5 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDeleteEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupDeleteEvent.java @@ -25,10 +25,10 @@ package me.lucko.luckperms.api.event.group; -import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; import me.lucko.luckperms.api.event.cause.DeletionCause; +import me.lucko.luckperms.api.node.Node; import org.checkerframework.checker.nullness.qual.NonNull; @@ -44,20 +44,23 @@ public interface GroupDeleteEvent extends LuckPermsEvent { * * @return the name of the deleted group */ - @NonNull @Param(0) String getGroupName(); + @Param(0) + @NonNull String getGroupName(); /** * Gets an immutable copy of the groups existing data * * @return a copy of the groups existing data */ - @NonNull @Param(1) Set getExistingData(); + @Param(1) + @NonNull Set getExistingData(); /** * Gets the cause of the deletion * * @return the cause of the deletion */ - @NonNull @Param(2) DeletionCause getCause(); + @Param(2) + @NonNull DeletionCause getCause(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupLoadEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupLoadEvent.java index 5a70d9338..c5f661464 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/group/GroupLoadEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/group/GroupLoadEvent.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.api.event.group; -import me.lucko.luckperms.api.Group; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.model.group.Group; import org.checkerframework.checker.nullness.qual.NonNull; @@ -43,6 +43,7 @@ public interface GroupLoadEvent extends LuckPermsEvent { * * @return the group that was loaded */ - @NonNull @Param(0) Group getGroup(); + @Param(0) + @NonNull Group getGroup(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java index 10b1838af..25defa791 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogBroadcastEvent.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.api.event.log; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.Cancellable; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; @@ -42,20 +42,19 @@ public interface LogBroadcastEvent extends LuckPermsEvent, Cancellable { * * @return the log entry to be broadcasted */ - @NonNull @Param(0) LogEntry getEntry(); + @Param(0) + @NonNull Action getEntry(); /** * Gets where the log entry originated from. * * @return the origin of the log - * @since 3.3 */ - @NonNull @Param(1) Origin getOrigin(); + @Param(1) + @NonNull Origin getOrigin(); /** * Represents where a log entry is from - * - * @since 3.3 */ enum Origin { diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java index 54beca9eb..fd54ca173 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogNetworkPublishEvent.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.api.event.log; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.Cancellable; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; @@ -36,8 +36,6 @@ import java.util.UUID; /** * Called when a log is about to be published to the network via the MessagingService - * - * @since 3.3 */ public interface LogNetworkPublishEvent extends LuckPermsEvent, Cancellable { @@ -46,13 +44,15 @@ public interface LogNetworkPublishEvent extends LuckPermsEvent, Cancellable { * * @return the id of the log entry being published */ - @NonNull @Param(0) UUID getLogId(); + @Param(0) + @NonNull UUID getLogId(); /** * Gets the log entry to be published * * @return the log entry to be published */ - @NonNull @Param(1) LogEntry getEntry(); + @Param(1) + @NonNull Action getEntry(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogNotifyEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogNotifyEvent.java index 10ebcda08..cef8a538b 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogNotifyEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogNotifyEvent.java @@ -25,11 +25,11 @@ package me.lucko.luckperms.api.event.log; -import me.lucko.luckperms.api.Entity; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.Cancellable; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.platform.PlatformEntity; import org.checkerframework.checker.nullness.qual.NonNull; @@ -40,8 +40,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; *

    This event is not called for players without the notify permission, * but is called for objects which are ignoring log notifications (called with * the cancelled flag set to true).

    - * - * @since 4.1 */ public interface LogNotifyEvent extends LuckPermsEvent, Cancellable { @@ -50,21 +48,24 @@ public interface LogNotifyEvent extends LuckPermsEvent, Cancellable { * * @return the log entry to be sent */ - @NonNull @Param(0) LogEntry getEntry(); + @Param(0) + @NonNull Action getEntry(); /** * Gets where the log entry originated from. * * @return the origin of the log */ - @NonNull @Param(1) Origin getOrigin(); + @Param(1) + @NonNull Origin getOrigin(); /** * Gets the object to be notified. * * @return the object to notify */ - @NonNull @Param(2) Entity getNotifiable(); + @Param(2) + @NonNull PlatformEntity getNotifiable(); /** * Represents where a log entry is from diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogPublishEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogPublishEvent.java index dd777ca2a..f746b1738 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogPublishEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogPublishEvent.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.api.event.log; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.Cancellable; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; @@ -42,6 +42,7 @@ public interface LogPublishEvent extends LuckPermsEvent, Cancellable { * * @return the log entry to be published */ - @NonNull @Param(0) LogEntry getEntry(); + @Param(0) + @NonNull Action getEntry(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java index a29bb9ac7..40eee6f27 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/log/LogReceiveEvent.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.api.event.log; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; @@ -35,8 +35,6 @@ import java.util.UUID; /** * Called when a log entry is received via the MessagingService - * - * @since 3.3 */ public interface LogReceiveEvent extends LuckPermsEvent { @@ -45,13 +43,15 @@ public interface LogReceiveEvent extends LuckPermsEvent { * * @return the id of the log entry being received */ - @NonNull @Param(0) UUID getLogId(); + @Param(0) + @NonNull UUID getLogId(); /** * Gets the log entry being received * * @return the log entry being received */ - @NonNull @Param(1) LogEntry getEntry(); + @Param(1) + @NonNull Action getEntry(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeAddEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeAddEvent.java index 23f0df5ad..0ceba5248 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeAddEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeAddEvent.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.api.event.node; -import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.node.Node; import org.checkerframework.checker.nullness.qual.NonNull; @@ -40,6 +40,7 @@ public interface NodeAddEvent extends NodeMutateEvent { * * @return the node that was added */ - @NonNull @Param(3) Node getNode(); + @Param(3) + @NonNull Node getNode(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeMutateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeMutateEvent.java index de4f49757..4ccb9da31 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeMutateEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeMutateEvent.java @@ -25,12 +25,12 @@ package me.lucko.luckperms.api.event.node; -import me.lucko.luckperms.api.Group; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.PermissionHolder; -import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.model.PermissionHolder; +import me.lucko.luckperms.api.model.group.Group; +import me.lucko.luckperms.api.model.user.User; +import me.lucko.luckperms.api.node.Node; import org.checkerframework.checker.nullness.qual.NonNull; @@ -46,24 +46,27 @@ public interface NodeMutateEvent extends LuckPermsEvent { * * @return the event target */ - @NonNull @Param(0) PermissionHolder getTarget(); + @Param(0) + @NonNull PermissionHolder getTarget(); /** * Gets an immutable copy of the holders data before the change * * @return the data before the change */ - @NonNull @Param(1) Set getDataBefore(); + @Param(1) + @NonNull Set getDataBefore(); /** * Gets an immutable copy of the holders data after the change * * @return the data after the change */ - @NonNull @Param(2) Set getDataAfter(); + @Param(2) + @NonNull Set getDataAfter(); /** - * Gets whether the target of this event is a {@link me.lucko.luckperms.api.User} + * Gets whether the target of this event is a {@link User} * *

    This is equivalent to checking if getTarget() instanceof User

    * @@ -74,7 +77,7 @@ public interface NodeMutateEvent extends LuckPermsEvent { } /** - * Gets whether the target of this event is a {@link me.lucko.luckperms.api.Group} + * Gets whether the target of this event is a {@link Group} * *

    This is equivalent to checking if getTarget() instanceof Group

    * diff --git a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeRemoveEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeRemoveEvent.java index 62222e3c1..68b6777cc 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/node/NodeRemoveEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/node/NodeRemoveEvent.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.api.event.node; -import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.node.Node; import org.checkerframework.checker.nullness.qual.NonNull; @@ -40,6 +40,7 @@ public interface NodeRemoveEvent extends NodeMutateEvent { * * @return the node that was removed */ - @NonNull @Param(3) Node getNode(); + @Param(3) + @NonNull Node getNode(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerDataSaveEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerDataSaveEvent.java index af0a03238..8a7609f2d 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerDataSaveEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerDataSaveEvent.java @@ -25,10 +25,10 @@ package me.lucko.luckperms.api.event.player; -import me.lucko.luckperms.api.PlayerSaveResult; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; -import me.lucko.luckperms.api.manager.UserManager; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.model.user.UserManager; import org.checkerframework.checker.nullness.qual.NonNull; @@ -38,8 +38,6 @@ import java.util.UUID; * Called when player data is saved to the storage. * *

    Data can be saved using {@link UserManager#savePlayerData(UUID, String)}.

    - * - * @since 4.3 */ public interface PlayerDataSaveEvent extends LuckPermsEvent { @@ -48,20 +46,23 @@ public interface PlayerDataSaveEvent extends LuckPermsEvent { * * @return the uuid */ - @NonNull @Param(0) UUID getUuid(); + @Param(0) + @NonNull UUID getUniqueId(); /** * Gets the username that was saved. * * @return the username */ - @NonNull @Param(1) String getUsername(); + @Param(1) + @NonNull String getUsername(); /** * Gets the result of the operation. * * @return the result */ - @NonNull @Param(2) PlayerSaveResult getResult(); + @Param(2) + @NonNull PlayerSaveResult getResult(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerLoginProcessEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerLoginProcessEvent.java index 9bc5c2d44..e6673df2e 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerLoginProcessEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/player/PlayerLoginProcessEvent.java @@ -25,9 +25,10 @@ package me.lucko.luckperms.api.event.player; -import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.model.user.User; +import me.lucko.luckperms.api.util.Result; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -49,30 +50,31 @@ import java.util.UUID; * for all connections, even if the operation to load User data was not * successful. Note that LuckPerms will usually cancel the platform connection * event if data could not be loaded.

    - * - * @since 4.4 */ -public interface PlayerLoginProcessEvent extends LuckPermsEvent { +public interface PlayerLoginProcessEvent extends LuckPermsEvent, Result { /** * Gets the UUID of the connection which was processed * * @return the uuid of the connection which was processed */ - @NonNull @Param(0) UUID getUuid(); + @Param(0) + @NonNull UUID getUniqueId(); /** * Gets the username of the connection which was processed * * @return the username of the connection which was processed */ - @NonNull @Param(1) String getUsername(); + @Param(1) + @NonNull String getUsername(); /** * Gets if the login was processed successfully. * * @return true if the login was successful */ + @Override default boolean wasSuccessful() { return getUser() != null; } @@ -85,6 +87,7 @@ public interface PlayerLoginProcessEvent extends LuckPermsEvent { * * @return the user instance */ - @Nullable @Param(2) User getUser(); + @Param(2) + @Nullable User getUser(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/source/EntitySource.java b/api/src/main/java/me/lucko/luckperms/api/event/source/EntitySource.java index d319a3ba0..2d1e7a136 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/source/EntitySource.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/source/EntitySource.java @@ -25,14 +25,12 @@ package me.lucko.luckperms.api.event.source; -import me.lucko.luckperms.api.Entity; +import me.lucko.luckperms.api.platform.PlatformEntity; import org.checkerframework.checker.nullness.qual.NonNull; /** - * Represents an {@link Entity} which was the {@link Source} of something. - * - * @since 4.1 + * Represents an {@link PlatformEntity} which was the {@link Source} of something. */ public interface EntitySource extends Source { @@ -41,6 +39,6 @@ public interface EntitySource extends Source { * * @return the entity */ - @NonNull Entity getEntity(); + @NonNull PlatformEntity getEntity(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/source/Source.java b/api/src/main/java/me/lucko/luckperms/api/event/source/Source.java index 77456e10a..e49b58ef0 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/source/Source.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/source/Source.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.api.event.source; -import me.lucko.luckperms.api.Entity; +import me.lucko.luckperms.api.platform.PlatformEntity; import org.checkerframework.checker.nullness.qual.NonNull; @@ -33,8 +33,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; * Represents the source of an event. * *

    Could also be described as the "thing" that caused an event to occur.

    - * - * @since 4.1 */ public interface Source { @@ -51,7 +49,7 @@ public interface Source { enum Type { /** - * Represents an {@link Entity} source + * Represents an {@link PlatformEntity} source * * @see EntitySource */ diff --git a/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java index dab6487f0..6b596c52b 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/sync/PreNetworkSyncEvent.java @@ -43,6 +43,7 @@ public interface PreNetworkSyncEvent extends LuckPermsEvent, Cancellable { * * @return the id of the sync request */ - @NonNull @Param(0) UUID getSyncId(); + @Param(0) + @NonNull UUID getSyncId(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackCreateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackCreateEvent.java index 77e7b5225..3c04da10c 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackCreateEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackCreateEvent.java @@ -25,10 +25,10 @@ package me.lucko.luckperms.api.event.track; -import me.lucko.luckperms.api.Track; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; import me.lucko.luckperms.api.event.cause.CreationCause; +import me.lucko.luckperms.api.track.Track; import org.checkerframework.checker.nullness.qual.NonNull; @@ -42,13 +42,15 @@ public interface TrackCreateEvent extends LuckPermsEvent { * * @return the new track */ - @NonNull @Param(0) Track getTrack(); + @Param(0) + @NonNull Track getTrack(); /** * Gets the cause of the creation * * @return the cause of the creation */ - @NonNull @Param(1) CreationCause getCause(); + @Param(1) + @NonNull CreationCause getCause(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackDeleteEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackDeleteEvent.java index 10d7fb82e..493611599 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackDeleteEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackDeleteEvent.java @@ -43,20 +43,23 @@ public interface TrackDeleteEvent extends LuckPermsEvent { * * @return the name of the deleted track */ - @NonNull @Param(0) String getTrackName(); + @Param(0) + @NonNull String getTrackName(); /** * Gets an immutable copy of the tracks existing data * * @return a copy of the tracks existing data */ - @NonNull @Param(1) List getExistingData(); + @Param(1) + @NonNull List getExistingData(); /** * Gets the cause of the deletion * * @return the cause of the deletion */ - @NonNull @Param(2) DeletionCause getCause(); + @Param(2) + @NonNull DeletionCause getCause(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackLoadEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackLoadEvent.java index 3b926f211..e0055b149 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/track/TrackLoadEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/track/TrackLoadEvent.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.api.event.track; -import me.lucko.luckperms.api.Track; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.track.Track; import org.checkerframework.checker.nullness.qual.NonNull; @@ -43,6 +43,7 @@ public interface TrackLoadEvent extends LuckPermsEvent { * * @return the track that was loaded */ - @NonNull @Param(0) Track getTrack(); + @Param(0) + @NonNull Track getTrack(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackAddGroupEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackAddGroupEvent.java index cbd54ca89..266198d51 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackAddGroupEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackAddGroupEvent.java @@ -39,6 +39,7 @@ public interface TrackAddGroupEvent extends TrackMutateEvent { * * @return the group that was added */ - @NonNull @Param(3) String getGroup(); + @Param(3) + @NonNull String getGroup(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackMutateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackMutateEvent.java index 9999bb801..91c77f6a5 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackMutateEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackMutateEvent.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.api.event.track.mutate; -import me.lucko.luckperms.api.Track; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.track.Track; import org.checkerframework.checker.nullness.qual.NonNull; @@ -43,20 +43,23 @@ public interface TrackMutateEvent extends LuckPermsEvent { * * @return the track that was mutated */ - @NonNull @Param(0) Track getTrack(); + @Param(0) + @NonNull Track getTrack(); /** * Gets an immutable copy of the tracks data before the change * * @return the data before the change */ - @NonNull @Param(1) List getDataBefore(); + @Param(1) + @NonNull List getDataBefore(); /** * Gets an immutable copy of the tracks data after the change * * @return the data after the change */ - @NonNull @Param(2) List getDataAfter(); + @Param(2) + @NonNull List getDataAfter(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackRemoveGroupEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackRemoveGroupEvent.java index 10d061aaa..77063e4bf 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackRemoveGroupEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/track/mutate/TrackRemoveGroupEvent.java @@ -39,6 +39,7 @@ public interface TrackRemoveGroupEvent extends TrackMutateEvent { * * @return the group that was removed */ - @NonNull @Param(3) String getGroup(); + @Param(3) + @NonNull String getGroup(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/user/UserCacheLoadEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/user/UserCacheLoadEvent.java index a2cf80926..9391c3529 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/user/UserCacheLoadEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/user/UserCacheLoadEvent.java @@ -25,15 +25,15 @@ package me.lucko.luckperms.api.event.user; -import me.lucko.luckperms.api.User; -import me.lucko.luckperms.api.caching.UserData; +import me.lucko.luckperms.api.cacheddata.CachedDataManager; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.model.user.User; import org.checkerframework.checker.nullness.qual.NonNull; /** - * Called when a users {@link UserData} is loaded. + * Called when a users {@link CachedDataManager} is loaded. */ public interface UserCacheLoadEvent extends LuckPermsEvent { @@ -42,13 +42,15 @@ public interface UserCacheLoadEvent extends LuckPermsEvent { * * @return the user */ - @NonNull @Param(0) User getUser(); + @Param(0) + @NonNull User getUser(); /** * Gets the data that was loaded * * @return the loaded data */ - @NonNull @Param(1) UserData getLoadedData(); + @Param(1) + @NonNull CachedDataManager getLoadedData(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/user/UserDataRecalculateEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/user/UserDataRecalculateEvent.java index 7067ae4b6..520ca568c 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/user/UserDataRecalculateEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/user/UserDataRecalculateEvent.java @@ -25,10 +25,10 @@ package me.lucko.luckperms.api.event.user; -import me.lucko.luckperms.api.User; -import me.lucko.luckperms.api.caching.UserData; +import me.lucko.luckperms.api.cacheddata.CachedDataManager; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.model.user.User; import org.checkerframework.checker.nullness.qual.NonNull; @@ -42,13 +42,15 @@ public interface UserDataRecalculateEvent extends LuckPermsEvent { * * @return the user */ - @NonNull @Param(0) User getUser(); + @Param(0) + @NonNull User getUser(); /** * Gets the data that was recalculated * * @return the data */ - @NonNull @Param(1) UserData getData(); + @Param(1) + @NonNull CachedDataManager getData(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/user/UserFirstLoginEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/user/UserFirstLoginEvent.java index e7eae3b5b..a3a6fe602 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/user/UserFirstLoginEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/user/UserFirstLoginEvent.java @@ -50,13 +50,15 @@ public interface UserFirstLoginEvent extends LuckPermsEvent { * * @return the uuid of the user */ - @NonNull @Param(0) UUID getUuid(); + @Param(0) + @NonNull UUID getUniqueId(); /** * Gets the username of the user * * @return the username of the user */ - @NonNull @Param(1) String getUsername(); + @Param(1) + @NonNull String getUsername(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/user/UserLoadEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/user/UserLoadEvent.java index 3a9d81e6c..e8233a0c8 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/user/UserLoadEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/user/UserLoadEvent.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.api.event.user; -import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; +import me.lucko.luckperms.api.model.user.User; import org.checkerframework.checker.nullness.qual.NonNull; @@ -41,6 +41,7 @@ public interface UserLoadEvent extends LuckPermsEvent { * * @return the user that was loaded */ - @NonNull @Param(0) User getUser(); + @Param(0) + @NonNull User getUser(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/event/user/track/UserTrackEvent.java b/api/src/main/java/me/lucko/luckperms/api/event/user/track/UserTrackEvent.java index b3013c331..19e974d9c 100644 --- a/api/src/main/java/me/lucko/luckperms/api/event/user/track/UserTrackEvent.java +++ b/api/src/main/java/me/lucko/luckperms/api/event/user/track/UserTrackEvent.java @@ -25,11 +25,11 @@ package me.lucko.luckperms.api.event.user.track; -import me.lucko.luckperms.api.Track; -import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; import me.lucko.luckperms.api.event.Sourced; +import me.lucko.luckperms.api.model.user.User; +import me.lucko.luckperms.api.track.Track; import org.checkerframework.checker.nullness.qual.NonNull; @@ -45,14 +45,16 @@ public interface UserTrackEvent extends LuckPermsEvent, Sourced { * * @return the track involved in the event */ - @NonNull @Param(0) Track getTrack(); + @Param(0) + @NonNull Track getTrack(); /** * Gets the user who was promoted or demoted * * @return the user involved in the event */ - @NonNull @Param(1) User getUser(); + @Param(1) + @NonNull User getUser(); /** * Gets the action performed @@ -68,13 +70,15 @@ public interface UserTrackEvent extends LuckPermsEvent, Sourced { * * @return the group the user was promoted/demoted from */ - @NonNull @Param(2) Optional getGroupFrom(); + @Param(2) + @NonNull Optional getGroupFrom(); /** * Gets the group the user was promoted/demoted to * * @return the group the user was promoted/demoted to */ - @NonNull @Param(3) Optional getGroupTo(); + @Param(3) + @NonNull Optional getGroupTo(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/MessagingService.java b/api/src/main/java/me/lucko/luckperms/api/messaging/MessagingService.java similarity index 93% rename from api/src/main/java/me/lucko/luckperms/api/MessagingService.java rename to api/src/main/java/me/lucko/luckperms/api/messaging/MessagingService.java index a35db6b3c..376499f22 100644 --- a/api/src/main/java/me/lucko/luckperms/api/MessagingService.java +++ b/api/src/main/java/me/lucko/luckperms/api/messaging/MessagingService.java @@ -23,14 +23,15 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.messaging; + +import me.lucko.luckperms.api.LuckPerms; +import me.lucko.luckperms.api.model.user.User; import org.checkerframework.checker.nullness.qual.NonNull; /** * A means to push changes to other servers using the platforms networking - * - * @since 2.14 */ public interface MessagingService { @@ -38,7 +39,6 @@ public interface MessagingService { * Gets the name of this messaging service * * @return the name of this messaging service - * @since 4.1 */ String getName(); @@ -48,7 +48,7 @@ public interface MessagingService { * *

    The standard response by other servers will be to execute a overall * sync of all live data, equivalent to calling - * {@link LuckPermsApi#runUpdateTask()}.

    + * {@link LuckPerms#runUpdateTask()}.

    * *

    This will push the update asynchronously, and this method will return * immediately. Note that this method will not cause an update to be @@ -69,7 +69,6 @@ public interface MessagingService { * processed on the local server.

    * * @param user the user to push the update for - * @since 4.1 */ void pushUserUpdate(@NonNull User user); diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/IncomingMessageConsumer.java b/api/src/main/java/me/lucko/luckperms/api/messenger/IncomingMessageConsumer.java index 4da213d66..d6e83232d 100644 --- a/api/src/main/java/me/lucko/luckperms/api/messenger/IncomingMessageConsumer.java +++ b/api/src/main/java/me/lucko/luckperms/api/messenger/IncomingMessageConsumer.java @@ -33,8 +33,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; /** * Encapsulates the LuckPerms system which accepts incoming {@link Message}s * from implementations of {@link Messenger}. - * - * @since 4.1 */ public interface IncomingMessageConsumer { diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/Messenger.java b/api/src/main/java/me/lucko/luckperms/api/messenger/Messenger.java index a49285384..6245016c6 100644 --- a/api/src/main/java/me/lucko/luckperms/api/messenger/Messenger.java +++ b/api/src/main/java/me/lucko/luckperms/api/messenger/Messenger.java @@ -32,8 +32,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; /** * Represents an object which dispatches {@link OutgoingMessage}s. - * - * @since 4.1 */ public interface Messenger extends AutoCloseable { diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/MessengerProvider.java b/api/src/main/java/me/lucko/luckperms/api/messenger/MessengerProvider.java index a912c9054..6222473a4 100644 --- a/api/src/main/java/me/lucko/luckperms/api/messenger/MessengerProvider.java +++ b/api/src/main/java/me/lucko/luckperms/api/messenger/MessengerProvider.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.api.messenger; -import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.LuckPerms; import org.checkerframework.checker.nullness.qual.NonNull; @@ -35,8 +35,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; *

    Users wishing to provide their own implementation for the plugins * "Messaging Service" should implement and register this interface.

    * - * @see LuckPermsApi#registerMessengerProvider(MessengerProvider) - * @since 4.1 + * @see LuckPerms#registerMessengerProvider(MessengerProvider) */ public interface MessengerProvider { diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/message/Message.java b/api/src/main/java/me/lucko/luckperms/api/messenger/message/Message.java index 710844557..f1f68ba23 100644 --- a/api/src/main/java/me/lucko/luckperms/api/messenger/message/Message.java +++ b/api/src/main/java/me/lucko/luckperms/api/messenger/message/Message.java @@ -33,8 +33,6 @@ import java.util.UUID; /** * Represents a message sent received via a {@link Messenger}. - * - * @since 4.1 */ public interface Message { diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/message/OutgoingMessage.java b/api/src/main/java/me/lucko/luckperms/api/messenger/message/OutgoingMessage.java index cdba6628b..0eabb3124 100644 --- a/api/src/main/java/me/lucko/luckperms/api/messenger/message/OutgoingMessage.java +++ b/api/src/main/java/me/lucko/luckperms/api/messenger/message/OutgoingMessage.java @@ -38,8 +38,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; *

    Note that all implementations of this interface are guaranteed to be an * instance of one of the interfaces extending {@link Message} in the * 'api.messenger.message.type' package.

    - * - * @since 4.1 */ public interface OutgoingMessage extends Message { diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/LogMessage.java b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/ActionLogMessage.java similarity index 82% rename from api/src/main/java/me/lucko/luckperms/api/messenger/message/type/LogMessage.java rename to api/src/main/java/me/lucko/luckperms/api/messenger/message/type/ActionLogMessage.java index 9f8448ed3..3e2286667 100644 --- a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/LogMessage.java +++ b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/ActionLogMessage.java @@ -25,25 +25,23 @@ package me.lucko.luckperms.api.messenger.message.type; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.messenger.message.Message; import org.checkerframework.checker.nullness.qual.NonNull; /** - * Represents an "log" message. + * Represents an "action log" message. * - *

    Used to dispatch live log updates to other servers.

    - * - * @since 4.1 + *

    Used to dispatch live action log updates to other servers.

    */ -public interface LogMessage extends Message { +public interface ActionLogMessage extends Message { /** - * Gets the log entry being sent + * Gets the action being sent * - * @return the log entry + * @return the action */ - @NonNull LogEntry getLogEntry(); + @NonNull Action getAction(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UpdateMessage.java b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UpdateMessage.java index e78ed5abf..cc83710b9 100644 --- a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UpdateMessage.java +++ b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UpdateMessage.java @@ -31,8 +31,6 @@ import me.lucko.luckperms.api.messenger.message.Message; * Represents an "update" message. * *

    Used to notify other servers of general changes.

    - * - * @since 4.1 */ public interface UpdateMessage extends Message { diff --git a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UserUpdateMessage.java b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UserUpdateMessage.java index 2cfe7cec1..3ca3a5d77 100644 --- a/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UserUpdateMessage.java +++ b/api/src/main/java/me/lucko/luckperms/api/messenger/message/type/UserUpdateMessage.java @@ -35,8 +35,6 @@ import java.util.UUID; * Represents an "user update" message. * *

    Used to notify other servers of a change to a specific user.

    - * - * @since 4.1 */ public interface UserUpdateMessage extends Message { @@ -45,6 +43,6 @@ public interface UserUpdateMessage extends Message { * * @return the user */ - @NonNull UUID getUser(); + @NonNull UUID getUserUniqueId(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/metastacking/DuplicateRemovalFunction.java b/api/src/main/java/me/lucko/luckperms/api/metastacking/DuplicateRemovalFunction.java index d3fc5d1e6..b3895823c 100644 --- a/api/src/main/java/me/lucko/luckperms/api/metastacking/DuplicateRemovalFunction.java +++ b/api/src/main/java/me/lucko/luckperms/api/metastacking/DuplicateRemovalFunction.java @@ -36,8 +36,6 @@ import java.util.Set; * Functional interface which removes duplicate entries from a list. * *

    Used by LuckPerms to remove duplicate entries from a MetaStack.

    - * - * @since 4.4 */ public interface DuplicateRemovalFunction { @@ -72,7 +70,7 @@ public interface DuplicateRemovalFunction { @SuppressWarnings("Java8CollectionRemoveIf") @Override public void processDuplicates(@NonNull List list) { - Set seen = new HashSet<>(); + Set seen = new HashSet<>(list.size()); for (ListIterator it = list.listIterator(); it.hasNext(); ) { T next = it.next(); if (!seen.add(next)) { @@ -93,7 +91,7 @@ public interface DuplicateRemovalFunction { DuplicateRemovalFunction LAST_ONLY = new DuplicateRemovalFunction() { @Override public void processDuplicates(@NonNull List list) { - Set seen = new HashSet<>(); + Set seen = new HashSet<>(list.size()); for (ListIterator it = list.listIterator(list.size()); it.hasPrevious(); ) { T next = it.previous(); if (!seen.add(next)) { diff --git a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackDefinition.java b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackDefinition.java index 01c0b473f..5c2845603 100644 --- a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackDefinition.java +++ b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackDefinition.java @@ -25,6 +25,8 @@ package me.lucko.luckperms.api.metastacking; +import me.lucko.luckperms.api.query.OptionKey; + import org.checkerframework.checker.nullness.qual.NonNull; import java.util.List; @@ -37,11 +39,19 @@ import java.util.List; * *

    Definitions can be passed to a users UserData instance using MetaContexts, and the result of this stack can be * retrieved from the returned MetaData instance.

    - * - * @since 2.3 */ public interface MetaStackDefinition { + /** + * The {@link OptionKey} for the prefix {@link MetaStackDefinition}. + */ + OptionKey PREFIX_STACK_KEY = new OptionKey(){}; + + /** + * The {@link OptionKey} for the suffix {@link MetaStackDefinition}. + */ + OptionKey SUFFIX_STACK_KEY = new OptionKey(){}; + /** * Gets an immutable list of the elements in this stack definition * @@ -54,7 +64,6 @@ public interface MetaStackDefinition { * formatting takes place. * * @return the duplicate removal function - * @since 4.4 */ @NonNull DuplicateRemovalFunction getDuplicateRemovalFunction(); diff --git a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackElement.java b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackElement.java index 1dc7c04b9..590b158fe 100644 --- a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackElement.java +++ b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackElement.java @@ -25,34 +25,27 @@ package me.lucko.luckperms.api.metastacking; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.types.ChatMetaNode; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import java.util.Map; - /** * Represents an element within a {@link MetaStackDefinition}. * *

    The element itself does not contain any mutable state.

    - * - * @since 3.2 */ public interface MetaStackElement { /** * Returns if the given node should be accumulated onto the stack. * - *

    The element being considered can be retrieved using {@link ChatMetaType#getEntry(Node)}.

    - * - * @param node the node being considered * @param type the type of entry being accumulated + * @param node the node being considered * @param current the current value being used. If this returns true, the current value will be replaced by this entry * @return true if the node should be accumulated into this element, replacing the current value */ - boolean shouldAccumulate(@NonNull LocalizedNode node, @NonNull ChatMetaType type, Map.@Nullable Entry current); + boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode node, @Nullable ChatMetaNode current); } diff --git a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackFactory.java b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackFactory.java index 22d601e10..0b606ed81 100644 --- a/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackFactory.java +++ b/api/src/main/java/me/lucko/luckperms/api/metastacking/MetaStackFactory.java @@ -32,8 +32,6 @@ import java.util.Optional; /** * Factory to create meta stack elements and definitions. - * - * @since 3.2 */ public interface MetaStackFactory { @@ -77,7 +75,6 @@ public interface MetaStackFactory { * @param middleSpacer the spacer to be included between stack elements * @param endSpacer the spacer to be included at the end of the stacks output * @return the new stack definition instance - * @since 4.4 */ @NonNull MetaStackDefinition createDefinition(@NonNull List elements, @NonNull DuplicateRemovalFunction duplicateRemovalFunction, @NonNull String startSpacer, @NonNull String middleSpacer, @NonNull String endSpacer); diff --git a/api/src/main/java/me/lucko/luckperms/api/DataMutateResult.java b/api/src/main/java/me/lucko/luckperms/api/model/DataMutateResult.java similarity index 90% rename from api/src/main/java/me/lucko/luckperms/api/DataMutateResult.java rename to api/src/main/java/me/lucko/luckperms/api/model/DataMutateResult.java index 8f738d722..48feb3ccf 100644 --- a/api/src/main/java/me/lucko/luckperms/api/DataMutateResult.java +++ b/api/src/main/java/me/lucko/luckperms/api/model/DataMutateResult.java @@ -23,14 +23,17 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.model; + +import me.lucko.luckperms.api.track.Track; +import me.lucko.luckperms.api.util.Result; /** * Represents the result of a data mutation call on a LuckPerms object. * *

    Usually as the result to a call on a {@link PermissionHolder} or {@link Track}.

    */ -public enum DataMutateResult implements MutateResult { +public enum DataMutateResult implements Result { /** * Indicates the mutation was a success @@ -59,7 +62,7 @@ public enum DataMutateResult implements MutateResult { } @Override - public boolean wasSuccess() { + public boolean wasSuccessful() { return this.success; } } diff --git a/api/src/main/java/me/lucko/luckperms/api/model/PermissionHolder.java b/api/src/main/java/me/lucko/luckperms/api/model/PermissionHolder.java new file mode 100644 index 000000000..8669316ab --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/model/PermissionHolder.java @@ -0,0 +1,468 @@ +/* + * 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.api.model; + +import me.lucko.luckperms.api.cacheddata.CachedDataManager; +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.model.group.Group; +import me.lucko.luckperms.api.model.group.GroupManager; +import me.lucko.luckperms.api.model.user.User; +import me.lucko.luckperms.api.model.user.UserManager; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.node.types.PrefixNode; +import me.lucko.luckperms.api.node.types.SuffixNode; +import me.lucko.luckperms.api.query.QueryOptions; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.function.Predicate; + +/** + * Generic superinterface for an object which holds permissions. + */ +public interface PermissionHolder { + + /** + * Gets the objects generic name. + * + *

    The result of this method is guaranteed to be a unique identifier for distinct instances + * of the same type of object.

    + * + *

    For {@link User}s, this method returns a {@link UUID#toString() string} representation of + * the users {@link User#getUniqueId() unique id}.

    + * + *

    For {@link Group}s, this method returns the {@link Group#getName() group name}.

    + * + *

    The {@link User#getUniqueId()}, {@link User#getUsername()} and {@link Group#getName()} methods + * define a "tighter" specification for obtaining object identifiers.

    + * + * @return the identifier for this object. Either a uuid string or name. + */ + @NonNull String getObjectName(); + + /** + * Gets a friendly name for this holder, to be displayed in command output, etc. + * + *

    This will always return a value, eventually falling back to + * {@link #getObjectName()} if no other "friendlier" identifiers are present.

    + * + *

    For {@link User}s, this method will attempt to return the {@link User#getUsername() username}, + * before falling back to {@link #getObjectName()}.

    + * + *

    For {@link Group}s, this method will attempt to return the groups display name, before + * falling back to {@link #getObjectName()}.

    + * + * @return a friendly identifier for this holder + */ + @NonNull String getFriendlyName(); + + /** + * Gets the holders {@link CachedDataManager} cache. + * + * @return the holders cached data. + */ + @NonNull CachedDataManager getCachedData(); + + /** + * Refreshes and applies any changes to the cached holder data. + * + *

    Calling this method is unnecessary in most cases. Cache updates are handled + * behind the scenes by the implementation.

    + * + * @return the task future + */ + @NonNull CompletableFuture refreshCachedData(); + + /** + * Gets the {@link Data} of a particular type. + * + * @param dataType the data type + * @return the data + */ + Data getData(@NonNull DataType dataType); + + /** + * Gets the holders {@link DataType#NORMAL} data. + * + * @return the normal data + */ + @NonNull Data data(); + + /** + * Gets the holders {@link DataType#TRANSIENT} data. + * + *

    Transient permissions only exist for the duration of the session.

    + * + *

    A transient node is a permission that does not persist. + * Whenever a user logs out of the server, or the server restarts, this permission will + * disappear. It is never saved to the datastore, and therefore will not apply on other + * servers.

    + * + *

    This is useful if you want to temporarily set a permission for a user while they're + * online, but don't want it to persist, and have to worry about removing it when they log + * out.

    + * + * @return the transient data + */ + @NonNull Data transientData(); + + /** + * Represents a type of data. + */ + enum DataType { + + /** + * Normal data. + */ + NORMAL, + + /** + * Data which expires automatically at the end of a session. + * (when a user logs off) + * + *

    This data is never saved to the backend storage provider.

    + */ + TRANSIENT + } + + interface Data { + + /** + * Gets the backing map containing every permission this holder has. + * + *

    This method does not resolve inheritance rules, and returns a + * view of what's 'in the file'.

    + * + * @return the holders own nodes + */ + @NonNull Map> getNodes(); + + /** + * Gets a flattened set of {@link Node}s the holder has. + * + *

    Effectively combines the value collections of the map returned by + * {@link #getNodes()}.

    + * + * @return a flattened set of the holders own nodes + */ + @NonNull Set getFlattenedNodes(); + + /** + * Checks to see if the object has a certain permission. + * + * @param node the node to check for + * @param equalityPredicate how to determine if a node matches + * @return a Tristate for the holders permission status for the node + * @throws NullPointerException if the node is null + */ + @NonNull Tristate hasNode(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate); + + /** + * Sets a permission node for the permission holder. + * + *

    Although this method is named setPermission, it can be used for all node types.

    + * + *

    The effect of this mutate operation will not persist in storage unless changes are + * explicitly saved. If changes are not saved, the effect will only be observed until the next + * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved + * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved + * using {@link GroupManager#saveGroup(Group)}.

    + * + *

    Before making changes to a user or group, it may be a good idea to load a fresh copy of + * the backing data from the storage if you haven't done so already, to avoid overwriting changes + * made already. This can be done via {@link UserManager#loadUser(UUID)} or + * {@link GroupManager#loadGroup(String)} respectively.

    + * + * @param node The node to be set + * @return the result of the operation + * @throws NullPointerException if the node is null + */ + @NonNull DataMutateResult addNode(@NonNull Node node); + + /** + * Sets a permission node for the permission holder. + * + *

    Although this method is named setPermission, it can be used for all node types.

    + * + *

    The effect of this mutate operation will not persist in storage unless changes are + * explicitly saved. If changes are not saved, the effect will only be observed until the next + * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved + * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved + * using {@link GroupManager#saveGroup(Group)}.

    + * + *

    Before making changes to a user or group, it may be a good idea to load a fresh copy of + * the backing data from the storage if you haven't done so already, to avoid overwriting changes + * made already. This can be done via {@link UserManager#loadUser(UUID)} or + * {@link GroupManager#loadGroup(String)} respectively.

    + * + * @param node The node to be set + * @param temporaryMergeBehaviour The behaviour used to merge temporary permission entries + * @return the result of the operation + * @throws NullPointerException if the node is null + */ + @NonNull TemporaryDataMutateResult addNode(@NonNull Node node, @NonNull TemporaryMergeBehaviour temporaryMergeBehaviour); + + /** + * Unsets a permission for the permission holder. + * + *

    Although this method is named unsetPermission, it can be used for all node types.

    + * + *

    The effect of this mutate operation will not persist in storage unless changes are + * explicitly saved. If changes are not saved, the effect will only be observed until the next + * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved + * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved + * using {@link GroupManager#saveGroup(Group)}.

    + * + *

    Before making changes to a user or group, it may be a good idea to load a fresh copy of + * the backing data from the storage if you haven't done so already, to avoid overwriting changes + * made already. This can be done via {@link UserManager#loadUser(UUID)} or + * {@link GroupManager#loadGroup(String)} respectively.

    + * + * @param node The node to be unset + * @return the result of the operation + * @throws NullPointerException if the node is null + */ + @NonNull DataMutateResult removeNode(@NonNull Node node); + + /** + * Clears any nodes from the holder which pass the predicate. + * + *

    This method only targets enduring data.

    + * + *

    The effect of this mutate operation will not persist in storage unless changes are + * explicitly saved. If changes are not saved, the effect will only be observed until the next + * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved + * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved + * using {@link GroupManager#saveGroup(Group)}.

    + * + *

    Before making changes to a user or group, it may be a good idea to load a fresh copy of + * the backing data from the storage if you haven't done so already, to avoid overwriting changes + * made already. This can be done via {@link UserManager#loadUser(UUID)} or + * {@link GroupManager#loadGroup(String)} respectively.

    + * + * @param test the predicate to test for nodes which should be removed + */ + void clearMatching(@NonNull Predicate test); + + /** + * Clears all nodes held by the permission holder. + * + *

    The effect of this mutate operation will not persist in storage unless changes are + * explicitly saved. If changes are not saved, the effect will only be observed until the next + * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved + * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved + * using {@link GroupManager#saveGroup(Group)}.

    + * + *

    Before making changes to a user or group, it may be a good idea to load a fresh copy of + * the backing data from the storage if you haven't done so already, to avoid overwriting changes + * made already. This can be done via {@link UserManager#loadUser(UUID)} or + * {@link GroupManager#loadGroup(String)} respectively.

    + */ + void clearNodes(); + + /** + * Clears all nodes held by the permission holder in a specific context. + * + *

    The effect of this mutate operation will not persist in storage unless changes are + * explicitly saved. If changes are not saved, the effect will only be observed until the next + * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved + * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved + * using {@link GroupManager#saveGroup(Group)}.

    + * + *

    Before making changes to a user or group, it may be a good idea to load a fresh copy of + * the backing data from the storage if you haven't done so already, to avoid overwriting changes + * made already. This can be done via {@link UserManager#loadUser(UUID)} or + * {@link GroupManager#loadGroup(String)} respectively.

    + * + * @param contextSet the contexts to filter by + */ + void clearNodes(@NonNull ContextSet contextSet); + + /** + * Clears all parent groups. + * + *

    The effect of this mutate operation will not persist in storage unless changes are + * explicitly saved. If changes are not saved, the effect will only be observed until the next + * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved + * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved + * using {@link GroupManager#saveGroup(Group)}.

    + * + *

    Before making changes to a user or group, it may be a good idea to load a fresh copy of + * the backing data from the storage if you haven't done so already, to avoid overwriting changes + * made already. This can be done via {@link UserManager#loadUser(UUID)} or + * {@link GroupManager#loadGroup(String)} respectively.

    + */ + void clearParents(); + + /** + * Clears all parent groups in a specific context. + * + *

    The effect of this mutate operation will not persist in storage unless changes are + * explicitly saved. If changes are not saved, the effect will only be observed until the next + * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved + * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved + * using {@link GroupManager#saveGroup(Group)}.

    + * + *

    Before making changes to a user or group, it may be a good idea to load a fresh copy of + * the backing data from the storage if you haven't done so already, to avoid overwriting changes + * made already. This can be done via {@link UserManager#loadUser(UUID)} or + * {@link GroupManager#loadGroup(String)} respectively.

    + * + * @param contextSet the contexts to filter by + */ + void clearParents(@NonNull ContextSet contextSet); + + /** + * Clears all meta held by the permission holder. + * + *

    Meta nodes in this case, are any nodes which have a {@link MetaNode}, {@link PrefixNode} + * or {@link SuffixNode} type.

    + * + *

    The effect of this mutate operation will not persist in storage unless changes are + * explicitly saved. If changes are not saved, the effect will only be observed until the next + * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved + * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved + * using {@link GroupManager#saveGroup(Group)}.

    + * + *

    Before making changes to a user or group, it may be a good idea to load a fresh copy of + * the backing data from the storage if you haven't done so already, to avoid overwriting changes + * made already. This can be done via {@link UserManager#loadUser(UUID)} or + * {@link GroupManager#loadGroup(String)} respectively.

    + */ + void clearMeta(); + + /** + * Clears all meta held by the permission holder in a specific context. + * + *

    Meta nodes in this case, are any nodes which have a {@link MetaNode}, {@link PrefixNode} + * or {@link SuffixNode} type.

    + * + *

    The effect of this mutate operation will not persist in storage unless changes are + * explicitly saved. If changes are not saved, the effect will only be observed until the next + * time the holders permission data is (re)loaded. Changes to {@link User}s should be saved + * using {@link UserManager#saveUser(User)}, and changes to {@link Group}s should be saved + * using {@link GroupManager#saveGroup(Group)}.

    + * + *

    Before making changes to a user or group, it may be a good idea to load a fresh copy of + * the backing data from the storage if you haven't done so already, to avoid overwriting changes + * made already. This can be done via {@link UserManager#loadUser(UUID)} or + * {@link GroupManager#loadGroup(String)} respectively.

    + * + * @param contextSet the contexts to filter by + */ + void clearMeta(@NonNull ContextSet contextSet); + + } + + /** + * Gets a flattened/squashed view of the holders permissions. + * + *

    This list is constructed using the values + * of both the transient and enduring backing multimaps.

    + * + *

    This means that it may contain duplicate entries.

    + * + *

    Use {@link #getDistinctNodes()} for a view without duplicates.

    + * + *

    This method does not resolve inheritance rules.

    + * + * @return a list of the holders own nodes. + */ + @NonNull List getNodes(); + + /** + * Gets a sorted set of all held nodes. + * + *

    Effectively a sorted version of {@link #getNodes()}, without duplicates. Use the + * aforementioned method if you don't require either of these attributes.

    + * + *

    This method does not resolve inheritance rules.

    + * + * @return an immutable set of permissions in priority order + */ + @NonNull SortedSet getDistinctNodes(); + + /** + * Recursively resolves this holders permissions. + * + *

    The returned list will contain every inherited + * node the holder has, in the order that they were inherited in.

    + * + *

    This means the list will contain duplicates.

    + * + *

    Inheritance is performed according to the platforms rules, and the order will vary + * depending on the accumulation order. By default, the holders own nodes are first in the list, + * with the entries from the end of the inheritance tree appearing last.

    + * + * @param queryOptions the query options + * @return a list of nodes + */ + @NonNull List resolveInheritedNodes(@NonNull QueryOptions queryOptions); + + /** + * Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context + * + *

    Nodes are sorted into priority order. The order of inheritance is only important during + * the process of flattening inherited entries.

    + * + * @param queryOptions the query options + * @return an immutable sorted set of permissions + * @throws NullPointerException if the context is null + */ + @NonNull SortedSet resolveDistinctInheritedNodes(@NonNull QueryOptions queryOptions); + + /** + * Removes any temporary permissions that have expired. + * + *

    This method is called periodically by the platform, so it is only necessary to run + * if you want to guarantee that the current data is totally up-to-date.

    + */ + void auditTemporaryPermissions(); + + /** + * Checks to see if the object inherits a certain permission. + * + *

    Although this method is named inheritsPermission, it can be used for all node types.

    + * + * @param node the node to check for + * @param equalityPredicate how to determine if a node matches + * @return a Tristate for the holders inheritance status for the node + * @throws NullPointerException if the node is null + */ + @NonNull Tristate inheritsNode(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate); + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/PlayerSaveResult.java b/api/src/main/java/me/lucko/luckperms/api/model/PlayerSaveResult.java similarity index 81% rename from api/src/main/java/me/lucko/luckperms/api/PlayerSaveResult.java rename to api/src/main/java/me/lucko/luckperms/api/model/PlayerSaveResult.java index cb63dab21..eca839e59 100644 --- a/api/src/main/java/me/lucko/luckperms/api/PlayerSaveResult.java +++ b/api/src/main/java/me/lucko/luckperms/api/model/PlayerSaveResult.java @@ -23,9 +23,9 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.model; -import me.lucko.luckperms.api.manager.UserManager; +import me.lucko.luckperms.api.model.user.UserManager; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -39,8 +39,6 @@ import java.util.UUID; * *

    The corresponding method can be found at * {@link UserManager#savePlayerData(UUID, String)}.

    - * - * @since 4.2 */ public interface PlayerSaveResult { @@ -49,45 +47,45 @@ public interface PlayerSaveResult { * * @return the status */ - @NonNull Set getStatus(); + @NonNull Set getOutcomes(); /** - * Gets if the result includes a certain status code. + * Gets if the result includes a certain outcome. * - * @param status the status to check for - * @return if the result includes the status + * @param outcome the outcome to check for + * @return if the result includes the outcome */ - default boolean includes(@NonNull Status status) { - Objects.requireNonNull(status, "status"); - return getStatus().contains(status); + default boolean includes(@NonNull Outcome outcome) { + Objects.requireNonNull(outcome, "outcome"); + return getOutcomes().contains(outcome); } /** * Gets the old username involved in the result. * - *

    Returns null when the result doesn't {@link #includes(Status) include} the - * {@link Status#USERNAME_UPDATED} status.

    + *

    Returns null when the result doesn't {@link #includes(Outcome) include} the + * {@link Outcome#USERNAME_UPDATED} status.

    * * @return the old username - * @see Status#USERNAME_UPDATED + * @see Outcome#USERNAME_UPDATED */ @Nullable String getOldUsername(); /** * Gets the other uuids involved in the result. * - *

    Returns null when the result doesn't {@link #includes(Status) include} the - * {@link Status#OTHER_UUIDS_PRESENT_FOR_USERNAME} status.

    + *

    Returns null when the result doesn't {@link #includes(Outcome) include} the + * {@link Outcome#OTHER_UNIQUE_IDS_PRESENT_FOR_USERNAME} status.

    * * @return the other uuids - * @see Status#OTHER_UUIDS_PRESENT_FOR_USERNAME + * @see Outcome#OTHER_UNIQUE_IDS_PRESENT_FOR_USERNAME */ - @Nullable Set getOtherUuids(); + @Nullable Set getOtherUniqueIds(); /** * The various states the result can take */ - enum Status { + enum Outcome { /** * There was no existing data saved for either the uuid or username @@ -119,6 +117,6 @@ public interface PlayerSaveResult { * that the user of the plugin is running a network off a shared database with one * server in online mode and another in offline mode.

    */ - OTHER_UUIDS_PRESENT_FOR_USERNAME, + OTHER_UNIQUE_IDS_PRESENT_FOR_USERNAME, } } diff --git a/api/src/main/java/me/lucko/luckperms/api/TemporaryDataMutateResult.java b/api/src/main/java/me/lucko/luckperms/api/model/TemporaryDataMutateResult.java similarity index 86% rename from api/src/main/java/me/lucko/luckperms/api/TemporaryDataMutateResult.java rename to api/src/main/java/me/lucko/luckperms/api/model/TemporaryDataMutateResult.java index fa9938302..d16e7c7fc 100644 --- a/api/src/main/java/me/lucko/luckperms/api/TemporaryDataMutateResult.java +++ b/api/src/main/java/me/lucko/luckperms/api/model/TemporaryDataMutateResult.java @@ -23,16 +23,17 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.model; + +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.util.Result; import org.checkerframework.checker.nullness.qual.NonNull; /** * Extension of {@link DataMutateResult} for temporary set operations. - * - * @since 4.3 */ -public interface TemporaryDataMutateResult { +public interface TemporaryDataMutateResult extends Result { /** * Gets the underlying result. @@ -52,4 +53,9 @@ public interface TemporaryDataMutateResult { */ @NonNull Node getMergedNode(); + @Override + default boolean wasSuccessful() { + return getResult().wasSuccessful(); + } + } diff --git a/api/src/main/java/me/lucko/luckperms/api/TemporaryMergeBehaviour.java b/api/src/main/java/me/lucko/luckperms/api/model/TemporaryMergeBehaviour.java similarity index 89% rename from api/src/main/java/me/lucko/luckperms/api/TemporaryMergeBehaviour.java rename to api/src/main/java/me/lucko/luckperms/api/model/TemporaryMergeBehaviour.java index 5d6b1a8d7..ca7402ae4 100644 --- a/api/src/main/java/me/lucko/luckperms/api/TemporaryMergeBehaviour.java +++ b/api/src/main/java/me/lucko/luckperms/api/model/TemporaryMergeBehaviour.java @@ -23,20 +23,20 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.model; + +import me.lucko.luckperms.api.node.Node; /** * Controls how the implementation should behave when new temporary nodes are set * that would otherwise conflict with existing entries. * - *

    The default behaviour of {@link PermissionHolder#setPermission(Node)} is + *

    The default behaviour of {@link PermissionHolder.Data#addNode(Node)} is * to return a result of {@link DataMutateResult#ALREADY_HAS} when an equivalent * node is found. This can be replicated using {@link #FAIL_WITH_ALREADY_HAS}.

    * - *

    However, the {@link PermissionHolder#setPermission(Node, TemporaryMergeBehaviour)} + *

    However, the {@link PermissionHolder.Data#addNode(Node, TemporaryMergeBehaviour)} * method allows this behaviour to be customized for temporary permissions.

    - * - * @since 4.3 */ public enum TemporaryMergeBehaviour { diff --git a/api/src/main/java/me/lucko/luckperms/api/Group.java b/api/src/main/java/me/lucko/luckperms/api/model/group/Group.java similarity index 89% rename from api/src/main/java/me/lucko/luckperms/api/Group.java rename to api/src/main/java/me/lucko/luckperms/api/model/group/Group.java index b9167c29c..43f9a2fb3 100644 --- a/api/src/main/java/me/lucko/luckperms/api/Group.java +++ b/api/src/main/java/me/lucko/luckperms/api/model/group/Group.java @@ -23,10 +23,10 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.model.group; -import me.lucko.luckperms.api.caching.GroupData; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.model.PermissionHolder; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -54,7 +54,6 @@ public interface Group extends PermissionHolder { * {@link #getName() actual name}.

    * * @return the display name - * @since 4.3 */ @Nullable String getDisplayName(); @@ -66,7 +65,6 @@ public interface Group extends PermissionHolder { * * @param contextSet the contexts to lookup in * @return the display name - * @since 4.3 */ @Nullable String getDisplayName(@NonNull ContextSet contextSet); @@ -74,17 +72,7 @@ public interface Group extends PermissionHolder { * Gets the weight of this group, if present. * * @return the group weight - * @since 2.17 */ @NonNull OptionalInt getWeight(); - /** - * Gets the groups's {@link GroupData} cache. - * - * @return the groups cached data. - * @since 4.0 - */ - @Override - @NonNull GroupData getCachedData(); - } diff --git a/api/src/main/java/me/lucko/luckperms/api/manager/GroupManager.java b/api/src/main/java/me/lucko/luckperms/api/model/group/GroupManager.java similarity index 67% rename from api/src/main/java/me/lucko/luckperms/api/manager/GroupManager.java rename to api/src/main/java/me/lucko/luckperms/api/model/group/GroupManager.java index b6557114b..5211c185f 100644 --- a/api/src/main/java/me/lucko/luckperms/api/manager/GroupManager.java +++ b/api/src/main/java/me/lucko/luckperms/api/model/group/GroupManager.java @@ -23,11 +23,9 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.manager; +package me.lucko.luckperms.api.model.group; -import me.lucko.luckperms.api.Group; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.Storage; +import me.lucko.luckperms.api.node.HeldNode; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -51,8 +49,6 @@ import java.util.function.Consumer; * not be called on the main server thread. If you need to use * the result of these operations on the main server thread, register a * callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.

    - * - * @since 4.0 */ public interface GroupManager { @@ -62,17 +58,9 @@ public interface GroupManager { * *

    If a group by the same name already exists, it will be loaded.

    * - *

    This method is effectively the same as - * {@link Storage#createAndLoadGroup(String)}, however, the Future returns - * the resultant group instance instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a group cannot be loaded, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param name the name of the group * @return the resultant group * @throws NullPointerException if the name is null - * @since 4.1 */ @NonNull CompletableFuture createAndLoadGroup(@NonNull String name); @@ -82,17 +70,9 @@ public interface GroupManager { *

    Returns an {@link Optional#empty() empty optional} if the group does * not exist.

    * - *

    This method is effectively the same as - * {@link Storage#loadGroup(String)}, however, the Future returns - * the resultant group instance instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a group cannot be loaded, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param name the name of the group * @return the resultant group * @throws NullPointerException if the name is null - * @since 4.1 */ @NonNull CompletableFuture> loadGroup(@NonNull String name); @@ -101,48 +81,27 @@ public interface GroupManager { * *

    You should call this after you make any changes to a group.

    * - *

    This method is effectively the same as {@link Storage#saveGroup(Group)}, - * however, the Future returns void instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a group cannot be saved, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param group the group to save * @return a future to encapsulate the operation. * @throws NullPointerException if group is null * @throws IllegalStateException if the group instance was not obtained from LuckPerms. - * @since 4.1 */ @NonNull CompletableFuture saveGroup(@NonNull Group group); /** * Permanently deletes a group from the plugin's storage provider. * - *

    This method is effectively the same as {@link Storage#deleteGroup(Group)}, - * however, the Future returns void instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a group cannot be deleted, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param group the group to delete * @return a future to encapsulate the operation. * @throws NullPointerException if group is null * @throws IllegalStateException if the group instance was not obtained from LuckPerms. - * @since 4.1 */ @NonNull CompletableFuture deleteGroup(@NonNull Group group); /** * Loads all groups into memory. * - *

    This method is effectively the same as {@link Storage#loadAllTracks()}, - * however, the Future returns void instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a group cannot be loaded, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @return a future to encapsulate the operation. - * @since 4.1 */ @NonNull CompletableFuture loadAllGroups(); @@ -152,9 +111,8 @@ public interface GroupManager { * @param permission the permission to search for * @return a list of held permissions, or null if the operation failed * @throws NullPointerException if the permission is null - * @since 4.2 */ - @NonNull CompletableFuture>> getWithPermission(@NonNull String permission); + @NonNull CompletableFuture>> getWithPermission(@NonNull String permission); /** * Gets a loaded group. @@ -165,19 +123,6 @@ public interface GroupManager { */ @Nullable Group getGroup(@NonNull String name); - /** - * Gets a loaded group. - * - *

    This method does not return null, unlike {@link #getGroup}

    - * - * @param name the name of the group to get - * @return an optional {@link Group} object - * @throws NullPointerException if the name is null - */ - default @NonNull Optional getGroupOpt(@NonNull String name) { - return Optional.ofNullable(getGroup(name)); - } - /** * Gets a set of all loaded groups. * diff --git a/api/src/main/java/me/lucko/luckperms/api/User.java b/api/src/main/java/me/lucko/luckperms/api/model/user/User.java similarity index 74% rename from api/src/main/java/me/lucko/luckperms/api/User.java rename to api/src/main/java/me/lucko/luckperms/api/model/user/User.java index 147e160e1..8c0be318d 100644 --- a/api/src/main/java/me/lucko/luckperms/api/User.java +++ b/api/src/main/java/me/lucko/luckperms/api/model/user/User.java @@ -23,9 +23,10 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.model.user; -import me.lucko.luckperms.api.caching.UserData; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.model.PermissionHolder; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -42,7 +43,7 @@ public interface User extends PermissionHolder { * * @return the users Mojang assigned unique id */ - @NonNull UUID getUuid(); + @NonNull UUID getUniqueId(); /** * Gets the users username @@ -51,7 +52,7 @@ public interface User extends PermissionHolder { * * @return the users username */ - @Nullable String getName(); + @Nullable String getUsername(); /** * Gets the users current primary group. @@ -77,32 +78,4 @@ public interface User extends PermissionHolder { */ @NonNull DataMutateResult setPrimaryGroup(@NonNull String group); - /** - * Gets the user's {@link UserData} cache. - * - * @return the users cached data. - * @since 3.2 - */ - @Override - @NonNull UserData getCachedData(); - - /** - * Refresh and re-assign the users permissions. - * - * @deprecated Calling this method is no longer necessary. Permissions data is now refreshed on - * demand, as changes are made. Consider use of {@link #refreshCachedData()} - * instead. This method is now implemented as a no-op. - */ - @Deprecated - void refreshPermissions(); - - /** - * Pre-calculates some values in the user's data cache. - * - * @since 2.17 - * @deprecated Use of this method is no longer necessary. It is implemented as a no-op. - */ - @Deprecated - void setupDataCache(); - } diff --git a/api/src/main/java/me/lucko/luckperms/api/manager/UserManager.java b/api/src/main/java/me/lucko/luckperms/api/model/user/UserManager.java similarity index 74% rename from api/src/main/java/me/lucko/luckperms/api/manager/UserManager.java rename to api/src/main/java/me/lucko/luckperms/api/model/user/UserManager.java index 2413fc036..e207719ea 100644 --- a/api/src/main/java/me/lucko/luckperms/api/manager/UserManager.java +++ b/api/src/main/java/me/lucko/luckperms/api/model/user/UserManager.java @@ -23,18 +23,15 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.manager; +package me.lucko.luckperms.api.model.user; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.PlayerSaveResult; -import me.lucko.luckperms.api.Storage; -import me.lucko.luckperms.api.User; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.node.HeldNode; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; -import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -56,43 +53,25 @@ import java.util.function.Consumer; * not be called on the main server thread. If you need to use * the result of these operations on the main server thread, register a * callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.

    - * - * @since 4.0 */ public interface UserManager { /** * Loads a user from the plugin's storage provider into memory. * - *

    This method is effectively the same as - * {@link Storage#loadUser(UUID, String)}, however, the Future returns the - * resultant user instance instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a user cannot be loaded, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param uuid the uuid of the user * @param username the username, if known * @return the resultant user * @throws NullPointerException if the uuid is null - * @since 4.1 */ @NonNull CompletableFuture loadUser(@NonNull UUID uuid, @Nullable String username); /** * Loads a user from the plugin's storage provider into memory. * - *

    This method is effectively the same as {@link Storage#loadUser(UUID)}, - * however, the Future returns the resultant user instance instead of a - * boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a user cannot be loaded, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param uuid the uuid of the user * @return the resultant user * @throws NullPointerException if the uuid is null - * @since 4.1 */ default @NonNull CompletableFuture loadUser(@NonNull UUID uuid) { return loadUser(uuid, null); @@ -107,9 +86,8 @@ public interface UserManager { * @return a uuid, could be null * @throws NullPointerException if either parameters are null * @throws IllegalArgumentException if the username is invalid - * @since 4.2 */ - @NonNull CompletableFuture lookupUuid(@NonNull String username); + @NonNull CompletableFuture lookupUniqueId(@NonNull String username); /** * Uses the LuckPerms cache to find a username for the given uuid. @@ -118,7 +96,6 @@ public interface UserManager { * @return a username, could be null * @throws NullPointerException if either parameters are null * @throws IllegalArgumentException if the username is invalid - * @since 4.2 */ @NonNull CompletableFuture lookupUsername(@NonNull UUID uuid); @@ -127,17 +104,10 @@ public interface UserManager { * *

    You should call this after you make any changes to a user.

    * - *

    This method is effectively the same as {@link Storage#saveUser(User)}, - * however, the Future returns void instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a user cannot be saved, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param user the user to save * @return a future to encapsulate the operation. * @throws NullPointerException if user is null * @throws IllegalStateException if the user instance was not obtained from LuckPerms. - * @since 4.1 */ @NonNull CompletableFuture saveUser(@NonNull User user); @@ -149,7 +119,6 @@ public interface UserManager { * @return the result of the operation. * @throws NullPointerException if either parameters are null * @throws IllegalArgumentException if the username is invalid - * @since 4.2 */ @NonNull CompletableFuture savePlayerData(@NonNull UUID uuid, @NonNull String username); @@ -159,7 +128,6 @@ public interface UserManager { *

    "Unique" meaning the user isn't just a member of the "default" group.

    * * @return a set of uuids - * @since 4.2 */ @NonNull CompletableFuture> getUniqueUsers(); @@ -169,9 +137,8 @@ public interface UserManager { * @param permission the permission to search for * @return a list of held permissions * @throws NullPointerException if the permission is null - * @since 4.2 */ - @NonNull CompletableFuture>> getWithPermission(@NonNull String permission); + @NonNull CompletableFuture>> getWithPermission(@NonNull String permission); /** * Gets a loaded user. @@ -182,17 +149,6 @@ public interface UserManager { */ @Nullable User getUser(@NonNull UUID uuid); - /** - * Gets a loaded user. - * - * @param uuid the uuid of the user to get - * @return an optional {@link User} object - * @throws NullPointerException if the uuid is null - */ - default @NonNull Optional getUserOpt(@NonNull UUID uuid) { - return Optional.ofNullable(getUser(uuid)); - } - /** * Gets a loaded user. * @@ -202,17 +158,6 @@ public interface UserManager { */ @Nullable User getUser(@NonNull String name); - /** - * Gets a loaded user. - * - * @param name the username of the user to get - * @return an optional {@link User} object - * @throws NullPointerException if the name is null - */ - default @NonNull Optional getUserOpt(@NonNull String name) { - return Optional.ofNullable(getUser(name)); - } - /** * Gets a set of all loaded users. * diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/MetaType.java b/api/src/main/java/me/lucko/luckperms/api/node/ChatMetaType.java similarity index 64% rename from api/src/main/java/me/lucko/luckperms/api/nodetype/types/MetaType.java rename to api/src/main/java/me/lucko/luckperms/api/node/ChatMetaType.java index 69e30d2aa..6ac530d6c 100644 --- a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/MetaType.java +++ b/api/src/main/java/me/lucko/luckperms/api/node/ChatMetaType.java @@ -23,45 +23,47 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.nodetype.types; +package me.lucko.luckperms.api.node; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; +import me.lucko.luckperms.api.node.types.ChatMetaNode; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.Map; - /** - * A sub-type of {@link Node} used to store meta assignments. - * - * @since 4.2 + * Represents a type of chat meta */ -public interface MetaType extends NodeType, Map.Entry { +public enum ChatMetaType { /** - * The key for this type. + * Represents a prefix */ - NodeTypeKey KEY = new NodeTypeKey(){}; + PREFIX(NodeType.PREFIX), /** - * Gets the meta key. + * Represents a suffix + */ + SUFFIX(NodeType.SUFFIX); + + private final String name; + private final NodeType> nodeType; + + ChatMetaType(NodeType> nodeType) { + this.name = nodeType.name().toLowerCase(); + this.nodeType = nodeType; + } + + /** + * Gets the {@link NodeType} for the {@link ChatMetaType}. * - * @return the meta key + * @return the node type */ - @NonNull String getKey(); - - /** - * Gets the meta value. - * - * @return the meta value - */ - @NonNull String getValue(); + public @NonNull NodeType> nodeType() { + return this.nodeType; + } @Override - @Deprecated - default String setValue(String value) { - throw new UnsupportedOperationException(); + public String toString() { + return this.name; } + } diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/WeightType.java b/api/src/main/java/me/lucko/luckperms/api/node/HeldNode.java similarity index 72% rename from api/src/main/java/me/lucko/luckperms/api/nodetype/types/WeightType.java rename to api/src/main/java/me/lucko/luckperms/api/node/HeldNode.java index b4f781922..21077f33d 100644 --- a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/WeightType.java +++ b/api/src/main/java/me/lucko/luckperms/api/node/HeldNode.java @@ -23,29 +23,31 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.nodetype.types; +package me.lucko.luckperms.api.node; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; +import me.lucko.luckperms.api.model.PermissionHolder; + +import org.checkerframework.checker.nullness.qual.NonNull; /** - * A sub-type of {@link Node} used to mark the weight of the node's holder. + * A relationship between a {@link PermissionHolder} and a {@link Node}. * - * @since 4.2 + * @param the identifier type of the holder */ -public interface WeightType extends NodeType { +public interface HeldNode { /** - * The key for this type. - */ - NodeTypeKey KEY = new NodeTypeKey(){}; - - /** - * Gets the weight value. + * Gets the holder of the node * - * @return the weight + * @return the holder */ - int getWeight(); + @NonNull T getHolder(); + + /** + * Gets the node + * + * @return the node + */ + @NonNull Node getNode(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/node/Node.java b/api/src/main/java/me/lucko/luckperms/api/node/Node.java new file mode 100644 index 000000000..07186c0c2 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/Node.java @@ -0,0 +1,237 @@ +/* + * 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.api.node; + +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.node.types.DisplayNameNode; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.node.types.PermissionNode; +import me.lucko.luckperms.api.node.types.PrefixNode; +import me.lucko.luckperms.api.node.types.RegexPermissionNode; +import me.lucko.luckperms.api.node.types.SuffixNode; +import me.lucko.luckperms.api.node.types.WeightNode; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +/** + * Represents a LuckPerms "node". + * + *

    The {@link Node} class encapsulates more than just permission assignments. + * Nodes are used to store data about inherited groups, as well as assigned + * prefixes, suffixes and meta values.

    + * + *

    Combining these various states into one object (a "node") means that a + * holder only has to have one type of data set (a set of nodes) in order to + * take on various properties.

    + * + *

    It is recommended that users of the API make use of {@link Stream}s + * to manipulate data and obtain the required information.

    + * + *

    This interface provides a number of methods to read the attributes of the + * node, as well as methods to query and extract additional state and properties + * from these settings.

    + * + *

    Nodes have the following attributes:

    + *

    + *
      + *
    • {@link #getKey() key} - the key of the node
    • + *
    • {@link #getValue() value} - the value of the node (false for negated)
    • + *
    • {@link #getContexts() context} - the contexts required for this node to apply
    • + *
    • {@link #getExpiry() expiry} - the time when this node should expire
    • + *
    + * + *

    There are a number of node types, all of which extend from this class:

    + *

    + *
      + *
    • {@link PermissionNode} - represents an assigned permission
    • + *
    • {@link RegexPermissionNode} - represents an assigned regex permission
    • + *
    • {@link InheritanceNode} - an "inheritance node" marks that the holder should inherit data from another group
    • + *
    • {@link PrefixNode} - represents an assigned prefix
    • + *
    • {@link SuffixNode} - represents an assigned suffix
    • + *
    • {@link MetaNode} - represents an assigned meta option
    • + *
    • {@link WeightNode} - marks the weight of the object holding this node
    • + *
    • {@link DisplayNameNode} - marks the display name of the object holding this node
    • + *
    + * + *

    The core node state must be immutable in all implementations.

    + */ +public interface Node { + + /** + * Gets a {@link NodeBuilder} for the given node {@link #getKey() key}. + * + * @param key the key + * @return the node builder + */ + static @NonNull NodeBuilder builder(@NonNull String key) { + return LuckPermsProvider.get().getNodeBuilderRegistry().forKey(key); + } + + /** + * Gets the key ({@link String}) of the node. + * + * @return the key + */ + @NonNull String getKey(); + + /** + * Gets the value of the node. + * + *

    A negated setting would result in a value of false.

    + * + * @return the nodes value + */ + boolean getValue(); + + /** + * Gets if the node is negated. + * + *

    This is the inverse of the {@link #getValue() value}.

    + * + * @return true if the node is negated + */ + default boolean isNegated() { + return !getValue(); + } + + /** + * Gets if this node applies globally, and therefore has no specific context. + * + * @return true if this node applies globally, and has no specific context + */ + boolean appliesGlobally(); + + /** + * Gets if this node should apply in the given context + * + * @param contextSet the context set + * @return true if the node should apply + */ + boolean shouldApplyWithContext(@NonNull ContextSet contextSet); + + /** + * Resolves any shorthand parts of this node and returns the full list of + * resolved nodes. + * + *

    The list will not contain the exact permission itself.

    + * + * @return a list of full nodes + */ + @NonNull List resolveShorthand(); + + /** + * Gets if this node is assigned temporarily. + * + * @return true if this node will expire in the future + */ + boolean hasExpiry(); + + /** + * Gets the time when this node will expire. + * + * @return the {@link Instant} when this node will expire, or null if it + * doesn't have an expiry time + */ + @Nullable Instant getExpiry() throws IllegalStateException; + + /** + * Gets if the node has expired. + * + *

    This returns false if the node is not temporary.

    + * + * @return true if this node has expired + */ + boolean hasExpired(); + + /** + * Gets the contexts required for this node to apply. + * + * @return the contexts required for this node to apply + */ + @NonNull ImmutableContextSet getContexts(); + + /** + * Gets the metadata corresponding to the given key, if present. + * + * @param key the key + * @param the {@link NodeMetadata} type + * @return the data, if present + */ + Optional getMetadata(NodeMetadataKey key); + + /** + * Gets the metadata corresponding to the given key, throwing an exception + * if no data is present. + * + * @param key the key + * @param the {@link NodeMetadata} type + * @return the data + * @throws IllegalStateException if data isn't present + */ + default T metadata(NodeMetadataKey key) throws IllegalStateException { + return getMetadata(key).orElseThrow(() -> new IllegalStateException("Node '" + getKey() + "' does not have '" + key.name() + "' attached.")); + } + + /** + * Gets if this Node is equal to another node. + * + * @param obj the other node + * @return true if this node is equal to the other provided + * @see NodeEqualityPredicate#EXACT + */ + @Override + boolean equals(Object obj); + + /** + * Gets if this Node is equal to another node as defined by the given + * {@link NodeEqualityPredicate}. + * + * @param other the other node + * @param equalityPredicate the predicate + * @return true if this node is considered equal + */ + boolean equals(@NonNull Node other, @NonNull NodeEqualityPredicate equalityPredicate); + + /** + * Gets a {@link NodeBuilder}, with the attributes of this node already + * applied. + * + * @return an editable, builder form of this node + */ + @NonNull NodeBuilder toBuilder(); + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilder.java b/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilder.java new file mode 100644 index 000000000..71e622848 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilder.java @@ -0,0 +1,149 @@ +/* + * 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.api.node; + +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +/** + * Builder for {@link Node}s. + * + * @param the node type + * @param the node builder type + */ +public interface NodeBuilder, B extends NodeBuilder> { + + /** + * Sets the value of the node. + * + * @param value the value + * @return the builder + * @see Node#getValue() + */ + @NonNull B value(boolean value); + + /** + * Sets the value of negated for the node. + * + * @param negated the value + * @return the builder + * @see Node#isNegated() + */ + @NonNull B negated(boolean negated); + + /** + * Sets the time when the node should expire. + * + *

    The parameter passed to this method must be the unix timestamp + * (in seconds) when the node should expire.

    + * + * @param expiryUnixTimestamp the expiry timestamp (unix seconds) + * @return the builder + * @see Node#getExpiry() + */ + @NonNull B expiry(long expiryUnixTimestamp); + + /** + * Sets the time when the node should expire. + * + *

    The expiry timestamp is calculated relative to the current + * system time.

    + * + * @param duration how long the node should be added for + * @param unit the unit duration is measured in + * @return the builder + */ + default @NonNull B expiry(long duration, TimeUnit unit) { + if (duration <= 0) { + throw new IllegalArgumentException("duration must be positive"); + } + long seconds = Objects.requireNonNull(unit, "unit").toSeconds(duration); + long timeNow = System.currentTimeMillis() / 1000L; + return expiry(timeNow + seconds); + } + + /** + * Marks that the node being built should never expire. + * + * @return the builder + */ + @NonNull B clearExpiry(); + + /** + * Sets the extra contexts for the node. + * + * @param contextSet a context set + * @return the builder + * @see ContextSet + * @see Node#getContexts() + */ + @NonNull B context(@NonNull ContextSet contextSet); + + /** + * Appends an extra context onto the node. + * + * @param key the context key + * @param value the context value + * @return the builder + * @see ContextSet + * @see Node#getContexts() + */ + @NonNull B withContext(@NonNull String key, @NonNull String value); + + /** + * Appends extra contexts onto the node. + * + * @param contextSet a context set + * @return the builder + * @see ContextSet + * @see Node#getContexts() + */ + @NonNull B withContext(@NonNull ContextSet contextSet); + + /** + * Sets the given metadata for the node. + * + * @param key the metadata key + * @param metadata the metadata + * @param the metadata type + * @return the builder + */ + @NonNull B withMetadata(@NonNull NodeMetadataKey key, @Nullable T metadata); + + /** + * Creates a {@link Node} instance from the builder. + * + * @return a new node instance + */ + @NonNull N build(); +} diff --git a/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilderRegistry.java b/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilderRegistry.java new file mode 100644 index 000000000..7833fde7a --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/NodeBuilderRegistry.java @@ -0,0 +1,109 @@ +/* + * 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.api.node; + +import me.lucko.luckperms.api.node.types.DisplayNameNode; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.node.types.PermissionNode; +import me.lucko.luckperms.api.node.types.PrefixNode; +import me.lucko.luckperms.api.node.types.RegexPermissionNode; +import me.lucko.luckperms.api.node.types.SuffixNode; +import me.lucko.luckperms.api.node.types.WeightNode; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * A registry of methods for obtaining {@link NodeBuilder}s for the various + * node types. + */ +public interface NodeBuilderRegistry { + + /** + * Gets a {@link NodeBuilder} applicable for the given key. + * + * @param key the key + * @return the node builder + */ + @NonNull NodeBuilder forKey(String key); + + /** + * Gets a {@link NodeBuilder} for {@link PermissionNode}s. + * + * @return the node builder + */ + PermissionNode.@NonNull Builder forPermission(); + + /** + * Gets a {@link NodeBuilder} for {@link RegexPermissionNode}s. + * + * @return the node builder + */ + RegexPermissionNode.@NonNull Builder forRegexPermission(); + + /** + * Gets a {@link NodeBuilder} for {@link InheritanceNode}s. + * + * @return the node builder + */ + InheritanceNode.@NonNull Builder forInheritance(); + + /** + * Gets a {@link NodeBuilder} for {@link PrefixNode}s. + * + * @return the node builder + */ + PrefixNode.@NonNull Builder forPrefix(); + + /** + * Gets a {@link NodeBuilder} for {@link SuffixNode}s. + * + * @return the node builder + */ + SuffixNode.@NonNull Builder forSuffix(); + + /** + * Gets a {@link NodeBuilder} for {@link MetaNode}s. + * + * @return the node builder + */ + MetaNode.@NonNull Builder forMeta(); + + /** + * Gets a {@link NodeBuilder} for {@link WeightNode}s. + * + * @return the node builder + */ + WeightNode.@NonNull Builder forWeight(); + + /** + * Gets a {@link NodeBuilder} for {@link DisplayNameNode}s. + * + * @return the node builder + */ + DisplayNameNode.@NonNull Builder forDisplayName(); + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/StandardNodeEquality.java b/api/src/main/java/me/lucko/luckperms/api/node/NodeEqualityPredicate.java similarity index 51% rename from api/src/main/java/me/lucko/luckperms/api/StandardNodeEquality.java rename to api/src/main/java/me/lucko/luckperms/api/node/NodeEqualityPredicate.java index 6b06c44db..467e2ddbb 100644 --- a/api/src/main/java/me/lucko/luckperms/api/StandardNodeEquality.java +++ b/api/src/main/java/me/lucko/luckperms/api/node/NodeEqualityPredicate.java @@ -23,16 +23,39 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.node; import org.checkerframework.checker.nullness.qual.NonNull; /** - * Standard {@link NodeEqualityPredicate}s. + * A rule for determining if two nodes are equal. * - * @since 4.1 + *

    Generally, implementations of this interface should fulfil the same + * requirements as the {@link Object#equals(Object)} contract.

    */ -public enum StandardNodeEquality implements NodeEqualityPredicate { +@FunctionalInterface +public interface NodeEqualityPredicate { + + /** + * Returns if the two nodes are equal. + * + *

    This method should avoid making calls to {@link Node#equals(Node, NodeEqualityPredicate)} + * with {@code this} as the second argument, directly or otherwise.

    + * + * @param o1 the first node + * @param o2 the second node + * @return true if equal + */ + boolean areEqual(@NonNull Node o1, @NonNull Node o2); + + + /* + * Some 'default' implementations of NodeEqualityPredicate are provided below. + * + * These are implemented in the common code, by a special case in the + * implementation of Node#equals. As noted above, this should generally be + * avoided. + */ /** * Represents an exact match. @@ -40,13 +63,17 @@ public enum StandardNodeEquality implements NodeEqualityPredicate { *

    All attributes of the nodes must match for them to be considered * equal.

    */ - EXACT, + NodeEqualityPredicate EXACT = new NodeEqualityPredicate() { + @Override public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { return o1.equals(o2, this); } + }; /** * All attributes must match, except for * {@link Node#getValue() value}, which is ignored. */ - IGNORE_VALUE, + NodeEqualityPredicate IGNORE_VALUE = new NodeEqualityPredicate() { + @Override public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { return o1.equals(o2, this); } + }; /** * All attributes must match, except for the @@ -55,24 +82,26 @@ public enum StandardNodeEquality implements NodeEqualityPredicate { *

    Note that with this setting, whether a node is temporary or not is * still considered.

    */ - IGNORE_EXPIRY_TIME, + NodeEqualityPredicate IGNORE_EXPIRY_TIME = new NodeEqualityPredicate() { + @Override public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { return o1.equals(o2, this); } + }; /** * All attributes must match, except for * {@link Node#getValue() value} and the * {@link Node#getExpiry() expiry time}, which are ignored. */ - IGNORE_EXPIRY_TIME_AND_VALUE, + NodeEqualityPredicate IGNORE_EXPIRY_TIME_AND_VALUE = new NodeEqualityPredicate() { + @Override public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { return o1.equals(o2, this); } + }; /** * All attributes must match, except for * {@link Node#getValue() value} and the if the node is - * {@link Node#isTemporary() temporary}, which are ignored. + * {@link Node#hasExpiry() temporary}, which are ignored. */ - IGNORE_VALUE_OR_IF_TEMPORARY; + NodeEqualityPredicate IGNORE_VALUE_OR_IF_TEMPORARY = new NodeEqualityPredicate() { + @Override public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { return o1.equals(o2, this); } + }; - @Override - public boolean areEqual(@NonNull Node o1, @NonNull Node o2) { - return o1.equals(o2, this); - } } diff --git a/api/src/main/java/me/lucko/luckperms/api/node/NodeType.java b/api/src/main/java/me/lucko/luckperms/api/node/NodeType.java new file mode 100644 index 000000000..e60a0510a --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/NodeType.java @@ -0,0 +1,166 @@ +/* + * 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.api.node; + +import me.lucko.luckperms.api.node.types.ChatMetaNode; +import me.lucko.luckperms.api.node.types.DisplayNameNode; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.node.types.PermissionNode; +import me.lucko.luckperms.api.node.types.PrefixNode; +import me.lucko.luckperms.api.node.types.RegexPermissionNode; +import me.lucko.luckperms.api.node.types.SuffixNode; +import me.lucko.luckperms.api.node.types.WeightNode; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * Represents a type of {@link Node}. + */ +public interface NodeType { + + /** + * Node type for {@link PermissionNode}. + */ + NodeType PERMISSION = new SimpleNodeType<>("PERMISSION", n -> n instanceof PermissionNode, n -> ((PermissionNode) n)); + + /** + * Node type for {@link RegexPermissionNode}. + */ + NodeType REGEX_PERMISSION = new SimpleNodeType<>("REGEX_PERMISSION", n -> n instanceof RegexPermissionNode, n -> ((RegexPermissionNode) n)); + + /** + * Node type for {@link InheritanceNode}. + */ + NodeType INHERITANCE = new SimpleNodeType<>("INHERITANCE", n -> n instanceof InheritanceNode, n -> ((InheritanceNode) n)); + + /** + * Node type for {@link PrefixNode}. + */ + NodeType PREFIX = new SimpleNodeType<>("PREFIX", n -> n instanceof PrefixNode, n -> ((PrefixNode) n)); + + /** + * Node type for {@link SuffixNode}. + */ + NodeType SUFFIX = new SimpleNodeType<>("SUFFIX", n -> n instanceof SuffixNode, n -> ((SuffixNode) n)); + + /** + * Node type for {@link MetaNode}. + */ + NodeType META = new SimpleNodeType<>("META", n -> n instanceof MetaNode, n -> ((MetaNode) n)); + + /** + * Node type for {@link WeightNode}. + */ + NodeType WEIGHT = new SimpleNodeType<>("WEIGHT", n -> n instanceof WeightNode, n -> ((WeightNode) n)); + + /** + * Node type for {@link DisplayNameNode}. + */ + NodeType DISPLAY_NAME = new SimpleNodeType<>("DISPLAY_NAME", n -> n instanceof DisplayNameNode, n -> ((DisplayNameNode) n)); + + /** + * Node type for {@link ChatMetaNode}. + */ + NodeType> CHAT_META = new SimpleNodeType<>("CHAT_META", n -> n instanceof ChatMetaNode, n -> ((ChatMetaNode) n)); + + /** + * Node type for {@link ChatMetaNode} or {@link MetaNode}. + */ + NodeType META_OR_CHAT_META = new SimpleNodeType<>("META_OR_CHAT_META", n -> META.matches(n) || CHAT_META.matches(n), Function.identity()); + + /** + * Gets a name for the node type. + * + * @return a name + */ + String name(); + + /** + * Returns if the passed node matches the type + * + * @param node the node to test + * @return true if the node has the same type + */ + boolean matches(Node node); + + /** + * Casts the given {@link Node} to the type defined by the {@link NodeType}. + * + *

    An {@link IllegalArgumentException} is thrown if the node to cast does + * not {@link #matches(Node) match} the type.

    + * + * @param node the node to cast + * @return the casted node + * @throws IllegalArgumentException if the node to cast does not match the type + */ + T cast(Node node); + + /** + * Attempts to cast the given {@link Node} to the type defined by the + * {@link NodeType}. + * + *

    Returns an {@link Optional#empty() empty optional} if the node to cast + * does not {@link #matches(Node) match} the type.

    + * + * @param node the node to cast + * @return an optional, possibly containing a casted node + */ + default Optional tryCast(Node node) { + Objects.requireNonNull(node, "node"); + if (!matches(node)) { + return Optional.empty(); + } else { + return Optional.of(cast(node)); + } + } + + /** + * Returns a {@link Predicate}, returning whether a {@link Node} + * {@link #matches(Node) matches} this type. + * + * @return a predicate for the {@link #matches(Node)} method. + */ + default Predicate predicate() { + return this::matches; + } + + /** + * Returns a {@link Predicate}, returning whether a {@link Node} + * {@link #matches(Node) matches} this type, and passes the given + * {@code and} {@link Predicate}. + * + * @param and a predicate to AND with the result of the type match check + * @return a matching predicate, ANDed with the given predicate parameter + */ + default Predicate predicate(Predicate and) { + return node -> matches(node) && and.test(cast(node)); + } + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/node/ScopedNode.java b/api/src/main/java/me/lucko/luckperms/api/node/ScopedNode.java new file mode 100644 index 000000000..8a78241f8 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/ScopedNode.java @@ -0,0 +1,42 @@ +/* + * 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.api.node; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * A {@link Node}, with its own type and the type of its associated builder + * defined as a type parameter. + * + * @param the node type + * @param the node builder type + */ +public interface ScopedNode, B extends NodeBuilder> extends Node { + + @Override + @NonNull B toBuilder(); + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableTransientNode.java b/api/src/main/java/me/lucko/luckperms/api/node/SimpleNodeType.java similarity index 61% rename from common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableTransientNode.java rename to api/src/main/java/me/lucko/luckperms/api/node/SimpleNodeType.java index 47aca455f..6626ecb8b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableTransientNode.java +++ b/api/src/main/java/me/lucko/luckperms/api/node/SimpleNodeType.java @@ -23,45 +23,44 @@ * SOFTWARE. */ -package me.lucko.luckperms.common.node.model; - -import me.lucko.luckperms.api.Node; +package me.lucko.luckperms.api.node; import java.util.Objects; +import java.util.function.Function; +import java.util.function.Predicate; -/** - * Holds a Node and plus an owning object. All calls are passed onto the contained Node instance. - */ -public final class ImmutableTransientNode extends ForwardingNode implements Node { - public static ImmutableTransientNode of(Node node, O owner) { - Objects.requireNonNull(node, "node"); - Objects.requireNonNull(owner, "owner"); - return new ImmutableTransientNode<>(node, owner); - } +final class SimpleNodeType implements NodeType { + private final String name; + private final Predicate matches; + private final Function cast; - private final Node node; - private final O owner; - - private ImmutableTransientNode(Node node, O owner) { - this.node = node; - this.owner = owner; + SimpleNodeType(String name, Predicate matches, Function cast) { + this.name = name; + this.matches = matches; + this.cast = cast; } @Override - public Node delegate() { - return this.node; + public String name() { + return this.name; } - public Node getNode() { - return this.node; + @Override + public boolean matches(Node node) { + Objects.requireNonNull(node, "node"); + return this.matches.test(node); } - public O getOwner() { - return this.owner; + @Override + public T cast(Node node) { + if (!matches(node)) { + throw new IllegalArgumentException("Node " + node.getClass() + " does not match " + this.name); + } + return this.cast.apply(node); } @Override public String toString() { - return "ImmutableTransientNode(node=" + this.getNode() + ", owner=" + this.getOwner() + ")"; + return name(); } } diff --git a/api/src/main/java/me/lucko/luckperms/api/Tristate.java b/api/src/main/java/me/lucko/luckperms/api/node/Tristate.java similarity index 91% rename from api/src/main/java/me/lucko/luckperms/api/Tristate.java rename to api/src/main/java/me/lucko/luckperms/api/node/Tristate.java index 4bd832d0d..7218e75d2 100644 --- a/api/src/main/java/me/lucko/luckperms/api/Tristate.java +++ b/api/src/main/java/me/lucko/luckperms/api/node/Tristate.java @@ -23,7 +23,7 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.node; import org.checkerframework.checker.nullness.qual.NonNull; @@ -61,22 +61,21 @@ public enum Tristate { * @param val the boolean value * @return {@link #TRUE} or {@link #FALSE}, if the value is true or false, respectively. */ - public static @NonNull Tristate fromBoolean(boolean val) { + public static @NonNull Tristate of(boolean val) { return val ? TRUE : FALSE; } /** * Returns a {@link Tristate} from a nullable boolean. * - *

    Unlike {@link #fromBoolean(boolean)}, this method returns {@link #UNDEFINED} + *

    Unlike {@link #of(boolean)}, this method returns {@link #UNDEFINED} * if the value is null.

    * * @param val the boolean value * @return {@link #UNDEFINED}, {@link #TRUE} or {@link #FALSE}, if the value * is null, true or false, respectively. - * @since 4.1 */ - public static @NonNull Tristate fromNullableBoolean(Boolean val) { + public static @NonNull Tristate of(Boolean val) { return val == null ? UNDEFINED : val ? TRUE : FALSE; } diff --git a/api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadata.java b/api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadata.java new file mode 100644 index 000000000..f46cf0aa5 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadata.java @@ -0,0 +1,36 @@ +/* + * 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.api.node.metadata; + +import me.lucko.luckperms.api.node.Node; + +/** + * Generic interface for an {@link Object} which can be attached to a + * {@link Node} as metadata. + */ +public interface NodeMetadata { + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/HeldPermission.java b/api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadataKey.java similarity index 50% rename from api/src/main/java/me/lucko/luckperms/api/HeldPermission.java rename to api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadataKey.java index f56f7f65e..9ddd18089 100644 --- a/api/src/main/java/me/lucko/luckperms/api/HeldPermission.java +++ b/api/src/main/java/me/lucko/luckperms/api/node/metadata/NodeMetadataKey.java @@ -23,77 +23,56 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; - -import me.lucko.luckperms.api.context.ContextSet; +package me.lucko.luckperms.api.node.metadata; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.Optional; -import java.util.OptionalLong; +import java.util.Objects; /** - * A relationship between a {@link PermissionHolder} and a permission. + * Represents a key for a specific type of {@link NodeMetadata}. * - * @param the identifier type of the holder - * @since 2.17 + *

    Metadata keys are compared using reference equality, the + * {@link #equals(Object)} method should not be implemented.

    + * + *

    It is intended that {@link NodeMetadataKey}s are obtained and stored as + * follows.

    + *

    + *     public static final NodeMetadataKey SPECIAL_METADATA_KEY = NodeMetadataKey.of("SpecialMetadata", SpecialMetadata.class);
    + * 

    + * + * @param the metadata type */ -public interface HeldPermission { +public interface NodeMetadataKey { /** - * Gets the holder of the permission + * Creates a new {@link NodeMetadataKey} for the given name and type. * - * @return the holder + *

    Note that the returned key implements object reference equality.

    + * + * @param name the name + * @param type the type + * @param the type parameter + * @return the key */ - @NonNull T getHolder(); + static @NonNull NodeMetadataKey of(@NonNull String name, @NonNull Class type) { + Objects.requireNonNull(name, "name"); + Objects.requireNonNull(type, "type"); + return new SimpleNodeMetadataKey<>(name, type); + } /** - * Gets the permission being held + * Gets a name describing the key type. * - * @return the permission + * @return the key name */ - @NonNull String getPermission(); + @NonNull String name(); /** - * Gets the value of the permission + * Gets the type of the key * - * @return the value + * @return the type */ - boolean getValue(); - - /** - * Gets the server where the permission is held - * - * @return the server - */ - @NonNull Optional getServer(); - - /** - * Gets the world where the permission is held - * - * @return the world - */ - @NonNull Optional getWorld(); - - /** - * Gets the time in unix time when the permission will expire - * - * @return the expiry time - */ - @NonNull OptionalLong getExpiry(); - - /** - * Gets the extra context for the permission. - * - * @return the extra context - */ - @NonNull ContextSet getContexts(); - - /** - * Converts this permission into a Node - * - * @return a Node copy of this permission - */ - @NonNull Node asNode(); + @NonNull Class getType(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/node/metadata/SimpleNodeMetadataKey.java b/api/src/main/java/me/lucko/luckperms/api/node/metadata/SimpleNodeMetadataKey.java new file mode 100644 index 000000000..740278558 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/metadata/SimpleNodeMetadataKey.java @@ -0,0 +1,53 @@ +/* + * 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.api.node.metadata; + +import org.checkerframework.checker.nullness.qual.NonNull; + +final class SimpleNodeMetadataKey implements NodeMetadataKey { + private final String name; + private final Class type; + + SimpleNodeMetadataKey(String name, Class type) { + this.name = name; + this.type = type; + } + + @Override + public @NonNull String name() { + return this.name; + } + + @Override + public @NonNull Class getType() { + return this.type; + } + + @Override + public String toString() { + return "NodeMetadataKey(name=" + this.name + ", type=" + this.type.getName() + ")"; + } +} diff --git a/api/src/main/java/me/lucko/luckperms/api/LocalizedNode.java b/api/src/main/java/me/lucko/luckperms/api/node/metadata/types/InheritanceOriginMetadata.java similarity index 74% rename from api/src/main/java/me/lucko/luckperms/api/LocalizedNode.java rename to api/src/main/java/me/lucko/luckperms/api/node/metadata/types/InheritanceOriginMetadata.java index e9bf05c17..0db8be19c 100644 --- a/api/src/main/java/me/lucko/luckperms/api/LocalizedNode.java +++ b/api/src/main/java/me/lucko/luckperms/api/node/metadata/types/InheritanceOriginMetadata.java @@ -23,26 +23,24 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.node.metadata.types; + +import me.lucko.luckperms.api.model.PermissionHolder; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; import org.checkerframework.checker.nullness.qual.NonNull; /** - * An extension of {@link Node}, providing information about - * where the node originated from. - * - * @since 2.11 + * {@link NodeMetadata} indicating where a node was inherited from. */ -public interface LocalizedNode extends Node { +public interface InheritanceOriginMetadata extends NodeMetadata { /** - * Gets the delegate node. - * - *

    Result is never another {@link LocalizedNode} instance.

    - * - * @return the node this instance is representing + * The {@link NodeMetadataKey} for {@link InheritanceOriginMetadata}. */ - @NonNull Node getNode(); + NodeMetadataKey KEY = NodeMetadataKey.of("InheritanceOrigin", InheritanceOriginMetadata.class); /** * Gets the location where the {@link Node} is inherited from. @@ -55,6 +53,6 @@ public interface LocalizedNode extends Node { * * @return where the node was inherited from. */ - @NonNull String getLocation(); + @NonNull String getOrigin(); } diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/ChatMetaNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/ChatMetaNode.java new file mode 100644 index 000000000..07b372ebc --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/types/ChatMetaNode.java @@ -0,0 +1,81 @@ +/* + * 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.api.node.types; + +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.ScopedNode; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Represents a chat meta node. (a {@link PrefixNode} or {@link SuffixNode}) + * + * @param the node type + * @param the node builder type + */ +public interface ChatMetaNode, B extends ChatMetaNode.Builder> extends ScopedNode { + + /** + * Gets the priority. + * + * @return the priority + */ + int getPriority(); + + /** + * Gets the meta value. + * + * @return the value + */ + String getMetaValue(); + + /** + * Gets the type. + * + * @return the type + */ + @NonNull ChatMetaType getType(); + + /** + * A {@link ChatMetaNode} builder. + * + * @param the node type + * @param the node builder type + */ + interface Builder, B extends ChatMetaNode.Builder> extends NodeBuilder { + + /** + * Sets the priority. + * + * @param priority the priority + * @return the builder + */ + @NonNull B priority(int priority); + + } + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/DisplayNameNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/DisplayNameNode.java new file mode 100644 index 000000000..079d41e22 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/types/DisplayNameNode.java @@ -0,0 +1,81 @@ +/* + * 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.api.node.types; + +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.ScopedNode; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * A sub-type of {@link Node} used to mark the display name of the node's holder. + */ +public interface DisplayNameNode extends ScopedNode { + + /** + * Gets the display name. + * + * @return the display name + */ + @NonNull String getDisplayName(); + + /** + * Creates a {@link DisplayNameNode} builder. + * + * @return the builder + */ + static @NonNull Builder builder() { + return LuckPermsProvider.get().getNodeBuilderRegistry().forDisplayName(); + } + + /** + * Creates a {@link DisplayNameNode} builder. + * + * @param displayName the display name to set + * @return the builder + */ + static @NonNull Builder builder(@NonNull String displayName) { + return builder().displayName(displayName); + } + + /** + * A {@link DisplayNameNode} builder. + */ + interface Builder extends NodeBuilder { + + /** + * Sets the display name. + * + * @param displayName the display name + * @return the builder + */ + @NonNull Builder displayName(@NonNull String displayName); + + } + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/InheritanceNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/InheritanceNode.java new file mode 100644 index 000000000..98b532cd5 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/types/InheritanceNode.java @@ -0,0 +1,109 @@ +/* + * 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.api.node.types; + +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.model.group.Group; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.ScopedNode; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * A sub-type of {@link Node} used to mark that the holder of the node should inherit + * from another group. + */ +public interface InheritanceNode extends ScopedNode { + + /** + * Gets the name of the group to be inherited. + * + *

    This is no guarantee that this group exists.

    + * + * @return the name of the group + */ + @NonNull String getGroupName(); + + /** + * Creates a {@link InheritanceNode} builder. + * + * @return the builder + */ + static @NonNull Builder builder() { + return LuckPermsProvider.get().getNodeBuilderRegistry().forInheritance(); + } + + /** + * Creates a {@link InheritanceNode} builder. + * + * @param group the group to set + * @return the builder + */ + static @NonNull Builder builder(@NonNull String group) { + return builder().group(group); + } + + /** + * Sets the name of group to inherit. + * + * @param group the group name + * @return the builder + */ + static @NonNull Builder builder(@NonNull Group group) { + return builder().group(group); + } + + /** + * A {@link InheritanceNode} builder. + */ + interface Builder extends NodeBuilder { + + /** + * Sets the name of the group to inherit. + * + *

    Note that only one of this method and {@link #group(Group)} + * need be called.

    + * + * @param group the group name + * @return the builder + */ + @NonNull Builder group(@NonNull String group); + + /** + * Sets the group to inherit. + * + *

    Note that only one of this method and {@link #group(String)} + * need be called.

    + * + * @param group the group + * @return the builder + */ + @NonNull Builder group(@NonNull Group group); + + } + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/MetaNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/MetaNode.java new file mode 100644 index 000000000..77739aaf5 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/types/MetaNode.java @@ -0,0 +1,97 @@ +/* + * 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.api.node.types; + +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.ScopedNode; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * A sub-type of {@link Node} used to store meta assignments. + */ +public interface MetaNode extends ScopedNode { + + /** + * Gets the meta key. + * + * @return the meta key + */ + @NonNull String getMetaKey(); + + /** + * Gets the meta value. + * + * @return the meta value + */ + @NonNull String getMetaValue(); + + /** + * Creates a {@link MetaNode} builder. + * + * @return the builder + */ + static @NonNull Builder builder() { + return LuckPermsProvider.get().getNodeBuilderRegistry().forMeta(); + } + + /** + * Creates a {@link MetaNode} builder. + * + * @param key the meta key to set + * @param value the meta value to set + * @return the builder + */ + static @NonNull Builder builder(@NonNull String key, @NonNull String value) { + return builder().key(key).value(value); + } + + /** + * A {@link MetaNode} builder. + */ + interface Builder extends NodeBuilder { + + /** + * Sets the meta key. + * + * @param key the meta key + * @return the builder + */ + @NonNull Builder key(@NonNull String key); + + /** + * Sets the meta value. + * + * @param value the meta value + * @return the builder + */ + @NonNull Builder value(@NonNull String value); + + } + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/PermissionNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/PermissionNode.java new file mode 100644 index 000000000..7573ddce6 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/types/PermissionNode.java @@ -0,0 +1,106 @@ +/* + * 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.api.node.types; + +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.ScopedNode; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.OptionalInt; + +/** + * A sub-type of {@link Node} representing basic permissions. + */ +public interface PermissionNode extends ScopedNode { + + /** + * Gets the permission string this node encapsulates. + * + *

    The exact value of this string may vary for nodes which aren't regular + * permission settings.

    + * + * @return the actual permission node + */ + @NonNull String getPermission(); + + /** + * Gets if this node is a wildcard permission. + * + * @return true if this node is a wildcard permission + */ + boolean isWildcard(); + + /** + * Gets the level of this wildcard. + * + *

    The node luckperms.* has a wildcard level of 1.

    + *

    The node luckperms.user.permission.* has a wildcard level of 3.

    + * + *

    Nodes with a higher wildcard level are more specific and have priority over + * less specific nodes (nodes with a lower wildcard level).

    + * + * @return the wildcard level + */ + @NonNull OptionalInt getWildcardLevel(); + + /** + * Creates a {@link PermissionNode} builder. + * + * @return the builder + */ + static @NonNull Builder builder() { + return LuckPermsProvider.get().getNodeBuilderRegistry().forPermission(); + } + + /** + * Creates a {@link PermissionNode} builder. + * + * @param permission the permission to set + * @return the builder + */ + static @NonNull Builder builder(@NonNull String permission) { + return builder().permission(permission); + } + + /** + * A {@link PermissionNode} builder. + */ + interface Builder extends NodeBuilder { + + /** + * Sets the permission. + * + * @param permission the permission + * @return the builder + */ + @NonNull Builder permission(@NonNull String permission); + + } + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/PrefixType.java b/api/src/main/java/me/lucko/luckperms/api/node/types/PrefixNode.java similarity index 58% rename from api/src/main/java/me/lucko/luckperms/api/nodetype/types/PrefixType.java rename to api/src/main/java/me/lucko/luckperms/api/node/types/PrefixNode.java index 58f0efb4c..8a1d24c1a 100644 --- a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/PrefixType.java +++ b/api/src/main/java/me/lucko/luckperms/api/node/types/PrefixNode.java @@ -23,47 +23,51 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.nodetype.types; +package me.lucko.luckperms.api.node.types; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.node.Node; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.Map; - /** * A sub-type of {@link Node} used to store prefix assignments. - * - * @since 4.2 */ -public interface PrefixType extends NodeType { +public interface PrefixNode extends ChatMetaNode { /** - * The key for this type. - */ - NodeTypeKey KEY = new NodeTypeKey(){}; - - /** - * Gets the priority of the prefix assignment. + * Creates a {@link PrefixNode} builder. * - * @return the priority + * @return the builder */ - int getPriority(); + static @NonNull Builder builder() { + return LuckPermsProvider.get().getNodeBuilderRegistry().forPrefix(); + } /** - * Gets the actual prefix string. + * Creates a {@link PrefixNode} builder. * - * @return the prefix + * @param prefix the prefix to set + * @param priority the priority to set + * @return the builder */ - @NonNull String getPrefix(); + static @NonNull Builder builder(@NonNull String prefix, int priority) { + return builder().prefix(prefix).priority(priority); + } /** - * Gets a representation of this instance as a {@link Map.Entry}. - * - * @return a map entry representation of the priority and prefix string + * A {@link PrefixNode} builder. */ - Map.@NonNull Entry getAsEntry(); + interface Builder extends ChatMetaNode.Builder { + + /** + * Sets the prefix. + * + * @param prefix the prefix + * @return the builder + */ + @NonNull Builder prefix(@NonNull String prefix); + + } } diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/RegexType.java b/api/src/main/java/me/lucko/luckperms/api/node/types/RegexPermissionNode.java similarity index 53% rename from api/src/main/java/me/lucko/luckperms/api/nodetype/types/RegexType.java rename to api/src/main/java/me/lucko/luckperms/api/node/types/RegexPermissionNode.java index 13c0f1020..eecdb13be 100644 --- a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/RegexType.java +++ b/api/src/main/java/me/lucko/luckperms/api/node/types/RegexPermissionNode.java @@ -23,11 +23,12 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.nodetype.types; +package me.lucko.luckperms.api.node.types; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.ScopedNode; import org.checkerframework.checker.nullness.qual.NonNull; @@ -36,15 +37,8 @@ import java.util.regex.Pattern; /** * A sub-type of {@link Node} used to store regex permissions. - * - * @since 4.3 */ -public interface RegexType extends NodeType { - - /** - * The key for this type. - */ - NodeTypeKey KEY = new NodeTypeKey(){}; +public interface RegexPermissionNode extends ScopedNode { /** * Gets the non-compiled pattern string. @@ -62,4 +56,56 @@ public interface RegexType extends NodeType { */ @NonNull Optional getPattern(); + /** + * Creates a {@link RegexPermissionNode} builder. + * + * @return the builder + */ + static @NonNull Builder builder() { + return LuckPermsProvider.get().getNodeBuilderRegistry().forRegexPermission(); + } + + /** + * Creates a {@link RegexPermissionNode} builder. + * + * @param pattern the pattern to set + * @return the builder + */ + static @NonNull Builder builder(@NonNull String pattern) { + return builder().pattern(pattern); + } + + /** + * Creates a {@link RegexPermissionNode} builder. + * + * @param pattern the pattern to set + * @return the builder + */ + static @NonNull Builder builder(@NonNull Pattern pattern) { + return builder().pattern(pattern); + } + + /** + * A {@link RegexPermissionNode} builder. + */ + interface Builder extends NodeBuilder { + + /** + * Sets the pattern. + * + * @param pattern the pattern + * @return the builder + */ + @NonNull Builder pattern(@NonNull String pattern); + + /** + * Sets the pattern. + * + * @param pattern the pattern + * @return the builder + */ + @NonNull Builder pattern(@NonNull Pattern pattern); + + } + } diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/SuffixType.java b/api/src/main/java/me/lucko/luckperms/api/node/types/SuffixNode.java similarity index 58% rename from api/src/main/java/me/lucko/luckperms/api/nodetype/types/SuffixType.java rename to api/src/main/java/me/lucko/luckperms/api/node/types/SuffixNode.java index a99d15b06..d8d2dce88 100644 --- a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/SuffixType.java +++ b/api/src/main/java/me/lucko/luckperms/api/node/types/SuffixNode.java @@ -23,47 +23,51 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.nodetype.types; +package me.lucko.luckperms.api.node.types; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.node.Node; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.Map; - /** * A sub-type of {@link Node} used to store suffix assignments. - * - * @since 4.2 */ -public interface SuffixType extends NodeType { +public interface SuffixNode extends ChatMetaNode { /** - * The key for this type. - */ - NodeTypeKey KEY = new NodeTypeKey(){}; - - /** - * Gets the priority of the suffix assignment. + * Creates a {@link SuffixNode} builder. * - * @return the priority + * @return the builder */ - int getPriority(); + static @NonNull Builder builder() { + return LuckPermsProvider.get().getNodeBuilderRegistry().forSuffix(); + } /** - * Gets the actual suffix string. + * Creates a {@link SuffixNode} builder. * - * @return the suffix + * @param suffix the suffix to set + * @param priority the priority to set + * @return the builder */ - @NonNull String getSuffix(); + static @NonNull Builder builder(@NonNull String suffix, int priority) { + return builder().suffix(suffix).priority(priority); + } /** - * Gets a representation of this instance as a {@link Map.Entry}. - * - * @return a map entry representation of the priority and suffix string + * A {@link SuffixNode} builder. */ - Map.@NonNull Entry getAsEntry(); + interface Builder extends ChatMetaNode.Builder { + + /** + * Sets the suffix. + * + * @param suffix the suffix + * @return the builder + */ + @NonNull Builder suffix(@NonNull String suffix); + + } } diff --git a/api/src/main/java/me/lucko/luckperms/api/node/types/WeightNode.java b/api/src/main/java/me/lucko/luckperms/api/node/types/WeightNode.java new file mode 100644 index 000000000..884d3a429 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/node/types/WeightNode.java @@ -0,0 +1,81 @@ +/* + * 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.api.node.types; + +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.ScopedNode; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * A sub-type of {@link Node} used to mark the weight of the node's holder. + */ +public interface WeightNode extends ScopedNode { + + /** + * Gets the weight value. + * + * @return the weight + */ + int getWeight(); + + /** + * Creates a {@link WeightNode} builder. + * + * @return the builder + */ + static @NonNull Builder builder() { + return LuckPermsProvider.get().getNodeBuilderRegistry().forWeight(); + } + + /** + * Creates a {@link WeightNode} builder. + * + * @param weight the weight to set + * @return the builder + */ + static @NonNull Builder builder(int weight) { + return builder().weight(weight); + } + + /** + * A {@link WeightNode} builder. + */ + interface Builder extends NodeBuilder { + + /** + * Sets the weight. + * + * @param weight the weight + * @return the builder + */ + @NonNull Builder weight(int weight); + + } + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeType.java b/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeType.java deleted file mode 100644 index abfb3d136..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeType.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.api.nodetype; - -import me.lucko.luckperms.api.Node; - -/** - * Superinterface for extended {@link Node} types. - * - *

    The 'permission' property of a {@link Node} is also used in some cases to represent state - * beyond a granted permission. This state is encapsulated by extra {@link NodeType} data which - * can be obtained from this instance using {@link Node#getTypeData(NodeTypeKey)}.

    - * - *

    Type data is mapped by {@link NodeTypeKey}s, which are usually stored as static members of the - * corresponding {@link NodeType} class under the KEY field.

    - * - * @since 4.2 - */ -public interface NodeType { - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeTypeKey.java b/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeTypeKey.java deleted file mode 100644 index 11103c00e..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/nodetype/NodeTypeKey.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.api.nodetype; - -import org.checkerframework.checker.nullness.qual.NonNull; - -/** - * Marks an instance used as a key for a {@link NodeType}. - * - *

    A single instance of this interface is created and stored statically for - * each sub-interface of {@link NodeType}.

    - * - * @param the type of the {@link NodeType} being indexed by this key - * @since 4.2 - */ -public interface NodeTypeKey { - - /** - * Gets the {@link Class#getSimpleName() class name} of the represented type. - * - * @return the name of the represented type - */ - default @NonNull String getTypeName() { - String name = getClass().getName(); - return name.substring(name.lastIndexOf('.') + 1, name.length() - 2); - } - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/InheritanceType.java b/api/src/main/java/me/lucko/luckperms/api/nodetype/types/InheritanceType.java deleted file mode 100644 index a6868fedb..000000000 --- a/api/src/main/java/me/lucko/luckperms/api/nodetype/types/InheritanceType.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.api.nodetype.types; - -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; - -import org.checkerframework.checker.nullness.qual.NonNull; - -/** - * A sub-type of {@link Node} used to mark that the holder of the node should inherit - * from another group. - * - * @since 4.2 - */ -public interface InheritanceType extends NodeType { - - /** - * The key for this type. - */ - NodeTypeKey KEY = new NodeTypeKey(){}; - - /** - * Gets the name of the group to be inherited. - * - *

    This is no guarantee that this group exists.

    - * - * @return the name of the group - */ - @NonNull String getGroupName(); - -} diff --git a/api/src/main/java/me/lucko/luckperms/api/platform/PlatformInfo.java b/api/src/main/java/me/lucko/luckperms/api/platform/Platform.java similarity index 70% rename from api/src/main/java/me/lucko/luckperms/api/platform/PlatformInfo.java rename to api/src/main/java/me/lucko/luckperms/api/platform/Platform.java index 82345a3da..0459eeade 100644 --- a/api/src/main/java/me/lucko/luckperms/api/platform/PlatformInfo.java +++ b/api/src/main/java/me/lucko/luckperms/api/platform/Platform.java @@ -27,36 +27,21 @@ package me.lucko.luckperms.api.platform; import org.checkerframework.checker.nullness.qual.NonNull; +import java.time.Instant; import java.util.Set; import java.util.UUID; /** * Provides information about the platform LuckPerms is running on. - * - * @since 4.0 */ -public interface PlatformInfo { - - /** - * Gets the plugin version - * - * @return the version of the plugin running on the platform - */ - @NonNull String getVersion(); - - /** - * Gets the API version - * - * @return the version of the API running on the platform - */ - double getApiVersion(); +public interface Platform { /** * Gets the type of platform LuckPerms is running on * * @return the type of platform LuckPerms is running on */ - @NonNull PlatformType getType(); + Platform.@NonNull Type getType(); /** * Gets the unique players which have connected to the server since it started. @@ -66,10 +51,35 @@ public interface PlatformInfo { @NonNull Set getUniqueConnections(); /** - * Gets the time when the plugin first started in milliseconds. + * Gets the time when the plugin first started. * * @return the enable time */ - long getStartTime(); + @NonNull Instant getStartTime(); + /** + * Represents a type of platform which LuckPerms can run on. + */ + enum Type { + BUKKIT("Bukkit"), + BUNGEECORD("BungeeCord"), + SPONGE("Sponge"), + NUKKIT("Nukkit"), + VELOCITY("Velocity"); + + private final String friendlyName; + + Type(String friendlyName) { + this.friendlyName = friendlyName; + } + + /** + * Gets a readable name for the platform type. + * + * @return a readable name + */ + public @NonNull String getFriendlyName() { + return this.friendlyName; + } + } } diff --git a/api/src/main/java/me/lucko/luckperms/api/Entity.java b/api/src/main/java/me/lucko/luckperms/api/platform/PlatformEntity.java similarity index 88% rename from api/src/main/java/me/lucko/luckperms/api/Entity.java rename to api/src/main/java/me/lucko/luckperms/api/platform/PlatformEntity.java index b0816def7..008553676 100644 --- a/api/src/main/java/me/lucko/luckperms/api/Entity.java +++ b/api/src/main/java/me/lucko/luckperms/api/platform/PlatformEntity.java @@ -23,7 +23,7 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.platform; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -34,13 +34,11 @@ import java.util.UUID; * Represents an entity on the server. * *

    This does not relate directly to a "Minecraft Entity". The closest - * comparison is to a "CommandSender" or "CommandSource" in Bukkit/Sponge.

    + * comparison is to a "CommandSender" or "CommandSource".

    * - *

    The various types of {@link Entity} are detailed in {@link Type}.

    - * - * @since 4.1 + *

    The various types of {@link PlatformEntity} are detailed in {@link Type}.

    */ -public interface Entity { +public interface PlatformEntity { /** * Gets the unique id of the entity, if it has one. @@ -66,7 +64,7 @@ public interface Entity { @NonNull Type getType(); /** - * The different types of {@link Entity} + * The different types of {@link PlatformEntity} */ enum Type { diff --git a/api/src/main/java/me/lucko/luckperms/api/platform/PlatformType.java b/api/src/main/java/me/lucko/luckperms/api/platform/PluginMetadata.java similarity index 73% rename from api/src/main/java/me/lucko/luckperms/api/platform/PlatformType.java rename to api/src/main/java/me/lucko/luckperms/api/platform/PluginMetadata.java index 04e31509c..e250b12f1 100644 --- a/api/src/main/java/me/lucko/luckperms/api/platform/PlatformType.java +++ b/api/src/main/java/me/lucko/luckperms/api/platform/PluginMetadata.java @@ -28,26 +28,22 @@ package me.lucko.luckperms.api.platform; import org.checkerframework.checker.nullness.qual.NonNull; /** - * Represents a type of platform which LuckPerms can run on. - * - * @since 2.7 + * Provides information about the LuckPerms plugin. */ -public enum PlatformType { - - BUKKIT("Bukkit"), BUNGEE("Bungee"), SPONGE("Sponge"), NUKKIT("Nukkit"), VELOCITY("Velocity"); - - private final String friendlyName; - - PlatformType(String friendlyName) { - this.friendlyName = friendlyName; - } +public interface PluginMetadata { /** - * Gets a readable name for the platform type. + * Gets the plugin version * - * @return a readable name + * @return the version of the plugin running on the platform */ - public @NonNull String getFriendlyName() { - return this.friendlyName; - } + @NonNull String getVersion(); + + /** + * Gets the API version + * + * @return the version of the API running on the platform + */ + @NonNull String getApiVersion(); + } diff --git a/api/src/main/java/me/lucko/luckperms/api/query/DefaultQueryOptions.java b/api/src/main/java/me/lucko/luckperms/api/query/DefaultQueryOptions.java new file mode 100644 index 000000000..628ce7769 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/query/DefaultQueryOptions.java @@ -0,0 +1,43 @@ +/* + * 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.api.query; + +import me.lucko.luckperms.api.context.ImmutableContextSet; + +import java.util.EnumSet; + +/** + * Some default {@link QueryOptions} instances. + */ +enum DefaultQueryOptions { + ; + + private static final EnumSet DEFAULT_FLAGS = EnumSet.allOf(Flag.class); + + static final QueryOptions CONTEXTUAL = QueryOptions.contextual(ImmutableContextSet.empty(), DEFAULT_FLAGS); + static final QueryOptions NON_CONTEXTUAL = QueryOptions.nonContextual(DEFAULT_FLAGS); + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/manager/CachedDataManager.java b/api/src/main/java/me/lucko/luckperms/api/query/Flag.java similarity index 65% rename from api/src/main/java/me/lucko/luckperms/api/manager/CachedDataManager.java rename to api/src/main/java/me/lucko/luckperms/api/query/Flag.java index 961f25e6c..1e3abf191 100644 --- a/api/src/main/java/me/lucko/luckperms/api/manager/CachedDataManager.java +++ b/api/src/main/java/me/lucko/luckperms/api/query/Flag.java @@ -23,31 +23,36 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.manager; - -import me.lucko.luckperms.api.Group; -import me.lucko.luckperms.api.User; -import me.lucko.luckperms.api.caching.CachedData; +package me.lucko.luckperms.api.query; /** - * Represents an object responsible for managing {@link CachedData} instances. - * - * @since 4.5 + * The flags which can be set for a query. */ -public interface CachedDataManager { +public enum Flag { /** - * Invalidate the {@link CachedData} instances for all loaded {@link User}s. - * - * @see CachedData#invalidate() + * If parent groups should be resolved */ - void invalidateAllUserCaches(); + RESOLVE_INHERITANCE, /** - * Invalidate the {@link CachedData} instances for all loaded {@link Group}s. - * - * @see CachedData#invalidate() + * If global or non-server-specific nodes should be applied */ - void invalidateAllGroupCaches(); + INCLUDE_NODES_WITHOUT_SERVER_CONTEXT, + + /** + * If global or non-world-specific nodes should be applied + */ + INCLUDE_NODES_WITHOUT_WORLD_CONTEXT, + + /** + * If global or non-server-specific group memberships should be applied + */ + APPLY_INHERITANCE_NODES_WITHOUT_SERVER_CONTEXT, + + /** + * If global or non-world-specific group memberships should be applied + */ + APPLY_INHERITANCE_NODES_WITHOUT_WORLD_CONTEXT } diff --git a/api/src/main/java/me/lucko/luckperms/api/query/OptionKey.java b/api/src/main/java/me/lucko/luckperms/api/query/OptionKey.java new file mode 100644 index 000000000..7d1dfbd29 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/query/OptionKey.java @@ -0,0 +1,43 @@ +/* + * 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.api.query; + +/** + * Represents a key for a custom option defined in {@link QueryOptions}. + * + *

    Option keys are compared using reference equality, the + * {@link #equals(Object)} method should not be implemented.

    + * + *

    It is intended that {@link OptionKey}s are created and defined as follows.

    + *

    + *     public static final OptionKey SPECIAL_OPTION = new OptionKey(){};
    + * 

    + * + * @param the option type + */ +public interface OptionKey { + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/query/QueryMode.java b/api/src/main/java/me/lucko/luckperms/api/query/QueryMode.java new file mode 100644 index 000000000..43e0973a9 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/query/QueryMode.java @@ -0,0 +1,49 @@ +/* + * 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.api.query; + +/** + * Represents the type of query associated with a given {@link QueryOptions}. + */ +public enum QueryMode { + + /** + * Contextual query. + * + *

    The query will use the {@link QueryOptions#context() contexts} defined + * in the {@link QueryOptions} to filter which data is applicable.

    + */ + CONTEXTUAL, + + /** + * Non-contextual query. + * + *

    The query will use not use contexts to filter which data is + * applicable.

    + */ + NON_CONTEXTUAL + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/query/QueryOptions.java b/api/src/main/java/me/lucko/luckperms/api/query/QueryOptions.java new file mode 100644 index 000000000..3a966b694 --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/query/QueryOptions.java @@ -0,0 +1,251 @@ +/* + * 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.api.query; + +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Represents the parameters for a lookup query. + */ +public interface QueryOptions { + + /** + * Creates a new {@link Builder} for the given {@link QueryMode}. + * + * @param mode the query mode + * @return a new builder + */ + static @NonNull Builder builder(@NonNull QueryMode mode) { + return LuckPermsProvider.get().getContextManager().queryOptionsBuilder(mode); + } + + /** + * Creates a {@link QueryMode#CONTEXTUAL contextual} {@link QueryOptions} + * instance with the given context and flags. + * + * @param context the contexts to query in + * @param flags the query flags + * @return the query options + */ + static @NonNull QueryOptions contextual(@NonNull ContextSet context, @NonNull Set flags) { + return builder(QueryMode.CONTEXTUAL).context(context).flags(flags).build(); + } + + /** + * Creates a {@link QueryMode#CONTEXTUAL contextual} {@link QueryOptions} + * instance with the given context and default flags. + * + * @param context the contexts to query in + * @return the query options + */ + static @NonNull QueryOptions contextual(@NonNull ContextSet context) { + return defaultContextualOptions().toBuilder().context(context).build(); + } + + /** + * Creates a {@link QueryMode#NON_CONTEXTUAL non contextual} {@link QueryOptions} + * instance with the given flags. + * + * @param flags the query flags + * @return the query options + */ + static @NonNull QueryOptions nonContextual(@NonNull Set flags) { + return builder(QueryMode.NON_CONTEXTUAL).flags(flags).build(); + } + + /** + * Gets the default {@link QueryMode#NON_CONTEXTUAL non contextual} + * query options. + * + *

    This instance has the default set of flags.

    + * + * @return the default non contextual query options + */ + static @NonNull QueryOptions nonContextual() { + return DefaultQueryOptions.NON_CONTEXTUAL; + } + + /** + * Gets the default {@link QueryMode#CONTEXTUAL contextual} + * query options. + * + *

    This instance has the default set of flags, and an empty set + * of contexts.

    + * + * @return the default contextual query options + */ + static @NonNull QueryOptions defaultContextualOptions() { + return DefaultQueryOptions.CONTEXTUAL; + } + + /** + * Gets the {@link QueryMode}. + * + * @return the query mode + */ + @NonNull QueryMode mode(); + + /** + * Gets the {@link ContextSet context}, if the options are + * {@link QueryMode#CONTEXTUAL contextual}. + * + *

    Throws {@link IllegalStateException} if the {@link #mode() mode} is + * {@link QueryMode#NON_CONTEXTUAL}.

    + * + * @return the context + */ + @NonNull ImmutableContextSet context(); + + /** + * Gets if the given {@link Flag} is set. + * + * @param flag the flag + * @return if the flag is set + */ + boolean flag(@NonNull Flag flag); + + /** + * Gets the {@link Flag}s which are set. + * + * @return the flags + */ + @NonNull Set flags(); + + /** + * Gets the value assigned to the given {@link OptionKey}. + * + *

    Returns an {@link Optional#empty() empty optional} if the option has + * not been set.

    + * + * @param key the key to lookup + * @param the option type + * @return the value assigned to the key + */ + @NonNull Optional option(@NonNull OptionKey key); + + /** + * Gets the options which are set. + * + * @return the options + */ + @NonNull Map, Object> options(); + + /** + * Gets whether this {@link QueryOptions} satisfies the given required + * {@link ContextSet context}. + * + * @param contextSet the contexts + * @return the result + */ + boolean satisfies(@NonNull ContextSet contextSet); + + /** + * Converts this {@link QueryOptions} to a mutable builder. + * + * @return a builder, with the same properties already set + */ + @NonNull Builder toBuilder(); + + /** + * Builder for {@link QueryOptions}. + */ + interface Builder { + + /** + * Sets the {@link QueryMode}. + * + * @param mode the mode to set + * @return this builder + */ + @NonNull Builder mode(@NonNull QueryMode mode); + + /** + * Sets the context. + * + *

    Note that this is a set operation, not append. Existing contexts + * will be overridden.

    + * + *

    Throws {@link IllegalStateException} if the mode is not + * {@link QueryMode#CONTEXTUAL}.

    + * + * @param context the context to set + * @return this builder + */ + @NonNull Builder context(@NonNull ContextSet context); + + /** + * Sets the value of the given flag. + * + * @param flag the flag + * @param value the value to set + * @return this builder + */ + @NonNull Builder flag(@NonNull Flag flag, boolean value); + + /** + * Sets the flags. + * + *

    Note that this is a set operation, not append. Existing flags will + * be overridden.

    + * + * @param flags the flags + * @return this builder + */ + @NonNull Builder flags(@NonNull Set flags); + + /** + * Sets the value of the given option. + * + *

    Passing {@code null} in place of a value will clear any existing + * value set for the key.

    + * + * @param key the option key + * @param value the value, or null to clear + * @param the option type + * @return this builder + */ + @NonNull Builder option(@NonNull OptionKey key, @Nullable O value); + + /** + * Builds a {@link QueryOptions} instance from the properties defined to + * the builder. + * + * @return a {@link QueryOptions} instance. + */ + @NonNull QueryOptions build(); + + } + +} diff --git a/api/src/main/java/me/lucko/luckperms/api/DemotionResult.java b/api/src/main/java/me/lucko/luckperms/api/track/DemotionResult.java similarity index 91% rename from api/src/main/java/me/lucko/luckperms/api/DemotionResult.java rename to api/src/main/java/me/lucko/luckperms/api/track/DemotionResult.java index 8bbf70b50..f9f878217 100644 --- a/api/src/main/java/me/lucko/luckperms/api/DemotionResult.java +++ b/api/src/main/java/me/lucko/luckperms/api/track/DemotionResult.java @@ -23,7 +23,10 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.track; + +import me.lucko.luckperms.api.model.user.User; +import me.lucko.luckperms.api.util.Result; import org.checkerframework.checker.nullness.qual.NonNull; @@ -31,10 +34,8 @@ import java.util.Optional; /** * Encapsulates the result of {@link User}s demotion along a {@link Track}. - * - * @since 4.2 */ -public interface DemotionResult extends MutateResult { +public interface DemotionResult extends Result { /** * Gets the status of the result. @@ -44,8 +45,8 @@ public interface DemotionResult extends MutateResult { @NonNull Status getStatus(); @Override - default boolean wasSuccess() { - return getStatus().wasSuccess(); + default boolean wasSuccessful() { + return getStatus().wasSuccessful(); } /** @@ -74,7 +75,7 @@ public interface DemotionResult extends MutateResult { /** * The result status */ - enum Status implements MutateResult { + enum Status implements Result { /** * Indicates that the user was demoted normally. @@ -119,7 +120,7 @@ public interface DemotionResult extends MutateResult { } @Override - public boolean wasSuccess() { + public boolean wasSuccessful() { return this.success; } } diff --git a/api/src/main/java/me/lucko/luckperms/api/PromotionResult.java b/api/src/main/java/me/lucko/luckperms/api/track/PromotionResult.java similarity index 91% rename from api/src/main/java/me/lucko/luckperms/api/PromotionResult.java rename to api/src/main/java/me/lucko/luckperms/api/track/PromotionResult.java index 68ecf0fff..7efc04cf8 100644 --- a/api/src/main/java/me/lucko/luckperms/api/PromotionResult.java +++ b/api/src/main/java/me/lucko/luckperms/api/track/PromotionResult.java @@ -23,7 +23,10 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.track; + +import me.lucko.luckperms.api.model.user.User; +import me.lucko.luckperms.api.util.Result; import org.checkerframework.checker.nullness.qual.NonNull; @@ -31,10 +34,8 @@ import java.util.Optional; /** * Encapsulates the result of {@link User}s promotion along a {@link Track}. - * - * @since 4.2 */ -public interface PromotionResult extends MutateResult { +public interface PromotionResult extends Result { /** * Gets the status of the result. @@ -44,8 +45,8 @@ public interface PromotionResult extends MutateResult { @NonNull Status getStatus(); @Override - default boolean wasSuccess() { - return getStatus().wasSuccess(); + default boolean wasSuccessful() { + return getStatus().wasSuccessful(); } /** @@ -74,7 +75,7 @@ public interface PromotionResult extends MutateResult { /** * The result status */ - enum Status implements MutateResult { + enum Status implements Result { /** * Indicates that the user was promoted normally. @@ -119,7 +120,7 @@ public interface PromotionResult extends MutateResult { } @Override - public boolean wasSuccess() { + public boolean wasSuccessful() { return this.success; } } diff --git a/api/src/main/java/me/lucko/luckperms/api/Track.java b/api/src/main/java/me/lucko/luckperms/api/track/Track.java similarity index 97% rename from api/src/main/java/me/lucko/luckperms/api/Track.java rename to api/src/main/java/me/lucko/luckperms/api/track/Track.java index 9e2610a32..81d969115 100644 --- a/api/src/main/java/me/lucko/luckperms/api/Track.java +++ b/api/src/main/java/me/lucko/luckperms/api/track/Track.java @@ -23,9 +23,12 @@ * SOFTWARE. */ -package me.lucko.luckperms.api; +package me.lucko.luckperms.api.track; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.model.group.Group; +import me.lucko.luckperms.api.model.user.User; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -92,7 +95,6 @@ public interface Track { * @param user the user to promote * @param contextSet the contexts to promote the user in * @return the result of the action - * @since 4.2 */ @NonNull PromotionResult promote(@NonNull User user, @NonNull ContextSet contextSet); @@ -102,7 +104,6 @@ public interface Track { * @param user the user to demote * @param contextSet the contexts to demote the user in * @return the result of the action - * @since 4.2 */ @NonNull DemotionResult demote(@NonNull User user, @NonNull ContextSet contextSet); diff --git a/api/src/main/java/me/lucko/luckperms/api/manager/TrackManager.java b/api/src/main/java/me/lucko/luckperms/api/track/TrackManager.java similarity index 67% rename from api/src/main/java/me/lucko/luckperms/api/manager/TrackManager.java rename to api/src/main/java/me/lucko/luckperms/api/track/TrackManager.java index 3890c0a7d..b31251f08 100644 --- a/api/src/main/java/me/lucko/luckperms/api/manager/TrackManager.java +++ b/api/src/main/java/me/lucko/luckperms/api/track/TrackManager.java @@ -23,10 +23,7 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.manager; - -import me.lucko.luckperms.api.Storage; -import me.lucko.luckperms.api.Track; +package me.lucko.luckperms.api.track; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -49,8 +46,6 @@ import java.util.function.Consumer; * not be called on the main server thread. If you need to use * the result of these operations on the main server thread, register a * callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.

    - * - * @since 4.0 */ public interface TrackManager { @@ -60,17 +55,9 @@ public interface TrackManager { * *

    If a track by the same name already exists, it will be loaded.

    * - *

    This method is effectively the same as - * {@link Storage#createAndLoadTrack(String)}, however, the Future returns - * the resultant track instance instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a track cannot be loaded, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param name the name of the track * @return the resultant track * @throws NullPointerException if the name is null - * @since 4.1 */ @NonNull CompletableFuture createAndLoadTrack(@NonNull String name); @@ -80,17 +67,9 @@ public interface TrackManager { *

    Returns an {@link Optional#empty() empty optional} if the track does * not exist.

    * - *

    This method is effectively the same as - * {@link Storage#loadTrack(String)}, however, the Future returns - * the resultant track instance instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a track cannot be loaded, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param name the name of the track * @return the resultant track * @throws NullPointerException if the name is null - * @since 4.1 */ @NonNull CompletableFuture> loadTrack(@NonNull String name); @@ -99,48 +78,27 @@ public interface TrackManager { * *

    You should call this after you make any changes to a track.

    * - *

    This method is effectively the same as {@link Storage#saveTrack(Track)}, - * however, the Future returns void instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a track cannot be saved, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param track the track to save * @return a future to encapsulate the operation. * @throws NullPointerException if track is null * @throws IllegalStateException if the track instance was not obtained from LuckPerms. - * @since 4.1 */ @NonNull CompletableFuture saveTrack(@NonNull Track track); /** * Permanently deletes a track from the plugin's storage provider. * - *

    This method is effectively the same as {@link Storage#deleteTrack(Track)}, - * however, the Future returns void instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a track cannot be deleted, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @param track the track to delete * @return a future to encapsulate the operation. * @throws NullPointerException if track is null * @throws IllegalStateException if the track instance was not obtained from LuckPerms. - * @since 4.1 */ @NonNull CompletableFuture deleteTrack(@NonNull Track track); /** * Loads all tracks into memory. * - *

    This method is effectively the same as {@link Storage#loadAllTracks()}, - * however, the Future returns void instead of a boolean flag.

    - * - *

    Unlike the method in {@link Storage}, when a track cannot be loaded, - * the future will be {@link CompletableFuture completed exceptionally}.

    - * * @return a future to encapsulate the operation. - * @since 4.1 */ @NonNull CompletableFuture loadAllTracks(); @@ -153,19 +111,6 @@ public interface TrackManager { */ @Nullable Track getTrack(@NonNull String name); - /** - * Gets a loaded track. - * - *

    This method does not return null, unlike {@link #getTrack}

    - * - * @param name the name of the track to get - * @return an optional {@link Track} object - * @throws NullPointerException if the name is null - */ - default @NonNull Optional getTrackOpt(@NonNull String name) { - return Optional.ofNullable(getTrack(name)); - } - /** * Gets a set of all loaded tracks. * diff --git a/api/src/main/java/me/lucko/luckperms/api/util/Result.java b/api/src/main/java/me/lucko/luckperms/api/util/Result.java new file mode 100644 index 000000000..8e84dbaff --- /dev/null +++ b/api/src/main/java/me/lucko/luckperms/api/util/Result.java @@ -0,0 +1,51 @@ +/* + * 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.api.util; + +/** + * Represents a generic result, which can either be successful or fail. + */ +@FunctionalInterface +public interface Result { + + /** + * Instance of {@link Result} which always reports success. + */ + Result GENERIC_SUCCESS = () -> true; + + /** + * Instance of {@link Result} which always reports failure. + */ + Result GENERIC_FAILURE = () -> false; + + /** + * Gets if the operation which produced this result completed successfully. + * + * @return if the result indicates a success + */ + boolean wasSuccessful(); + +} diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitSenderFactory.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitSenderFactory.java index 47796abfc..6ca99e6f0 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitSenderFactory.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/BukkitSenderFactory.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.bukkit; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.bukkit.compat.CraftBukkitUtil; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; @@ -91,7 +91,7 @@ public class BukkitSenderFactory extends SenderFactory { boolean isSet = sender.isPermissionSet(node); boolean val = sender.hasPermission(node); - return !isSet ? val ? Tristate.TRUE : Tristate.UNDEFINED : Tristate.fromBoolean(val); + return !isSet ? val ? Tristate.TRUE : Tristate.UNDEFINED : Tristate.of(val); } @Override diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitBootstrap.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitBootstrap.java index 972ba6900..aeb515936 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitBootstrap.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitBootstrap.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.bukkit; -import me.lucko.luckperms.api.platform.PlatformType; +import me.lucko.luckperms.api.platform.Platform; import me.lucko.luckperms.bukkit.compat.NullSafeConsoleCommandSender; import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader; import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader; @@ -198,8 +198,8 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap // provide information about the platform @Override - public PlatformType getType() { - return PlatformType.BUKKIT; + public Platform.Type getType() { + return Platform.Type.BUKKIT; } @Override diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java index 7232ab369..73205a2ee 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.bukkit; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.LuckPerms; import me.lucko.luckperms.api.event.user.UserDataRecalculateEvent; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.bukkit.calculator.BukkitCalculatorFactory; import me.lucko.luckperms.bukkit.compat.LuckPermsBrigadier; import me.lucko.luckperms.bukkit.context.BukkitContextManager; @@ -230,8 +230,8 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin { } @Override - protected void registerApiOnPlatform(LuckPermsApi api) { - this.bootstrap.getServer().getServicesManager().register(LuckPermsApi.class, api, this.bootstrap, ServicePriority.Normal); + protected void registerApiOnPlatform(LuckPerms api) { + this.bootstrap.getServer().getServicesManager().register(LuckPerms.class, api, this.bootstrap, ServicePriority.Normal); } @Override @@ -336,7 +336,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin { boolean value; if (user != null) { - Map permData = user.getCachedData().getPermissionData(this.contextManager.getApplicableContexts(player)).getImmutableBacking(); + Map permData = user.getCachedData().getPermissionData(this.contextManager.getQueryOptions(player)).getPermissionMap(); value = permData.getOrDefault("luckperms.autoop", false); } else { value = false; @@ -359,8 +359,8 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin { } @Override - public Optional getContextForUser(User user) { - return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getApplicableContexts(player)); + public Optional getQueryOptionsForUser(User user) { + return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getQueryOptions(player)); } @Override diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/BukkitCalculatorFactory.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/BukkitCalculatorFactory.java index 77220895c..54c128577 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/BukkitCalculatorFactory.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/BukkitCalculatorFactory.java @@ -27,9 +27,9 @@ package me.lucko.luckperms.bukkit.calculator; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LookupSetting; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.bukkit.LPBukkitPlugin; +import me.lucko.luckperms.bukkit.context.BukkitContextManager; import me.lucko.luckperms.common.cacheddata.CacheMetadata; import me.lucko.luckperms.common.calculator.CalculatorFactory; import me.lucko.luckperms.common.calculator.PermissionCalculator; @@ -48,7 +48,7 @@ public class BukkitCalculatorFactory implements CalculatorFactory { } @Override - public PermissionCalculator build(Contexts contexts, CacheMetadata metadata) { + public PermissionCalculator build(QueryOptions queryOptions, CacheMetadata metadata) { ImmutableList.Builder processors = ImmutableList.builder(); processors.add(new MapProcessor()); @@ -66,7 +66,7 @@ public class BukkitCalculatorFactory implements CalculatorFactory { } if (this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUKKIT_DEFAULT_PERMISSIONS) && metadata.getHolderType() == HolderType.USER) { - processors.add(new DefaultsProcessor(this.plugin, contexts.hasSetting(LookupSetting.IS_OP))); + processors.add(new DefaultsProcessor(this.plugin, queryOptions.option(BukkitContextManager.OP_OPTION).orElse(false))); } return new PermissionCalculator(this.plugin, metadata, processors.build()); diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/ChildProcessor.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/ChildProcessor.java index 7eb073a90..2906b9b51 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/ChildProcessor.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/ChildProcessor.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.bukkit.calculator; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.bukkit.LPBukkitPlugin; import me.lucko.luckperms.common.calculator.processor.AbstractPermissionProcessor; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; @@ -42,7 +42,7 @@ public class ChildProcessor extends AbstractPermissionProcessor implements Permi private static final TristateResult.Factory RESULT_FACTORY = new TristateResult.Factory(ChildProcessor.class); private final LPBukkitPlugin plugin; - private Map childPermissions = Collections.emptyMap(); + private Map childPermissions = Collections.emptyMap(); public ChildProcessor(LPBukkitPlugin plugin) { this.plugin = plugin; @@ -50,16 +50,16 @@ public class ChildProcessor extends AbstractPermissionProcessor implements Permi @Override public TristateResult hasPermission(String permission) { - return RESULT_FACTORY.result(Tristate.fromNullableBoolean(this.childPermissions.get(permission))); + return this.childPermissions.getOrDefault(permission, TristateResult.UNDEFINED);; } @Override public void refresh() { - Map builder = new ConcurrentHashMap<>(); + Map builder = new ConcurrentHashMap<>(); for (Map.Entry e : this.sourceMap.entrySet()) { Map children = this.plugin.getPermissionMap().getChildPermissions(e.getKey(), e.getValue()); - if (children != null) { - builder.putAll(children); + for (Map.Entry child : children.entrySet()) { + builder.put(child.getKey(), RESULT_FACTORY.result(Tristate.of(child.getValue()), "parent: " + e.getKey())); } } this.childPermissions = builder; diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/DefaultsProcessor.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/DefaultsProcessor.java index cdc99566c..d05db50b0 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/DefaultsProcessor.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/calculator/DefaultsProcessor.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.bukkit.calculator; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.bukkit.LPBukkitPlugin; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; import me.lucko.luckperms.common.calculator.result.TristateResult; @@ -58,6 +58,6 @@ public class DefaultsProcessor implements PermissionProcessor { if (defPerm == null) { return TristateResult.UNDEFINED; } - return PERMISSION_MAP_RESULT_FACTORY.result(Tristate.fromBoolean(defPerm.getDefault().getValue(this.isOp))); + return PERMISSION_MAP_RESULT_FACTORY.result(Tristate.of(defPerm.getDefault().getValue(this.isOp))); } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/compat/NullSafeConsoleCommandSender.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/compat/NullSafeConsoleCommandSender.java index fed518aa8..e41312dab 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/compat/NullSafeConsoleCommandSender.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/compat/NullSafeConsoleCommandSender.java @@ -50,6 +50,7 @@ public class NullSafeConsoleCommandSender implements ConsoleCommandSender { } private Optional get() { + //noinspection ConstantConditions return Optional.ofNullable(this.server.getConsoleSender()); } 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 e9fa36651..15dc23a05 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 @@ -27,36 +27,37 @@ package me.lucko.luckperms.bukkit.context; import com.github.benmanes.caffeine.cache.LoadingCache; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LookupSetting; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.OptionKey; +import me.lucko.luckperms.api.query.QueryOptions; 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.ContextManager; -import me.lucko.luckperms.common.context.ContextsCache; -import me.lucko.luckperms.common.context.ContextsSupplier; +import me.lucko.luckperms.common.context.QueryOptionsCache; +import me.lucko.luckperms.common.context.QueryOptionsSupplier; import me.lucko.luckperms.common.util.CaffeineFactory; import org.bukkit.entity.Player; -import java.util.EnumSet; import java.util.concurrent.TimeUnit; public class BukkitContextManager extends ContextManager { + public static final OptionKey OP_OPTION = new OptionKey(){}; + // cache the creation of ContextsCache instances for online players with no expiry - private final LoadingMap> onlineSubjectCaches = LoadingMap.of(key -> new ContextsCache<>(key, this)); + 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() + private final LoadingCache> offlineSubjectCaches = CaffeineFactory.newBuilder() .expireAfterAccess(1, TimeUnit.MINUTES) .build(key -> { - ContextsCache cache = this.onlineSubjectCaches.getIfPresent(key); + QueryOptionsCache cache = this.onlineSubjectCaches.getIfPresent(key); if (cache != null) { return cache; } - return new ContextsCache<>(key, this); + return new QueryOptionsCache<>(key, this); }); public BukkitContextManager(LPBukkitPlugin plugin) { @@ -68,7 +69,7 @@ public class BukkitContextManager extends ContextManager { } @Override - public ContextsSupplier getCacheFor(Player subject) { + public QueryOptionsSupplier getCacheFor(Player subject) { if (subject == null) { throw new NullPointerException("subject"); } @@ -86,7 +87,7 @@ public class BukkitContextManager extends ContextManager { throw new NullPointerException("subject"); } - ContextsCache cache = this.onlineSubjectCaches.getIfPresent(subject); + QueryOptionsCache cache = this.onlineSubjectCaches.getIfPresent(subject); if (cache != null) { cache.invalidate(); } @@ -98,14 +99,12 @@ public class BukkitContextManager extends ContextManager { } @Override - public Contexts formContexts(Player subject, ImmutableContextSet contextSet) { - Contexts contexts = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_CONTEXTS); + public QueryOptions formQueryOptions(Player subject, ImmutableContextSet contextSet) { + QueryOptions.Builder queryOptions = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_CONTEXTS).toBuilder(); if (subject.isOp()) { - EnumSet settings = EnumSet.copyOf(contexts.getSettings()); - settings.add(LookupSetting.IS_OP); - contexts = contexts.setSettings(settings); + queryOptions.option(OP_OPTION, true); } - return contexts.setContexts(contextSet); + return queryOptions.context(contextSet).build(); } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/WorldCalculator.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/WorldCalculator.java index 0ec54ceeb..27e5e1bce 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/WorldCalculator.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/context/WorldCalculator.java @@ -25,15 +25,18 @@ package me.lucko.luckperms.bukkit.context; -import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ContextCalculator; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ContextConsumer; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import org.bukkit.entity.Player; import org.checkerframework.checker.nullness.qual.NonNull; +import java.util.HashSet; +import java.util.Set; + public class WorldCalculator implements ContextCalculator { private final LuckPermsPlugin plugin; @@ -42,13 +45,12 @@ public class WorldCalculator implements ContextCalculator { } @Override - public @NonNull MutableContextSet giveApplicableContext(@NonNull Player subject, @NonNull MutableContextSet accumulator) { + public void giveApplicableContext(@NonNull Player subject, @NonNull ContextConsumer consumer) { + Set seen = new HashSet<>(); String world = subject.getWorld().getName().toLowerCase(); - while (!accumulator.has(Contexts.WORLD_KEY, world)) { - accumulator.add(Contexts.WORLD_KEY, world); + while (seen.add(world)) { + consumer.accept(DefaultContextKeys.WORLD_KEY, world); world = this.plugin.getConfiguration().get(ConfigKeys.WORLD_REWRITES).getOrDefault(world, world).toLowerCase(); } - - return accumulator; } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LPPermissible.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LPPermissible.java index b8a973c4a..63e5cfbe7 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LPPermissible.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LPPermissible.java @@ -27,12 +27,12 @@ package me.lucko.luckperms.bukkit.inject.permissible; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.bukkit.LPBukkitPlugin; import me.lucko.luckperms.bukkit.calculator.DefaultsProcessor; import me.lucko.luckperms.common.calculator.result.TristateResult; import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.context.ContextsSupplier; +import me.lucko.luckperms.common.context.QueryOptionsSupplier; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.util.ImmutableCollectors; import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent; @@ -92,7 +92,7 @@ public class LPPermissible extends PermissibleBase { private final LPBukkitPlugin plugin; // caches context lookups for the player - private final ContextsSupplier contextsSupplier; + private final QueryOptionsSupplier queryOptionsSupplier; // the players previous permissible. (the one they had before this one was injected) private PermissibleBase oldPermissible = null; @@ -109,7 +109,7 @@ public class LPPermissible extends PermissibleBase { this.user = Objects.requireNonNull(user, "user"); this.player = Objects.requireNonNull(player, "player"); this.plugin = Objects.requireNonNull(plugin, "plugin"); - this.contextsSupplier = plugin.getContextManager().getCacheFor(player); + this.queryOptionsSupplier = plugin.getContextManager().getCacheFor(player); injectFakeAttachmentsList(); } @@ -138,7 +138,7 @@ public class LPPermissible extends PermissibleBase { throw new NullPointerException("permission"); } - TristateResult result = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission, PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK); + TristateResult result = this.user.getCachedData().getPermissionData(this.queryOptionsSupplier.getQueryOptions()).checkPermission(permission, PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK); if (result.result() == Tristate.UNDEFINED) { return false; } @@ -166,7 +166,7 @@ public class LPPermissible extends PermissibleBase { throw new NullPointerException("permission"); } - Tristate ts = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission, PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result(); + Tristate ts = this.user.getCachedData().getPermissionData(this.queryOptionsSupplier.getQueryOptions()).checkPermission(permission, PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result(); return ts != Tristate.UNDEFINED ? ts.asBoolean() : Permission.DEFAULT_PERMISSION.getValue(isOp()); } @@ -176,7 +176,7 @@ public class LPPermissible extends PermissibleBase { throw new NullPointerException("permission"); } - Tristate ts = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission.getName(), PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result(); + Tristate ts = this.user.getCachedData().getPermissionData(this.queryOptionsSupplier.getQueryOptions()).checkPermission(permission.getName(), PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result(); if (ts != Tristate.UNDEFINED) { return ts.asBoolean(); } @@ -206,7 +206,7 @@ public class LPPermissible extends PermissibleBase { @Override public Set getEffectivePermissions() { - return this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getImmutableBacking().entrySet().stream() + return this.user.getCachedData().getPermissionData(this.queryOptionsSupplier.getQueryOptions()).getPermissionMap().entrySet().stream() .map(entry -> new PermissionAttachmentInfo(this.player, entry.getKey(), null, entry.getValue())) .collect(ImmutableCollectors.toSet()); } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LPPermissionAttachment.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LPPermissionAttachment.java index 3c3fc8810..1f77fbf97 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LPPermissionAttachment.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/LPPermissionAttachment.java @@ -27,13 +27,13 @@ package me.lucko.luckperms.bukkit.inject.permissible; import com.google.common.base.Preconditions; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; import me.lucko.luckperms.bukkit.inject.dummy.DummyPlugin; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.ImmutableTransientNode; -import me.lucko.luckperms.common.node.utils.NodeTools; import org.bukkit.permissions.PermissionAttachment; import org.bukkit.permissions.PermissionRemovedExecutor; @@ -52,7 +52,9 @@ import java.util.Set; * * Applies all permissions directly to the backing user instance via transient nodes. */ -public class LPPermissionAttachment extends PermissionAttachment { +public class LPPermissionAttachment extends PermissionAttachment implements NodeMetadata { + + public static final NodeMetadataKey TRANSIENT_SOURCE_KEY = NodeMetadataKey.of("TransientSource", LPPermissionAttachment.class); /** * The field in PermissionAttachment where the attachments applied permissions @@ -180,16 +182,14 @@ public class LPPermissionAttachment extends PermissionAttachment { // construct a node for the permission being set // we use the servers static context to *try* to ensure that the node will apply Node node = NodeFactory.builder(name) - .setValue(value) - .withExtraContext(this.permissible.getPlugin().getContextManager().getStaticContext()) + .value(value) + .withContext(this.permissible.getPlugin().getContextManager().getStaticContext()) + .withMetadata(TRANSIENT_SOURCE_KEY, this) .build(); - // convert the constructed node to a transient node instance to refer back to this attachment - ImmutableTransientNode transientNode = ImmutableTransientNode.of(node, this); - // set the transient node User user = this.permissible.getUser(); - user.setTransientPermission(transientNode); + user.setTransientPermission(node); } private void unsetPermissionInternal(String name) { @@ -199,13 +199,13 @@ public class LPPermissionAttachment extends PermissionAttachment { // remove transient permissions from the holder which were added by this attachment & equal the permission User user = this.permissible.getUser(); - user.removeIfTransient(NodeTools.localizedNodeComposedPredicate(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this && n.getPermission().equals(name))); + user.removeIfTransient(n -> n.getMetadata(TRANSIENT_SOURCE_KEY).orElse(null) == this && n.getKey().equals(name)); } private void clearInternal() { // remove all transient permissions added by this attachment User user = this.permissible.getUser(); - user.removeIfTransient(NodeTools.localizedNodeComposedPredicate(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this)); + user.removeIfTransient(n -> n.getMetadata(TRANSIENT_SOURCE_KEY).orElse(null) == this); } @Override diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/MonitoredPermissibleBase.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/MonitoredPermissibleBase.java index 73019aabc..11c02e00f 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/MonitoredPermissibleBase.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/permissible/MonitoredPermissibleBase.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.bukkit.inject.permissible; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.bukkit.inject.dummy.DummyPermissibleBase; import me.lucko.luckperms.common.calculator.result.TristateResult; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -68,7 +68,7 @@ public class MonitoredPermissibleBase extends PermissibleBase { } private void logCheck(PermissionCheckEvent.Origin origin, String permission, boolean result) { - this.plugin.getVerboseHandler().offerPermissionCheckEvent(origin, this.name, ContextSet.empty(), permission, TristateResult.of(Tristate.fromBoolean(result))); + this.plugin.getVerboseHandler().offerPermissionCheckEvent(origin, this.name, QueryOptions.defaultContextualOptions(), permission, TristateResult.of(Tristate.of(result))); this.plugin.getPermissionRegistry().offer(permission); } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/server/LPDefaultsMap.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/server/LPDefaultsMap.java index fb56ddfa5..5f0390993 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/server/LPDefaultsMap.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/inject/server/LPDefaultsMap.java @@ -31,7 +31,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.bukkit.LPBukkitPlugin; import me.lucko.luckperms.common.cache.Cache; @@ -108,7 +108,7 @@ public final class LPDefaultsMap implements Map> { */ public Tristate lookupDefaultPermission(String permission, boolean isOp) { Map map = getCache(isOp).get(); - return Tristate.fromNullableBoolean(map.get(permission)); + return Tristate.of(map.get(permission)); } // return wrappers around this map impl diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java index b3f63f18c..8f47356fe 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java @@ -31,8 +31,9 @@ import de.bananaco.bpermissions.api.Permission; import de.bananaco.bpermissions.api.World; import de.bananaco.bpermissions.api.WorldManager; -import me.lucko.luckperms.api.ChatMetaType; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.event.cause.CreationCause; +import me.lucko.luckperms.api.node.ChatMetaType; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; import me.lucko.luckperms.common.command.access.CommandPermission; @@ -44,7 +45,7 @@ import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; +import me.lucko.luckperms.common.node.factory.NodeTypes; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.util.Iterators; @@ -215,11 +216,11 @@ public class MigrationBPermissions extends SubCommand { if (meta.getKey().equalsIgnoreCase(NodeTypes.PREFIX_KEY) || meta.getKey().equalsIgnoreCase(NodeTypes.SUFFIX_KEY)) { ChatMetaType type = ChatMetaType.valueOf(meta.getKey().toUpperCase()); - holder.setPermission(NodeFactory.buildChatMetaNode(type, c.getPriority(), meta.getValue()).setWorld(world.getName()).build()); + holder.setPermission(NodeFactory.buildChatMetaNode(type, c.getPriority(), meta.getValue()).withContext(DefaultContextKeys.WORLD_KEY, world.getName()).build()); continue; } - holder.setPermission(NodeFactory.buildMetaNode(meta.getKey(), meta.getValue()).setWorld(world.getName()).build()); + holder.setPermission(NodeFactory.buildMetaNode(meta.getKey(), meta.getValue()).withContext(DefaultContextKeys.WORLD_KEY, world.getName()).build()); } } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationGroupManager.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationGroupManager.java index 1d79516d6..227196ef1 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationGroupManager.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationGroupManager.java @@ -25,9 +25,10 @@ package me.lucko.luckperms.bukkit.migration; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.event.cause.CreationCause; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; import me.lucko.luckperms.common.command.access.CommandPermission; @@ -39,7 +40,7 @@ import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.UserIdentifier; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; +import me.lucko.luckperms.common.node.factory.NodeTypes; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.util.Iterators; @@ -137,7 +138,7 @@ public class MigrationGroupManager extends SubCommand { for (String node : group.getPermissionList()) { if (node.isEmpty()) continue; - groups.get(groupName).add(MigrationUtils.parseNode(node, true).setWorld(worldMappingFunc.apply(world)).build()); + groups.get(groupName).add(MigrationUtils.parseNode(node, true).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build()); } for (String s : group.getInherits()) { if (s.isEmpty()) continue; @@ -153,9 +154,9 @@ public class MigrationGroupManager extends SubCommand { if (key.equals(NodeTypes.PREFIX_KEY) || key.equals(NodeTypes.SUFFIX_KEY)) { ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase()); - groups.get(groupName).add(NodeFactory.buildChatMetaNode(type, 50, value).setWorld(worldMappingFunc.apply(world)).build()); + groups.get(groupName).add(NodeFactory.buildChatMetaNode(type, 50, value).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build()); } else { - groups.get(groupName).add(NodeFactory.buildMetaNode(key, value).setWorld(worldMappingFunc.apply(world)).build()); + groups.get(groupName).add(NodeFactory.buildMetaNode(key, value).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build()); } } @@ -181,7 +182,7 @@ public class MigrationGroupManager extends SubCommand { for (String node : user.getPermissionList()) { if (node.isEmpty()) continue; - users.get(id).add(MigrationUtils.parseNode(node, true).setWorld(worldMappingFunc.apply(world)).build()); + users.get(id).add(MigrationUtils.parseNode(node, true).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build()); } // Collect sub groups @@ -205,9 +206,9 @@ public class MigrationGroupManager extends SubCommand { if (key.equals(NodeTypes.PREFIX_KEY) || key.equals(NodeTypes.SUFFIX_KEY)) { ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase()); - users.get(id).add(NodeFactory.buildChatMetaNode(type, 100, value).setWorld(worldMappingFunc.apply(world)).build()); + users.get(id).add(NodeFactory.buildChatMetaNode(type, 100, value).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build()); } else { - users.get(id).add(NodeFactory.buildMetaNode(key, value).setWorld(worldMappingFunc.apply(world)).build()); + users.get(id).add(NodeFactory.buildMetaNode(key, value).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build()); } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsBukkit.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsBukkit.java index a32436c18..bb3ca8902 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsBukkit.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsBukkit.java @@ -27,6 +27,7 @@ package me.lucko.luckperms.bukkit.migration; import com.platymuus.bukkit.permissions.PermissionsPlugin; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; @@ -140,7 +141,7 @@ public class MigrationPermissionsBukkit extends SubCommand { ConfigurationSection permsSection = worldSection.getConfigurationSection(world); for (String perm : permsSection.getKeys(false)) { boolean value = permsSection.getBoolean(perm); - holder.setPermission(MigrationUtils.parseNode(perm, value).setWorld(world).build()); + holder.setPermission(MigrationUtils.parseNode(perm, value).withContext(DefaultContextKeys.WORLD_KEY, world).build()); } } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsEx.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsEx.java index 96342dd39..67dcabffe 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsEx.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsEx.java @@ -27,6 +27,7 @@ package me.lucko.luckperms.bukkit.migration; import com.google.common.base.Strings; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; @@ -40,7 +41,7 @@ import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; +import me.lucko.luckperms.common.node.factory.NodeTypes; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.util.Iterators; @@ -199,7 +200,7 @@ public class MigrationPermissionsEx extends SubCommand { String world = standardizeWorld(worldData.getKey()); for (String node : worldData.getValue()) { if (node.isEmpty()) continue; - holder.setPermission(MigrationUtils.parseNode(node, true).setWorld(world).build()); + holder.setPermission(MigrationUtils.parseNode(node, true).withContext(DefaultContextKeys.WORLD_KEY, world).build()); } } @@ -221,7 +222,7 @@ public class MigrationPermissionsEx extends SubCommand { for (String node : worldData.getValue()) { if (node.isEmpty()) continue; long expiry = timedPermissionsTime.getOrDefault(Strings.nullToEmpty(world) + ":" + node, 0L); - holder.setPermission(MigrationUtils.parseNode(node, true).setWorld(world).setExpiry(expiry).build()); + holder.setPermission(MigrationUtils.parseNode(node, true).withContext(DefaultContextKeys.WORLD_KEY, world).expiry(expiry).build()); } } @@ -249,7 +250,7 @@ public class MigrationPermissionsEx extends SubCommand { } } - holder.setPermission(NodeFactory.buildGroupNode(MigrationUtils.standardizeName(parentName)).setWorld(world).setExpiry(expiry).build()); + holder.setPermission(NodeFactory.buildGroupNode(MigrationUtils.standardizeName(parentName)).withContext(DefaultContextKeys.WORLD_KEY, world).expiry(expiry).build()); // migrate primary groups if (world == null && holder instanceof User && expiry == 0) { @@ -301,7 +302,7 @@ public class MigrationPermissionsEx extends SubCommand { continue; } - holder.setPermission(NodeFactory.buildMetaNode(opt.getKey(), opt.getValue()).setWorld(world).build()); + holder.setPermission(NodeFactory.buildMetaNode(opt.getKey(), opt.getValue()).withContext(DefaultContextKeys.WORLD_KEY, world).build()); } } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPowerfulPerms.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPowerfulPerms.java index ba497d09f..838842c50 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPowerfulPerms.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPowerfulPerms.java @@ -33,8 +33,9 @@ import com.github.gustav9797.PowerfulPermsAPI.PowerfulPermsPlugin; import com.google.common.collect.ImmutableSet; import com.zaxxer.hikari.HikariDataSource; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.event.cause.CreationCause; +import me.lucko.luckperms.api.node.NodeBuilder; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; import me.lucko.luckperms.common.command.access.CommandPermission; @@ -183,7 +184,7 @@ public class MigrationPowerfulPerms extends SubCommand { } if (server != null) { - group.setPermission(NodeFactory.buildPrefixNode(g.getRank(), prefix.getValue()).setServer(server).build()); + group.setPermission(NodeFactory.buildPrefixNode(g.getRank(), prefix.getValue()).withContext(DefaultContextKeys.SERVER_KEY, server).build()); } else { group.setPermission(NodeFactory.buildPrefixNode(g.getRank(), prefix.getValue()).build()); } @@ -198,7 +199,7 @@ public class MigrationPowerfulPerms extends SubCommand { } if (server != null) { - group.setPermission(NodeFactory.buildSuffixNode(g.getRank(), suffix.getValue()).setServer(server).build()); + group.setPermission(NodeFactory.buildSuffixNode(g.getRank(), suffix.getValue()).withContext(DefaultContextKeys.SERVER_KEY, server).build()); } else { group.setPermission(NodeFactory.buildSuffixNode(g.getRank(), suffix.getValue()).build()); } @@ -302,10 +303,10 @@ public class MigrationPowerfulPerms extends SubCommand { server = "global"; } - Node.Builder nb = NodeFactory.builder(node).setValue(value); - if (expireAt != 0) nb.setExpiry(expireAt); - if (server != null) nb.setServer(server); - if (world != null) nb.setWorld(world); + NodeBuilder nb = NodeFactory.builder(node).value(value); + if (expireAt != 0) nb.expiry(expireAt); + if (server != null) nb.withContext(DefaultContextKeys.SERVER_KEY, server); + if (world != null) nb.withContext(DefaultContextKeys.WORLD_KEY, world); holder.setPermission(nb.build()); } @@ -319,14 +320,14 @@ public class MigrationPowerfulPerms extends SubCommand { expireAt = g.getExpirationDate().getTime() / 1000L; } - Node.Builder nb = NodeFactory.builder(node); + NodeBuilder nb = NodeFactory.builder(node); if (expireAt != 0) { - nb.setExpiry(expireAt); + nb.expiry(expireAt); } if (server != null) { - nb.setServer(server); + nb.withContext(DefaultContextKeys.SERVER_KEY, server); } holder.setPermission(nb.build()); diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationZPermissions.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationZPermissions.java index e966b41bd..226bfd8da 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationZPermissions.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationZPermissions.java @@ -25,9 +25,10 @@ package me.lucko.luckperms.bukkit.migration; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.event.cause.CreationCause; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; import me.lucko.luckperms.common.command.access.CommandPermission; @@ -40,7 +41,7 @@ import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; +import me.lucko.luckperms.common.node.factory.NodeTypes; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.util.Iterators; @@ -128,7 +129,7 @@ public class MigrationZPermissions extends SubCommand { nodes.add(NodeFactory.buildGroupNode(groupName).build()); } else { long expiry = membership.getExpiration().toInstant().getEpochSecond(); - nodes.add(NodeFactory.buildGroupNode(groupName).setExpiry(expiry).build()); + nodes.add(NodeFactory.buildGroupNode(groupName).expiry(expiry).build()); } } @@ -196,9 +197,9 @@ public class MigrationZPermissions extends SubCommand { if (e.getPermission().isEmpty()) continue; if (e.getWorld() != null && !e.getWorld().getName().equals("")) { - holder.setPermission(NodeFactory.builder(e.getPermission()).setValue(e.isValue()).setWorld(e.getWorld().getName()).build()); + holder.setPermission(NodeFactory.builder(e.getPermission()).value(e.isValue()).withContext(DefaultContextKeys.WORLD_KEY, e.getWorld().getName()).build()); } else { - holder.setPermission(NodeFactory.builder(e.getPermission()).setValue(e.isValue()).build()); + holder.setPermission(NodeFactory.builder(e.getPermission()).value(e.isValue()).build()); } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultChat.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultChat.java index bbb20724a..663ad6439 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultChat.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultChat.java @@ -27,10 +27,13 @@ package me.lucko.luckperms.bukkit.vault; import com.google.common.base.Strings; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.query.Flag; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.bukkit.LPBukkitPlugin; import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; import me.lucko.luckperms.common.cacheddata.type.MetaCache; @@ -39,7 +42,7 @@ import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; +import me.lucko.luckperms.common.node.factory.NodeTypes; import me.lucko.luckperms.common.verbose.event.MetaCheckEvent; import net.milkbowl.vault.chat.Chat; @@ -85,11 +88,11 @@ public class LuckPermsVaultChat extends AbstractVaultChat { Objects.requireNonNull(uuid, "uuid"); PermissionHolder user = this.vaultPermission.lookupUser(uuid); - Contexts contexts = this.vaultPermission.contextForLookup(uuid, world); - MetaCache metaData = user.getCachedData().getMetaData(contexts); + QueryOptions queryOptions = this.vaultPermission.getQueryOptions(uuid, world); + MetaCache metaData = user.getCachedData().getMetaData(queryOptions); String ret = metaData.getPrefix(MetaCheckEvent.Origin.THIRD_PARTY_API); if (log()) { - logMsg("#getUserChatPrefix: %s - %s - %s", user.getPlainDisplayName(), contexts.getContexts().toMultimap(), ret); + logMsg("#getUserChatPrefix: %s - %s - %s", user.getPlainDisplayName(), queryOptions.context(), ret); } return Strings.nullToEmpty(ret); } @@ -99,11 +102,11 @@ public class LuckPermsVaultChat extends AbstractVaultChat { Objects.requireNonNull(uuid, "uuid"); PermissionHolder user = this.vaultPermission.lookupUser(uuid); - Contexts contexts = this.vaultPermission.contextForLookup(uuid, world); - MetaCache metaData = user.getCachedData().getMetaData(contexts); + QueryOptions queryOptions = this.vaultPermission.getQueryOptions(uuid, world); + MetaCache metaData = user.getCachedData().getMetaData(queryOptions); String ret = metaData.getSuffix(MetaCheckEvent.Origin.THIRD_PARTY_API); if (log()) { - logMsg("#getUserChatSuffix: %s - %s - %s", user.getPlainDisplayName(), contexts.getContexts().toMultimap(), ret); + logMsg("#getUserChatSuffix: %s - %s - %s", user.getPlainDisplayName(), queryOptions.context(), ret); } return Strings.nullToEmpty(ret); } @@ -136,11 +139,11 @@ public class LuckPermsVaultChat extends AbstractVaultChat { Objects.requireNonNull(key, "key"); PermissionHolder user = this.vaultPermission.lookupUser(uuid); - Contexts contexts = this.vaultPermission.contextForLookup(uuid, world); - MetaCache metaData = user.getCachedData().getMetaData(contexts); - String ret = metaData.getMeta(MetaCheckEvent.Origin.THIRD_PARTY_API).get(key); + QueryOptions queryOptions = this.vaultPermission.getQueryOptions(uuid, world); + MetaCache metaData = user.getCachedData().getMetaData(queryOptions); + String ret = metaData.getMetaValue(key, MetaCheckEvent.Origin.THIRD_PARTY_API); if (log()) { - logMsg("#getUserMeta: %s - %s - %s - %s", user.getPlainDisplayName(), contexts.getContexts().toMultimap(), key, ret); + logMsg("#getUserMeta: %s - %s - %s - %s", user.getPlainDisplayName(), queryOptions.context(), key, ret); } return ret; } @@ -164,11 +167,11 @@ public class LuckPermsVaultChat extends AbstractVaultChat { if (group == null) { return null; } - Contexts contexts = this.vaultPermission.contextForLookup(null, world); - MetaCache metaData = group.getCachedData().getMetaData(contexts); + QueryOptions queryOptions = this.vaultPermission.getQueryOptions(null, world); + MetaCache metaData = group.getCachedData().getMetaData(queryOptions); String ret = metaData.getPrefix(MetaCheckEvent.Origin.THIRD_PARTY_API); if (log()) { - logMsg("#getGroupPrefix: %s - %s - %s", group.getName(), contexts.getContexts().toMultimap(), ret); + logMsg("#getGroupPrefix: %s - %s - %s", group.getName(), queryOptions.context(), ret); } return Strings.nullToEmpty(ret); } @@ -180,11 +183,11 @@ public class LuckPermsVaultChat extends AbstractVaultChat { if (group == null) { return null; } - Contexts contexts = this.vaultPermission.contextForLookup(null, world); - MetaCache metaData = group.getCachedData().getMetaData(contexts); + QueryOptions queryOptions = this.vaultPermission.getQueryOptions(null, world); + MetaCache metaData = group.getCachedData().getMetaData(queryOptions); String ret = metaData.getSuffix(MetaCheckEvent.Origin.THIRD_PARTY_API); if (log()) { - logMsg("#getGroupSuffix: %s - %s - %s", group.getName(), contexts.getContexts().toMultimap(), ret); + logMsg("#getGroupSuffix: %s - %s - %s", group.getName(), queryOptions.context(), ret); } return Strings.nullToEmpty(ret); } @@ -217,11 +220,11 @@ public class LuckPermsVaultChat extends AbstractVaultChat { if (group == null) { return null; } - Contexts contexts = this.vaultPermission.contextForLookup(null, world); - MetaCache metaData = group.getCachedData().getMetaData(contexts); - String ret = metaData.getMeta(MetaCheckEvent.Origin.THIRD_PARTY_API).get(key); + QueryOptions queryOptions = this.vaultPermission.getQueryOptions(null, world); + MetaCache metaData = group.getCachedData().getMetaData(queryOptions); + String ret = metaData.getMetaValue(key, MetaCheckEvent.Origin.THIRD_PARTY_API); if (log()) { - logMsg("#getGroupMeta: %s - %s - %s - %s", group.getName(), contexts.getContexts().toMultimap(), key, ret); + logMsg("#getGroupMeta: %s - %s - %s - %s", group.getName(), queryOptions.context(), key, ret); } return ret; } @@ -260,7 +263,7 @@ public class LuckPermsVaultChat extends AbstractVaultChat { } // remove all prefixes/suffixes directly set on the user/group - holder.removeIf(type::matches); + holder.removeIfEnduring(node -> type.nodeType().matches(node)); if (value == null) { this.vaultPermission.holderSave(holder); @@ -268,13 +271,13 @@ public class LuckPermsVaultChat extends AbstractVaultChat { } // find the max inherited priority & add 10 - MetaAccumulator metaAccumulator = holder.accumulateMeta(null, createContextForWorldSet(world)); + MetaAccumulator metaAccumulator = holder.accumulateMeta(null, createQueryOptionsForWorldSet(world)); metaAccumulator.complete(); int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 10; - Node.Builder chatMetaNode = NodeFactory.buildChatMetaNode(type, priority, value); - chatMetaNode.setServer(this.vaultPermission.getVaultServer()); - chatMetaNode.setWorld(world); + NodeBuilder chatMetaNode = NodeFactory.buildChatMetaNode(type, priority, value); + chatMetaNode.withContext(DefaultContextKeys.SERVER_KEY, this.vaultPermission.getVaultServer()); + chatMetaNode.withContext(DefaultContextKeys.WORLD_KEY, world); holder.setPermission(chatMetaNode.build()); // assume success this.vaultPermission.holderSave(holder); @@ -285,33 +288,37 @@ public class LuckPermsVaultChat extends AbstractVaultChat { logMsg("#setMeta: %s - %s - %s - %s", holder.getPlainDisplayName(), key, value, world); } - holder.removeIf(n -> n.isMeta() && n.getMeta().getKey().equals(key)); + holder.removeIfEnduring(n -> n instanceof MetaNode && ((MetaNode) n).getMetaKey().equals(key)); if (value == null) { this.vaultPermission.holderSave(holder); return; } - Node.Builder metaNode; + NodeBuilder metaNode; if (key.equalsIgnoreCase(NodeTypes.PREFIX_KEY) || key.equalsIgnoreCase(NodeTypes.SUFFIX_KEY)) { metaNode = NodeFactory.buildChatMetaNode(ChatMetaType.valueOf(key.toUpperCase()), 100, value.toString()); } else { metaNode = NodeFactory.buildMetaNode(key, value.toString()); } - metaNode.setServer(this.vaultPermission.getVaultServer()); - metaNode.setWorld(world); + metaNode.withContext(DefaultContextKeys.SERVER_KEY, this.vaultPermission.getVaultServer()); + metaNode.withContext(DefaultContextKeys.WORLD_KEY, world); holder.setPermission(metaNode.build()); // assume success this.vaultPermission.holderSave(holder); } - private Contexts createContextForWorldSet(String world) { + private QueryOptions createQueryOptionsForWorldSet(String world) { ImmutableContextSet.Builder context = ImmutableContextSet.builder(); if (world != null && !world.equals("") && !world.equalsIgnoreCase("global")) { - context.add(Contexts.WORLD_KEY, world.toLowerCase()); + context.add(DefaultContextKeys.WORLD_KEY, world.toLowerCase()); } - context.add(Contexts.SERVER_KEY, this.vaultPermission.getVaultServer()); - return Contexts.of(context.build(), this.vaultPermission.isIncludeGlobal(), true, true, true, true, false); + context.add(DefaultContextKeys.SERVER_KEY, this.vaultPermission.getVaultServer()); + + QueryOptions.Builder builder = QueryOptions.defaultContextualOptions().toBuilder(); + builder.context(context.build()); + builder.flag(Flag.INCLUDE_NODES_WITHOUT_SERVER_CONTEXT, this.vaultPermission.isIncludeGlobal()); + return builder.build(); } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultPermission.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultPermission.java index e54d9307c..71441fbf2 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultPermission.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/LuckPermsVaultPermission.java @@ -27,13 +27,16 @@ package me.lucko.luckperms.bukkit.vault; import com.google.common.base.Preconditions; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LookupSetting; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.node.NodeType; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.Flag; +import me.lucko.luckperms.api.query.QueryOptions; +import me.lucko.luckperms.api.util.Result; import me.lucko.luckperms.bukkit.LPBukkitPlugin; +import me.lucko.luckperms.bukkit.context.BukkitContextManager; import me.lucko.luckperms.common.cacheddata.type.PermissionCache; import me.lucko.luckperms.common.calculator.processor.MapProcessor; import me.lucko.luckperms.common.calculator.result.TristateResult; @@ -187,14 +190,14 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { Objects.requireNonNull(permission, "permission"); PermissionHolder user = lookupUser(uuid); - Contexts contexts = contextForLookup(uuid, world); - PermissionCache permissionData = user.getCachedData().getPermissionData(contexts); + QueryOptions queryOptions = getQueryOptions(uuid, world); + PermissionCache permissionData = user.getCachedData().getPermissionData(queryOptions); - Tristate result = permissionData.getPermissionValue(permission, PermissionCheckEvent.Origin.THIRD_PARTY_API).result(); + Tristate result = permissionData.checkPermission(permission, PermissionCheckEvent.Origin.THIRD_PARTY_API).result(); if (log()) { - logMsg("#userHasPermission: %s - %s - %s - %s", user.getPlainDisplayName(), contexts.getContexts().toMultimap(), permission, result); + logMsg("#userHasPermission: %s - %s - %s - %s", user.getPlainDisplayName(), queryOptions.context(), permission, result); } - return result != Tristate.UNDEFINED ? result.asBoolean() : org.bukkit.permissions.Permission.DEFAULT_PERMISSION.getValue(contexts.hasSetting(LookupSetting.IS_OP)); + return result != Tristate.UNDEFINED ? result.asBoolean() : org.bukkit.permissions.Permission.DEFAULT_PERMISSION.getValue(queryOptions.option(BukkitContextManager.OP_OPTION).orElse(false)); } @Override @@ -227,12 +230,12 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { Objects.requireNonNull(group, "group"); PermissionHolder user = lookupUser(uuid); - Contexts contexts = contextForLookup(uuid, world); - PermissionCache permissionData = user.getCachedData().getPermissionData(contexts); + QueryOptions queryOptions = getQueryOptions(uuid, world); + PermissionCache permissionData = user.getCachedData().getPermissionData(queryOptions); - TristateResult result = permissionData.getPermissionValue(NodeFactory.groupNode(rewriteGroupName(group)), PermissionCheckEvent.Origin.THIRD_PARTY_API); + TristateResult result = permissionData.checkPermission(NodeFactory.groupNode(rewriteGroupName(group)), PermissionCheckEvent.Origin.THIRD_PARTY_API); if (log()) { - logMsg("#userInGroup: %s - %s - %s - %s", user.getPlainDisplayName(), contexts.getContexts().toMultimap(), group, result); + logMsg("#userInGroup: %s - %s - %s - %s", user.getPlainDisplayName(), queryOptions.context(), group, result); } return result.processorClass() == MapProcessor.class && result.result().asBoolean(); } @@ -256,10 +259,11 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { Objects.requireNonNull(uuid, "uuid"); PermissionHolder user = lookupUser(uuid); - ContextSet contexts = contextForLookup(uuid, world).getContexts(); + ContextSet contexts = getQueryOptions(uuid, world).context(); String[] ret = user.enduringData().immutable().values().stream() - .filter(Node::isGroupNode) + .filter(NodeType.INHERITANCE::matches) + .map(NodeType.INHERITANCE::cast) .filter(n -> n.shouldApplyWithContext(contexts)) .map(n -> { Group group = this.plugin.getGroupManager().getIfLoaded(n.getGroupName()); @@ -291,7 +295,7 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { value = group.getPlainDisplayName(); } - this.plugin.getVerboseHandler().offerMetaCheckEvent(MetaCheckEvent.Origin.THIRD_PARTY_API, user.getPlainDisplayName(), ContextSet.empty(), "primarygroup", value); + this.plugin.getVerboseHandler().offerMetaCheckEvent(MetaCheckEvent.Origin.THIRD_PARTY_API, user.getPlainDisplayName(), QueryOptions.defaultContextualOptions(), "primarygroup", value); if (log()) { logMsg("#userGetPrimaryGroup: %s - %s - %s", user.getPlainDisplayName(), world, value); @@ -310,12 +314,12 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { return false; } - Contexts contexts = contextForLookup(null, world); - PermissionCache permissionData = group.getCachedData().getPermissionData(contexts); + QueryOptions queryOptions = getQueryOptions(null, world); + PermissionCache permissionData = group.getCachedData().getPermissionData(queryOptions); - Tristate result = permissionData.getPermissionValue(permission, PermissionCheckEvent.Origin.THIRD_PARTY_API).result(); + Tristate result = permissionData.checkPermission(permission, PermissionCheckEvent.Origin.THIRD_PARTY_API).result(); if (log()) { - logMsg("#groupHasPermission: %s - %s - %s - %s", group.getName(), contexts.getContexts().toMultimap(), permission, result); + logMsg("#groupHasPermission: %s - %s - %s - %s", group.getName(), queryOptions.context(), permission, result); } return result.asBoolean(); } @@ -376,12 +380,12 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { } // utility method for getting a contexts instance for a given vault lookup. - Contexts contextForLookup(@Nullable UUID uuid, @Nullable String world) { + QueryOptions getQueryOptions(@Nullable UUID uuid, @Nullable String world) { MutableContextSet context; Player player = Optional.ofNullable(uuid).flatMap(u -> this.plugin.getBootstrap().getPlayer(u)).orElse(null); if (player != null) { - context = this.plugin.getContextManager().getApplicableContext(player).mutableCopy(); + context = this.plugin.getContextManager().getContext(player).mutableCopy(); } else { context = this.plugin.getContextManager().getStaticContext().mutableCopy(); } @@ -392,19 +396,19 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { // if world is not null, we want to do a lookup in that specific world if (world != null && !world.isEmpty() && !world.equalsIgnoreCase(playerWorld)) { // remove already accumulated worlds - context.removeAll(Contexts.WORLD_KEY); + context.removeAll(DefaultContextKeys.WORLD_KEY); // add the vault world - context.add(Contexts.WORLD_KEY, world.toLowerCase()); + context.add(DefaultContextKeys.WORLD_KEY, world.toLowerCase()); } // if we're using a special vault server if (useVaultServer()) { // remove the normal server context from the set - context.remove(Contexts.SERVER_KEY, getServer()); + context.remove(DefaultContextKeys.SERVER_KEY, getServer()); // add the vault specific server if (!getVaultServer().equals("global")) { - context.add(Contexts.SERVER_KEY, getVaultServer()); + context.add(DefaultContextKeys.SERVER_KEY, getVaultServer()); } } @@ -415,7 +419,13 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { op = this.plugin.getConfiguration().get(ConfigKeys.VAULT_NPC_OP_STATUS); } - return Contexts.of(context, isIncludeGlobal(), true, true, true, true, op); + QueryOptions.Builder builder = QueryOptions.defaultContextualOptions().toBuilder(); + builder.context(context); + builder.flag(Flag.INCLUDE_NODES_WITHOUT_SERVER_CONTEXT, isIncludeGlobal()); + if (op) { + builder.option(BukkitContextManager.OP_OPTION, true); + } + return builder.build(); } // utility methods for modifying the state of PermissionHolders @@ -428,7 +438,7 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { logMsg("#holderAddPermission: %s - %s - %s", holder.getPlainDisplayName(), permission, world); } - if (holder.setPermission(NodeFactory.make(permission, true, getVaultServer(), world)).asBoolean()) { + if (((Result) holder.setPermission(NodeFactory.make(permission, true, getVaultServer(), world))).wasSuccessful()) { return holderSave(holder); } return false; @@ -442,7 +452,7 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission { logMsg("#holderRemovePermission: %s - %s - %s", holder.getPlainDisplayName(), permission, world); } - if (holder.unsetPermission(NodeFactory.make(permission, getVaultServer(), world)).asBoolean()) { + if (((Result) holder.unsetPermission(NodeFactory.make(permission, getVaultServer(), world))).wasSuccessful()) { return holderSave(holder); } return false; diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeSenderFactory.java b/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeSenderFactory.java index 79dc19964..6b540d7b0 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeSenderFactory.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeSenderFactory.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.bungee; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.bungee.event.TristateCheckEvent; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeeBootstrap.java b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeeBootstrap.java index db9a1b5b5..1360fb02d 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeeBootstrap.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeeBootstrap.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.bungee; -import me.lucko.luckperms.api.platform.PlatformType; +import me.lucko.luckperms.api.platform.Platform; import me.lucko.luckperms.bungee.util.RedisBungeeUtil; import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader; import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader; @@ -157,8 +157,8 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap { // provide information about the platform @Override - public PlatformType getType() { - return PlatformType.BUNGEE; + public Platform.Type getType() { + return Platform.Type.BUNGEECORD; } @Override diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java index 3ece1deb1..52beba035 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.bungee; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.LuckPerms; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.bungee.calculator.BungeeCalculatorFactory; import me.lucko.luckperms.bungee.context.BackendServerCalculator; import me.lucko.luckperms.bungee.context.BungeeContextManager; @@ -157,7 +157,7 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin { } @Override - protected void registerApiOnPlatform(LuckPermsApi api) { + protected void registerApiOnPlatform(LuckPerms api) { // BungeeCord doesn't have a services manager } @@ -188,8 +188,8 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin { } @Override - public Optional getContextForUser(User user) { - return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getApplicableContexts(player)); + public Optional getQueryOptionsForUser(User user) { + return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getQueryOptions(player)); } @Override diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/calculator/BungeeCalculatorFactory.java b/bungee/src/main/java/me/lucko/luckperms/bungee/calculator/BungeeCalculatorFactory.java index f75ff5f02..9cb2710a3 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/calculator/BungeeCalculatorFactory.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/calculator/BungeeCalculatorFactory.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.bungee.calculator; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.bungee.LPBungeePlugin; import me.lucko.luckperms.common.cacheddata.CacheMetadata; import me.lucko.luckperms.common.calculator.CalculatorFactory; @@ -46,7 +46,7 @@ public class BungeeCalculatorFactory implements CalculatorFactory { } @Override - public PermissionCalculator build(Contexts contexts, CacheMetadata metadata) { + public PermissionCalculator build(QueryOptions queryOptions, CacheMetadata metadata) { ImmutableList.Builder processors = ImmutableList.builder(); processors.add(new MapProcessor()); diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/context/BackendServerCalculator.java b/bungee/src/main/java/me/lucko/luckperms/bungee/context/BackendServerCalculator.java index 712ce5d10..b6b48b93a 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/context/BackendServerCalculator.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/context/BackendServerCalculator.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.bungee.context; -import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ContextCalculator; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ContextConsumer; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -35,6 +35,9 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import org.checkerframework.checker.nullness.qual.NonNull; +import java.util.HashSet; +import java.util.Set; + public class BackendServerCalculator implements ContextCalculator { private static String getServer(ProxiedPlayer player) { @@ -48,13 +51,12 @@ public class BackendServerCalculator implements ContextCalculator } @Override - public @NonNull MutableContextSet giveApplicableContext(@NonNull ProxiedPlayer subject, @NonNull MutableContextSet accumulator) { + public void giveApplicableContext(@NonNull ProxiedPlayer subject, @NonNull ContextConsumer consumer) { + Set seen = new HashSet<>(); String server = getServer(subject); - while (server != null && !accumulator.has(Contexts.WORLD_KEY, server)) { - accumulator.add(Contexts.WORLD_KEY, server); + while (server != null && seen.add(server)) { + consumer.accept(DefaultContextKeys.WORLD_KEY, server); server = this.plugin.getConfiguration().get(ConfigKeys.WORLD_REWRITES).getOrDefault(server, server).toLowerCase(); } - - return accumulator; } } 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 7a046f616..62cbe3907 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 @@ -27,11 +27,11 @@ package me.lucko.luckperms.bungee.context; import com.github.benmanes.caffeine.cache.LoadingCache; -import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.bungee.LPBungeePlugin; import me.lucko.luckperms.common.context.ContextManager; -import me.lucko.luckperms.common.context.ContextsSupplier; +import me.lucko.luckperms.common.context.QueryOptionsSupplier; import me.lucko.luckperms.common.util.CaffeineFactory; import net.md_5.bungee.api.connection.ProxiedPlayer; @@ -40,7 +40,7 @@ import java.util.concurrent.TimeUnit; public class BungeeContextManager extends ContextManager { - private final LoadingCache contextsCache = CaffeineFactory.newBuilder() + private final LoadingCache contextsCache = CaffeineFactory.newBuilder() .expireAfterWrite(50, TimeUnit.MILLISECONDS) .build(this::calculate); @@ -49,21 +49,21 @@ public class BungeeContextManager extends ContextManager { } @Override - public ContextsSupplier getCacheFor(ProxiedPlayer subject) { + public QueryOptionsSupplier getCacheFor(ProxiedPlayer subject) { if (subject == null) { throw new NullPointerException("subject"); } - return new InlineContextsSupplier(subject, this.contextsCache); + return new InlineQueryOptionsSupplier(subject, this.contextsCache); } @Override - public ImmutableContextSet getApplicableContext(ProxiedPlayer subject) { - return getApplicableContexts(subject).getContexts().makeImmutable(); + public ImmutableContextSet getContext(ProxiedPlayer subject) { + return getQueryOptions(subject).context(); } @Override - public Contexts getApplicableContexts(ProxiedPlayer subject) { + public QueryOptions getQueryOptions(ProxiedPlayer subject) { return this.contextsCache.get(subject); } @@ -73,22 +73,22 @@ public class BungeeContextManager extends ContextManager { } @Override - public Contexts formContexts(ProxiedPlayer subject, ImmutableContextSet contextSet) { - return formContexts(contextSet); + public QueryOptions formQueryOptions(ProxiedPlayer subject, ImmutableContextSet contextSet) { + return formQueryOptions(contextSet); } - private static final class InlineContextsSupplier implements ContextsSupplier { + private static final class InlineQueryOptionsSupplier implements QueryOptionsSupplier { private final ProxiedPlayer key; - private final LoadingCache contextsCache; + private final LoadingCache cache; - private InlineContextsSupplier(ProxiedPlayer key, LoadingCache contextsCache) { + private InlineQueryOptionsSupplier(ProxiedPlayer key, LoadingCache cache) { this.key = key; - this.contextsCache = contextsCache; + this.cache = cache; } @Override - public Contexts getContexts() { - return this.contextsCache.get(this.key); + public QueryOptions getQueryOptions() { + return this.cache.get(this.key); } } } diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/context/RedisBungeeCalculator.java b/bungee/src/main/java/me/lucko/luckperms/bungee/context/RedisBungeeCalculator.java index 013018c23..f61130695 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/context/RedisBungeeCalculator.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/context/RedisBungeeCalculator.java @@ -28,7 +28,7 @@ package me.lucko.luckperms.bungee.context; import com.imaginarycode.minecraft.redisbungee.RedisBungee; import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ContextConsumer; import me.lucko.luckperms.api.context.StaticContextCalculator; import org.checkerframework.checker.nullness.qual.NonNull; @@ -37,11 +37,10 @@ public class RedisBungeeCalculator implements StaticContextCalculator { private static final String PROXY_KEY = "proxy"; @Override - public @NonNull MutableContextSet giveApplicableContext(@NonNull MutableContextSet accumulator) { + public void giveApplicableContext(@NonNull ContextConsumer consumer) { RedisBungeeAPI redisBungee = RedisBungee.getApi(); if (redisBungee != null) { - accumulator.add(PROXY_KEY, redisBungee.getServerId()); + consumer.accept(PROXY_KEY, redisBungee.getServerId()); } - return accumulator; } } diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/event/TristateCheckEvent.java b/bungee/src/main/java/me/lucko/luckperms/bungee/event/TristateCheckEvent.java index 24af1d3a8..7cd68d467 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/event/TristateCheckEvent.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/event/TristateCheckEvent.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.bungee.event; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ProxyServer; diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeePermissionCheckListener.java b/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeePermissionCheckListener.java index ddf783849..5f51bb42b 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeePermissionCheckListener.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/listeners/BungeePermissionCheckListener.java @@ -25,9 +25,8 @@ package me.lucko.luckperms.bungee.listeners; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.bungee.LPBungeePlugin; import me.lucko.luckperms.bungee.event.TristateCheckEvent; import me.lucko.luckperms.common.calculator.result.TristateResult; @@ -66,8 +65,8 @@ public class BungeePermissionCheckListener implements Listener { throw new IllegalStateException("No permissions data present for player: " + player.getName() + " - " + player.getUniqueId()); } - Contexts contexts = this.plugin.getContextManager().getApplicableContexts(player); - Tristate result = user.getCachedData().getPermissionData(contexts).getPermissionValue(e.getPermission(), me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result(); + QueryOptions queryOptions = this.plugin.getContextManager().getQueryOptions(player); + Tristate result = user.getCachedData().getPermissionData(queryOptions).checkPermission(e.getPermission(), me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result(); if (result == Tristate.UNDEFINED && this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUNGEE_CONFIG_PERMISSIONS)) { return; // just use the result provided by the proxy when the event was created } @@ -92,8 +91,8 @@ public class BungeePermissionCheckListener implements Listener { throw new IllegalStateException("No permissions data present for player: " + player.getName() + " - " + player.getUniqueId()); } - Contexts contexts = this.plugin.getContextManager().getApplicableContexts(player); - Tristate result = user.getCachedData().getPermissionData(contexts).getPermissionValue(e.getPermission(), me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK).result(); + QueryOptions queryOptions = this.plugin.getContextManager().getQueryOptions(player); + Tristate result = user.getCachedData().getPermissionData(queryOptions).checkPermission(e.getPermission(), me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK).result(); if (result == Tristate.UNDEFINED && this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUNGEE_CONFIG_PERMISSIONS)) { return; // just use the result provided by the proxy when the event was created } @@ -111,10 +110,10 @@ public class BungeePermissionCheckListener implements Listener { Objects.requireNonNull(e.getSender(), "sender"); String permission = e.getPermission(); - Tristate result = Tristate.fromBoolean(e.hasPermission()); + Tristate result = Tristate.of(e.hasPermission()); String name = "internal/" + e.getSender().getName(); - this.plugin.getVerboseHandler().offerPermissionCheckEvent(me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK, name, ContextSet.empty(), permission, TristateResult.of(result)); + this.plugin.getVerboseHandler().offerPermissionCheckEvent(me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK, name, QueryOptions.defaultContextualOptions(), permission, TristateResult.of(result)); this.plugin.getPermissionRegistry().offer(permission); } @@ -131,7 +130,7 @@ public class BungeePermissionCheckListener implements Listener { Tristate result = e.getResult(); String name = "internal/" + e.getSender().getName(); - this.plugin.getVerboseHandler().offerPermissionCheckEvent(me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK, name, ContextSet.empty(), permission, TristateResult.of(result)); + this.plugin.getVerboseHandler().offerPermissionCheckEvent(me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK, name, QueryOptions.defaultContextualOptions(), permission, TristateResult.of(result)); this.plugin.getPermissionRegistry().offer(permission); } } diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/migration/MigrationBungeePerms.java b/bungee/src/main/java/me/lucko/luckperms/bungee/migration/MigrationBungeePerms.java index 71a205a5b..54ccd9cc9 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/migration/MigrationBungeePerms.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/migration/MigrationBungeePerms.java @@ -25,6 +25,7 @@ package me.lucko.luckperms.bungee.migration; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; @@ -138,14 +139,14 @@ public class MigrationBungeePerms extends SubCommand { for (Map.Entry e : entity.getServers().entrySet()) { for (String perm : e.getValue().getPerms()) { if (perm.isEmpty()) continue; - holder.setPermission(MigrationUtils.parseNode(perm, true).setServer(e.getKey()).build()); + holder.setPermission(MigrationUtils.parseNode(perm, true).withContext(DefaultContextKeys.SERVER_KEY, e.getKey()).build()); } // Migrate per-world perms for (Map.Entry we : e.getValue().getWorlds().entrySet()) { for (String perm : we.getValue().getPerms()) { if (perm.isEmpty()) continue; - holder.setPermission(MigrationUtils.parseNode(perm, true).setServer(e.getKey()).setWorld(we.getKey()).build()); + holder.setPermission(MigrationUtils.parseNode(perm, true).withContext(DefaultContextKeys.SERVER_KEY, e.getKey()).withContext(DefaultContextKeys.WORLD_KEY, we.getKey()).build()); } } } diff --git a/common/src/main/java/me/lucko/luckperms/common/actionlog/ExtendedLogEntry.java b/common/src/main/java/me/lucko/luckperms/common/actionlog/ExtendedLogEntry.java index b76150619..65fd73955 100644 --- a/common/src/main/java/me/lucko/luckperms/common/actionlog/ExtendedLogEntry.java +++ b/common/src/main/java/me/lucko/luckperms/common/actionlog/ExtendedLogEntry.java @@ -27,9 +27,9 @@ package me.lucko.luckperms.common.actionlog; import com.google.common.base.Strings; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.HolderType; import me.lucko.luckperms.common.model.PermissionHolder; @@ -49,20 +49,20 @@ import java.util.Optional; import java.util.UUID; /** - * An implementation of {@link LogEntry} and {@link LogEntry.Builder}, + * An implementation of {@link Action} and {@link Action.Builder}, * with helper methods for populating and using the entry using internal * LuckPerms classes. */ -public class ExtendedLogEntry implements LogEntry { +public class ExtendedLogEntry implements Action { - private static final Comparator COMPARATOR = Comparator - .comparingLong(LogEntry::getTimestamp) - .thenComparing(LogEntry::getActor) - .thenComparing(LogEntry::getActorName, String.CASE_INSENSITIVE_ORDER) - .thenComparing(LogEntry::getType) + private static final Comparator COMPARATOR = Comparator + .comparingLong(Action::getTimestamp) + .thenComparing(Action::getActor) + .thenComparing(Action::getActorName, String.CASE_INSENSITIVE_ORDER) + .thenComparing(Action::getType) .thenComparing(e -> e.getActed().map(UUID::toString).orElse("")) - .thenComparing(LogEntry::getActedName, String.CASE_INSENSITIVE_ORDER) - .thenComparing(LogEntry::getAction); + .thenComparing(Action::getActedName, String.CASE_INSENSITIVE_ORDER) + .thenComparing(Action::getAction); /** * Creates a new log entry builder @@ -143,7 +143,7 @@ public class ExtendedLogEntry implements LogEntry { } @Override - public int compareTo(@NonNull LogEntry other) { + public int compareTo(@NonNull Action other) { Objects.requireNonNull(other, "other"); return COMPARATOR.compare(this, other); } @@ -174,8 +174,8 @@ public class ExtendedLogEntry implements LogEntry { @Override public boolean equals(Object o) { if (o == this) return true; - if (!(o instanceof LogEntry)) return false; - final LogEntry that = (LogEntry) o; + if (!(o instanceof Action)) return false; + final Action that = (Action) o; return this.getTimestamp() == that.getTimestamp() && this.getActor().equals(that.getActor()) && @@ -200,7 +200,7 @@ public class ExtendedLogEntry implements LogEntry { return result; } - public static class Builder implements LogEntry.Builder { + public static class Builder implements Action.Builder { private long timestamp = 0L; private UUID actor = null; @@ -210,76 +210,41 @@ public class ExtendedLogEntry implements LogEntry { private String actedName = null; private String action = null; - @Override - public @NonNull Builder setTimestamp(long timestamp) { + public @NonNull Builder timestamp(long timestamp) { this.timestamp = timestamp; return this; } - @Override - public @NonNull Builder setActor(@NonNull UUID actor) { + public @NonNull Builder actor(@NonNull UUID actor) { this.actor = Objects.requireNonNull(actor, "actor"); return this; } - @Override - public @NonNull Builder setActorName(@NonNull String actorName) { + public @NonNull Builder actorName(@NonNull String actorName) { this.actorName = Objects.requireNonNull(actorName, "actorName"); return this; } - @Override - public @NonNull Builder setType(@NonNull Type type) { + public @NonNull Builder type(@NonNull Type type) { this.type = Objects.requireNonNull(type, "type"); return this; } - @Override - public @NonNull Builder setActed(UUID acted) { + public @NonNull Builder acted(UUID acted) { this.acted = acted; // nullable return this; } - @Override - public @NonNull Builder setActedName(@NonNull String actedName) { + public @NonNull Builder actedName(@NonNull String actedName) { this.actedName = Objects.requireNonNull(actedName, "actedName"); return this; } - @Override - public @NonNull Builder setAction(@NonNull String action) { + public @NonNull Builder action(@NonNull String action) { this.action = Objects.requireNonNull(action, "action"); return this; } - public Builder timestamp(long timestamp) { - return setTimestamp(timestamp); - } - - public Builder actor(UUID actor) { - return setActor(actor); - } - - public Builder actorName(String actorName) { - return setActorName(actorName); - } - - public Builder type(Type type) { - return setType(type); - } - - public Builder acted(UUID acted) { - return setActed(acted); - } - - public Builder actedName(String actedName) { - return setActedName(actedName); - } - - public Builder action(String action) { - return setAction(action); - } - public Builder actor(Sender actor) { actorName(actor.getNameWithLocation()); actor(actor.getUuid()); @@ -313,15 +278,15 @@ public class ExtendedLogEntry implements LogEntry { if (o instanceof ContextSet) { ContextSet set = (ContextSet) o; - for (String value : set.getValues(Contexts.SERVER_KEY)) { + for (String value : set.getValues(DefaultContextKeys.SERVER_KEY)) { parts.add("server=" + value); } - for (String value : set.getValues(Contexts.WORLD_KEY)) { + for (String value : set.getValues(DefaultContextKeys.WORLD_KEY)) { parts.add("world=" + value); } for (Map.Entry context : set.toSet()) { - if (context.getKey().equals(Contexts.SERVER_KEY) || context.getKey().equals(Contexts.WORLD_KEY)) { + if (context.getKey().equals(DefaultContextKeys.SERVER_KEY) || context.getKey().equals(DefaultContextKeys.WORLD_KEY)) { continue; } parts.add(context.getKey() + "=" + context.getValue()); diff --git a/common/src/main/java/me/lucko/luckperms/common/actionlog/Log.java b/common/src/main/java/me/lucko/luckperms/common/actionlog/Log.java index e5f9e6fbb..da7244655 100644 --- a/common/src/main/java/me/lucko/luckperms/common/actionlog/Log.java +++ b/common/src/main/java/me/lucko/luckperms/common/actionlog/Log.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.common.actionlog; import com.google.common.collect.ImmutableSortedSet; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.common.util.ImmutableCollectors; import java.util.Comparator; @@ -68,21 +68,21 @@ public class Log { public SortedSet getUserHistory(UUID uuid) { return this.content.stream() - .filter(e -> e.getType() == LogEntry.Type.USER) + .filter(e -> e.getType() == Action.Type.USER) .filter(e -> e.getActed().isPresent() && e.getActed().get().equals(uuid)) .collect(ImmutableCollectors.toSortedSet(Comparator.naturalOrder())); } public SortedSet getGroupHistory(String name) { return this.content.stream() - .filter(e -> e.getType() == LogEntry.Type.GROUP) + .filter(e -> e.getType() == Action.Type.GROUP) .filter(e -> e.getActedName().equals(name)) .collect(ImmutableCollectors.toSortedSet(Comparator.naturalOrder())); } public SortedSet getTrackHistory(String name) { return this.content.stream() - .filter(e -> e.getType() == LogEntry.Type.TRACK) + .filter(e -> e.getType() == Action.Type.TRACK) .filter(e -> e.getActedName().equals(name)) .collect(ImmutableCollectors.toSortedSet(Comparator.naturalOrder())); } diff --git a/common/src/main/java/me/lucko/luckperms/common/actionlog/LogEntryJsonSerializer.java b/common/src/main/java/me/lucko/luckperms/common/actionlog/LogEntryJsonSerializer.java index fdf4fccf9..36a02267b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/actionlog/LogEntryJsonSerializer.java +++ b/common/src/main/java/me/lucko/luckperms/common/actionlog/LogEntryJsonSerializer.java @@ -30,14 +30,14 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import java.util.UUID; public final class LogEntryJsonSerializer { private LogEntryJsonSerializer() {} - public static JsonObject serialize(LogEntry logEntry) { + public static JsonObject serialize(Action logEntry) { JsonObject data = new JsonObject(); data.add("actor", new JsonPrimitive(logEntry.getActor().toString())); data.add("actorName", new JsonPrimitive(logEntry.getActorName())); @@ -59,7 +59,7 @@ public final class LogEntryJsonSerializer { builder.actor(UUID.fromString(data.get("actor").getAsString())); builder.actorName(data.get("actorName").getAsString()); - builder.type(LogEntry.Type.parse(data.get("type").getAsString())); + builder.type(Action.Type.parse(data.get("type").getAsString())); if (data.has("acted")) { builder.actor(UUID.fromString(data.get("acted").getAsString())); } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/ApiRegistrationUtil.java b/common/src/main/java/me/lucko/luckperms/common/api/ApiRegistrationUtil.java index 74413ecb5..418372837 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/ApiRegistrationUtil.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/ApiRegistrationUtil.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.api; -import me.lucko.luckperms.LuckPerms; -import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.LuckPermsProvider; +import me.lucko.luckperms.api.LuckPerms; import java.lang.reflect.Method; @@ -35,17 +35,17 @@ public class ApiRegistrationUtil { private static final Method UNREGISTER; static { try { - REGISTER = LuckPerms.class.getDeclaredMethod("registerProvider", LuckPermsApi.class); + REGISTER = LuckPermsProvider.class.getDeclaredMethod("register", LuckPerms.class); REGISTER.setAccessible(true); - UNREGISTER = LuckPerms.class.getDeclaredMethod("unregisterProvider"); + UNREGISTER = LuckPermsProvider.class.getDeclaredMethod("unregister"); UNREGISTER.setAccessible(true); } catch (NoSuchMethodException e) { throw new ExceptionInInitializerError(e); } } - public static void registerProvider(LuckPermsApi luckPermsApi) { + public static void registerProvider(LuckPerms luckPermsApi) { try { REGISTER.invoke(null, luckPermsApi); } catch (Exception e) { diff --git a/common/src/main/java/me/lucko/luckperms/common/api/LuckPermsApiProvider.java b/common/src/main/java/me/lucko/luckperms/common/api/LuckPermsApiProvider.java index 794372715..c3885f98d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/LuckPermsApiProvider.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/LuckPermsApiProvider.java @@ -25,28 +25,26 @@ package me.lucko.luckperms.common.api; -import me.lucko.luckperms.api.ActionLogger; -import me.lucko.luckperms.api.LPConfiguration; -import me.lucko.luckperms.api.LuckPermsApi; -import me.lucko.luckperms.api.MessagingService; -import me.lucko.luckperms.api.NodeFactory; +import me.lucko.luckperms.api.LuckPerms; +import me.lucko.luckperms.api.actionlog.ActionLogger; import me.lucko.luckperms.api.context.ContextManager; import me.lucko.luckperms.api.event.EventBus; -import me.lucko.luckperms.api.manager.CachedDataManager; -import me.lucko.luckperms.api.manager.GroupManager; -import me.lucko.luckperms.api.manager.TrackManager; -import me.lucko.luckperms.api.manager.UserManager; +import me.lucko.luckperms.api.messaging.MessagingService; import me.lucko.luckperms.api.messenger.MessengerProvider; import me.lucko.luckperms.api.metastacking.MetaStackFactory; -import me.lucko.luckperms.api.platform.PlatformInfo; +import me.lucko.luckperms.api.model.group.GroupManager; +import me.lucko.luckperms.api.model.user.UserManager; +import me.lucko.luckperms.api.node.NodeBuilderRegistry; +import me.lucko.luckperms.api.platform.Platform; +import me.lucko.luckperms.api.platform.PluginMetadata; +import me.lucko.luckperms.api.track.TrackManager; import me.lucko.luckperms.common.api.implementation.ApiActionLogger; -import me.lucko.luckperms.common.api.implementation.ApiCachedDataManager; import me.lucko.luckperms.common.api.implementation.ApiContextManager; import me.lucko.luckperms.common.api.implementation.ApiGroupManager; import me.lucko.luckperms.common.api.implementation.ApiMessagingService; import me.lucko.luckperms.common.api.implementation.ApiMetaStackFactory; -import me.lucko.luckperms.common.api.implementation.ApiNodeFactory; -import me.lucko.luckperms.common.api.implementation.ApiPlatformInfo; +import me.lucko.luckperms.common.api.implementation.ApiNodeBuilderRegistry; +import me.lucko.luckperms.common.api.implementation.ApiPlatform; import me.lucko.luckperms.common.api.implementation.ApiTrackManager; import me.lucko.luckperms.common.api.implementation.ApiUserManager; import me.lucko.luckperms.common.config.ConfigKeys; @@ -62,15 +60,14 @@ import java.util.concurrent.CompletableFuture; /** * Implements the LuckPerms API using the plugin instance */ -public class LuckPermsApiProvider implements LuckPermsApi { +public class LuckPermsApiProvider implements LuckPerms { private final LuckPermsPlugin plugin; - private final PlatformInfo platformInfo; + private final ApiPlatform platform; private final UserManager userManager; private final GroupManager groupManager; private final TrackManager trackManager; - private final CachedDataManager cachedDataManager; private final ActionLogger actionLogger; private final ContextManager contextManager; private final MetaStackFactory metaStackFactory; @@ -78,19 +75,28 @@ public class LuckPermsApiProvider implements LuckPermsApi { public LuckPermsApiProvider(LuckPermsPlugin plugin) { this.plugin = plugin; - this.platformInfo = new ApiPlatformInfo(plugin); + this.platform = new ApiPlatform(plugin); this.userManager = new ApiUserManager(plugin, plugin.getUserManager()); this.groupManager = new ApiGroupManager(plugin, plugin.getGroupManager()); this.trackManager = new ApiTrackManager(plugin, plugin.getTrackManager()); - this.cachedDataManager = new ApiCachedDataManager(plugin.getUserManager(), plugin.getGroupManager()); this.actionLogger = new ApiActionLogger(plugin); this.contextManager = new ApiContextManager(plugin, plugin.getContextManager()); this.metaStackFactory = new ApiMetaStackFactory(plugin); } @Override - public @NonNull PlatformInfo getPlatformInfo() { - return this.platformInfo; + public String getServerName() { + return this.plugin.getConfiguration().get(ConfigKeys.SERVER); + } + + @Override + public @NonNull Platform getPlatform() { + return this.platform; + } + + @Override + public @NonNull PluginMetadata getPluginMetadata() { + return this.platform; } @Override @@ -108,11 +114,6 @@ public class LuckPermsApiProvider implements LuckPermsApi { return this.trackManager; } - @Override - public @NonNull CachedDataManager getCachedDataManager() { - return this.cachedDataManager; - } - @Override public @NonNull CompletableFuture runUpdateTask() { return this.plugin.getSyncTaskBuffer().request(); @@ -123,11 +124,6 @@ public class LuckPermsApiProvider implements LuckPermsApi { return this.plugin.getEventFactory().getEventBus(); } - @Override - public @NonNull LPConfiguration getConfiguration() { - return this.plugin.getConfiguration().getDelegate(); - } - @Override public @NonNull Optional getMessagingService() { return this.plugin.getMessagingService().map(ApiMessagingService::new); @@ -156,8 +152,8 @@ public class LuckPermsApiProvider implements LuckPermsApi { } @Override - public @NonNull NodeFactory getNodeFactory() { - return ApiNodeFactory.INSTANCE; + public @NonNull NodeBuilderRegistry getNodeBuilderRegistry() { + return ApiNodeBuilderRegistry.INSTANCE; } @Override diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiLog.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiActionLog.java similarity index 80% rename from common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiLog.java rename to common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiActionLog.java index a3993f11b..f20f1eece 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiLog.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiActionLog.java @@ -25,7 +25,8 @@ package me.lucko.luckperms.common.api.implementation; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; +import me.lucko.luckperms.api.actionlog.ActionLog; import me.lucko.luckperms.common.actionlog.Log; import me.lucko.luckperms.common.api.ApiUtils; @@ -36,38 +37,38 @@ import java.util.SortedSet; import java.util.UUID; @SuppressWarnings("unchecked") -public class ApiLog implements me.lucko.luckperms.api.Log { +public class ApiActionLog implements ActionLog { private final Log handle; - public ApiLog(Log handle) { + public ApiActionLog(Log handle) { this.handle = handle; } @Override - public @NonNull SortedSet getContent() { + public @NonNull SortedSet getContent() { return (SortedSet) this.handle.getContent(); } @Override - public @NonNull SortedSet getContent(@NonNull UUID actor) { + public @NonNull SortedSet getContent(@NonNull UUID actor) { Objects.requireNonNull(actor, "actor"); return (SortedSet) this.handle.getContent(actor); } @Override - public @NonNull SortedSet getUserHistory(@NonNull UUID uuid) { + public @NonNull SortedSet getUserHistory(@NonNull UUID uuid) { Objects.requireNonNull(uuid, "uuid"); return (SortedSet) this.handle.getUserHistory(uuid); } @Override - public @NonNull SortedSet getGroupHistory(@NonNull String name) { + public @NonNull SortedSet getGroupHistory(@NonNull String name) { Objects.requireNonNull(name, "name"); return (SortedSet) this.handle.getGroupHistory(ApiUtils.checkName(name)); } @Override - public @NonNull SortedSet getTrackHistory(@NonNull String name) { + public @NonNull SortedSet getTrackHistory(@NonNull String name) { Objects.requireNonNull(name, "name"); return (SortedSet) this.handle.getTrackHistory(ApiUtils.checkName(name)); } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiActionLogger.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiActionLogger.java index cf09d0374..6a0ad1f7c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiActionLogger.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiActionLogger.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.api.implementation; -import me.lucko.luckperms.api.ActionLogger; -import me.lucko.luckperms.api.Log; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; +import me.lucko.luckperms.api.actionlog.ActionLog; +import me.lucko.luckperms.api.actionlog.ActionLogger; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -43,27 +43,27 @@ public class ApiActionLogger implements ActionLogger { } @Override - public LogEntry.@NonNull Builder newEntryBuilder() { + public Action.@NonNull Builder actionBuilder() { return ExtendedLogEntry.build(); } @Override - public @NonNull CompletableFuture getLog() { - return this.plugin.getStorage().getLog().thenApply(ApiLog::new); + public @NonNull CompletableFuture getLog() { + return this.plugin.getStorage().getLog().thenApply(ApiActionLog::new); } @Override - public @NonNull CompletableFuture submit(@NonNull LogEntry entry) { + public @NonNull CompletableFuture submit(@NonNull Action entry) { return CompletableFuture.runAsync(() -> this.plugin.getLogDispatcher().dispatchFromApi((ExtendedLogEntry) entry), this.plugin.getBootstrap().getScheduler().async()); } @Override - public @NonNull CompletableFuture submitToStorage(@NonNull LogEntry entry) { + public @NonNull CompletableFuture submitToStorage(@NonNull Action entry) { return this.plugin.getStorage().logAction(entry); } @Override - public @NonNull CompletableFuture broadcastAction(@NonNull LogEntry entry) { + public @NonNull CompletableFuture broadcastAction(@NonNull Action entry) { return CompletableFuture.runAsync(() -> this.plugin.getLogDispatcher().broadcastFromApi((ExtendedLogEntry) entry), this.plugin.getBootstrap().getScheduler().async()); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiConfiguration.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiConfiguration.java deleted file mode 100644 index b7733f9a1..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiConfiguration.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.api.implementation; - -import me.lucko.luckperms.api.LPConfiguration; -import me.lucko.luckperms.api.LookupSetting; -import me.lucko.luckperms.common.config.ConfigKey; -import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.config.LuckPermsConfiguration; -import me.lucko.luckperms.common.util.ImmutableCollectors; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Map; - -public class ApiConfiguration implements LPConfiguration { - private final LuckPermsConfiguration handle; - private final Unsafe unsafe; - - public ApiConfiguration(LuckPermsConfiguration handle) { - this.handle = handle; - this.unsafe = new UnsafeImpl(); - } - - @Override - public @NonNull String getServer() { - return this.handle.get(ConfigKeys.SERVER); - } - - @Override - public boolean getIncludeGlobalPerms() { - return this.handle.get(ConfigKeys.GLOBAL_CONTEXTS).hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER); - } - - @Override - public boolean getIncludeGlobalWorldPerms() { - return this.handle.get(ConfigKeys.GLOBAL_CONTEXTS).hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD); - } - - @Override - public boolean getApplyGlobalGroups() { - return this.handle.get(ConfigKeys.GLOBAL_CONTEXTS).hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER); - } - - @Override - public boolean getApplyGlobalWorldGroups() { - return this.handle.get(ConfigKeys.GLOBAL_CONTEXTS).hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD); - } - - @Override - public @NonNull String getStorageMethod() { - return this.handle.get(ConfigKeys.STORAGE_METHOD).getName(); - } - - @Override - public boolean getSplitStorage() { - return this.handle.get(ConfigKeys.SPLIT_STORAGE); - } - - @Override - public @NonNull Map getSplitStorageOptions() { - return this.handle.get(ConfigKeys.SPLIT_STORAGE_OPTIONS).entrySet().stream() - .collect(ImmutableCollectors.toMap(e -> e.getKey().name().toLowerCase(), e -> e.getValue().getName())); - } - - @Override - public @NonNull Unsafe unsafe() { - return this.unsafe; - } - - private final class UnsafeImpl implements Unsafe { - - @Override - public @NonNull Object getObject(String key) { - ConfigKey configKey = ConfigKeys.getKeys().get(key.toUpperCase()); - if (configKey == null) { - throw new IllegalArgumentException("Unknown key: " + key); - } - return ApiConfiguration.this.handle.get(configKey); - } - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextManager.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextManager.java index 5b864f250..25f565092 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextManager.java @@ -25,12 +25,15 @@ package me.lucko.luckperms.common.api.implementation; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.context.ContextCalculator; +import me.lucko.luckperms.api.context.ContextSetFactory; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.model.user.User; +import me.lucko.luckperms.api.query.QueryMode; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.context.ContextManager; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import me.lucko.luckperms.common.query.QueryOptionsBuilderImpl; import org.checkerframework.checker.nullness.qual.NonNull; @@ -55,27 +58,15 @@ public class ApiContextManager implements me.lucko.luckperms.api.context.Context } @Override - public @NonNull ImmutableContextSet getApplicableContext(@NonNull Object subject) { + public @NonNull ImmutableContextSet getContext(@NonNull Object subject) { Objects.requireNonNull(subject, "subject"); - return this.handle.getApplicableContext(checkType(subject)); + return this.handle.getContext(checkType(subject)); } @Override - public @NonNull Contexts getApplicableContexts(@NonNull Object subject) { - Objects.requireNonNull(subject, "subject"); - return this.handle.getApplicableContexts(checkType(subject)); - } - - @Override - public @NonNull Optional lookupApplicableContext(@NonNull User user) { + public @NonNull Optional lookupContext(@NonNull User user) { Objects.requireNonNull(user, "user"); - return this.plugin.getContextForUser(ApiUser.cast(user)).map(c -> c.getContexts().makeImmutable()); - } - - @Override - public @NonNull Optional lookupApplicableContexts(@NonNull User user) { - Objects.requireNonNull(user, "user"); - return this.plugin.getContextForUser(ApiUser.cast(user)); + return this.plugin.getQueryOptionsForUser(ApiUser.cast(user)).map(QueryOptions::context); } @Override @@ -84,21 +75,39 @@ public class ApiContextManager implements me.lucko.luckperms.api.context.Context } @Override - public @NonNull Contexts getStaticContexts() { - return this.handle.getStaticContexts(); + public QueryOptions.@NonNull Builder queryOptionsBuilder(@NonNull QueryMode mode) { + Objects.requireNonNull(mode, "mode"); + return new QueryOptionsBuilderImpl(mode); } @Override - public @NonNull Contexts formContexts(@NonNull Object subject, @NonNull ImmutableContextSet contextSet) { + public @NonNull QueryOptions getQueryOptions(@NonNull Object subject) { + Objects.requireNonNull(subject, "subject"); + return this.handle.getQueryOptions(subject); + } + + @Override + public @NonNull Optional lookupQueryOptions(@NonNull User user) { + Objects.requireNonNull(user, "user"); + return this.plugin.getQueryOptionsForUser(ApiUser.cast(user)); + } + + @Override + public @NonNull QueryOptions getStaticQueryOptions() { + return this.handle.getStaticQueryOptions(); + } + + @Override + public @NonNull QueryOptions formQueryOptions(@NonNull Object subject, @NonNull ImmutableContextSet contextSet) { Objects.requireNonNull(subject, "subject"); Objects.requireNonNull(contextSet, "contextSet"); - return this.handle.formContexts(checkType(subject), contextSet); + return this.handle.formQueryOptions(subject, contextSet); } @Override - public @NonNull Contexts formContexts(@NonNull ImmutableContextSet contextSet) { + public @NonNull QueryOptions formQueryOptions(@NonNull ImmutableContextSet contextSet) { Objects.requireNonNull(contextSet, "contextSet"); - return this.handle.formContexts(contextSet); + return handle.formQueryOptions(contextSet); } @Override @@ -113,6 +122,11 @@ public class ApiContextManager implements me.lucko.luckperms.api.context.Context this.handle.unregisterCalculator(calculator); } + @Override + public @NonNull ContextSetFactory getContextSetFactory() { + return ApiContextSetFactory.INSTANCE; + } + @Override public void invalidateCache(@NonNull Object subject) { Objects.requireNonNull(subject, "subject"); diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextSetFactory.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextSetFactory.java new file mode 100644 index 000000000..2b76e2996 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiContextSetFactory.java @@ -0,0 +1,67 @@ +/* + * 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.api.implementation; + +import me.lucko.luckperms.api.context.ContextSetFactory; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl; +import me.lucko.luckperms.common.context.contextset.MutableContextSetImpl; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public class ApiContextSetFactory implements ContextSetFactory { + public static final ApiContextSetFactory INSTANCE = new ApiContextSetFactory(); + + private ApiContextSetFactory() { + + } + + @Override + public ImmutableContextSet.@NonNull Builder immutableBuilder() { + return new ImmutableContextSetImpl.BuilderImpl(); + } + + @Override + public @NonNull ImmutableContextSet immutableOf(@NonNull String key, @NonNull String value) { + return ImmutableContextSetImpl.of(key, value); + } + + @Override + public @NonNull ImmutableContextSet immutableOf(@NonNull String key1, @NonNull String value1, @NonNull String key2, @NonNull String value2) { + return ImmutableContextSetImpl.of(key1, value1, key2, value2); + } + + @Override + public @NonNull ImmutableContextSet immutableEmpty() { + return ImmutableContextSetImpl.EMPTY; + } + + @Override + public @NonNull MutableContextSet mutable() { + return new MutableContextSetImpl(); + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiGroup.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiGroup.java index 387363ed7..bc58ce3e3 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiGroup.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiGroup.java @@ -27,8 +27,8 @@ package me.lucko.luckperms.common.api.implementation; import com.google.common.base.Preconditions; -import me.lucko.luckperms.api.caching.GroupData; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.common.cacheddata.GroupCachedDataManager; import me.lucko.luckperms.common.model.Group; import org.checkerframework.checker.nullness.qual.NonNull; @@ -37,8 +37,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Objects; import java.util.OptionalInt; -public class ApiGroup extends ApiPermissionHolder implements me.lucko.luckperms.api.Group { - public static Group cast(me.lucko.luckperms.api.Group group) { +public class ApiGroup extends ApiPermissionHolder implements me.lucko.luckperms.api.model.group.Group { + public static Group cast(me.lucko.luckperms.api.model.group.Group group) { Objects.requireNonNull(group, "group"); Preconditions.checkState(group instanceof ApiGroup, "Illegal instance " + group.getClass() + " cannot be handled by this implementation."); return ((ApiGroup) group).getHandle(); @@ -76,8 +76,9 @@ public class ApiGroup extends ApiPermissionHolder implements me.lucko.luckperms. return this.handle.getWeight(); } + @NonNull @Override - public @NonNull GroupData getCachedData() { + public GroupCachedDataManager getCachedData() { return this.handle.getCachedData(); } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiGroupManager.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiGroupManager.java index 96cb7202f..6e60d839d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiGroupManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiGroupManager.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.api.implementation; -import me.lucko.luckperms.api.HeldPermission; import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.api.event.cause.DeletionCause; +import me.lucko.luckperms.api.node.HeldNode; import me.lucko.luckperms.common.api.ApiUtils; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison; @@ -45,13 +45,13 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; -public class ApiGroupManager extends ApiAbstractManager> implements me.lucko.luckperms.api.manager.GroupManager { +public class ApiGroupManager extends ApiAbstractManager> implements me.lucko.luckperms.api.model.group.GroupManager { public ApiGroupManager(LuckPermsPlugin plugin, GroupManager handle) { super(plugin, handle); } @Override - protected me.lucko.luckperms.api.Group getDelegateFor(me.lucko.luckperms.common.model.Group internal) { + protected me.lucko.luckperms.api.model.group.Group getDelegateFor(me.lucko.luckperms.common.model.Group internal) { if (internal == null) { return null; } @@ -60,20 +60,20 @@ public class ApiGroupManager extends ApiAbstractManager createAndLoadGroup(@NonNull String name) { + public @NonNull CompletableFuture createAndLoadGroup(@NonNull String name) { name = ApiUtils.checkName(Objects.requireNonNull(name, "name")); return this.plugin.getStorage().createAndLoadGroup(name, CreationCause.API) .thenApply(this::getDelegateFor); } @Override - public @NonNull CompletableFuture> loadGroup(@NonNull String name) { + public @NonNull CompletableFuture> loadGroup(@NonNull String name) { name = ApiUtils.checkName(Objects.requireNonNull(name, "name")); return this.plugin.getStorage().loadGroup(name).thenApply(opt -> opt.map(this::getDelegateFor)); } @Override - public @NonNull CompletableFuture saveGroup(me.lucko.luckperms.api.@NonNull Group group) { + public @NonNull CompletableFuture saveGroup(me.lucko.luckperms.api.model.group.Group group) { Objects.requireNonNull(group, "group"); return this.plugin.getStorage().saveGroup(ApiGroup.cast(group)).thenRun(() -> { // invalidate caches - they have potentially been affected by @@ -84,7 +84,7 @@ public class ApiGroupManager extends ApiAbstractManager deleteGroup(me.lucko.luckperms.api.@NonNull Group group) { + public @NonNull CompletableFuture deleteGroup(me.lucko.luckperms.api.model.group.Group group) { Objects.requireNonNull(group, "group"); if (group.getName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) { throw new IllegalArgumentException("Cannot delete the default group."); @@ -104,19 +104,19 @@ public class ApiGroupManager extends ApiAbstractManager>> getWithPermission(@NonNull String permission) { + public @NonNull CompletableFuture>> getWithPermission(@NonNull String permission) { Objects.requireNonNull(permission, "permission"); return this.plugin.getStorage().getGroupsWithPermission(Constraint.of(StandardComparison.EQUAL, permission)); } @Override - public me.lucko.luckperms.api.Group getGroup(@NonNull String name) { + public me.lucko.luckperms.api.model.group.Group getGroup(@NonNull String name) { Objects.requireNonNull(name, "name"); return getDelegateFor(this.handle.getIfLoaded(name)); } @Override - public @NonNull Set getLoadedGroups() { + public @NonNull Set getLoadedGroups() { return this.handle.getAll().values().stream() .map(this::getDelegateFor) .collect(ImmutableCollectors.toSet()); diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiMessagingService.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiMessagingService.java index f3bf71f0e..4192989ab 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiMessagingService.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiMessagingService.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.api.implementation; -import me.lucko.luckperms.api.MessagingService; -import me.lucko.luckperms.api.User; +import me.lucko.luckperms.api.messaging.MessagingService; +import me.lucko.luckperms.api.model.user.User; import me.lucko.luckperms.common.messaging.InternalMessagingService; import org.checkerframework.checker.nullness.qual.NonNull; diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiNodeBuilderRegistry.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiNodeBuilderRegistry.java new file mode 100644 index 000000000..d7987bbb8 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiNodeBuilderRegistry.java @@ -0,0 +1,101 @@ +/* + * 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.api.implementation; + +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.NodeBuilderRegistry; +import me.lucko.luckperms.api.node.types.DisplayNameNode; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.node.types.PermissionNode; +import me.lucko.luckperms.api.node.types.PrefixNode; +import me.lucko.luckperms.api.node.types.RegexPermissionNode; +import me.lucko.luckperms.api.node.types.SuffixNode; +import me.lucko.luckperms.api.node.types.WeightNode; +import me.lucko.luckperms.common.node.factory.NodeFactory; +import me.lucko.luckperms.common.node.types.DisplayName; +import me.lucko.luckperms.common.node.types.Inheritance; +import me.lucko.luckperms.common.node.types.Meta; +import me.lucko.luckperms.common.node.types.Permission; +import me.lucko.luckperms.common.node.types.Prefix; +import me.lucko.luckperms.common.node.types.RegexPermission; +import me.lucko.luckperms.common.node.types.Suffix; +import me.lucko.luckperms.common.node.types.Weight; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public final class ApiNodeBuilderRegistry implements NodeBuilderRegistry { + public static final ApiNodeBuilderRegistry INSTANCE = new ApiNodeBuilderRegistry(); + + private ApiNodeBuilderRegistry() { + + } + + @Override + public @NonNull NodeBuilder forKey(String key) { + return NodeFactory.builder(key); + } + + @Override + public PermissionNode.@NonNull Builder forPermission() { + return new Permission.Builder(); + } + + @Override + public RegexPermissionNode.@NonNull Builder forRegexPermission() { + return new RegexPermission.Builder(); + } + + @Override + public InheritanceNode.@NonNull Builder forInheritance() { + return new Inheritance.Builder(); + } + + @Override + public PrefixNode.@NonNull Builder forPrefix() { + return new Prefix.Builder(); + } + + @Override + public SuffixNode.@NonNull Builder forSuffix() { + return new Suffix.Builder(); + } + + @Override + public MetaNode.@NonNull Builder forMeta() { + return new Meta.Builder(); + } + + @Override + public WeightNode.@NonNull Builder forWeight() { + return new Weight.Builder(); + } + + @Override + public DisplayNameNode.@NonNull Builder forDisplayName() { + return new DisplayName.Builder(); + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiNodeFactory.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiNodeFactory.java deleted file mode 100644 index fb53e5812..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiNodeFactory.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.api.implementation; - -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.Group; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.common.node.factory.NodeFactory; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Objects; - -public final class ApiNodeFactory implements me.lucko.luckperms.api.NodeFactory { - public static final ApiNodeFactory INSTANCE = new ApiNodeFactory(); - - private ApiNodeFactory() { - - } - - @Override - public Node.@NonNull Builder newBuilder(@NonNull String permission) { - Objects.requireNonNull(permission, "permission"); - return NodeFactory.builder(permission); - } - - @Override - public Node.@NonNull Builder newBuilderFromExisting(@NonNull Node other) { - return Objects.requireNonNull(other, "other").toBuilder(); - } - - @Override - public Node.@NonNull Builder makeGroupNode(@NonNull Group group) { - Objects.requireNonNull(group, "group"); - return NodeFactory.buildGroupNode(ApiGroup.cast(group)); - } - - @Override - public Node.@NonNull Builder makeGroupNode(@NonNull String groupName) { - Objects.requireNonNull(groupName, "groupName"); - return NodeFactory.buildGroupNode(groupName); - } - - @Override - public Node.@NonNull Builder makeMetaNode(@NonNull String key, @NonNull String value) { - Objects.requireNonNull(key, "key"); - Objects.requireNonNull(value, "value"); - return NodeFactory.buildMetaNode(key, value); - } - - @Override - public Node.@NonNull Builder makeChatMetaNode(@NonNull ChatMetaType type, int priority, @NonNull String value) { - Objects.requireNonNull(type, "type"); - Objects.requireNonNull(value, "value"); - return NodeFactory.buildChatMetaNode(type, priority, value); - } - - @Override - public Node.@NonNull Builder makePrefixNode(int priority, @NonNull String prefix) { - Objects.requireNonNull(prefix, "prefix"); - return NodeFactory.buildPrefixNode(priority, prefix); - } - - @Override - public Node.@NonNull Builder makeSuffixNode(int priority, @NonNull String suffix) { - Objects.requireNonNull(suffix, "suffix"); - return NodeFactory.buildSuffixNode(priority, suffix); - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPermissionHolder.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPermissionHolder.java index 488fa857c..509ebada8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPermissionHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPermissionHolder.java @@ -25,38 +25,27 @@ package me.lucko.luckperms.common.api.implementation; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.ImmutableSortedSet; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.DataMutateResult; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.NodeEqualityPredicate; -import me.lucko.luckperms.api.StandardNodeEquality; -import me.lucko.luckperms.api.TemporaryDataMutateResult; -import me.lucko.luckperms.api.TemporaryMergeBehaviour; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.caching.CachedData; +import me.lucko.luckperms.api.cacheddata.CachedDataManager; import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.common.model.Group; -import me.lucko.luckperms.common.model.HolderType; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.model.TemporaryDataMutateResult; +import me.lucko.luckperms.api.model.TemporaryMergeBehaviour; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; +import me.lucko.luckperms.api.node.NodeType; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.PermissionHolder; -import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator; -import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.utils.MetaType; import me.lucko.luckperms.common.node.utils.NodeTools; -import me.lucko.luckperms.common.util.ImmutableCollectors; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.LinkedList; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; @@ -66,11 +55,16 @@ import java.util.TreeSet; import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; -public class ApiPermissionHolder implements me.lucko.luckperms.api.PermissionHolder { +public class ApiPermissionHolder implements me.lucko.luckperms.api.model.PermissionHolder { private final PermissionHolder handle; + private final Enduring enduringData; + private final Transient transientData; + ApiPermissionHolder(PermissionHolder handle) { this.handle = Objects.requireNonNull(handle, "handle"); + this.enduringData = new Enduring(); + this.transientData = new Transient(); } PermissionHolder getHandle() { @@ -88,7 +82,7 @@ public class ApiPermissionHolder implements me.lucko.luckperms.api.PermissionHol } @Override - public @NonNull CachedData getCachedData() { + public @NonNull CachedDataManager getCachedData() { return this.handle.getCachedData(); } @@ -98,256 +92,51 @@ public class ApiPermissionHolder implements me.lucko.luckperms.api.PermissionHol } @Override - public @NonNull ImmutableSetMultimap getNodes() { - //noinspection unchecked - return (ImmutableSetMultimap) this.handle.enduringData().immutable(); + public Data getData(@NonNull DataType dataType) { + switch (dataType) { + case NORMAL: + return this.enduringData; + case TRANSIENT: + return this.transientData; + default: + throw new AssertionError(); + } } @Override - public @NonNull ImmutableSetMultimap getTransientNodes() { - //noinspection unchecked - return (ImmutableSetMultimap) this.handle.transientData().immutable(); + public @NonNull Data data() { + return this.enduringData; } @Override - public @NonNull List getOwnNodes() { - return ImmutableList.copyOf(this.handle.getOwnNodes()); + public @NonNull Data transientData() { + return this.transientData; } @Override - public @NonNull SortedSet getPermissions() { - return ImmutableSortedSet.copyOfSorted(this.handle.getOwnNodesSorted()); + public @NonNull List getNodes() { + return this.handle.getOwnNodes(); } @Override - public @NonNull Set getEnduringPermissions() { - return ImmutableSet.copyOf(this.handle.enduringData().immutable().values()); + public @NonNull SortedSet getDistinctNodes() { + return this.handle.getOwnNodesSorted(); } @Override - public @NonNull Set getTransientPermissions() { - return ImmutableSet.copyOf(this.handle.transientData().immutable().values()); + public @NonNull List resolveInheritedNodes(@NonNull QueryOptions queryOptions) { + return this.handle.resolveInheritances(queryOptions); } @Override - public @NonNull SortedSet getAllNodes(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - - List nodes = new LinkedList<>(); - this.handle.accumulateInheritancesTo(nodes, contexts); - NodeTools.removeEqual(nodes.iterator(), StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE); - - SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse()); - ret.addAll(nodes); - - return ImmutableSortedSet.copyOfSorted(ret); - } - - @Override - public @NonNull SortedSet getAllNodes() { - List nodes = new LinkedList<>(); - this.handle.accumulateInheritancesTo(nodes); - NodeTools.removeEqual(nodes.iterator(), StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE); - - SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse()); - ret.addAll(nodes); - - return ImmutableSortedSet.copyOfSorted(ret); - } - - @Override - public @NonNull Set getAllNodesFiltered(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - - List entries = this.handle.getAllEntries(contexts); + public @NonNull SortedSet resolveDistinctInheritedNodes(@NonNull QueryOptions queryOptions) { + List entries = this.handle.getAllEntries(queryOptions); NodeTools.removeSamePermission(entries.iterator()); - SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse()); + SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse()); ret.addAll(entries); - return ImmutableSet.copyOf(ret); - } - - @Override - public @NonNull Map exportNodes(@NonNull Contexts contexts, boolean lowerCase) { - Objects.requireNonNull(contexts, "contexts"); - return ImmutableMap.copyOf(this.handle.exportPermissions(contexts, lowerCase, true)); - } - - @Override - public @NonNull Tristate hasPermission(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate) { - Objects.requireNonNull(node, "node"); - Objects.requireNonNull(equalityPredicate, "equalityPredicate"); - return this.handle.hasPermission(NodeMapType.ENDURING, node, equalityPredicate); - } - - @Override - public @NonNull Tristate hasTransientPermission(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate) { - Objects.requireNonNull(node, "node"); - Objects.requireNonNull(equalityPredicate, "equalityPredicate"); - return this.handle.hasPermission(NodeMapType.TRANSIENT, node, equalityPredicate); - } - - @Override - public @NonNull Tristate inheritsPermission(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate) { - Objects.requireNonNull(node, "node"); - Objects.requireNonNull(equalityPredicate, "equalityPredicate"); - return this.handle.inheritsPermission(node, equalityPredicate); - } - - @Override - public @NonNull Tristate hasPermission(@NonNull Node node) { - Objects.requireNonNull(node, "node"); - return this.handle.hasPermission(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE); - } - - @Override - public @NonNull Tristate hasTransientPermission(@NonNull Node node) { - Objects.requireNonNull(node, "node"); - return this.handle.hasPermission(NodeMapType.TRANSIENT, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE); - } - - @Override - public @NonNull Tristate inheritsPermission(@NonNull Node node) { - Objects.requireNonNull(node, "node"); - return this.handle.inheritsPermission(node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE); - } - - @Override - public boolean inheritsGroup(me.lucko.luckperms.api.@NonNull Group group) { - Objects.requireNonNull(group, "group"); - - Group g = ApiGroup.cast(group); - if (this.handle.getType() == HolderType.GROUP && g.getName().equals(this.handle.getObjectName())) { - return true; - } - - return this.handle.hasPermission(NodeMapType.ENDURING, NodeFactory.buildGroupNode(g.getName()).build(), StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE).asBoolean(); - } - - @Override - public boolean inheritsGroup(me.lucko.luckperms.api.@NonNull Group group, @NonNull ContextSet contextSet) { - Objects.requireNonNull(group, "group"); - Objects.requireNonNull(contextSet, "contextSet"); - - Group g = ApiGroup.cast(group); - if (this.handle.getType() == HolderType.GROUP && g.getName().equals(this.handle.getObjectName())) { - return true; - } - - return this.handle.hasPermission(NodeMapType.ENDURING, NodeFactory.buildGroupNode(g.getName()).withExtraContext(contextSet).build(), StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE).asBoolean(); - } - - @Override - public @NonNull DataMutateResult setPermission(@NonNull Node node) { - Objects.requireNonNull(node, "node"); - return this.handle.setPermission(node); - } - - @Override - public @NonNull TemporaryDataMutateResult setPermission(@NonNull Node node, @NonNull TemporaryMergeBehaviour temporaryMergeBehaviour) { - Objects.requireNonNull(node, "node"); - Objects.requireNonNull(temporaryMergeBehaviour, "temporaryMergeBehaviour"); - return this.handle.setPermission(node, temporaryMergeBehaviour); - } - - @Override - public @NonNull DataMutateResult setTransientPermission(@NonNull Node node) { - Objects.requireNonNull(node, "node"); - return this.handle.setTransientPermission(node); - } - - @Override - public @NonNull TemporaryDataMutateResult setTransientPermission(@NonNull Node node, @NonNull TemporaryMergeBehaviour temporaryMergeBehaviour) { - Objects.requireNonNull(node, "node"); - Objects.requireNonNull(temporaryMergeBehaviour, "temporaryMergeBehaviour"); - return this.handle.setTransientPermission(node, temporaryMergeBehaviour); - } - - @Override - public @NonNull DataMutateResult unsetPermission(@NonNull Node node) { - Objects.requireNonNull(node, "node"); - return this.handle.unsetPermission(node); - } - - @Override - public @NonNull DataMutateResult unsetTransientPermission(@NonNull Node node) { - Objects.requireNonNull(node, "node"); - return this.handle.unsetTransientPermission(node); - } - - @Override - public void clearMatching(@NonNull Predicate test) { - Objects.requireNonNull(test, "test"); - this.handle.removeIf(test); - if (this.handle.getType() == HolderType.USER) { - this.handle.getPlugin().getUserManager().giveDefaultIfNeeded((User) this.handle, false); - } - } - - @Override - public void clearMatchingTransient(@NonNull Predicate test) { - Objects.requireNonNull(test, "test"); - this.handle.removeIfTransient(test); - } - - @Override - public void clearNodes() { - this.handle.clearNodes(); - } - - @Override - public void clearNodes(@NonNull ContextSet contextSet) { - Objects.requireNonNull(contextSet, "contextSet"); - this.handle.clearNodes(contextSet); - } - - @Override - public void clearParents() { - this.handle.clearParents(true); - } - - @Override - public void clearParents(@NonNull ContextSet contextSet) { - Objects.requireNonNull(contextSet, "contextSet"); - this.handle.clearParents(contextSet, true); - } - - @Override - public void clearMeta() { - this.handle.clearMeta(MetaType.ANY); - } - - @Override - public void clearMeta(@NonNull ContextSet contextSet) { - Objects.requireNonNull(contextSet, "contextSet"); - this.handle.clearMeta(MetaType.ANY, contextSet); - } - - @Override - public void clearTransientNodes() { - this.handle.clearTransientNodes(); - } - - @Override - public @NonNull List resolveInheritances(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - return ImmutableList.copyOf(this.handle.resolveInheritances(contexts)); - } - - @Override - public @NonNull List resolveInheritances() { - return ImmutableList.copyOf(this.handle.resolveInheritances()); - } - - @Override - public @NonNull Set getPermanentPermissionNodes() { - return this.handle.getOwnNodes().stream().filter(Node::isPermanent).collect(ImmutableCollectors.toSet()); - } - - @Override - public @NonNull Set getTemporaryPermissionNodes() { - return this.handle.getOwnNodes().stream().filter(Node::isPrefix).collect(ImmutableCollectors.toSet()); + return ImmutableSortedSet.copyOfSorted(ret); } @Override @@ -355,4 +144,143 @@ public class ApiPermissionHolder implements me.lucko.luckperms.api.PermissionHol this.handle.auditTemporaryPermissions(); } + @Override + public @NonNull Tristate inheritsNode(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate) { + return this.handle.inheritsPermission(node, equalityPredicate); + } + + private final class Enduring implements Data { + @Override + public @NonNull Map> getNodes() { + return ApiPermissionHolder.this.handle.enduringData().immutable().asMap(); + } + + @Override + public @NonNull Set getFlattenedNodes() { + return ApiPermissionHolder.this.handle.enduringData().asSet(); + } + + @Override + public @NonNull Tristate hasNode(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate) { + return ApiPermissionHolder.this.handle.hasPermission(NodeMapType.ENDURING, node, equalityPredicate); + } + + @Override + public @NonNull DataMutateResult addNode(@NonNull Node node) { + return ApiPermissionHolder.this.handle.setPermission(node); + } + + @Override + public @NonNull TemporaryDataMutateResult addNode(@NonNull Node node, @NonNull TemporaryMergeBehaviour temporaryMergeBehaviour) { + return ApiPermissionHolder.this.handle.setPermission(node, temporaryMergeBehaviour); + } + + @Override + public @NonNull DataMutateResult removeNode(@NonNull Node node) { + return ApiPermissionHolder.this.handle.unsetPermission(node); + } + + @Override + public void clearMatching(@NonNull Predicate test) { + ApiPermissionHolder.this.handle.removeIfEnduring(test); + } + + @Override + public void clearNodes() { + ApiPermissionHolder.this.handle.clearEnduringNodes(); + } + + @Override + public void clearNodes(@NonNull ContextSet contextSet) { + ApiPermissionHolder.this.handle.clearEnduringNodes(contextSet); + } + + @Override + public void clearParents() { + ApiPermissionHolder.this.handle.clearEnduringParents(true); + } + + @Override + public void clearParents(@NonNull ContextSet contextSet) { + ApiPermissionHolder.this.handle.clearEnduringParents(contextSet, true); + } + + @Override + public void clearMeta() { + ApiPermissionHolder.this.handle.removeIfEnduring(NodeType.META_OR_CHAT_META::matches); + } + + @Override + public void clearMeta(@NonNull ContextSet contextSet) { + ApiPermissionHolder.this.handle.removeIfEnduring(contextSet, NodeType.META_OR_CHAT_META::matches); + } + } + + private final class Transient implements Data { + @Override + public @NonNull Map> getNodes() { + return ApiPermissionHolder.this.handle.transientData().immutable().asMap(); + } + + @Override + public @NonNull Set getFlattenedNodes() { + return ApiPermissionHolder.this.handle.transientData().asSet(); + } + + @Override + public @NonNull Tristate hasNode(@NonNull Node node, @NonNull NodeEqualityPredicate equalityPredicate) { + return ApiPermissionHolder.this.handle.hasPermission(NodeMapType.TRANSIENT, node, equalityPredicate); + } + + @Override + public @NonNull DataMutateResult addNode(@NonNull Node node) { + return ApiPermissionHolder.this.handle.setTransientPermission(node); + } + + @Override + public @NonNull TemporaryDataMutateResult addNode(@NonNull Node node, @NonNull TemporaryMergeBehaviour temporaryMergeBehaviour) { + return ApiPermissionHolder.this.handle.setTransientPermission(node, temporaryMergeBehaviour); + } + + @Override + public @NonNull DataMutateResult removeNode(@NonNull Node node) { + return ApiPermissionHolder.this.handle.unsetTransientPermission(node); + } + + @Override + public void clearMatching(@NonNull Predicate test) { + ApiPermissionHolder.this.handle.removeIfTransient(test); + } + + @Override + public void clearNodes() { + ApiPermissionHolder.this.handle.clearTransientNodes(); + } + + @Override + public void clearNodes(@NonNull ContextSet contextSet) { + ApiPermissionHolder.this.handle.clearTransientNodes(contextSet); + } + + @Override + public void clearParents() { + ApiPermissionHolder.this.handle.removeIfTransient(NodeType.INHERITANCE::matches); + } + + @Override + public void clearParents(@NonNull ContextSet contextSet) { + ApiPermissionHolder.this.handle.removeIfTransient(contextSet, NodeType.INHERITANCE::matches); + } + + @Override + public void clearMeta() { + ApiPermissionHolder.this.handle.removeIfTransient(NodeType.META_OR_CHAT_META::matches); + } + + @Override + public void clearMeta(@NonNull ContextSet contextSet) { + ApiPermissionHolder.this.handle.removeIfTransient(contextSet, NodeType.META_OR_CHAT_META::matches); + } + } + } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPlatformInfo.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPlatform.java similarity index 80% rename from common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPlatformInfo.java rename to common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPlatform.java index 37701dca5..6f5ba1611 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPlatformInfo.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiPlatform.java @@ -25,20 +25,21 @@ package me.lucko.luckperms.common.api.implementation; -import me.lucko.luckperms.api.platform.PlatformInfo; -import me.lucko.luckperms.api.platform.PlatformType; +import me.lucko.luckperms.api.platform.Platform; +import me.lucko.luckperms.api.platform.PluginMetadata; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import org.checkerframework.checker.nullness.qual.NonNull; +import java.time.Instant; import java.util.Collections; import java.util.Set; import java.util.UUID; -public class ApiPlatformInfo implements PlatformInfo { +public class ApiPlatform implements Platform, PluginMetadata { private final LuckPermsPlugin plugin; - public ApiPlatformInfo(LuckPermsPlugin plugin) { + public ApiPlatform(LuckPermsPlugin plugin) { this.plugin = plugin; } @@ -48,12 +49,12 @@ public class ApiPlatformInfo implements PlatformInfo { } @Override - public double getApiVersion() { - return 4.4; + public @NonNull String getApiVersion() { + return "5.0"; } @Override - public @NonNull PlatformType getType() { + public Platform.@NonNull Type getType() { return this.plugin.getBootstrap().getType(); } @@ -63,7 +64,7 @@ public class ApiPlatformInfo implements PlatformInfo { } @Override - public long getStartTime() { - return this.plugin.getBootstrap().getStartupTime(); + public Instant getStartTime() { + return Instant.ofEpochMilli(this.plugin.getBootstrap().getStartupTime()); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiTrack.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiTrack.java index 67f526895..bf79ec043 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiTrack.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiTrack.java @@ -27,12 +27,12 @@ package me.lucko.luckperms.common.api.implementation; import com.google.common.base.Preconditions; -import me.lucko.luckperms.api.DataMutateResult; -import me.lucko.luckperms.api.DemotionResult; -import me.lucko.luckperms.api.Group; -import me.lucko.luckperms.api.PromotionResult; -import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.model.group.Group; +import me.lucko.luckperms.api.model.user.User; +import me.lucko.luckperms.api.track.DemotionResult; +import me.lucko.luckperms.api.track.PromotionResult; import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.util.Predicates; @@ -41,8 +41,8 @@ import org.checkerframework.checker.nullness.qual.NonNull; import java.util.List; import java.util.Objects; -public class ApiTrack implements me.lucko.luckperms.api.Track { - public static Track cast(me.lucko.luckperms.api.Track track) { +public class ApiTrack implements me.lucko.luckperms.api.track.Track { + public static Track cast(me.lucko.luckperms.api.track.Track track) { Objects.requireNonNull(track, "track"); Preconditions.checkState(track instanceof ApiTrack, "Illegal instance " + track.getClass() + " cannot be handled by this implementation."); return ((ApiTrack) track).getHandle(); diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiTrackManager.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiTrackManager.java index 435cd12d8..ac4ab5099 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiTrackManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiTrackManager.java @@ -40,13 +40,13 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; -public class ApiTrackManager extends ApiAbstractManager> implements me.lucko.luckperms.api.manager.TrackManager { +public class ApiTrackManager extends ApiAbstractManager> implements me.lucko.luckperms.api.track.TrackManager { public ApiTrackManager(LuckPermsPlugin plugin, TrackManager handle) { super(plugin, handle); } @Override - protected me.lucko.luckperms.api.Track getDelegateFor(Track internal) { + protected me.lucko.luckperms.api.track.Track getDelegateFor(Track internal) { if (internal == null) { return null; } @@ -55,26 +55,26 @@ public class ApiTrackManager extends ApiAbstractManager createAndLoadTrack(@NonNull String name) { + public @NonNull CompletableFuture createAndLoadTrack(@NonNull String name) { name = ApiUtils.checkName(Objects.requireNonNull(name, "name")); return this.plugin.getStorage().createAndLoadTrack(name, CreationCause.API) .thenApply(this::getDelegateFor); } @Override - public @NonNull CompletableFuture> loadTrack(@NonNull String name) { + public @NonNull CompletableFuture> loadTrack(@NonNull String name) { name = ApiUtils.checkName(Objects.requireNonNull(name, "name")); return this.plugin.getStorage().loadTrack(name).thenApply(opt -> opt.map(this::getDelegateFor)); } @Override - public @NonNull CompletableFuture saveTrack(me.lucko.luckperms.api.@NonNull Track track) { + public @NonNull CompletableFuture saveTrack(me.lucko.luckperms.api.track.Track track) { Objects.requireNonNull(track, "track"); return this.plugin.getStorage().saveTrack(ApiTrack.cast(track)); } @Override - public @NonNull CompletableFuture deleteTrack(me.lucko.luckperms.api.@NonNull Track track) { + public @NonNull CompletableFuture deleteTrack(me.lucko.luckperms.api.track.Track track) { Objects.requireNonNull(track, "track"); return this.plugin.getStorage().deleteTrack(ApiTrack.cast(track), DeletionCause.API); } @@ -85,13 +85,13 @@ public class ApiTrackManager extends ApiAbstractManager getLoadedTracks() { + public @NonNull Set getLoadedTracks() { return this.handle.getAll().values().stream() .map(this::getDelegateFor) .collect(ImmutableCollectors.toSet()); diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiUser.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiUser.java index 24633bf74..cdfff0b64 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiUser.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiUser.java @@ -27,9 +27,9 @@ package me.lucko.luckperms.common.api.implementation; import com.google.common.base.Preconditions; -import me.lucko.luckperms.api.DataMutateResult; -import me.lucko.luckperms.api.StandardNodeEquality; -import me.lucko.luckperms.api.caching.UserData; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; +import me.lucko.luckperms.common.cacheddata.UserCachedDataManager; import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.factory.NodeFactory; @@ -39,8 +39,8 @@ import org.checkerframework.checker.nullness.qual.NonNull; import java.util.Objects; import java.util.UUID; -public class ApiUser extends ApiPermissionHolder implements me.lucko.luckperms.api.User { - public static User cast(me.lucko.luckperms.api.User u) { +public class ApiUser extends ApiPermissionHolder implements me.lucko.luckperms.api.model.user.User { + public static User cast(me.lucko.luckperms.api.model.user.User u) { Preconditions.checkState(u instanceof ApiUser, "Illegal instance " + u.getClass() + " cannot be handled by this implementation."); return ((ApiUser) u).getHandle(); } @@ -58,12 +58,12 @@ public class ApiUser extends ApiPermissionHolder implements me.lucko.luckperms.a } @Override - public @NonNull UUID getUuid() { + public @NonNull UUID getUniqueId() { return this.handle.getUuid(); } @Override - public String getName() { + public String getUsername() { return this.handle.getName().orElse(null); } @@ -79,7 +79,7 @@ public class ApiUser extends ApiPermissionHolder implements me.lucko.luckperms.a return DataMutateResult.ALREADY_HAS; } - if (!this.handle.hasPermission(NodeMapType.ENDURING, NodeFactory.buildGroupNode(group.toLowerCase()).build(), StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE).asBoolean()) { + if (!this.handle.hasPermission(NodeMapType.ENDURING, NodeFactory.buildGroupNode(group.toLowerCase()).build(), NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE).asBoolean()) { return DataMutateResult.FAIL; } @@ -87,23 +87,12 @@ public class ApiUser extends ApiPermissionHolder implements me.lucko.luckperms.a return DataMutateResult.SUCCESS; } + @NonNull @Override - public @NonNull UserData getCachedData() { + public UserCachedDataManager getCachedData() { return this.handle.getCachedData(); } - @Override - @Deprecated - public void refreshPermissions() { - - } - - @Override - @Deprecated - public void setupDataCache() { - - } - @Override public boolean equals(Object o) { if (o == this) return true; diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiUserManager.java b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiUserManager.java index a30a62649..4c6030ec8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiUserManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiUserManager.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.api.implementation; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.PlayerSaveResult; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.node.HeldNode; import me.lucko.luckperms.common.api.ApiUtils; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison; @@ -45,13 +45,13 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; -public class ApiUserManager extends ApiAbstractManager> implements me.lucko.luckperms.api.manager.UserManager { +public class ApiUserManager extends ApiAbstractManager> implements me.lucko.luckperms.api.model.user.UserManager { public ApiUserManager(LuckPermsPlugin plugin, UserManager handle) { super(plugin, handle); } @Override - protected me.lucko.luckperms.api.User getDelegateFor(User internal) { + protected me.lucko.luckperms.api.model.user.User getDelegateFor(User internal) { if (internal == null) { return null; } @@ -59,7 +59,7 @@ public class ApiUserManager extends ApiAbstractManager loadUser(@NonNull UUID uuid, @Nullable String username) { + public @NonNull CompletableFuture loadUser(@NonNull UUID uuid, @Nullable String username) { Objects.requireNonNull(uuid, "uuid"); ApiUtils.checkUsername(username, this.plugin); @@ -72,7 +72,7 @@ public class ApiUserManager extends ApiAbstractManager lookupUuid(@NonNull String username) { + public @NonNull CompletableFuture lookupUniqueId(@NonNull String username) { Objects.requireNonNull(username, "username"); return this.plugin.getStorage().getPlayerUuid(username); } @@ -84,7 +84,7 @@ public class ApiUserManager extends ApiAbstractManager saveUser(me.lucko.luckperms.api.@NonNull User user) { + public @NonNull CompletableFuture saveUser(me.lucko.luckperms.api.model.user.User user) { Objects.requireNonNull(user, "user"); return this.plugin.getStorage().saveUser(ApiUser.cast(user)); } @@ -102,25 +102,25 @@ public class ApiUserManager extends ApiAbstractManager>> getWithPermission(@NonNull String permission) { + public @NonNull CompletableFuture>> getWithPermission(@NonNull String permission) { Objects.requireNonNull(permission, "permission"); return this.plugin.getStorage().getUsersWithPermission(Constraint.of(StandardComparison.EQUAL, permission)); } @Override - public me.lucko.luckperms.api.User getUser(@NonNull UUID uuid) { + public me.lucko.luckperms.api.model.user.User getUser(@NonNull UUID uuid) { Objects.requireNonNull(uuid, "uuid"); return getDelegateFor(this.handle.getIfLoaded(uuid)); } @Override - public me.lucko.luckperms.api.User getUser(@NonNull String name) { + public me.lucko.luckperms.api.model.user.User getUser(@NonNull String name) { Objects.requireNonNull(name, "name"); return getDelegateFor(this.handle.getByUsername(name)); } @Override - public @NonNull Set getLoadedUsers() { + public @NonNull Set getLoadedUsers() { return this.handle.getAll().values().stream() .map(this::getDelegateFor) .collect(ImmutableCollectors.toSet()); @@ -133,7 +133,7 @@ public class ApiUserManager extends ApiAbstractManager n.getGroupName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)).orElse(false)) { inDefault = true; continue; } diff --git a/common/src/main/java/me/lucko/luckperms/common/cacheddata/AbstractCachedData.java b/common/src/main/java/me/lucko/luckperms/common/cacheddata/AbstractCachedData.java deleted file mode 100644 index 1d0a6b6d8..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/cacheddata/AbstractCachedData.java +++ /dev/null @@ -1,454 +0,0 @@ -/* - * 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.cacheddata; - -import com.github.benmanes.caffeine.cache.AsyncLoadingCache; -import com.github.benmanes.caffeine.cache.CacheLoader; - -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.FullySatisfiedContexts; -import me.lucko.luckperms.api.caching.CachedData; -import me.lucko.luckperms.api.caching.MetaContexts; -import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; -import me.lucko.luckperms.common.cacheddata.type.MetaCache; -import me.lucko.luckperms.common.cacheddata.type.PermissionCache; -import me.lucko.luckperms.common.calculator.CalculatorFactory; -import me.lucko.luckperms.common.calculator.PermissionCalculator; -import me.lucko.luckperms.common.metastacking.SimpleMetaStack; -import me.lucko.luckperms.common.plugin.LuckPermsPlugin; -import me.lucko.luckperms.common.util.CaffeineFactory; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; - -/** - * Abstract implementation of {@link CachedData}. - */ -public abstract class AbstractCachedData implements CachedData { - - /** - * The plugin instance - */ - private final LuckPermsPlugin plugin; - - /** - * The cache used for {@link PermissionCache} instances. - */ - private final AsyncLoadingCache permission = CaffeineFactory.newBuilder() - .expireAfterAccess(2, TimeUnit.MINUTES) - .buildAsync(new PermissionCacheLoader()); - - /** - * The cache used for {@link MetaCache} instances. - */ - private final AsyncLoadingCache meta = CaffeineFactory.newBuilder() - .expireAfterAccess(2, TimeUnit.MINUTES) - .buildAsync(new MetaCacheLoader()); - - // cache the most recent lookup. - private RecentPermissionData recentPermissionData = null; - private RecentMetaData recentMetaData = null; - - public AbstractCachedData(LuckPermsPlugin plugin) { - this.plugin = plugin; - } - - public LuckPermsPlugin getPlugin() { - return this.plugin; - } - - /** - * Returns a {@link CacheMetadata} instance for the given {@link Contexts}. - * - * @param contexts the contexts the cache is for - * @return the metadata instance - */ - protected abstract CacheMetadata getMetadataForContexts(Contexts contexts); - - /** - * Gets the {@link CalculatorFactory} used to build {@link PermissionCalculator}s. - * - * @return the calculator factory - */ - protected abstract CalculatorFactory getCalculatorFactory(); - - /** - * Upgrades the given {@link Contexts} to a {@link MetaContexts} instance using the default settings. - * - * @param contexts the contexts to upgrade - * @return a meta contexts instance - */ - protected abstract MetaContexts getDefaultMetaContexts(Contexts contexts); - - /** - * Resolves the owners permissions data according to the specification - * outlined by {@link FullySatisfiedContexts}. - * - * @return a map of permissions to back the {@link PermissionCache} - */ - protected abstract Map resolvePermissions(); - - /** - * Resolves the owners permissions data in the given {@link Contexts}. - * - * @param contexts the contexts - * @return a map of permissions to back the {@link PermissionCache} - */ - protected abstract Map resolvePermissions(Contexts contexts); - - /** - * Resolves the owners meta data according to the specification - * outlined by {@link FullySatisfiedContexts}. - * - * @param accumulator the accumulator to add resolved meta to - */ - protected abstract void resolveMeta(MetaAccumulator accumulator); - - /** - * Resolves the owners meta data in the given {@link Contexts}. - * - * @param accumulator the accumulator to add resolved meta to - * @param contexts the contexts - */ - protected abstract void resolveMeta(MetaAccumulator accumulator, MetaContexts contexts); - - /** - * Calculates a {@link PermissionCache} instance. - * - * @param contexts the contexts to calculate in - * @param data an old data instance to try to reuse - ignored if null - * @return the calculated instance - */ - private PermissionCache calculatePermissions(Contexts contexts, PermissionCache data) { - Objects.requireNonNull(contexts, "contexts"); - - if (data == null) { - CacheMetadata metadata = getMetadataForContexts(contexts); - data = new PermissionCache(contexts, metadata, getCalculatorFactory()); - } - - if (contexts == Contexts.allowAll()) { - data.setPermissions(resolvePermissions()); - } else { - data.setPermissions(resolvePermissions(contexts)); - } - - return data; - } - - /** - * Calculates a {@link MetaCache} instance. - * - * @param contexts the contexts to calculate in - * @param data an old data instance to try to reuse - ignored if null - * @return the calculated instance - */ - private MetaCache calculateMeta(MetaContexts contexts, MetaCache data) { - Objects.requireNonNull(contexts, "contexts"); - - if (data == null) { - CacheMetadata metadata = getMetadataForContexts(contexts.getContexts()); - data = new MetaCache(contexts, metadata); - } - - MetaAccumulator accumulator = newAccumulator(contexts); - if (contexts.getContexts() == Contexts.allowAll()) { - resolveMeta(accumulator); - } else { - resolveMeta(accumulator, contexts); - } - data.loadMeta(accumulator); - - return data; - } - - @Override - public final @NonNull PermissionCache getPermissionData(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - - RecentPermissionData recent = this.recentPermissionData; - if (recent != null && contexts.equals(recent.contexts)) { - return recent.permissionData; - } - - PermissionCache data = this.permission.synchronous().get(contexts); - this.recentPermissionData = new RecentPermissionData(contexts, data); - - //noinspection ConstantConditions - return data; - } - - @Override - public final @NonNull MetaCache getMetaData(@NonNull MetaContexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - - RecentMetaData recent = this.recentMetaData; - if (recent != null && contexts.equals(recent.contexts)) { - return recent.metaData; - } - - MetaCache data = this.meta.synchronous().get(contexts); - this.recentMetaData = new RecentMetaData(contexts, data); - - //noinspection ConstantConditions - return data; - } - - @Override - public final @NonNull MetaCache getMetaData(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - return getMetaData(getDefaultMetaContexts(contexts)); - } - - @Override - public final @NonNull PermissionCache calculatePermissions(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - return calculatePermissions(contexts, null); - } - - @Override - public final @NonNull MetaCache calculateMeta(@NonNull MetaContexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - return calculateMeta(contexts, null); - } - - @Override - public final @NonNull MetaCache calculateMeta(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - return calculateMeta(getDefaultMetaContexts(contexts)); - } - - @Override - public final void recalculatePermissions(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - this.permission.synchronous().refresh(contexts); - this.recentPermissionData = null; - } - - @Override - public final void recalculateMeta(@NonNull MetaContexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - this.meta.synchronous().refresh(contexts); - this.recentMetaData = null; - } - - @Override - public final void recalculateMeta(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - recalculateMeta(getDefaultMetaContexts(contexts)); - } - - @Override - public final @NonNull CompletableFuture reloadPermissions(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - - // get the previous value - to use when recalculating - CompletableFuture previous = this.permission.getIfPresent(contexts); - - // invalidate any previous setting - this.permission.synchronous().invalidate(contexts); - this.recentPermissionData = null; - - // if the previous value is already calculated, use it when recalculating. - PermissionCache value = getIfReady(previous); - if (value != null) { - return this.permission.get(contexts, c -> calculatePermissions(c, value)); - } - - // otherwise, just calculate a new value - return this.permission.get(contexts); - } - - @Override - public final @NonNull CompletableFuture reloadMeta(@NonNull MetaContexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - - // get the previous value - to use when recalculating - CompletableFuture previous = this.meta.getIfPresent(contexts); - - // invalidate any previous setting - this.meta.synchronous().invalidate(contexts); - this.recentMetaData = null; - - // if the previous value is already calculated, use it when recalculating. - MetaCache value = getIfReady(previous); - if (value != null) { - return this.meta.get(contexts, c -> calculateMeta(c, value)); - } - - // otherwise, just calculate a new value - return this.meta.get(contexts); - } - - @Override - public final @NonNull CompletableFuture reloadMeta(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - return reloadMeta(getDefaultMetaContexts(contexts)); - } - - @Override - public final void recalculatePermissions() { - Set keys = this.permission.synchronous().asMap().keySet(); - keys.forEach(this::recalculatePermissions); - } - - @Override - public final void recalculateMeta() { - Set keys = this.meta.synchronous().asMap().keySet(); - keys.forEach(this::recalculateMeta); - } - - @Override - public final @NonNull CompletableFuture reloadPermissions() { - Set keys = this.permission.synchronous().asMap().keySet(); - return CompletableFuture.allOf(keys.stream().map(this::reloadPermissions).toArray(CompletableFuture[]::new)); - } - - @Override - public final @NonNull CompletableFuture reloadMeta() { - Set keys = this.meta.synchronous().asMap().keySet(); - return CompletableFuture.allOf(keys.stream().map(this::reloadMeta).toArray(CompletableFuture[]::new)); - } - - @Override - public final void invalidatePermissions(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - this.permission.synchronous().invalidate(contexts); - this.recentPermissionData = null; - } - - @Override - public final void invalidateMeta(@NonNull MetaContexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - this.meta.synchronous().invalidate(contexts); - this.recentMetaData = null; - } - - @Override - public final void invalidateMeta(@NonNull Contexts contexts) { - Objects.requireNonNull(contexts, "contexts"); - this.meta.synchronous().invalidate(getDefaultMetaContexts(contexts)); - this.recentMetaData = null; - } - - @Override - public final void invalidatePermissions() { - this.permission.synchronous().invalidateAll(); - this.recentPermissionData = null; - } - - @Override - public final void invalidateMeta() { - this.meta.synchronous().invalidateAll(); - this.recentMetaData = null; - } - - @Override - public final void invalidate() { - invalidatePermissions(); - invalidateMeta(); - } - - @Override - public final void invalidatePermissionCalculators() { - this.permission.synchronous().asMap().values().forEach(PermissionCache::invalidateCache); - } - - public final void performCacheCleanup() { - this.permission.synchronous().cleanUp(); - this.meta.synchronous().cleanUp(); - } - - private static boolean isReady(@Nullable CompletableFuture future) { - return (future != null) && future.isDone() - && !future.isCompletedExceptionally() - && (future.join() != null); - } - - /** Returns the current value or null if either not done or failed. */ - private static V getIfReady(@Nullable CompletableFuture future) { - return isReady(future) ? future.join() : null; - } - - private final class PermissionCacheLoader implements CacheLoader { - @Override - public PermissionCache load(@NonNull Contexts contexts) { - return calculatePermissions(contexts); - } - - @Override - public PermissionCache reload(@NonNull Contexts contexts, @NonNull PermissionCache oldData) { - return calculatePermissions(contexts, oldData); - } - } - - private final class MetaCacheLoader implements CacheLoader { - @Override - public MetaCache load(@NonNull MetaContexts contexts) { - return calculateMeta(contexts); - } - - @Override - public MetaCache reload(@NonNull MetaContexts contexts, @NonNull MetaCache oldData) { - return calculateMeta(contexts, oldData); - } - } - - private static MetaAccumulator newAccumulator(MetaContexts contexts) { - return new MetaAccumulator( - new SimpleMetaStack(contexts.getPrefixStackDefinition(), ChatMetaType.PREFIX), - new SimpleMetaStack(contexts.getSuffixStackDefinition(), ChatMetaType.SUFFIX) - ); - } - - private static final class RecentPermissionData { - final Contexts contexts; - final PermissionCache permissionData; - - RecentPermissionData(Contexts contexts, PermissionCache permissionData) { - this.contexts = contexts; - this.permissionData = permissionData; - } - } - - private static final class RecentMetaData { - final MetaContexts contexts; - final MetaCache metaData; - - RecentMetaData(MetaContexts contexts, MetaCache metaData) { - this.contexts = contexts; - this.metaData = metaData; - } - } - -} diff --git a/common/src/main/java/me/lucko/luckperms/common/cacheddata/AbstractCachedDataManager.java b/common/src/main/java/me/lucko/luckperms/common/cacheddata/AbstractCachedDataManager.java new file mode 100644 index 000000000..5eb2a3cc3 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/cacheddata/AbstractCachedDataManager.java @@ -0,0 +1,421 @@ +/* + * 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.cacheddata; + +import com.github.benmanes.caffeine.cache.AsyncLoadingCache; +import com.github.benmanes.caffeine.cache.CacheLoader; + +import me.lucko.luckperms.api.cacheddata.CachedDataManager; +import me.lucko.luckperms.api.cacheddata.CachedMetaData; +import me.lucko.luckperms.api.cacheddata.CachedPermissionData; +import me.lucko.luckperms.api.metastacking.MetaStackDefinition; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.query.QueryOptions; +import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; +import me.lucko.luckperms.common.cacheddata.type.MetaCache; +import me.lucko.luckperms.common.cacheddata.type.PermissionCache; +import me.lucko.luckperms.common.calculator.CalculatorFactory; +import me.lucko.luckperms.common.calculator.PermissionCalculator; +import me.lucko.luckperms.common.metastacking.SimpleMetaStack; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import me.lucko.luckperms.common.util.CaffeineFactory; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +/** + * Abstract implementation of {@link CachedDataManager}. + */ +public abstract class AbstractCachedDataManager implements CachedDataManager { + + /** + * The plugin instance + */ + private final LuckPermsPlugin plugin; + + private final Permission permissionDataManager; + private final Meta metaDataManager; + + public AbstractCachedDataManager(LuckPermsPlugin plugin) { + this.plugin = plugin; + this.permissionDataManager = new Permission(); + this.metaDataManager = new Meta(); + } + + public LuckPermsPlugin getPlugin() { + return this.plugin; + } + + @Override + public @NonNull Container permissionData() { + return this.permissionDataManager; + } + + @Override + public @NonNull Container metaData() { + return this.metaDataManager; + } + + @Override + public @NonNull PermissionCache getPermissionData(@NonNull QueryOptions queryOptions) { + return this.permissionDataManager.get(queryOptions); + } + + @Override + public @NonNull MetaCache getMetaData(@NonNull QueryOptions queryOptions) { + return this.metaDataManager.get(queryOptions); + } + + /** + * Returns a {@link CacheMetadata} instance for the given {@link QueryOptions}. + * + * @param queryOptions the query options the cache is for + * @return the metadata instance + */ + protected abstract CacheMetadata getMetadataForQueryOptions(QueryOptions queryOptions); + + /** + * Gets the {@link CalculatorFactory} used to build {@link PermissionCalculator}s. + * + * @return the calculator factory + */ + protected abstract CalculatorFactory getCalculatorFactory(); + + /** + * Gets the default {@link MetaStackDefinition} for use if one wasn't specifically provided. + * + * @param type the type of meta stack + * @return a meta stack definition instance + */ + protected abstract MetaStackDefinition getDefaultMetaStackDefinition(ChatMetaType type); + + /** + * Resolves the owners permissions data for the given {@link QueryOptions}. + * + * @param queryOptions the query options + * @return a map of permissions to back the {@link PermissionCache} + */ + protected abstract Map resolvePermissions(QueryOptions queryOptions); + + /** + * Resolves the owners meta data for the given {@link QueryOptions}. + * + * @param accumulator the accumulator to add resolved meta to + * @param queryOptions the query options + */ + protected abstract void resolveMeta(MetaAccumulator accumulator, QueryOptions queryOptions); + + private PermissionCache calculatePermissions(QueryOptions queryOptions, PermissionCache data) { + Objects.requireNonNull(queryOptions, "queryOptions"); + + if (data == null) { + CacheMetadata metadata = getMetadataForQueryOptions(queryOptions); + data = new PermissionCache(queryOptions, metadata, getCalculatorFactory()); + } + + data.setPermissions(resolvePermissions(queryOptions)); + return data; + } + + private MetaCache calculateMeta(QueryOptions queryOptions, MetaCache data) { + Objects.requireNonNull(queryOptions, "queryOptions"); + + if (data == null) { + CacheMetadata metadata = getMetadataForQueryOptions(queryOptions); + data = new MetaCache(queryOptions, metadata); + } + + MetaAccumulator accumulator = newAccumulator(queryOptions); + resolveMeta(accumulator, queryOptions); + data.loadMeta(accumulator); + + return data; + } + + @Override + public final void invalidate() { + this.permissionDataManager.invalidate(); + this.metaDataManager.invalidate(); + } + + @Override + public final void invalidatePermissionCalculators() { + this.permissionDataManager.cache.synchronous().asMap().values().forEach(PermissionCache::invalidateCache); + } + + public final void performCacheCleanup() { + this.permissionDataManager.cache.synchronous().cleanUp(); + this.metaDataManager.cache.synchronous().cleanUp(); + } + + private final class Permission implements Container { + private final AsyncLoadingCache cache = CaffeineFactory.newBuilder() + .expireAfterAccess(2, TimeUnit.MINUTES) + .buildAsync(new PermissionCacheLoader()); + + // cache the most recent lookup. + private RecentPermissionData recentPermissionData = null; + + @Override + public @NonNull PermissionCache get(@NonNull QueryOptions queryOptions) { + Objects.requireNonNull(queryOptions, "queryOptions"); + + RecentPermissionData recent = this.recentPermissionData; + if (recent != null && queryOptions.equals(recent.queryOptions)) { + return recent.permissionData; + } + + PermissionCache data = this.cache.synchronous().get(queryOptions); + this.recentPermissionData = new RecentPermissionData(queryOptions, data); + + //noinspection ConstantConditions + return data; + } + + @Override + public @NonNull PermissionCache calculate(@NonNull QueryOptions queryOptions) { + Objects.requireNonNull(queryOptions, "queryOptions"); + return calculatePermissions(queryOptions, null); + } + + @Override + public void recalculate(@NonNull QueryOptions queryOptions) { + Objects.requireNonNull(queryOptions, "queryOptions"); + this.cache.synchronous().refresh(queryOptions); + this.recentPermissionData = null; + } + + @Override + public @NonNull CompletableFuture reload(@NonNull QueryOptions queryOptions) { + Objects.requireNonNull(queryOptions, "queryOptions"); + + // get the previous value - to use when recalculating + CompletableFuture previous = this.cache.getIfPresent(queryOptions); + + // invalidate any previous setting + this.cache.synchronous().invalidate(queryOptions); + this.recentPermissionData = null; + + // if the previous value is already calculated, use it when recalculating. + PermissionCache value = getIfReady(previous); + if (value != null) { + return this.cache.get(queryOptions, c -> calculatePermissions(c, value)); + } + + // otherwise, just calculate a new value + return this.cache.get(queryOptions); + } + + @Override + public void recalculate() { + Set keys = this.cache.synchronous().asMap().keySet(); + keys.forEach(this::recalculate); + } + + @Override + public @NonNull CompletableFuture reload() { + Set keys = this.cache.synchronous().asMap().keySet(); + return CompletableFuture.allOf(keys.stream().map(this::reload).toArray(CompletableFuture[]::new)); + } + + @Override + public void invalidate(@NonNull QueryOptions queryOptions) { + Objects.requireNonNull(queryOptions, "queryOptions"); + this.cache.synchronous().invalidate(queryOptions); + this.recentPermissionData = null; + } + + @Override + public void invalidate() { + this.cache.synchronous().invalidateAll(); + this.recentPermissionData = null; + } + } + + private final class Meta implements Container { + private final AsyncLoadingCache cache = CaffeineFactory.newBuilder() + .expireAfterAccess(2, TimeUnit.MINUTES) + .buildAsync(new MetaCacheLoader()); + + // cache the most recent lookup. + private RecentMetaData recentMetaData = null; + + @Override + public @NonNull MetaCache get(@NonNull QueryOptions queryOptions) { + Objects.requireNonNull(queryOptions, "queryOptions"); + + RecentMetaData recent = this.recentMetaData; + if (recent != null && queryOptions.equals(recent.queryOptions)) { + return recent.metaData; + } + + MetaCache data = this.cache.synchronous().get(queryOptions); + this.recentMetaData = new RecentMetaData(queryOptions, data); + + //noinspection ConstantConditions + return data; + } + + @Override + public @NonNull MetaCache calculate(@NonNull QueryOptions queryOptions) { + Objects.requireNonNull(queryOptions, "queryOptions"); + return calculateMeta(queryOptions, null); + } + + @Override + public void recalculate(@NonNull QueryOptions queryOptions) { + Objects.requireNonNull(queryOptions, "queryOptions"); + this.cache.synchronous().refresh(queryOptions); + this.recentMetaData = null; + } + + @Override + public @NonNull CompletableFuture reload(@NonNull QueryOptions queryOptions) { + Objects.requireNonNull(queryOptions, "queryOptions"); + + // get the previous value - to use when recalculating + CompletableFuture previous = this.cache.getIfPresent(queryOptions); + + // invalidate any previous setting + this.cache.synchronous().invalidate(queryOptions); + this.recentMetaData = null; + + // if the previous value is already calculated, use it when recalculating. + MetaCache value = getIfReady(previous); + if (value != null) { + return this.cache.get(queryOptions, c -> calculateMeta(c, value)); + } + + // otherwise, just calculate a new value + return this.cache.get(queryOptions); + } + + @Override + public void recalculate() { + Set keys = this.cache.synchronous().asMap().keySet(); + keys.forEach(this::recalculate); + } + + @Override + public @NonNull CompletableFuture reload() { + Set keys = this.cache.synchronous().asMap().keySet(); + return CompletableFuture.allOf(keys.stream().map(this::reload).toArray(CompletableFuture[]::new)); + } + + @Override + public void invalidate(@NonNull QueryOptions queryOptions) { + Objects.requireNonNull(queryOptions, "queryOptions"); + this.cache.synchronous().invalidate(queryOptions); + this.recentMetaData = null; + } + + @Override + public void invalidate() { + this.cache.synchronous().invalidateAll(); + this.recentMetaData = null; + } + } + + private static boolean isReady(@Nullable CompletableFuture future) { + return (future != null) && future.isDone() + && !future.isCompletedExceptionally() + && (future.join() != null); + } + + /** Returns the current value or null if either not done or failed. */ + private static V getIfReady(@Nullable CompletableFuture future) { + return isReady(future) ? future.join() : null; + } + + private final class PermissionCacheLoader implements CacheLoader { + @Override + public PermissionCache load(@NonNull QueryOptions queryOptions) { + return calculatePermissions(queryOptions, null); + } + + @Override + public PermissionCache reload(@NonNull QueryOptions queryOptions, @NonNull PermissionCache oldData) { + return calculatePermissions(queryOptions, oldData); + } + } + + private final class MetaCacheLoader implements CacheLoader { + @Override + public MetaCache load(@NonNull QueryOptions queryOptions) { + return calculateMeta(queryOptions, null); + } + + @Override + public MetaCache reload(@NonNull QueryOptions queryOptions, @NonNull MetaCache oldData) { + return calculateMeta(queryOptions, oldData); + } + } + + private MetaStackDefinition getMetaStackDefinition(QueryOptions queryOptions, ChatMetaType type) { + MetaStackDefinition stack = queryOptions.option(type == ChatMetaType.PREFIX ? + MetaStackDefinition.PREFIX_STACK_KEY : + MetaStackDefinition.SUFFIX_STACK_KEY + ).orElse(null); + if (stack == null) { + stack = getDefaultMetaStackDefinition(type); + } + return stack; + } + + private MetaAccumulator newAccumulator(QueryOptions queryOptions) { + return new MetaAccumulator( + new SimpleMetaStack(getMetaStackDefinition(queryOptions, ChatMetaType.PREFIX), ChatMetaType.PREFIX), + new SimpleMetaStack(getMetaStackDefinition(queryOptions, ChatMetaType.SUFFIX), ChatMetaType.SUFFIX) + ); + } + + private static final class RecentPermissionData { + final QueryOptions queryOptions; + final PermissionCache permissionData; + + RecentPermissionData(QueryOptions queryOptions, PermissionCache permissionData) { + this.queryOptions = queryOptions; + this.permissionData = permissionData; + } + } + + private static final class RecentMetaData { + final QueryOptions queryOptions; + final MetaCache metaData; + + RecentMetaData(QueryOptions queryOptions, MetaCache metaData) { + this.queryOptions = queryOptions; + this.metaData = metaData; + } + } + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/cacheddata/CacheMetadata.java b/common/src/main/java/me/lucko/luckperms/common/cacheddata/CacheMetadata.java index 827608b7c..adb2cf698 100644 --- a/common/src/main/java/me/lucko/luckperms/common/cacheddata/CacheMetadata.java +++ b/common/src/main/java/me/lucko/luckperms/common/cacheddata/CacheMetadata.java @@ -25,19 +25,19 @@ package me.lucko.luckperms.common.cacheddata; -import me.lucko.luckperms.api.caching.CachedDataContainer; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.cacheddata.CachedData; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.model.HolderType; /** - * Metadata about a given {@link CachedDataContainer}. + * Metadata about a given {@link CachedData}. */ public class CacheMetadata { /** * The cached data instance which creates this container */ - private final AbstractCachedData parentContainer; + private final AbstractCachedDataManager parentContainer; /** * The type of the object which owns the cache @@ -50,18 +50,18 @@ public class CacheMetadata { private final String objectName; /** - * The context the permission calculator works with + * The query options */ - private final ContextSet context; + private final QueryOptions queryOptions; - public CacheMetadata(AbstractCachedData parentContainer, HolderType holderType, String objectName, ContextSet context) { + public CacheMetadata(AbstractCachedDataManager parentContainer, HolderType holderType, String objectName, QueryOptions queryOptions) { this.parentContainer = parentContainer; this.holderType = holderType; this.objectName = objectName; - this.context = context; + this.queryOptions = queryOptions; } - public AbstractCachedData getParentContainer() { + public AbstractCachedDataManager getParentContainer() { return this.parentContainer; } @@ -73,7 +73,7 @@ public class CacheMetadata { return this.objectName; } - public ContextSet getContext() { - return this.context; + public QueryOptions getQueryOptions() { + return this.queryOptions; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/cacheddata/GroupCachedData.java b/common/src/main/java/me/lucko/luckperms/common/cacheddata/GroupCachedDataManager.java similarity index 80% rename from common/src/main/java/me/lucko/luckperms/common/cacheddata/GroupCachedData.java rename to common/src/main/java/me/lucko/luckperms/common/cacheddata/GroupCachedDataManager.java index 006bcab73..2e09405f1 100644 --- a/common/src/main/java/me/lucko/luckperms/common/cacheddata/GroupCachedData.java +++ b/common/src/main/java/me/lucko/luckperms/common/cacheddata/GroupCachedDataManager.java @@ -25,22 +25,22 @@ package me.lucko.luckperms.common.cacheddata; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.caching.GroupData; +import me.lucko.luckperms.api.cacheddata.CachedDataManager; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.HolderType; /** * Holds an easily accessible cache of a groups's data in a number of contexts */ -public class GroupCachedData extends HolderCachedData implements GroupData { +public class GroupCachedDataManager extends HolderCachedDataManager implements CachedDataManager { - public GroupCachedData(Group holder) { + public GroupCachedDataManager(Group holder) { super(holder); } @Override - protected CacheMetadata getMetadataForContexts(Contexts contexts) { - return new CacheMetadata(this, HolderType.GROUP, this.holder.getPlainDisplayName(), contexts.getContexts()); + protected CacheMetadata getMetadataForQueryOptions(QueryOptions queryOptions) { + return new CacheMetadata(this, HolderType.GROUP, this.holder.getPlainDisplayName(), queryOptions); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/cacheddata/HolderCachedData.java b/common/src/main/java/me/lucko/luckperms/common/cacheddata/HolderCachedDataManager.java similarity index 64% rename from common/src/main/java/me/lucko/luckperms/common/cacheddata/HolderCachedData.java rename to common/src/main/java/me/lucko/luckperms/common/cacheddata/HolderCachedDataManager.java index 5775a8b76..d05472cee 100644 --- a/common/src/main/java/me/lucko/luckperms/common/cacheddata/HolderCachedData.java +++ b/common/src/main/java/me/lucko/luckperms/common/cacheddata/HolderCachedDataManager.java @@ -25,8 +25,9 @@ package me.lucko.luckperms.common.cacheddata; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.caching.MetaContexts; +import me.lucko.luckperms.api.metastacking.MetaStackDefinition; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; import me.lucko.luckperms.common.calculator.CalculatorFactory; import me.lucko.luckperms.common.config.ConfigKeys; @@ -37,14 +38,14 @@ import java.util.Map; /** * Holds an easily accessible cache of a holders data in a number of contexts */ -public abstract class HolderCachedData extends AbstractCachedData { +public abstract class HolderCachedDataManager extends AbstractCachedDataManager { /** * The holder whom this data instance is representing */ protected final T holder; - public HolderCachedData(T holder) { + public HolderCachedDataManager(T holder) { super(holder.getPlugin()); this.holder = holder; } @@ -55,27 +56,24 @@ public abstract class HolderCachedData extends Abstr } @Override - protected MetaContexts getDefaultMetaContexts(Contexts contexts) { - return getPlugin().getContextManager().formMetaContexts(contexts); + protected MetaStackDefinition getDefaultMetaStackDefinition(ChatMetaType type) { + switch (type) { + case PREFIX: + return getPlugin().getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS); + case SUFFIX: + return getPlugin().getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS); + default: + throw new AssertionError(); + } } @Override - protected Map resolvePermissions() { - return this.holder.exportPermissions(true, getPlugin().getConfiguration().get(ConfigKeys.APPLYING_SHORTHAND)); + protected Map resolvePermissions(QueryOptions queryOptions) { + return this.holder.exportPermissions(queryOptions, true, getPlugin().getConfiguration().get(ConfigKeys.APPLYING_SHORTHAND)); } @Override - protected Map resolvePermissions(Contexts contexts) { - return this.holder.exportPermissions(contexts, true, getPlugin().getConfiguration().get(ConfigKeys.APPLYING_SHORTHAND)); - } - - @Override - protected void resolveMeta(MetaAccumulator accumulator) { - this.holder.accumulateMeta(accumulator); - } - - @Override - protected void resolveMeta(MetaAccumulator accumulator, MetaContexts contexts) { - this.holder.accumulateMeta(accumulator, contexts.getContexts()); + protected void resolveMeta(MetaAccumulator accumulator, QueryOptions queryOptions) { + this.holder.accumulateMeta(accumulator, queryOptions); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/cacheddata/UserCachedData.java b/common/src/main/java/me/lucko/luckperms/common/cacheddata/UserCachedDataManager.java similarity index 80% rename from common/src/main/java/me/lucko/luckperms/common/cacheddata/UserCachedData.java rename to common/src/main/java/me/lucko/luckperms/common/cacheddata/UserCachedDataManager.java index 5545125d5..32695cd0d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/cacheddata/UserCachedData.java +++ b/common/src/main/java/me/lucko/luckperms/common/cacheddata/UserCachedDataManager.java @@ -25,22 +25,22 @@ package me.lucko.luckperms.common.cacheddata; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.caching.UserData; +import me.lucko.luckperms.api.cacheddata.CachedDataManager; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.model.HolderType; import me.lucko.luckperms.common.model.User; /** * Holds an easily accessible cache of a user's data in a number of contexts */ -public class UserCachedData extends HolderCachedData implements UserData { +public class UserCachedDataManager extends HolderCachedDataManager implements CachedDataManager { - public UserCachedData(User holder) { + public UserCachedDataManager(User holder) { super(holder); } @Override - protected CacheMetadata getMetadataForContexts(Contexts contexts) { - return new CacheMetadata(this, HolderType.USER, this.holder.getPlainDisplayName(), contexts.getContexts()); + protected CacheMetadata getMetadataForQueryOptions(QueryOptions queryOptions) { + return new CacheMetadata(this, HolderType.USER, this.holder.getPlainDisplayName(), queryOptions); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/MetaAccumulator.java b/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/MetaAccumulator.java index 2a7e182a5..fc852aa20 100644 --- a/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/MetaAccumulator.java +++ b/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/MetaAccumulator.java @@ -28,15 +28,15 @@ package me.lucko.luckperms.common.cacheddata.type; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.nodetype.types.MetaType; -import me.lucko.luckperms.api.nodetype.types.PrefixType; -import me.lucko.luckperms.api.nodetype.types.SuffixType; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.node.types.PrefixNode; +import me.lucko.luckperms.api.node.types.SuffixNode; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.metastacking.MetaStack; import me.lucko.luckperms.common.metastacking.SimpleMetaStack; -import me.lucko.luckperms.common.node.model.NodeTypes; +import me.lucko.luckperms.common.node.factory.NodeTypes; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import java.util.Comparator; @@ -118,22 +118,25 @@ public class MetaAccumulator { // accumulate methods - public void accumulateNode(LocalizedNode n) { + public void accumulateNode(Node n) { ensureState(State.ACCUMULATING); + + if (n instanceof MetaNode) { + MetaNode mn = (MetaNode) n; + this.meta.put(mn.getMetaKey(), mn.getMetaValue()); + } - n.getTypeData(MetaType.KEY).ifPresent(metaType -> - this.meta.put(metaType.getKey(), metaType.getValue()) - ); - - n.getTypeData(PrefixType.KEY).ifPresent(prefix -> { - this.prefixes.putIfAbsent(prefix.getPriority(), prefix.getPrefix()); - this.prefixStack.accumulateToAll(n); - }); - - n.getTypeData(SuffixType.KEY).ifPresent(suffix -> { - this.suffixes.putIfAbsent(suffix.getPriority(), suffix.getSuffix()); - this.suffixStack.accumulateToAll(n); - }); + if (n instanceof PrefixNode) { + PrefixNode pn = (PrefixNode) n; + this.prefixes.putIfAbsent(pn.getPriority(), pn.getMetaValue()); + this.prefixStack.accumulateToAll(pn); + } + + if (n instanceof SuffixNode) { + SuffixNode pn = (SuffixNode) n; + this.suffixes.putIfAbsent(pn.getPriority(), pn.getMetaValue()); + this.suffixStack.accumulateToAll(pn); + } } public void accumulateMeta(String key, String value) { diff --git a/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/MetaCache.java b/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/MetaCache.java index 1fe4e11a1..dbf0d3832 100644 --- a/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/MetaCache.java +++ b/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/MetaCache.java @@ -25,20 +25,18 @@ package me.lucko.luckperms.common.cacheddata.type; -import com.google.common.collect.ForwardingListMultimap; -import com.google.common.collect.ForwardingMap; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ListMultimap; +import com.google.common.collect.Multimaps; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.caching.MetaContexts; -import me.lucko.luckperms.api.caching.MetaData; +import me.lucko.luckperms.api.cacheddata.CachedMetaData; import me.lucko.luckperms.api.metastacking.MetaStackDefinition; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.CacheMetadata; import me.lucko.luckperms.common.metastacking.MetaStack; -import me.lucko.luckperms.common.node.model.NodeTypes; +import me.lucko.luckperms.common.node.factory.NodeTypes; import me.lucko.luckperms.common.verbose.VerboseHandler; import me.lucko.luckperms.common.verbose.event.MetaCheckEvent; @@ -52,37 +50,37 @@ import java.util.SortedMap; /** * Holds cached meta for a given context */ -public class MetaCache implements MetaData { +public class MetaCache implements CachedMetaData { /** - * The contexts this container is holding data for + * The query options this container is holding data for */ - private final MetaContexts metaContexts; + private final QueryOptions queryOptions; /** * The metadata for this cache */ private final CacheMetadata metadata; - private ListMultimap metaMultimap = ImmutableListMultimap.of(); - private Map meta = ImmutableMap.of(); + private ListMultimap meta = ImmutableListMultimap.of(); + private Map flattenedMeta = ImmutableMap.of(); private SortedMap prefixes = ImmutableSortedMap.of(); private SortedMap suffixes = ImmutableSortedMap.of(); private MetaStack prefixStack = null; private MetaStack suffixStack = null; - public MetaCache(MetaContexts metaContexts, CacheMetadata metadata) { - this.metaContexts = metaContexts; + public MetaCache(QueryOptions queryOptions, CacheMetadata metadata) { + this.queryOptions = queryOptions; this.metadata = metadata; } public void loadMeta(MetaAccumulator meta) { meta.complete(); - this.metaMultimap = ImmutableListMultimap.copyOf(meta.getMeta()); + this.meta = ImmutableListMultimap.copyOf(meta.getMeta()); //noinspection unchecked - Map> metaMap = (Map) this.metaMultimap.asMap(); + Map> metaMap = (Map) this.meta.asMap(); ImmutableMap.Builder metaMapBuilder = ImmutableMap.builder(); for (Map.Entry> e : metaMap.entrySet()) { @@ -93,7 +91,7 @@ public class MetaCache implements MetaData { // take the value which was accumulated first metaMapBuilder.put(e.getKey(), e.getValue().get(0)); } - this.meta = metaMapBuilder.build(); + this.flattenedMeta = metaMapBuilder.build(); this.prefixes = ImmutableSortedMap.copyOfSorted(meta.getPrefixes()); this.suffixes = ImmutableSortedMap.copyOfSorted(meta.getSuffixes()); @@ -101,9 +99,20 @@ public class MetaCache implements MetaData { this.suffixStack = meta.getSuffixStack(); } + public String getMetaValue(String key, MetaCheckEvent.Origin origin) { + Objects.requireNonNull(key, "key"); + String value = this.flattenedMeta.get(key); + + // log this meta lookup to the verbose handler + VerboseHandler verboseHandler = MetaCache.this.metadata.getParentContainer().getPlugin().getVerboseHandler(); + verboseHandler.offerMetaCheckEvent(origin, MetaCache.this.metadata.getObjectName(), MetaCache.this.metadata.getQueryOptions(), key, String.valueOf(value)); + + return value; + } + @Override - public String getPrefix() { - return getPrefix(MetaCheckEvent.Origin.LUCKPERMS_API); + public String getMetaValue(String key) { + return getMetaValue(key, MetaCheckEvent.Origin.LUCKPERMS_API); } public String getPrefix(MetaCheckEvent.Origin origin) { @@ -112,7 +121,23 @@ public class MetaCache implements MetaData { // log this meta lookup to the verbose handler VerboseHandler verboseHandler = this.metadata.getParentContainer().getPlugin().getVerboseHandler(); - verboseHandler.offerMetaCheckEvent(origin, this.metadata.getObjectName(), this.metadata.getContext(), NodeTypes.PREFIX_KEY, String.valueOf(value)); + verboseHandler.offerMetaCheckEvent(origin, this.metadata.getObjectName(), this.metadata.getQueryOptions(), NodeTypes.PREFIX_KEY, String.valueOf(value)); + + return value; + } + + @Override + public String getPrefix() { + return getPrefix(MetaCheckEvent.Origin.LUCKPERMS_API); + } + + public String getSuffix(MetaCheckEvent.Origin origin) { + MetaStack suffixStack = this.suffixStack; + String value = suffixStack == null ? null : suffixStack.toFormattedString(); + + // log this meta lookup to the verbose handler + VerboseHandler verboseHandler = this.metadata.getParentContainer().getPlugin().getVerboseHandler(); + verboseHandler.offerMetaCheckEvent(origin, this.metadata.getObjectName(), this.metadata.getQueryOptions(), NodeTypes.SUFFIX_KEY, String.valueOf(value)); return value; } @@ -122,15 +147,19 @@ public class MetaCache implements MetaData { return getSuffix(MetaCheckEvent.Origin.LUCKPERMS_API); } - public String getSuffix(MetaCheckEvent.Origin origin) { - MetaStack suffixStack = this.suffixStack; - String value = suffixStack == null ? null : suffixStack.toFormattedString(); + @Override + public @NonNull Map> getMeta() { + return Multimaps.asMap(this.meta); + } - // log this meta lookup to the verbose handler - VerboseHandler verboseHandler = this.metadata.getParentContainer().getPlugin().getVerboseHandler(); - verboseHandler.offerMetaCheckEvent(origin, this.metadata.getObjectName(), this.metadata.getContext(), NodeTypes.SUFFIX_KEY, String.valueOf(value)); + @Override + public @NonNull SortedMap getPrefixes() { + return this.prefixes; + } - return value; + @Override + public @NonNull SortedMap getSuffixes() { + return this.suffixes; } @Override @@ -144,97 +173,8 @@ public class MetaCache implements MetaData { } @Override - public @NonNull Contexts getContexts() { - return this.metaContexts.getContexts(); - } - - @Override - public @NonNull MetaContexts getMetaContexts() { - return this.metaContexts; - } - - @Override - public @NonNull ListMultimap getMetaMultimap() { - return getMetaMultimap(MetaCheckEvent.Origin.LUCKPERMS_API); - } - - public ListMultimap getMetaMultimap(MetaCheckEvent.Origin origin) { - return new VerboseLoggedMetaMultimap(origin); - } - - @Override - public @NonNull Map getMeta() { - return getMeta(MetaCheckEvent.Origin.LUCKPERMS_API); - } - - public Map getMeta(MetaCheckEvent.Origin origin) { - return new VerboseLoggedMetaMap(origin); - } - - @Override - public @NonNull SortedMap getPrefixes() { - return this.prefixes; - } - - @Override - public @NonNull SortedMap getSuffixes() { - return this.suffixes; - } - - private final class VerboseLoggedMetaMap extends ForwardingMap { - private final MetaCheckEvent.Origin origin; - - private VerboseLoggedMetaMap(MetaCheckEvent.Origin origin) { - this.origin = origin; - } - - @Override - protected Map delegate() { - return MetaCache.this.meta; - } - - @Override - public String get(Object key) { - Objects.requireNonNull(key, "key"); - String value = super.get(key); - - // log this meta lookup to the verbose handler - VerboseHandler verboseHandler = MetaCache.this.metadata.getParentContainer().getPlugin().getVerboseHandler(); - verboseHandler.offerMetaCheckEvent(this.origin, MetaCache.this.metadata.getObjectName(), MetaCache.this.metadata.getContext(), (String) key, String.valueOf(value)); - - return value; - } - } - - private final class VerboseLoggedMetaMultimap extends ForwardingListMultimap { - private final MetaCheckEvent.Origin origin; - - private VerboseLoggedMetaMultimap(MetaCheckEvent.Origin origin) { - this.origin = origin; - } - - @Override - protected ListMultimap delegate() { - return MetaCache.this.metaMultimap; - } - - @Override - public List get(String key) { - Objects.requireNonNull(key, "key"); - List values = super.get(key); - - // log this meta lookup to the verbose handler - VerboseHandler verboseHandler = MetaCache.this.metadata.getParentContainer().getPlugin().getVerboseHandler(); - if (!values.isEmpty()) { - for (String value : values) { - verboseHandler.offerMetaCheckEvent(this.origin, MetaCache.this.metadata.getObjectName(), MetaCache.this.metadata.getContext(), key, String.valueOf(value)); - } - } else { - verboseHandler.offerMetaCheckEvent(this.origin, MetaCache.this.metadata.getObjectName(), MetaCache.this.metadata.getContext(), key, "null"); - } - - return values; - } + public @NonNull QueryOptions getQueryOptions() { + return this.queryOptions; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/PermissionCache.java b/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/PermissionCache.java index df47dd80c..d304b398b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/PermissionCache.java +++ b/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/PermissionCache.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.cacheddata.type; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.caching.PermissionData; +import me.lucko.luckperms.api.cacheddata.CachedPermissionData; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.CacheMetadata; import me.lucko.luckperms.common.calculator.CalculatorFactory; import me.lucko.luckperms.common.calculator.PermissionCalculator; @@ -43,12 +43,12 @@ import java.util.concurrent.ConcurrentHashMap; /** * Holds cached permissions data for a given context */ -public class PermissionCache implements PermissionData { +public class PermissionCache implements CachedPermissionData { /** - * The contexts this container is holding data for + * The query options this container is holding data for */ - private final Contexts contexts; + private final QueryOptions queryOptions; /** * The raw set of permission strings. @@ -67,12 +67,12 @@ public class PermissionCache implements PermissionData { */ private final PermissionCalculator calculator; - public PermissionCache(Contexts contexts, CacheMetadata metadata, CalculatorFactory calculatorFactory) { - this.contexts = contexts; + public PermissionCache(QueryOptions queryOptions, CacheMetadata metadata, CalculatorFactory calculatorFactory) { + this.queryOptions = queryOptions; this.permissions = new ConcurrentHashMap<>(); this.permissionsUnmodifiable = Collections.unmodifiableMap(this.permissions); - this.calculator = calculatorFactory.build(contexts, metadata); + this.calculator = calculatorFactory.build(queryOptions, metadata); this.calculator.setSourcePermissions(this.permissions); // Initial setup. } @@ -99,25 +99,25 @@ public class PermissionCache implements PermissionData { } @Override - public @NonNull Map getImmutableBacking() { + public @NonNull Map getPermissionMap() { return this.permissionsUnmodifiable; } - public TristateResult getPermissionValue(String permission, PermissionCheckEvent.Origin origin) { + public TristateResult checkPermission(String permission, PermissionCheckEvent.Origin origin) { if (permission == null) { throw new NullPointerException("permission"); } - return this.calculator.getPermissionValue(permission, origin); + return this.calculator.checkPermission(permission, origin); } @Override - public @NonNull Tristate getPermissionValue(@NonNull String permission) { - return getPermissionValue(permission, PermissionCheckEvent.Origin.LUCKPERMS_API).result(); + public @NonNull Tristate checkPermission(@NonNull String permission) { + return checkPermission(permission, PermissionCheckEvent.Origin.LUCKPERMS_API).result(); } @Override - public @NonNull Contexts getContexts() { - return this.contexts; + public @NonNull QueryOptions getQueryOptions() { + return this.queryOptions; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/calculator/CalculatorFactory.java b/common/src/main/java/me/lucko/luckperms/common/calculator/CalculatorFactory.java index a7f876cae..e8f8093a7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/calculator/CalculatorFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/calculator/CalculatorFactory.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.calculator; -import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.CacheMetadata; /** @@ -36,10 +36,10 @@ public interface CalculatorFactory { /** * Builds a PermissionCalculator for the user in the given context * - * @param contexts the contexts to build the calculator in + * @param queryOptions the query options to build the calculator for * @param metadata the calculator metadata * @return a permission calculator instance */ - PermissionCalculator build(Contexts contexts, CacheMetadata metadata); + PermissionCalculator build(QueryOptions queryOptions, CacheMetadata metadata); } diff --git a/common/src/main/java/me/lucko/luckperms/common/calculator/PermissionCalculator.java b/common/src/main/java/me/lucko/luckperms/common/calculator/PermissionCalculator.java index 84b41ff2f..d29bead90 100644 --- a/common/src/main/java/me/lucko/luckperms/common/calculator/PermissionCalculator.java +++ b/common/src/main/java/me/lucko/luckperms/common/calculator/PermissionCalculator.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.common.calculator; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.cache.LoadingMap; import me.lucko.luckperms.common.cacheddata.CacheMetadata; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; @@ -81,12 +81,12 @@ public class PermissionCalculator implements Function { * @param origin marks where this check originated from * @return the result */ - public TristateResult getPermissionValue(String permission, PermissionCheckEvent.Origin origin) { + public TristateResult checkPermission(String permission, PermissionCheckEvent.Origin origin) { // get the result TristateResult result = this.lookupCache.get(permission); // log this permission lookup to the verbose handler - this.plugin.getVerboseHandler().offerPermissionCheckEvent(origin, this.metadata.getObjectName(), this.metadata.getContext(), permission, result); + this.plugin.getVerboseHandler().offerPermissionCheckEvent(origin, this.metadata.getObjectName(), this.metadata.getQueryOptions(), permission, result); // return the result return result; diff --git a/common/src/main/java/me/lucko/luckperms/common/calculator/processor/MapProcessor.java b/common/src/main/java/me/lucko/luckperms/common/calculator/processor/MapProcessor.java index cb37b5632..c593e74f2 100644 --- a/common/src/main/java/me/lucko/luckperms/common/calculator/processor/MapProcessor.java +++ b/common/src/main/java/me/lucko/luckperms/common/calculator/processor/MapProcessor.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.calculator.processor; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.calculator.result.TristateResult; public class MapProcessor extends AbstractPermissionProcessor implements PermissionProcessor { @@ -33,7 +33,7 @@ public class MapProcessor extends AbstractPermissionProcessor implements Permiss @Override public TristateResult hasPermission(String permission) { - return RESULT_FACTORY.result(Tristate.fromNullableBoolean(this.sourceMap.get(permission))); + return RESULT_FACTORY.result(Tristate.of(this.sourceMap.get(permission))); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/calculator/processor/RegexProcessor.java b/common/src/main/java/me/lucko/luckperms/common/calculator/processor/RegexProcessor.java index 961902da3..a259edff5 100644 --- a/common/src/main/java/me/lucko/luckperms/common/calculator/processor/RegexProcessor.java +++ b/common/src/main/java/me/lucko/luckperms/common/calculator/processor/RegexProcessor.java @@ -28,10 +28,11 @@ package me.lucko.luckperms.common.calculator.processor; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.nodetype.types.RegexType; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.node.types.RegexPermissionNode; import me.lucko.luckperms.common.calculator.result.TristateResult; -import me.lucko.luckperms.common.node.model.NodeTypes; +import me.lucko.luckperms.common.node.factory.NodeTypes; import java.util.Collections; import java.util.List; @@ -57,17 +58,17 @@ public class RegexProcessor extends AbstractPermissionProcessor implements Permi public void refresh() { ImmutableList.Builder> builder = ImmutableList.builder(); for (Map.Entry e : this.sourceMap.entrySet()) { - RegexType regexType = NodeTypes.parseRegexType(e.getKey()); - if (regexType == null) { + Node builtNode = NodeTypes.newBuilder(e.getKey()).build(); + if (!(builtNode instanceof RegexPermissionNode)) { continue; } - Pattern pattern = regexType.getPattern().orElse(null); + Pattern pattern = ((RegexPermissionNode) builtNode).getPattern().orElse(null); if (pattern == null) { continue; } - TristateResult value = RESULT_FACTORY.result(Tristate.fromBoolean(e.getValue()), "pattern: " + pattern.pattern()); + TristateResult value = RESULT_FACTORY.result(Tristate.of(e.getValue()), "pattern: " + pattern.pattern()); builder.add(Maps.immutableEntry(pattern, value)); } this.regexPermissions = builder.build(); diff --git a/common/src/main/java/me/lucko/luckperms/common/calculator/processor/WildcardProcessor.java b/common/src/main/java/me/lucko/luckperms/common/calculator/processor/WildcardProcessor.java index a7c5c77e9..ad495ec67 100644 --- a/common/src/main/java/me/lucko/luckperms/common/calculator/processor/WildcardProcessor.java +++ b/common/src/main/java/me/lucko/luckperms/common/calculator/processor/WildcardProcessor.java @@ -27,9 +27,9 @@ package me.lucko.luckperms.common.calculator.processor; import com.google.common.collect.ImmutableMap; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.calculator.result.TristateResult; -import me.lucko.luckperms.common.node.model.ImmutableNode; +import me.lucko.luckperms.common.node.AbstractNode; import java.util.Collections; import java.util.Map; @@ -49,7 +49,7 @@ public class WildcardProcessor extends AbstractPermissionProcessor implements Pe String node = permission; while (true) { - int endIndex = node.lastIndexOf(ImmutableNode.NODE_SEPARATOR); + int endIndex = node.lastIndexOf(AbstractNode.NODE_SEPARATOR); if (endIndex == -1) { break; } @@ -76,14 +76,14 @@ public class WildcardProcessor extends AbstractPermissionProcessor implements Pe } key = key.substring(0, key.length() - 2); - TristateResult value = RESULT_FACTORY.result(Tristate.fromBoolean(e.getValue()), "match: " + key); + TristateResult value = RESULT_FACTORY.result(Tristate.of(e.getValue()), "match: " + key); builder.put(key, value); } this.wildcardPermissions = builder.build(); - Tristate state = Tristate.fromNullableBoolean(this.sourceMap.get(ROOT_WILDCARD)); + Tristate state = Tristate.of(this.sourceMap.get(ROOT_WILDCARD)); if (state == Tristate.UNDEFINED) { - state = Tristate.fromNullableBoolean(this.sourceMap.get(ROOT_WILDCARD_WITH_QUOTES)); + state = Tristate.of(this.sourceMap.get(ROOT_WILDCARD_WITH_QUOTES)); } this.rootWildcardState = RESULT_FACTORY.result(state, "root"); } diff --git a/common/src/main/java/me/lucko/luckperms/common/calculator/result/TristateResult.java b/common/src/main/java/me/lucko/luckperms/common/calculator/result/TristateResult.java index ff772eddc..94aeb69e6 100644 --- a/common/src/main/java/me/lucko/luckperms/common/calculator/result/TristateResult.java +++ b/common/src/main/java/me/lucko/luckperms/common/calculator/result/TristateResult.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.calculator.result; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.calculator.PermissionCalculator; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; diff --git a/common/src/main/java/me/lucko/luckperms/common/command/access/ArgumentPermissions.java b/common/src/main/java/me/lucko/luckperms/common/command/access/ArgumentPermissions.java index afbf7103e..36a00578c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/command/access/ArgumentPermissions.java +++ b/common/src/main/java/me/lucko/luckperms/common/command/access/ArgumentPermissions.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.command.access; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.type.PermissionCache; import me.lucko.luckperms.common.calculator.processor.MapProcessor; import me.lucko.luckperms.common.calculator.result.TristateResult; @@ -303,8 +303,8 @@ public final class ArgumentPermissions { throw new IllegalStateException("Unable to get a User for " + sender.getUuid() + " - " + sender.getName()); } - PermissionCache permissionData = user.getCachedData().getPermissionData(Contexts.global().setContexts(contextSet)); - TristateResult result = permissionData.getPermissionValue(NodeFactory.groupNode(targetGroupName), PermissionCheckEvent.Origin.INTERNAL); + PermissionCache permissionData = user.getCachedData().getPermissionData(QueryOptions.defaultContextualOptions().toBuilder().context(contextSet).build()); + TristateResult result = permissionData.checkPermission(NodeFactory.groupNode(targetGroupName), PermissionCheckEvent.Origin.INTERNAL); return result.result() != Tristate.TRUE || result.processorClass() != MapProcessor.class; } diff --git a/common/src/main/java/me/lucko/luckperms/common/command/utils/ArgumentParser.java b/common/src/main/java/me/lucko/luckperms/common/command/utils/ArgumentParser.java index 31e14e588..440000d41 100644 --- a/common/src/main/java/me/lucko/luckperms/common/command/utils/ArgumentParser.java +++ b/common/src/main/java/me/lucko/luckperms/common/command/utils/ArgumentParser.java @@ -25,10 +25,10 @@ package me.lucko.luckperms.common.command.utils; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.TemporaryMergeBehaviour; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.TemporaryMergeBehaviour; import me.lucko.luckperms.common.command.abstraction.CommandException; import me.lucko.luckperms.common.commands.user.UserMainCommand; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -160,7 +160,7 @@ public class ArgumentParser { // one of the first two values, and doesn't have a key if (i <= 1 && !pair.contains("=")) { - String key = i == 0 ? Contexts.SERVER_KEY : Contexts.WORLD_KEY; + String key = i == 0 ? DefaultContextKeys.SERVER_KEY : DefaultContextKeys.WORLD_KEY; set.add(key, pair); continue; } @@ -191,28 +191,28 @@ public class ArgumentParser { private static MutableContextSet sanitizeContexts(MutableContextSet set) throws ArgumentException { // remove any potential "global" context mappings - set.remove(Contexts.SERVER_KEY, "global"); - set.remove(Contexts.WORLD_KEY, "global"); - set.remove(Contexts.SERVER_KEY, "null"); - set.remove(Contexts.WORLD_KEY, "null"); - set.remove(Contexts.SERVER_KEY, "*"); - set.remove(Contexts.WORLD_KEY, "*"); + set.remove(DefaultContextKeys.SERVER_KEY, "global"); + set.remove(DefaultContextKeys.WORLD_KEY, "global"); + set.remove(DefaultContextKeys.SERVER_KEY, "null"); + set.remove(DefaultContextKeys.WORLD_KEY, "null"); + set.remove(DefaultContextKeys.SERVER_KEY, "*"); + set.remove(DefaultContextKeys.WORLD_KEY, "*"); // remove excess entries from the set. // (it can only have one server and one world.) - List servers = new ArrayList<>(set.getValues(Contexts.SERVER_KEY)); + List servers = new ArrayList<>(set.getValues(DefaultContextKeys.SERVER_KEY)); if (servers.size() > 1) { // start iterating at index 1 for (int i = 1; i < servers.size(); i++) { - set.remove(Contexts.SERVER_KEY, servers.get(i)); + set.remove(DefaultContextKeys.SERVER_KEY, servers.get(i)); } } - List worlds = new ArrayList<>(set.getValues(Contexts.WORLD_KEY)); + List worlds = new ArrayList<>(set.getValues(DefaultContextKeys.WORLD_KEY)); if (worlds.size() > 1) { // start iterating at index 1 for (int i = 1; i < worlds.size(); i++) { - set.remove(Contexts.WORLD_KEY, worlds.get(i)); + set.remove(DefaultContextKeys.WORLD_KEY, worlds.get(i)); } } @@ -265,7 +265,7 @@ public class ArgumentParser { } } - return contextSet.makeImmutable(); + return contextSet.immutableCopy(); } public static UUID parseUserTarget(int index, List args, LuckPermsPlugin plugin, Sender sender) { diff --git a/common/src/main/java/me/lucko/luckperms/common/command/utils/MessageUtils.java b/common/src/main/java/me/lucko/luckperms/common/command/utils/MessageUtils.java index 2be1e535a..bf9a3e92e 100644 --- a/common/src/main/java/me/lucko/luckperms/common/command/utils/MessageUtils.java +++ b/common/src/main/java/me/lucko/luckperms/common/command/utils/MessageUtils.java @@ -25,10 +25,9 @@ package me.lucko.luckperms.common.command.utils; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.locale.LocaleManager; import me.lucko.luckperms.common.locale.message.Message; @@ -125,16 +124,9 @@ public final class MessageUtils { */ public static String getAppendableNodeContextString(LocaleManager localeManager, Node node) { StringBuilder sb = new StringBuilder(); - if (node.isServerSpecific()) { - sb.append(" ").append(contextToString(localeManager, Contexts.SERVER_KEY, node.getServer().get())); - } - if (node.isWorldSpecific()) { - sb.append(" ").append(contextToString(localeManager, Contexts.WORLD_KEY, node.getWorld().get())); - } for (Map.Entry c : node.getContexts().toSet()) { sb.append(" ").append(contextToString(localeManager, c.getKey(), c.getValue())); } - return sb.toString(); } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/CommandMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/CommandMeta.java index 714511e41..f313d32b9 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/CommandMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/CommandMeta.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.common.commands.generic.meta; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.ChatMetaType; +import me.lucko.luckperms.api.node.ChatMetaType; import me.lucko.luckperms.common.command.abstraction.SharedMainCommand; import me.lucko.luckperms.common.command.abstraction.SharedSubCommand; import me.lucko.luckperms.common.locale.LocaleManager; diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddChatMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddChatMeta.java index 1b911e45a..dcec00c98 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddChatMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddChatMeta.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.commands.generic.meta; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.node.ChatMetaType; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -83,8 +83,8 @@ public class MetaAddChatMeta extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - DataMutateResult result = holder.setPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).withExtraContext(context).build()); - if (result.asBoolean()) { + DataMutateResult result = holder.setPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).withContext(context).build()); + if (result.wasSuccessful()) { TextComponent.Builder builder = Message.ADD_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFormattedDisplayName(), this.type.name().toLowerCase(), meta, priority, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder(); HoverEvent event = HoverEvent.showText(TextUtils.fromLegacy( "¥3Raw " + this.type.name().toLowerCase() + ": ¥r" + meta, diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempChatMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempChatMeta.java index cf138cf01..a0de59ac7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempChatMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaAddTempChatMeta.java @@ -25,10 +25,11 @@ package me.lucko.luckperms.common.commands.generic.meta; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.TemporaryDataMutateResult; -import me.lucko.luckperms.api.TemporaryMergeBehaviour; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.TemporaryDataMutateResult; +import me.lucko.luckperms.api.model.TemporaryMergeBehaviour; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.util.Result; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -88,10 +89,10 @@ public class MetaAddTempChatMeta extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - TemporaryDataMutateResult ret = holder.setPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).setExpiry(duration).withExtraContext(context).build(), modifier); + TemporaryDataMutateResult ret = holder.setPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).expiry(duration).withContext(context).build(), modifier); - if (ret.getResult().asBoolean()) { - duration = ret.getMergedNode().getExpiryUnixTime(); + if (((Result) ret.getResult()).wasSuccessful()) { + duration = ret.getMergedNode().getExpiry().getEpochSecond(); TextComponent.Builder builder = Message.ADD_TEMP_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFormattedDisplayName(), this.type.name().toLowerCase(), meta, priority, DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder(); HoverEvent event = HoverEvent.showText(TextUtils.fromLegacy( diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaClear.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaClear.java index 86fba13b0..b901796f2 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaClear.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaClear.java @@ -26,6 +26,7 @@ package me.lucko.luckperms.common.commands.generic.meta; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.node.NodeType; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -39,8 +40,7 @@ import me.lucko.luckperms.common.locale.LocaleManager; import me.lucko.luckperms.common.locale.command.CommandSpec; import me.lucko.luckperms.common.locale.message.Message; import me.lucko.luckperms.common.model.PermissionHolder; -import me.lucko.luckperms.common.node.model.NodeTypes; -import me.lucko.luckperms.common.node.utils.MetaType; +import me.lucko.luckperms.common.node.factory.NodeTypes; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.util.Predicates; @@ -59,23 +59,23 @@ public class MetaClear extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - MetaType type = null; + NodeType type = null; if (!args.isEmpty()) { String typeId = args.get(0).toLowerCase(); if (typeId.equals("any") || typeId.equals("all") || typeId.equals("*")) { - type = MetaType.ANY; + type = NodeType.META_OR_CHAT_META; } if (typeId.equals("chat") || typeId.equals("chatmeta")) { - type = MetaType.CHAT; + type = NodeType.CHAT_META; } if (typeId.equals(NodeTypes.META_KEY)) { - type = MetaType.META; + type = NodeType.META; } if (typeId.equals(NodeTypes.PREFIX_KEY) || typeId.equals("prefixes")) { - type = MetaType.PREFIX; + type = NodeType.PREFIX; } if (typeId.equals(NodeTypes.SUFFIX_KEY) || typeId.equals("suffixes")) { - type = MetaType.SUFFIX; + type = NodeType.SUFFIX; } if (type != null) { @@ -84,7 +84,7 @@ public class MetaClear extends SharedSubCommand { } if (type == null) { - type = MetaType.ANY; + type = NodeType.META_OR_CHAT_META; } int before = holder.enduringData().immutable().size(); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaInfo.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaInfo.java index 7d12812a1..4d0195f8a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaInfo.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaInfo.java @@ -27,8 +27,14 @@ package me.lucko.luckperms.common.commands.generic.meta; import com.google.common.collect.Maps; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.LocalizedNode; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeType; +import me.lucko.luckperms.api.node.metadata.types.InheritanceOriginMetadata; +import me.lucko.luckperms.api.node.types.ChatMetaNode; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.node.types.PrefixNode; +import me.lucko.luckperms.api.node.types.SuffixNode; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SharedSubCommand; import me.lucko.luckperms.common.command.access.ArgumentPermissions; @@ -62,8 +68,9 @@ import java.util.TreeSet; import java.util.function.Consumer; public class MetaInfo extends SharedSubCommand { - private static String processLocation(LocalizedNode node, PermissionHolder holder) { - return node.getLocation().equalsIgnoreCase(holder.getObjectName()) ? "self" : node.getLocation(); + private static String processLocation(Node node, PermissionHolder holder) { + String location = node.metadata(InheritanceOriginMetadata.KEY).getOrigin(); + return location.equalsIgnoreCase(holder.getObjectName()) ? "self" : location; } public MetaInfo(LocaleManager locale) { @@ -77,22 +84,24 @@ public class MetaInfo extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - SortedSet> prefixes = new TreeSet<>(MetaComparator.INSTANCE.reversed()); - SortedSet> suffixes = new TreeSet<>(MetaComparator.INSTANCE.reversed()); - Set meta = new LinkedHashSet<>(); + SortedSet> prefixes = new TreeSet<>(MetaComparator.INSTANCE.reversed()); + SortedSet> suffixes = new TreeSet<>(MetaComparator.INSTANCE.reversed()); + Set meta = new LinkedHashSet<>(); // Collect data - for (LocalizedNode node : holder.resolveInheritances()) { - if (!node.isSuffix() && !node.isPrefix() && !node.isMeta()) { + for (Node node : holder.resolveInheritances(QueryOptions.nonContextual())) { + if (!NodeType.META_OR_CHAT_META.matches(node)) { continue; } - if (node.isPrefix()) { - prefixes.add(Maps.immutableEntry(node.getPrefix().getKey(), node)); - } else if (node.isSuffix()) { - suffixes.add(Maps.immutableEntry(node.getSuffix().getKey(), node)); - } else if (node.isMeta()) { - meta.add(node); + if (node instanceof PrefixNode) { + PrefixNode pn = (PrefixNode) node; + prefixes.add(Maps.immutableEntry(pn.getPriority(), pn)); + } else if (node instanceof SuffixNode) { + SuffixNode sn = (SuffixNode) node; + suffixes.add(Maps.immutableEntry(sn.getPriority(), sn)); + } else if (node instanceof MetaNode) { + meta.add(((MetaNode) node)); } } @@ -100,14 +109,14 @@ public class MetaInfo extends SharedSubCommand { Message.CHAT_META_PREFIX_NONE.send(sender, holder.getFormattedDisplayName()); } else { Message.CHAT_META_PREFIX_HEADER.send(sender, holder.getFormattedDisplayName()); - sendChatMetaMessage(ChatMetaType.PREFIX, prefixes, sender, holder, label); + sendChatMetaMessage(prefixes, sender, holder, label); } if (suffixes.isEmpty()) { Message.CHAT_META_SUFFIX_NONE.send(sender, holder.getFormattedDisplayName()); } else { Message.CHAT_META_SUFFIX_HEADER.send(sender, holder.getFormattedDisplayName()); - sendChatMetaMessage(ChatMetaType.SUFFIX, suffixes, sender, holder, label); + sendChatMetaMessage(suffixes, sender, holder, label); } if (meta.isEmpty()) { @@ -120,51 +129,52 @@ public class MetaInfo extends SharedSubCommand { return CommandResult.SUCCESS; } - private static void sendMetaMessage(Set meta, Sender sender, PermissionHolder holder, String label) { - for (LocalizedNode m : meta) { + private static void sendMetaMessage(Set meta, Sender sender, PermissionHolder holder, String label) { + for (MetaNode m : meta) { String location = processLocation(m, holder); - if (m.hasSpecificContext()) { + if (!m.getContexts().isEmpty()) { String context = MessageUtils.getAppendableNodeContextString(sender.getPlugin().getLocaleManager(), m); - TextComponent.Builder builder = Message.META_ENTRY_WITH_CONTEXT.asComponent(sender.getPlugin().getLocaleManager(), m.getMeta().getKey(), m.getMeta().getValue(), location, context).toBuilder(); + TextComponent.Builder builder = Message.META_ENTRY_WITH_CONTEXT.asComponent(sender.getPlugin().getLocaleManager(), m.getMetaKey(), m.getMetaValue(), location, context).toBuilder(); builder.applyDeep(makeFancy(holder, label, m)); sender.sendMessage(builder.build()); } else { - TextComponent.Builder builder = Message.META_ENTRY.asComponent(sender.getPlugin().getLocaleManager(), m.getMeta().getKey(), m.getMeta().getValue(), location).toBuilder(); + TextComponent.Builder builder = Message.META_ENTRY.asComponent(sender.getPlugin().getLocaleManager(), m.getMetaKey(), m.getMetaValue(), location).toBuilder(); builder.applyDeep(makeFancy(holder, label, m)); sender.sendMessage(builder.build()); } } } - private static void sendChatMetaMessage(ChatMetaType type, SortedSet> meta, Sender sender, PermissionHolder holder, String label) { - for (Map.Entry e : meta) { + private static void sendChatMetaMessage(SortedSet>> meta, Sender sender, PermissionHolder holder, String label) { + for (Map.Entry> e : meta) { String location = processLocation(e.getValue(), holder); - if (e.getValue().hasSpecificContext()) { + if (!e.getValue().getContexts().isEmpty()) { String context = MessageUtils.getAppendableNodeContextString(sender.getPlugin().getLocaleManager(), e.getValue()); - TextComponent.Builder builder = Message.CHAT_META_ENTRY_WITH_CONTEXT.asComponent(sender.getPlugin().getLocaleManager(), e.getKey(), type.getEntry(e.getValue()).getValue(), location, context).toBuilder(); - builder.applyDeep(makeFancy(type, holder, label, e.getValue())); + TextComponent.Builder builder = Message.CHAT_META_ENTRY_WITH_CONTEXT.asComponent(sender.getPlugin().getLocaleManager(), e.getKey(), e.getValue().getMetaValue(), location, context).toBuilder(); + builder.applyDeep(makeFancy(holder, label, e.getValue())); sender.sendMessage(builder.build()); } else { - TextComponent.Builder builder = Message.CHAT_META_ENTRY.asComponent(sender.getPlugin().getLocaleManager(), e.getKey(), type.getEntry(e.getValue()).getValue(), location).toBuilder(); - builder.applyDeep(makeFancy(type, holder, label, e.getValue())); + TextComponent.Builder builder = Message.CHAT_META_ENTRY.asComponent(sender.getPlugin().getLocaleManager(), e.getKey(), e.getValue().getMetaValue(), location).toBuilder(); + builder.applyDeep(makeFancy(holder, label, e.getValue())); sender.sendMessage(builder.build()); } } } - private static Consumer> makeFancy(ChatMetaType type, PermissionHolder holder, String label, LocalizedNode node) { - if (!node.getLocation().equals(holder.getObjectName())) { + private static Consumer> makeFancy(PermissionHolder holder, String label, ChatMetaNode node) { + String location = node.metadata(InheritanceOriginMetadata.KEY).getOrigin(); + if (!location.equals(holder.getObjectName())) { // inherited. - Group group = holder.getPlugin().getGroupManager().getIfLoaded(node.getLocation()); + Group group = holder.getPlugin().getGroupManager().getIfLoaded(location); if (group != null) { holder = group; } } HoverEvent hoverEvent = HoverEvent.showText(TextUtils.fromLegacy(TextUtils.joinNewline( - "¥3> ¥a" + type.getEntry(node).getKey() + " ¥7- ¥r" + type.getEntry(node).getValue(), + "¥3> ¥a" + node.getPriority() + " ¥7- ¥r" + node.getMetaValue(), " ", - "¥7Click to remove this " + type.name().toLowerCase() + " from " + holder.getFormattedDisplayName() + "¥7Click to remove this " + node.getType().name().toLowerCase() + " from " + holder.getFormattedDisplayName() ), '¥')); String command = "/" + label + " " + NodeFactory.nodeAsCommand(node, holder.getType() == HolderType.GROUP ? holder.getObjectName() : holder.getFormattedDisplayName(), holder.getType(), false, !holder.getPlugin().getConfiguration().getContextsFile().getDefaultContexts().isEmpty()); @@ -176,17 +186,18 @@ public class MetaInfo extends SharedSubCommand { }; } - private static Consumer> makeFancy(PermissionHolder holder, String label, LocalizedNode node) { - if (!node.getLocation().equals(holder.getObjectName())) { + private static Consumer> makeFancy(PermissionHolder holder, String label, MetaNode node) { + String location = node.metadata(InheritanceOriginMetadata.KEY).getOrigin(); + if (!location.equals(holder.getObjectName())) { // inherited. - Group group = holder.getPlugin().getGroupManager().getIfLoaded(node.getLocation()); + Group group = holder.getPlugin().getGroupManager().getIfLoaded(location); if (group != null) { holder = group; } } HoverEvent hoverEvent = HoverEvent.showText(TextUtils.fromLegacy(TextUtils.joinNewline( - "¥3> ¥r" + node.getMeta().getKey() + " ¥7- ¥r" + node.getMeta().getValue(), + "¥3> ¥r" + node.getMetaKey() + " ¥7- ¥r" + node.getMetaValue(), " ", "¥7Click to remove this meta pair from " + holder.getFormattedDisplayName() ), '¥')); @@ -200,11 +211,11 @@ public class MetaInfo extends SharedSubCommand { }; } - private static final class MetaComparator implements Comparator> { + private static final class MetaComparator implements Comparator>> { public static final MetaComparator INSTANCE = new MetaComparator(); @Override - public int compare(Map.Entry o1, Map.Entry o2) { + public int compare(Map.Entry> o1, Map.Entry> o2) { int result = Integer.compare(o1.getKey(), o2.getKey()); if (result != 0) { return result; diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaRemoveChatMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaRemoveChatMeta.java index 25a7174dc..59652b63d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaRemoveChatMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaRemoveChatMeta.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.commands.generic.meta; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.DataMutateResult; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.node.ChatMetaType; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -75,7 +75,7 @@ public class MetaRemoveChatMeta extends SharedSubCommand { int priority = ArgumentParser.parsePriority(0, args); String meta = ArgumentParser.parseStringOrElse(1, args, "null"); - MutableContextSet context = ArgumentParser.parseContext(2, args, plugin); + ImmutableContextSet context = ArgumentParser.parseContext(2, args, plugin).immutableCopy(); if (ArgumentPermissions.checkContext(plugin, sender, permission, context) || ArgumentPermissions.checkGroup(plugin, sender, holder, context)) { @@ -85,11 +85,10 @@ public class MetaRemoveChatMeta extends SharedSubCommand { // Handle bulk removal if (meta.equalsIgnoreCase("null") || meta.equals("*")) { - holder.removeIf(n -> - this.type.matches(n) && - this.type.getEntry(n).getKey() == priority && - !n.isTemporary() && - n.getFullContexts().makeImmutable().equals(context.makeImmutable()) + holder.removeIfEnduring(n -> this.type.nodeType().matches(n) && + this.type.nodeType().cast(n).getPriority() == priority && + !n.hasExpiry() && + n.getContexts().equals(context) ); Message.BULK_REMOVE_CHATMETA_SUCCESS.send(sender, holder.getFormattedDisplayName(), this.type.name().toLowerCase(), priority, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); @@ -101,9 +100,9 @@ public class MetaRemoveChatMeta extends SharedSubCommand { return CommandResult.SUCCESS; } - DataMutateResult result = holder.unsetPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).withExtraContext(context).build()); + DataMutateResult result = holder.unsetPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).withContext(context).build()); - if (result.asBoolean()) { + if (result.wasSuccessful()) { TextComponent.Builder builder = Message.REMOVE_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFormattedDisplayName(), this.type.name().toLowerCase(), meta, priority, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder(); HoverEvent event = HoverEvent.showText(TextUtils.fromLegacy( "¥3Raw " + this.type.name().toLowerCase() + ": ¥r" + meta, diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaRemoveTempChatMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaRemoveTempChatMeta.java index 9809431dc..9c8b82a11 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaRemoveTempChatMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaRemoveTempChatMeta.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.commands.generic.meta; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.DataMutateResult; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.node.ChatMetaType; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -75,7 +75,7 @@ public class MetaRemoveTempChatMeta extends SharedSubCommand { int priority = ArgumentParser.parsePriority(0, args); String meta = ArgumentParser.parseStringOrElse(1, args, "null"); - MutableContextSet context = ArgumentParser.parseContext(2, args, plugin); + ImmutableContextSet context = ArgumentParser.parseContext(2, args, plugin).immutableCopy(); if (ArgumentPermissions.checkContext(plugin, sender, permission, context) || ArgumentPermissions.checkGroup(plugin, sender, holder, context)) { @@ -85,11 +85,10 @@ public class MetaRemoveTempChatMeta extends SharedSubCommand { // Handle bulk removal if (meta.equalsIgnoreCase("null") || meta.equals("*")) { - holder.removeIf(n -> - this.type.matches(n) && - this.type.getEntry(n).getKey() == priority && - !n.isPermanent() && - n.getFullContexts().makeImmutable().equals(context.makeImmutable()) + holder.removeIfEnduring(n -> this.type.nodeType().matches(n) && + this.type.nodeType().cast(n).getPriority() == priority && + n.hasExpiry() && + n.getContexts().equals(context) ); Message.BULK_REMOVE_TEMP_CHATMETA_SUCCESS.send(sender, holder.getFormattedDisplayName(), this.type.name().toLowerCase(), priority, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); @@ -101,9 +100,9 @@ public class MetaRemoveTempChatMeta extends SharedSubCommand { return CommandResult.SUCCESS; } - DataMutateResult result = holder.unsetPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).setExpiry(10L).withExtraContext(context).build()); + DataMutateResult result = holder.unsetPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).expiry(10L).withContext(context).build()); - if (result.asBoolean()) { + if (result.wasSuccessful()) { TextComponent.Builder builder = Message.REMOVE_TEMP_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFormattedDisplayName(), this.type.name().toLowerCase(), meta, priority, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder(); HoverEvent event = HoverEvent.showText(TextUtils.fromLegacy( "¥3Raw " + this.type.name().toLowerCase() + ": ¥r" + meta, diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSet.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSet.java index af357d8ad..5dbd31381 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSet.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSet.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.commands.generic.meta; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.StandardNodeEquality; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -76,9 +76,9 @@ public class MetaSet extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - Node n = NodeFactory.buildMetaNode(key, value).withExtraContext(context).build(); + Node n = NodeFactory.buildMetaNode(key, value).withContext(context).build(); - if (holder.hasPermission(NodeMapType.ENDURING, n, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE).asBoolean()) { + if (holder.hasPermission(NodeMapType.ENDURING, n, NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE).asBoolean()) { Message.ALREADY_HAS_META.send(sender, holder.getFormattedDisplayName(), key, value, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); return CommandResult.STATE_ERROR; } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetChatMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetChatMeta.java index 891c527b5..17f0a3478 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetChatMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetChatMeta.java @@ -25,10 +25,10 @@ package me.lucko.luckperms.common.commands.generic.meta; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; import me.lucko.luckperms.common.command.CommandResult; @@ -103,11 +103,11 @@ public class MetaSetChatMeta extends SharedSubCommand { } // remove all other prefixes/suffixes set in these contexts - holder.removeIf(context, this.type::matches); + holder.removeIfEnduring(context, node -> this.type.nodeType().matches(node)); // determine the priority to set at if (priority == Integer.MIN_VALUE) { - MetaAccumulator metaAccumulator = holder.accumulateMeta(null, Contexts.global().setContexts(context)); + MetaAccumulator metaAccumulator = holder.accumulateMeta(null, QueryOptions.defaultContextualOptions().toBuilder().context(context).build()); metaAccumulator.complete(); priority = metaAccumulator.getChatMeta(this.type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 1; @@ -119,8 +119,8 @@ public class MetaSetChatMeta extends SharedSubCommand { } } - DataMutateResult result = holder.setPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).withExtraContext(context).build()); - if (result.asBoolean()) { + DataMutateResult result = holder.setPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).withContext(context).build()); + if (result.wasSuccessful()) { TextComponent.Builder builder = Message.ADD_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFormattedDisplayName(), this.type.name().toLowerCase(), meta, priority, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder(); HoverEvent event = HoverEvent.showText(TextUtils.fromLegacy( "¥3Raw " + this.type.name().toLowerCase() + ": ¥r" + meta, diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTemp.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTemp.java index fbc0b51c0..dcc0a34df 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTemp.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTemp.java @@ -25,10 +25,10 @@ package me.lucko.luckperms.common.commands.generic.meta; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.StandardNodeEquality; -import me.lucko.luckperms.api.TemporaryMergeBehaviour; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.TemporaryMergeBehaviour; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -81,15 +81,15 @@ public class MetaSetTemp extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - Node n = NodeFactory.buildMetaNode(key, value).withExtraContext(context).setExpiry(duration).build(); + Node n = NodeFactory.buildMetaNode(key, value).withContext(context).expiry(duration).build(); - if (holder.hasPermission(NodeMapType.ENDURING, n, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE).asBoolean()) { + if (holder.hasPermission(NodeMapType.ENDURING, n, NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE).asBoolean()) { Message.ALREADY_HAS_TEMP_META.send(sender, holder.getFormattedDisplayName(), key, value, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); return CommandResult.STATE_ERROR; } holder.clearMetaKeys(key, context, true); - duration = holder.setPermission(n, modifier).getMergedNode().getExpiryUnixTime(); + duration = holder.setPermission(n, modifier).getMergedNode().getExpiry().getEpochSecond(); TextComponent.Builder builder = Message.SET_META_TEMP_SUCCESS.asComponent(plugin.getLocaleManager(), key, value, holder.getFormattedDisplayName(), DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder(); HoverEvent event = HoverEvent.showText(TextUtils.fromLegacy( diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTempChatMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTempChatMeta.java index 7adc45bc9..c2e160d91 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTempChatMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/meta/MetaSetTempChatMeta.java @@ -25,11 +25,12 @@ package me.lucko.luckperms.common.commands.generic.meta; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.TemporaryDataMutateResult; -import me.lucko.luckperms.api.TemporaryMergeBehaviour; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.TemporaryDataMutateResult; +import me.lucko.luckperms.api.model.TemporaryMergeBehaviour; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.query.QueryOptions; +import me.lucko.luckperms.api.util.Result; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; import me.lucko.luckperms.common.command.CommandResult; @@ -112,11 +113,11 @@ public class MetaSetTempChatMeta extends SharedSubCommand { } // remove all other prefixes/suffixes set in these contexts - holder.removeIf(context, this.type::matches); + holder.removeIfEnduring(context, node -> this.type.nodeType().matches(node)); // determine the priority to set at if (priority == Integer.MIN_VALUE) { - MetaAccumulator metaAccumulator = holder.accumulateMeta(null, Contexts.global().setContexts(context)); + MetaAccumulator metaAccumulator = holder.accumulateMeta(null, QueryOptions.defaultContextualOptions().toBuilder().context(context).build()); metaAccumulator.complete(); priority = metaAccumulator.getChatMeta(this.type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 1; @@ -128,10 +129,10 @@ public class MetaSetTempChatMeta extends SharedSubCommand { } } - TemporaryDataMutateResult ret = holder.setPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).setExpiry(duration).withExtraContext(context).build(), modifier); + TemporaryDataMutateResult ret = holder.setPermission(NodeFactory.buildChatMetaNode(this.type, priority, meta).expiry(duration).withContext(context).build(), modifier); - if (ret.getResult().asBoolean()) { - duration = ret.getMergedNode().getExpiryUnixTime(); + if (((Result) ret.getResult()).wasSuccessful()) { + duration = ret.getMergedNode().getExpiry().getEpochSecond(); TextComponent.Builder builder = Message.ADD_TEMP_CHATMETA_SUCCESS.asComponent(plugin.getLocaleManager(), holder.getFormattedDisplayName(), this.type.name().toLowerCase(), meta, priority, DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)).toBuilder(); HoverEvent event = HoverEvent.showText(TextUtils.fromLegacy( diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderClear.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderClear.java index 69309274a..ef99a73da 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderClear.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderClear.java @@ -68,9 +68,9 @@ public class HolderClear extends SubCommand { } if (context.isEmpty()) { - holder.clearNodes(); + holder.clearEnduringNodes(); } else { - holder.clearNodes(context); + holder.clearEnduringNodes(context); } int changed = before - holder.enduringData().immutable().size(); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java index b82ba0992..caa39c391 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderEditor.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.common.commands.generic.other; import com.google.gson.JsonObject; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; import me.lucko.luckperms.common.command.access.ArgumentPermissions; @@ -58,7 +58,7 @@ public class HolderEditor extends SubCommand { @Override public CommandResult execute(LuckPermsPlugin plugin, Sender sender, T holder, List args, String label) { - if (ArgumentPermissions.checkViewPerms(plugin, sender, getPermission().get(), holder) || ArgumentPermissions.checkGroup(plugin, sender, holder, ContextSet.empty())) { + if (ArgumentPermissions.checkViewPerms(plugin, sender, getPermission().get(), holder) || ArgumentPermissions.checkGroup(plugin, sender, holder, ImmutableContextSet.empty())) { Message.COMMAND_NO_PERMISSION.send(sender); return CommandResult.NO_PERMISSION; } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderShowTracks.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderShowTracks.java index 4b0e9595c..55df218de 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderShowTracks.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/other/HolderShowTracks.java @@ -27,7 +27,9 @@ package me.lucko.luckperms.common.commands.generic.other; import com.google.common.collect.Maps; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeType; +import me.lucko.luckperms.api.node.types.InheritanceNode; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; import me.lucko.luckperms.common.command.access.ArgumentPermissions; @@ -74,13 +76,14 @@ public class HolderShowTracks extends SubCommand if (holder.getType() == HolderType.USER) { // if the holder is a user, we want to query parent groups for tracks - Set nodes = holder.enduringData().immutable().values().stream() - .filter(Node::isGroupNode) + Set nodes = holder.enduringData().immutable().values().stream() + .filter(NodeType.INHERITANCE::matches) + .map(NodeType.INHERITANCE::cast) .filter(Node::getValue) - .filter(Node::isPermanent) + .filter(n -> !n.hasExpiry()) .collect(Collectors.toSet()); - for (Node node : nodes) { + for (InheritanceNode node : nodes) { String groupName = node.getGroupName(); List tracks = plugin.getTrackManager().getAll().values().stream() .filter(t -> t.containsGroup(groupName)) diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAdd.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAdd.java index ad5f49355..9e1bfaa51 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAdd.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAdd.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.commands.generic.parent; -import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -78,9 +78,9 @@ public class ParentAdd extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - DataMutateResult result = holder.setPermission(NodeFactory.buildGroupNode(group.getName()).withExtraContext(context).build()); + DataMutateResult result = holder.setPermission(NodeFactory.buildGroupNode(group.getName()).withContext(context).build()); - if (result.asBoolean()) { + if (result.wasSuccessful()) { Message.SET_INHERIT_SUCCESS.send(sender, holder.getFormattedDisplayName(), group.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); ExtendedLogEntry.build().actor(sender).acted(holder) diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAddTemp.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAddTemp.java index 2e10409f8..0d5f9f305 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAddTemp.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentAddTemp.java @@ -25,9 +25,10 @@ package me.lucko.luckperms.common.commands.generic.parent; -import me.lucko.luckperms.api.TemporaryDataMutateResult; -import me.lucko.luckperms.api.TemporaryMergeBehaviour; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.TemporaryDataMutateResult; +import me.lucko.luckperms.api.model.TemporaryMergeBehaviour; +import me.lucko.luckperms.api.util.Result; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -88,10 +89,10 @@ public class ParentAddTemp extends SharedSubCommand { return CommandResult.STATE_ERROR; } - TemporaryDataMutateResult ret = holder.setPermission(NodeFactory.buildGroupNode(group.getName()).setExpiry(duration).withExtraContext(context).build(), modifier); + TemporaryDataMutateResult ret = holder.setPermission(NodeFactory.buildGroupNode(group.getName()).expiry(duration).withContext(context).build(), modifier); - if (ret.getResult().asBoolean()) { - duration = ret.getMergedNode().getExpiryUnixTime(); + if (((Result) ret.getResult()).wasSuccessful()) { + duration = ret.getMergedNode().getExpiry().getEpochSecond(); Message.SET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFormattedDisplayName(), group.getFormattedDisplayName(), DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); ExtendedLogEntry.build().actor(sender).acted(holder) diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClear.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClear.java index cdfe2fff3..26f42a6fb 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClear.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClear.java @@ -67,9 +67,9 @@ public class ParentClear extends SharedSubCommand { } if (context.isEmpty()) { - holder.clearParents(true); + holder.clearEnduringParents(true); } else { - holder.clearParents(context, true); + holder.clearEnduringParents(context, true); } int changed = before - holder.enduringData().immutable().size(); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClearTrack.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClearTrack.java index 6fec96c3d..d2aba1415 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClearTrack.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentClearTrack.java @@ -25,7 +25,8 @@ package me.lucko.luckperms.common.commands.generic.parent; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.NodeType; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -81,7 +82,7 @@ public class ParentClearTrack extends SharedSubCommand { int before = holder.enduringData().immutable().size(); - MutableContextSet context = ArgumentParser.parseContext(1, args, plugin); + ImmutableContextSet context = ArgumentParser.parseContext(1, args, plugin).immutableCopy(); if (ArgumentPermissions.checkContext(plugin, sender, permission, context) || ArgumentPermissions.checkGroup(plugin, sender, holder, context) || @@ -91,9 +92,9 @@ public class ParentClearTrack extends SharedSubCommand { } if (context.isEmpty()) { - holder.removeIf(node -> node.isGroupNode() && track.containsGroup(node.getGroupName())); + holder.removeIfEnduring(NodeType.INHERITANCE.predicate(n -> track.containsGroup(n.getGroupName()))); } else { - holder.removeIf(node -> node.isGroupNode() && node.getFullContexts().equals(context) && track.containsGroup(node.getGroupName())); + holder.removeIfEnduring(NodeType.INHERITANCE.predicate(n -> n.getContexts().equals(context) && track.containsGroup(n.getGroupName()))); } if (holder.getType() == HolderType.USER) { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentInfo.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentInfo.java index 7f32aca7c..ea654ea14 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentInfo.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentInfo.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.commands.generic.parent; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.command.CommandManager; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SharedSubCommand; @@ -55,9 +55,9 @@ import net.kyori.text.TextComponent; import net.kyori.text.event.ClickEvent; import net.kyori.text.event.HoverEvent; -import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.LinkedList; import java.util.List; import java.util.function.Consumer; @@ -77,10 +77,11 @@ public class ParentInfo extends SharedSubCommand { SortMode sortMode = SortMode.determine(args); // get the holders nodes - List nodes = new ArrayList<>(holder.enduringData().asSortedSet()); + List nodes = new LinkedList<>(); + holder.enduringData().copyInheritanceNodesTo(nodes, QueryOptions.nonContextual()); // remove irrelevant types (these are displayed in the other info commands) - nodes.removeIf(node -> !node.isGroupNode() || !node.getValue()); + nodes.removeIf(node -> !node.getValue()); // handle empty if (nodes.isEmpty()) { @@ -99,23 +100,23 @@ public class ParentInfo extends SharedSubCommand { } int pageIndex = page - 1; - List> pages = Iterators.divideIterable(nodes, 19); + List> pages = Iterators.divideIterable(nodes, 19); if (pageIndex < 0 || pageIndex >= pages.size()) { page = 1; pageIndex = 0; } - List content = pages.get(pageIndex); + List content = pages.get(pageIndex); // send header Message.PARENT_INFO.send(sender, holder.getFormattedDisplayName(), page, pages.size(), nodes.size()); // send content - for (LocalizedNode node : content) { + for (InheritanceNode node : content) { String s = "&3> &a" + node.getGroupName() + MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node); - if (node.isTemporary()) { - s += "\n&2 expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime()); + if (node.hasExpiry()) { + s += "\n&2 expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond()); } TextComponent message = TextUtils.fromLegacy(s, CommandManager.AMPERSAND_CHAR).toBuilder().applyDeep(makeFancy(holder, label, node)).build(); @@ -125,7 +126,7 @@ public class ParentInfo extends SharedSubCommand { return CommandResult.SUCCESS; } - private static final Comparator ALPHABETICAL_NODE_COMPARATOR = (o1, o2) -> { + private static final Comparator ALPHABETICAL_NODE_COMPARATOR = (o1, o2) -> { int i = o1.getGroupName().compareTo(o2.getGroupName()); if (i != 0) { return i; @@ -135,7 +136,7 @@ public class ParentInfo extends SharedSubCommand { return NodeWithContextComparator.reverse().compare(o1, o2); }; - private static Consumer> makeFancy(PermissionHolder holder, String label, Node node) { + private static Consumer> makeFancy(PermissionHolder holder, String label, InheritanceNode node) { HoverEvent hoverEvent = HoverEvent.showText(TextUtils.fromLegacy(TextUtils.joinNewline( "&3> &f" + node.getGroupName(), " ", diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentRemove.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentRemove.java index c217930b9..c106c057e 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentRemove.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentRemove.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.commands.generic.parent; -import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -89,8 +89,8 @@ public class ParentRemove extends SharedSubCommand { } } - DataMutateResult result = holder.unsetPermission(NodeFactory.buildGroupNode(groupName).withExtraContext(context).build()); - if (result.asBoolean()) { + DataMutateResult result = holder.unsetPermission(NodeFactory.buildGroupNode(groupName).withContext(context).build()); + if (result.wasSuccessful()) { Message.UNSET_INHERIT_SUCCESS.send(sender, holder.getFormattedDisplayName(), groupName, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); ExtendedLogEntry.build().actor(sender).acted(holder) diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentRemoveTemp.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentRemoveTemp.java index d63940215..115d3afe8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentRemoveTemp.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentRemoveTemp.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.commands.generic.parent; -import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -72,9 +72,9 @@ public class ParentRemoveTemp extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - DataMutateResult result = holder.unsetPermission(NodeFactory.buildGroupNode(groupName).setExpiry(10L).withExtraContext(context).build()); + DataMutateResult result = holder.unsetPermission(NodeFactory.buildGroupNode(groupName).expiry(10L).withContext(context).build()); - if (result.asBoolean()) { + if (result.wasSuccessful()) { Message.UNSET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFormattedDisplayName(), groupName, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); ExtendedLogEntry.build().actor(sender).acted(holder) diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentSet.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentSet.java index 83bffb0f5..aacecb508 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentSet.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentSet.java @@ -79,8 +79,8 @@ public class ParentSet extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - holder.clearParents(context, false); - holder.setPermission(NodeFactory.buildGroupNode(group.getName()).withExtraContext(context).build()); + holder.clearEnduringParents(context, false); + holder.setPermission(NodeFactory.buildGroupNode(group.getName()).withContext(context).build()); if (holder.getType() == HolderType.USER) { ((User) holder).getPrimaryGroup().setStoredValue(group.getName()); } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentSetTrack.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentSetTrack.java index 35f5a1df2..6c40cf05a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentSetTrack.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/ParentSetTrack.java @@ -25,7 +25,8 @@ package me.lucko.luckperms.common.commands.generic.parent; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.NodeType; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -96,7 +97,7 @@ public class ParentSetTrack extends SharedSubCommand { } } - MutableContextSet context = ArgumentParser.parseContext(2, args, plugin); + ImmutableContextSet context = ArgumentParser.parseContext(2, args, plugin).immutableCopy(); Group group = StorageAssistant.loadGroup(groupName, sender, plugin, false); if (group == null) { @@ -111,8 +112,8 @@ public class ParentSetTrack extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - holder.removeIf(node -> node.isGroupNode() && node.getFullContexts().equals(context) && track.containsGroup(node.getGroupName())); - holder.setPermission(NodeFactory.buildGroupNode(group.getName()).withExtraContext(context).build()); + holder.removeIfEnduring(NodeType.INHERITANCE.predicate(n -> n.getContexts().equals(context) && track.containsGroup(n.getGroupName()))); + holder.setPermission(NodeFactory.buildGroupNode(group.getName()).withContext(context).build()); Message.SET_TRACK_PARENT_SUCCESS.send(sender, holder.getFormattedDisplayName(), track.getName(), group.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/UserSwitchPrimaryGroup.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/UserSwitchPrimaryGroup.java index 8a8e98b99..46fe40c4c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/UserSwitchPrimaryGroup.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/parent/UserSwitchPrimaryGroup.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.commands.generic.parent; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.StandardNodeEquality; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SharedSubCommand; @@ -79,9 +79,9 @@ public class UserSwitchPrimaryGroup extends SharedSubCommand { return CommandResult.INVALID_ARGS; } - if (ArgumentPermissions.checkContext(plugin, sender, permission, ContextSet.empty()) || - ArgumentPermissions.checkGroup(plugin, sender, holder, ContextSet.empty()) || - ArgumentPermissions.checkGroup(plugin, sender, group, ContextSet.empty()) || + if (ArgumentPermissions.checkContext(plugin, sender, permission, ImmutableContextSet.empty()) || + ArgumentPermissions.checkGroup(plugin, sender, holder, ImmutableContextSet.empty()) || + ArgumentPermissions.checkGroup(plugin, sender, group, ImmutableContextSet.empty()) || ArgumentPermissions.checkArguments(plugin, sender, permission, group.getName())) { Message.COMMAND_NO_PERMISSION.send(sender); return CommandResult.NO_PERMISSION; @@ -93,7 +93,7 @@ public class UserSwitchPrimaryGroup extends SharedSubCommand { } Node node = NodeFactory.buildGroupNode(group.getName()).build(); - if (!user.hasPermission(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_VALUE).asBoolean()) { + if (!user.hasPermission(NodeMapType.ENDURING, node, NodeEqualityPredicate.IGNORE_VALUE).asBoolean()) { Message.USER_PRIMARYGROUP_ERROR_NOTMEMBER.send(sender, user.getFormattedDisplayName(), group.getName()); user.setPermission(node); } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionCheck.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionCheck.java index 0f5e022df..f59398a5d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionCheck.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionCheck.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.commands.generic.permission; -import me.lucko.luckperms.api.StandardNodeEquality; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; import me.lucko.luckperms.common.command.abstraction.SharedSubCommand; @@ -64,7 +64,7 @@ public class PermissionCheck extends SharedSubCommand { String node = ArgumentParser.parseString(0, args); MutableContextSet context = ArgumentParser.parseContext(1, args, plugin); - Tristate result = holder.hasPermission(NodeMapType.ENDURING, NodeFactory.builder(node).withExtraContext(context).build(), StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY); + Tristate result = holder.hasPermission(NodeMapType.ENDURING, NodeFactory.builder(node).withContext(context).build(), NodeEqualityPredicate.IGNORE_VALUE_OR_IF_TEMPORARY); String s = MessageUtils.formatTristate(result); Message.CHECK_PERMISSION.send(sender, holder.getFormattedDisplayName(), node, s, MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionCheckInherits.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionCheckInherits.java index 69036df8f..d64738207 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionCheckInherits.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionCheckInherits.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.commands.generic.permission; -import me.lucko.luckperms.api.StandardNodeEquality; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; import me.lucko.luckperms.common.command.abstraction.SharedSubCommand; @@ -63,7 +63,7 @@ public class PermissionCheckInherits extends SharedSubCommand { String node = ArgumentParser.parseString(0, args); MutableContextSet context = ArgumentParser.parseContext(1, args, plugin); - InheritanceInfo result = holder.searchForInheritedMatch(NodeFactory.builder(node).withExtraContext(context).build(), StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY); + InheritanceInfo result = holder.searchForInheritedMatch(NodeFactory.builder(node).withContext(context).build(), NodeEqualityPredicate.IGNORE_VALUE_OR_IF_TEMPORARY); String location = result.getLocation().orElse(null); if (location == null || location.equalsIgnoreCase(holder.getObjectName())) { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionClear.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionClear.java index e1f6311c9..ad0c1ad8f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionClear.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionClear.java @@ -26,6 +26,7 @@ package me.lucko.luckperms.common.commands.generic.permission; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.node.types.PermissionNode; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -68,9 +69,9 @@ public class PermissionClear extends SharedSubCommand { } if (context.isEmpty()) { - holder.clearPermissions(); + holder.removeIfEnduring(node -> node instanceof PermissionNode); } else { - holder.clearPermissions(context); + holder.removeIfEnduring(context, node -> node instanceof PermissionNode); } int changed = before - holder.enduringData().immutable().size(); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionInfo.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionInfo.java index 489c4e7e3..932cf0c1d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionInfo.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionInfo.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.commands.generic.permission; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeType; import me.lucko.luckperms.common.command.CommandManager; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SharedSubCommand; @@ -77,12 +77,11 @@ public class PermissionInfo extends SharedSubCommand { SortMode sortMode = SortMode.determine(args); // get the holders nodes - List nodes = new ArrayList<>(holder.enduringData().asSortedSet()); + List nodes = new ArrayList<>(holder.enduringData().asSortedSet()); // remove irrelevant types (these are displayed in the other info commands) - nodes.removeIf(node -> (node.isGroupNode() && node.getValue() && plugin.getGroupManager().isLoaded(node.getGroupName())) || - // remove if the node is a meta node - node.isPrefix() || node.isSuffix() || node.isMeta()); + nodes.removeIf(NodeType.INHERITANCE.predicate(n -> n.getValue() && plugin.getGroupManager().isLoaded(n.getGroupName())) + .or(NodeType.META_OR_CHAT_META.predicate())); // handle empty if (nodes.isEmpty()) { @@ -101,23 +100,23 @@ public class PermissionInfo extends SharedSubCommand { } int pageIndex = page - 1; - List> pages = Iterators.divideIterable(nodes, 19); + List> pages = Iterators.divideIterable(nodes, 19); if (pageIndex < 0 || pageIndex >= pages.size()) { page = 1; pageIndex = 0; } - List content = pages.get(pageIndex); + List content = pages.get(pageIndex); // send header Message.PERMISSION_INFO.send(sender, holder.getFormattedDisplayName(), page, pages.size(), nodes.size()); // send content - for (LocalizedNode node : content) { - String s = "&3> " + (node.getValue() ? "&a" : "&c") + node.getPermission() + (sender.isConsole() ? " &7(" + node.getValue() + "&7)" : "") + MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node); - if (node.isTemporary()) { - s += "\n&2- expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime()); + for (Node node : content) { + String s = "&3> " + (node.getValue() ? "&a" : "&c") + node.getKey() + (sender.isConsole() ? " &7(" + node.getValue() + "&7)" : "") + MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node); + if (node.hasExpiry()) { + s += "\n&2- expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond()); } TextComponent message = TextUtils.fromLegacy(s, CommandManager.AMPERSAND_CHAR).toBuilder().applyDeep(makeFancy(holder, label, node)).build(); @@ -127,8 +126,8 @@ public class PermissionInfo extends SharedSubCommand { return CommandResult.SUCCESS; } - private static final Comparator ALPHABETICAL_NODE_COMPARATOR = (o1, o2) -> { - int i = o1.getPermission().compareTo(o2.getPermission()); + private static final Comparator ALPHABETICAL_NODE_COMPARATOR = (o1, o2) -> { + int i = o1.getKey().compareTo(o2.getKey()); if (i != 0) { return i; } @@ -139,7 +138,7 @@ public class PermissionInfo extends SharedSubCommand { private static Consumer> makeFancy(PermissionHolder holder, String label, Node node) { HoverEvent hoverEvent = HoverEvent.showText(TextUtils.fromLegacy(TextUtils.joinNewline( - "¥3> " + (node.getValue() ? "¥a" : "¥c") + node.getPermission(), + "¥3> " + (node.getValue() ? "¥a" : "¥c") + node.getKey(), " ", "¥7Click to remove this node from " + holder.getFormattedDisplayName() ), '¥')); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSet.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSet.java index 576f6cc0b..8082957fd 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSet.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSet.java @@ -25,9 +25,10 @@ package me.lucko.luckperms.common.commands.generic.permission; -import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.context.MutableContextSet; -import me.lucko.luckperms.api.nodetype.types.InheritanceType; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.InheritanceNode; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -44,7 +45,6 @@ import me.lucko.luckperms.common.locale.command.CommandSpec; import me.lucko.luckperms.common.locale.message.Message; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.util.Predicates; @@ -74,17 +74,18 @@ public class PermissionSet extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - InheritanceType inheritanceType = NodeTypes.parseInheritanceType(node); - if (inheritanceType != null) { - if (ArgumentPermissions.checkGroup(plugin, sender, inheritanceType.getGroupName(), context)) { + Node builtNode = NodeFactory.builder(node).value(value).withContext(context).build(); + + if (builtNode instanceof InheritanceNode) { + if (ArgumentPermissions.checkGroup(plugin, sender, ((InheritanceNode) builtNode).getGroupName(), context)) { Message.COMMAND_NO_PERMISSION.send(sender); return CommandResult.NO_PERMISSION; } } - DataMutateResult result = holder.setPermission(NodeFactory.builder(node).setValue(value).withExtraContext(context).build()); + DataMutateResult result = holder.setPermission(builtNode); - if (result.asBoolean()) { + if (result.wasSuccessful()) { Message.SETPERMISSION_SUCCESS.send(sender, node, value, holder.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); ExtendedLogEntry.build().actor(sender).acted(holder) diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSetTemp.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSetTemp.java index 9efce9773..1eeffaef4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSetTemp.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionSetTemp.java @@ -25,10 +25,12 @@ package me.lucko.luckperms.common.commands.generic.permission; -import me.lucko.luckperms.api.TemporaryDataMutateResult; -import me.lucko.luckperms.api.TemporaryMergeBehaviour; import me.lucko.luckperms.api.context.MutableContextSet; -import me.lucko.luckperms.api.nodetype.types.InheritanceType; +import me.lucko.luckperms.api.model.TemporaryDataMutateResult; +import me.lucko.luckperms.api.model.TemporaryMergeBehaviour; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.util.Result; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -46,7 +48,6 @@ import me.lucko.luckperms.common.locale.command.CommandSpec; import me.lucko.luckperms.common.locale.message.Message; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.util.DurationFormatter; @@ -79,18 +80,19 @@ public class PermissionSetTemp extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - InheritanceType inheritanceType = NodeTypes.parseInheritanceType(node); - if (inheritanceType != null) { - if (ArgumentPermissions.checkGroup(plugin, sender, inheritanceType.getGroupName(), context)) { + Node builtNode = NodeFactory.builder(node).value(value).withContext(context).expiry(duration).build(); + + if (builtNode instanceof InheritanceNode) { + if (ArgumentPermissions.checkGroup(plugin, sender, ((InheritanceNode) builtNode).getGroupName(), context)) { Message.COMMAND_NO_PERMISSION.send(sender); return CommandResult.NO_PERMISSION; } } - TemporaryDataMutateResult result = holder.setPermission(NodeFactory.builder(node).setValue(value).withExtraContext(context).setExpiry(duration).build(), modifier); + TemporaryDataMutateResult result = holder.setPermission(builtNode, modifier); - if (result.getResult().asBoolean()) { - duration = result.getMergedNode().getExpiryUnixTime(); + if (((Result) result.getResult()).wasSuccessful()) { + duration = result.getMergedNode().getExpiry().getEpochSecond(); Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, value, holder.getFormattedDisplayName(), DurationFormatter.LONG.formatDateDiff(duration), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); ExtendedLogEntry.build().actor(sender).acted(holder) diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionUnset.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionUnset.java index 60fb1d580..91f400c15 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionUnset.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionUnset.java @@ -25,9 +25,10 @@ package me.lucko.luckperms.common.commands.generic.permission; -import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.context.MutableContextSet; -import me.lucko.luckperms.api.nodetype.types.InheritanceType; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.InheritanceNode; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -44,7 +45,6 @@ import me.lucko.luckperms.common.locale.command.CommandSpec; import me.lucko.luckperms.common.locale.message.Message; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.util.Predicates; @@ -73,17 +73,18 @@ public class PermissionUnset extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - InheritanceType inheritanceType = NodeTypes.parseInheritanceType(node); - if (inheritanceType != null) { - if (ArgumentPermissions.checkGroup(plugin, sender, inheritanceType.getGroupName(), context)) { + Node builtNode = NodeFactory.builder(node).withContext(context).build(); + + if (builtNode instanceof InheritanceNode) { + if (ArgumentPermissions.checkGroup(plugin, sender, ((InheritanceNode) builtNode).getGroupName(), context)) { Message.COMMAND_NO_PERMISSION.send(sender); return CommandResult.NO_PERMISSION; } } - DataMutateResult result = holder.unsetPermission(NodeFactory.builder(node).withExtraContext(context).build()); + DataMutateResult result = holder.unsetPermission(builtNode); - if (result.asBoolean()) { + if (result.wasSuccessful()) { Message.UNSETPERMISSION_SUCCESS.send(sender, node, holder.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); ExtendedLogEntry.build().actor(sender).acted(holder) diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionUnsetTemp.java b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionUnsetTemp.java index 47e94fa74..036a5d393 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionUnsetTemp.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/generic/permission/PermissionUnsetTemp.java @@ -25,9 +25,10 @@ package me.lucko.luckperms.common.commands.generic.permission; -import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.context.MutableContextSet; -import me.lucko.luckperms.api.nodetype.types.InheritanceType; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.InheritanceNode; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -44,7 +45,6 @@ import me.lucko.luckperms.common.locale.command.CommandSpec; import me.lucko.luckperms.common.locale.message.Message; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.util.Predicates; @@ -73,17 +73,18 @@ public class PermissionUnsetTemp extends SharedSubCommand { return CommandResult.NO_PERMISSION; } - InheritanceType inheritanceType = NodeTypes.parseInheritanceType(node); - if (inheritanceType != null) { - if (ArgumentPermissions.checkGroup(plugin, sender, inheritanceType.getGroupName(), context)) { + Node builtNode = NodeFactory.builder(node).expiry(10L).withContext(context).build(); + + if (builtNode instanceof InheritanceNode) { + if (ArgumentPermissions.checkGroup(plugin, sender, ((InheritanceNode) builtNode).getGroupName(), context)) { Message.COMMAND_NO_PERMISSION.send(sender); return CommandResult.NO_PERMISSION; } } - DataMutateResult result = holder.unsetPermission(NodeFactory.builder(node).setExpiry(10L).withExtraContext(context).build()); + DataMutateResult result = holder.unsetPermission(builtNode); - if (result.asBoolean()) { + if (result.wasSuccessful()) { Message.UNSET_TEMP_PERMISSION_SUCCESS.send(sender, node, holder.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); ExtendedLogEntry.build().actor(sender).acted(holder) diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/group/CreateGroup.java b/common/src/main/java/me/lucko/luckperms/common/commands/group/CreateGroup.java index 508d9d234..ec4db0565 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/group/CreateGroup.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/group/CreateGroup.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.commands.group; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; @@ -74,7 +74,7 @@ public class CreateGroup extends SingleCommand { Message.CREATE_SUCCESS.send(sender, groupName); - ExtendedLogEntry.build().actor(sender).actedName(groupName).type(LogEntry.Type.GROUP) + ExtendedLogEntry.build().actor(sender).actedName(groupName).type(Action.Type.GROUP) .action("create") .build().submit(plugin, sender); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/group/DeleteGroup.java b/common/src/main/java/me/lucko/luckperms/common/commands/group/DeleteGroup.java index bc9a57d8f..9be80c985 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/group/DeleteGroup.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/group/DeleteGroup.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.commands.group; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.cause.DeletionCause; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; @@ -79,7 +79,7 @@ public class DeleteGroup extends SingleCommand { Message.DELETE_SUCCESS.send(sender, group.getFormattedDisplayName()); - ExtendedLogEntry.build().actor(sender).actedName(groupName).type(LogEntry.Type.GROUP) + ExtendedLogEntry.build().actor(sender).actedName(groupName).type(Action.Type.GROUP) .action("delete") .build().submit(plugin, sender); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupInfo.java b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupInfo.java index 7972f03fb..749b8a47a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupInfo.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupInfo.java @@ -25,7 +25,8 @@ package me.lucko.luckperms.common.commands.group; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.InheritanceNode; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; import me.lucko.luckperms.common.command.access.ArgumentPermissions; @@ -41,7 +42,6 @@ import me.lucko.luckperms.common.util.DurationFormatter; import me.lucko.luckperms.common.util.Predicates; import java.util.List; -import java.util.Set; import java.util.stream.Collectors; public class GroupInfo extends SubCommand { @@ -62,28 +62,28 @@ public class GroupInfo extends SubCommand { group.getWeight().isPresent() ? group.getWeight().getAsInt() : "None" ); - Set parents = group.enduringData().asSet().stream() - .filter(Node::isGroupNode) - .filter(Node::isPermanent) - .collect(Collectors.toSet()); + List parents = group.enduringData().inheritanceAsSortedSet().stream() + .filter(Node::getValue) + .filter(n -> !n.hasExpiry()) + .collect(Collectors.toList()); - Set tempParents = group.enduringData().asSet().stream() - .filter(Node::isGroupNode) - .filter(Node::isTemporary) - .collect(Collectors.toSet()); + List tempParents = group.enduringData().inheritanceAsSortedSet().stream() + .filter(Node::getValue) + .filter(Node::hasExpiry) + .collect(Collectors.toList()); if (!parents.isEmpty()) { Message.INFO_PARENT_HEADER.send(sender); - for (Node node : parents) { + for (InheritanceNode node : parents) { Message.INFO_PARENT_ENTRY.send(sender, node.getGroupName(), MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node)); } } if (!tempParents.isEmpty()) { Message.INFO_TEMP_PARENT_HEADER.send(sender); - for (Node node : tempParents) { + for (InheritanceNode node : tempParents) { Message.INFO_PARENT_ENTRY.send(sender, node.getGroupName(), MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node)); - Message.INFO_PARENT_ENTRY_EXPIRY.send(sender, DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime())); + Message.INFO_PARENT_ENTRY_EXPIRY.send(sender, DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond())); } } return CommandResult.SUCCESS; diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupListMembers.java b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupListMembers.java index b89a1f119..783034136 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupListMembers.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupListMembers.java @@ -27,8 +27,9 @@ package me.lucko.luckperms.common.commands.group; import com.google.common.collect.Maps; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.HeldNode; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.InheritanceNode; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison; import me.lucko.luckperms.common.cache.LoadingMap; @@ -84,12 +85,12 @@ public class GroupListMembers extends SubCommand { Message.SEARCH_SEARCHING_MEMBERS.send(sender, group.getName()); - List> matchedUsers = plugin.getStorage().getUsersWithPermission(constraint).join().stream() - .filter(HeldPermission::getValue) + List> matchedUsers = plugin.getStorage().getUsersWithPermission(constraint).join().stream() + .filter(n -> n.getNode().getValue()) .collect(Collectors.toList()); - List> matchedGroups = plugin.getStorage().getGroupsWithPermission(constraint).join().stream() - .filter(HeldPermission::getValue) + List> matchedGroups = plugin.getStorage().getGroupsWithPermission(constraint).join().stream() + .filter(n -> n.getNode().getValue()) .collect(Collectors.toList()); int users = matchedUsers.size(); @@ -123,50 +124,50 @@ public class GroupListMembers extends SubCommand { return CommandResult.SUCCESS; } - private static > void sendResult(Sender sender, List> results, Function lookupFunction, Message headerMessage, HolderType holderType, String label, int page) { + private static > void sendResult(Sender sender, List> results, Function lookupFunction, Message headerMessage, HolderType holderType, String label, int page) { results = new ArrayList<>(results); results.sort(HeldPermissionComparator.normal()); int pageIndex = page - 1; - List>> pages = Iterators.divideIterable(results, 15); + List>> pages = Iterators.divideIterable(results, 15); if (pageIndex < 0 || pageIndex >= pages.size()) { page = 1; pageIndex = 0; } - List> content = pages.get(pageIndex); + List> content = pages.get(pageIndex); - List>> mappedContent = content.stream() + List>> mappedContent = content.stream() .map(hp -> Maps.immutableEntry(lookupFunction.apply(hp.getHolder()), hp)) .collect(Collectors.toList()); // send header headerMessage.send(sender, page, pages.size(), results.size()); - for (Map.Entry> ent : mappedContent) { - String s = "&3> &b" + ent.getKey() + " " + getNodeExpiryString(ent.getValue().asNode()) + MessageUtils.getAppendableNodeContextString(sender.getPlugin().getLocaleManager(), ent.getValue().asNode()); + for (Map.Entry> ent : mappedContent) { + String s = "&3> &b" + ent.getKey() + " " + getNodeExpiryString(ent.getValue().getNode()) + MessageUtils.getAppendableNodeContextString(sender.getPlugin().getLocaleManager(), ent.getValue().getNode()); TextComponent message = TextUtils.fromLegacy(s, CommandManager.AMPERSAND_CHAR).toBuilder().applyDeep(makeFancy(ent.getKey(), holderType, label, ent.getValue(), sender.getPlugin())).build(); sender.sendMessage(message); } } private static String getNodeExpiryString(Node node) { - if (!node.isTemporary()) { + if (!node.hasExpiry()) { return ""; } - return " &8(&7expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime()) + "&8)"; + return " &8(&7expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond()) + "&8)"; } - private static Consumer> makeFancy(String holderName, HolderType holderType, String label, HeldPermission perm, LuckPermsPlugin plugin) { + private static Consumer> makeFancy(String holderName, HolderType holderType, String label, HeldNode perm, LuckPermsPlugin plugin) { HoverEvent hoverEvent = HoverEvent.showText(TextUtils.fromLegacy(TextUtils.joinNewline( - "&3> &b" + perm.asNode().getGroupName(), + "&3> &b" + ((InheritanceNode) perm.getNode()).getGroupName(), " ", "&7Click to remove this parent from " + holderName ), CommandManager.AMPERSAND_CHAR)); - String command = "/" + label + " " + NodeFactory.nodeAsCommand(perm.asNode(), holderName, holderType, false, !plugin.getConfiguration().getContextsFile().getDefaultContexts().isEmpty()); + String command = "/" + label + " " + NodeFactory.nodeAsCommand(perm.getNode(), holderName, holderType, false, !plugin.getConfiguration().getContextsFile().getDefaultContexts().isEmpty()); ClickEvent clickEvent = ClickEvent.suggestCommand(command); return component -> { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetDisplayName.java b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetDisplayName.java index bd66461f2..73239ae67 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetDisplayName.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetDisplayName.java @@ -26,7 +26,7 @@ package me.lucko.luckperms.common.commands.group; import me.lucko.luckperms.api.context.MutableContextSet; -import me.lucko.luckperms.api.nodetype.types.DisplayNameType; +import me.lucko.luckperms.api.node.types.DisplayNameNode; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -80,7 +80,7 @@ public class GroupSetDisplayName extends SubCommand { return CommandResult.STATE_ERROR; } - group.removeIf(context, n -> n.getTypeData(DisplayNameType.KEY).isPresent()); + group.removeIfEnduring(context, n -> n instanceof DisplayNameNode); if (name.equals(group.getName())) { Message.GROUP_SET_DISPLAY_NAME_REMOVED.send(sender, group.getName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); @@ -93,7 +93,7 @@ public class GroupSetDisplayName extends SubCommand { return CommandResult.SUCCESS; } - group.setPermission(NodeFactory.builder("displayname." + name).withExtraContext(context).build()); + group.setPermission(NodeFactory.builder(NodeFactory.displayName(name)).withContext(context).build()); Message.GROUP_SET_DISPLAY_NAME.send(sender, name, group.getName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context)); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetWeight.java b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetWeight.java index 6ef9e01e2..243d7dc5b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetWeight.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/group/GroupSetWeight.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.commands.group; -import me.lucko.luckperms.api.nodetype.types.WeightType; +import me.lucko.luckperms.api.node.types.WeightNode; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; @@ -59,7 +59,7 @@ public class GroupSetWeight extends SubCommand { int weight = ArgumentParser.parsePriority(0, args); - group.removeIf(n -> n.getTypeData(WeightType.KEY).isPresent()); + group.removeIfEnduring(n -> n instanceof WeightNode); group.setPermission(NodeFactory.buildWeightNode(weight).build()); Message.GROUP_SET_WEIGHT.send(sender, weight, group.getFormattedDisplayName()); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogNotify.java b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogNotify.java index 91acd2c5f..fe4f1a08b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/log/LogNotify.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/log/LogNotify.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.commands.log; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.actionlog.Log; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; @@ -57,8 +57,8 @@ public class LogNotify extends SubCommand { return false; } - Optional ret = user.enduringData().immutable().get(ContextSet.empty()).stream() - .filter(n -> n.getPermission().equalsIgnoreCase(IGNORE_NODE)) + Optional ret = user.enduringData().immutable().get(ImmutableContextSet.empty()).stream() + .filter(n -> n.getKey().equalsIgnoreCase(IGNORE_NODE)) .findFirst(); // if they don't have the perm, they're not ignoring @@ -77,7 +77,7 @@ public class LogNotify extends SubCommand { user.setPermission(NodeFactory.make(IGNORE_NODE)); } else { // remove the perm - user.removeIf(ContextSet.empty(), n -> n.getPermission().equalsIgnoreCase(IGNORE_NODE)); + user.removeIfEnduring(ImmutableContextSet.empty(), n -> n.getKey().equalsIgnoreCase(IGNORE_NODE)); } plugin.getStorage().saveUser(user).join(); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/migration/MigrationUtils.java b/common/src/main/java/me/lucko/luckperms/common/commands/migration/MigrationUtils.java index 210d529c5..25619ca6b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/migration/MigrationUtils.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/migration/MigrationUtils.java @@ -25,36 +25,36 @@ package me.lucko.luckperms.common.commands.migration; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.nodetype.types.WeightType; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.NodeType; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.node.factory.NodeFactory; public final class MigrationUtils { private MigrationUtils() {} - public static Node.Builder parseNode(String permission, boolean value) { + public static NodeBuilder parseNode(String permission, boolean value) { if (permission.startsWith("-") || permission.startsWith("!")) { if (permission.length() == 1) { - return NodeFactory.builder(permission).setValue(value); + return NodeFactory.builder(permission).value(value); } permission = permission.substring(1); value = false; } else if (permission.startsWith("+")) { if (permission.length() == 1) { - return NodeFactory.builder(permission).setValue(value); + return NodeFactory.builder(permission).value(value); } permission = permission.substring(1); value = true; } - return NodeFactory.builder(permission).setValue(value); + return NodeFactory.builder(permission).value(value); } public static void setGroupWeight(Group group, int weight) { - group.removeIf(n -> n.getTypeData(WeightType.KEY).isPresent()); + group.removeIfEnduring(NodeType.WEIGHT::matches); group.setPermission(NodeFactory.buildWeightNode(weight).build()); } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java index 75a552944..d6f2a0ff5 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/misc/ApplyEditsCommand.java @@ -30,7 +30,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SingleCommand; @@ -134,12 +134,12 @@ public class ApplyEditsCommand extends SingleCommand { for (Node n : diffAdded) { ExtendedLogEntry.build().actor(sender).acted(holder) - .action("webeditor", "add", n.getPermission(), n.getValue(), n.getFullContexts()) + .action("webeditor", "add", n.getKey(), n.getValue(), n.getContexts()) .build().submit(plugin, sender); } for (Node n : diffRemoved) { ExtendedLogEntry.build().actor(sender).acted(holder) - .action("webeditor", "remove", n.getPermission(), n.getValue(), n.getFullContexts()) + .action("webeditor", "remove", n.getKey(), n.getValue(), n.getContexts()) .build().submit(plugin, sender); } @@ -159,8 +159,8 @@ public class ApplyEditsCommand extends SingleCommand { } private static String formatNode(LocaleManager localeManager, Node n) { - return n.getPermission() + " &7(" + (n.getValue() ? "&a" : "&c") + n.getValue() + "&7)" + MessageUtils.getAppendableNodeContextString(localeManager, n) + - (n.isTemporary() ? " &7(" + DurationFormatter.CONCISE.formatDateDiff(n.getExpiryUnixTime()) + ")" : ""); + return n.getKey() + " &7(" + (n.getValue() ? "&a" : "&c") + n.getValue() + "&7)" + MessageUtils.getAppendableNodeContextString(localeManager, n) + + (n.hasExpiry() ? " &7(" + DurationFormatter.CONCISE.formatDateDiff(n.getExpiry().getEpochSecond()) + ")" : ""); } private static Map.Entry, Set> diff(Set before, Set after) { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/misc/CheckCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/misc/CheckCommand.java index 7248c7c4a..7db3f7fc6 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/misc/CheckCommand.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/misc/CheckCommand.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.commands.misc; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SingleCommand; import me.lucko.luckperms.common.command.access.CommandPermission; @@ -70,7 +70,7 @@ public class CheckCommand extends SingleCommand { return CommandResult.STATE_ERROR; } - Tristate tristate = user.getCachedData().getPermissionData(plugin.getContextForUser(user).orElse(plugin.getContextManager().getStaticContexts())).getPermissionValue(permission, PermissionCheckEvent.Origin.INTERNAL).result(); + Tristate tristate = user.getCachedData().getPermissionData(plugin.getQueryOptionsForUser(user).orElse(plugin.getContextManager().getStaticQueryOptions())).checkPermission(permission, PermissionCheckEvent.Origin.INTERNAL).result(); Message.CHECK_RESULT.send(sender, user.getFormattedDisplayName(), permission, MessageUtils.formatTristate(tristate)); return CommandResult.SUCCESS; } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/misc/DebugCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/misc/DebugCommand.java index 37194d2fe..eaa2e09c7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/misc/DebugCommand.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/misc/DebugCommand.java @@ -25,13 +25,12 @@ package me.lucko.luckperms.common.commands.misc; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LookupSetting; -import me.lucko.luckperms.api.caching.MetaContexts; import me.lucko.luckperms.api.context.ContextCalculator; import me.lucko.luckperms.api.context.StaticContextCalculator; import me.lucko.luckperms.api.metastacking.MetaStackDefinition; import me.lucko.luckperms.api.metastacking.MetaStackElement; +import me.lucko.luckperms.api.query.Flag; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.type.MetaCache; import me.lucko.luckperms.common.cacheddata.type.PermissionCache; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; @@ -59,9 +58,9 @@ import net.kyori.text.event.ClickEvent; import net.kyori.text.event.HoverEvent; import net.kyori.text.format.TextColor; -import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.function.BiConsumer; @@ -107,7 +106,7 @@ public class DebugCommand extends SingleCommand { return new JObject() .add("type", plugin.getBootstrap().getType().name()) .add("version", new JObject() - .add("api", String.valueOf(plugin.getApiProvider().getPlatformInfo().getApiVersion())) + .add("api", String.valueOf(plugin.getApiProvider().getPlatform().getApiVersion())) .add("plugin", plugin.getBootstrap().getVersion()) ) .add("server", new JObject() @@ -193,16 +192,15 @@ public class DebugCommand extends SingleCommand { ) .add("activeContext", () -> { JObject obj = new JObject(); - Contexts contexts = plugin.getContextForUser(user).orElse(null); - if (contexts != null) { - MetaContexts metaContexts = plugin.getContextManager().formMetaContexts(contexts); + QueryOptions queryOptions = plugin.getQueryOptionsForUser(user).orElse(null); + if (queryOptions != null) { obj.add("data", new JObject() - .add("permissions", serializePermissionsData(user.getCachedData().getPermissionData(contexts))) - .add("meta", serializeMetaData(user.getCachedData().getMetaData(metaContexts))) + .add("permissions", serializePermissionsData(user.getCachedData().getPermissionData(queryOptions))) + .add("meta", serializeMetaData(user.getCachedData().getMetaData(queryOptions))) ) - .add("contextSet", ContextSetJsonSerializer.serializeContextSet(contexts.getContexts())) - .add("settings", serializeContextsSettings(contexts)) - .add("metaSettings", serializeMetaContextsSettings(metaContexts)); + .add("contextSet", ContextSetJsonSerializer.serializeContextSet(queryOptions.context())) + .add("queryOptions", serializeQueryOptions(queryOptions)) + .add("metaSettings", serializeMetaContextsSettings(queryOptions)); } return obj; }) @@ -212,18 +210,24 @@ public class DebugCommand extends SingleCommand { return ret; } - private static JArray serializeContextsSettings(Contexts contexts) { + private static JArray serializeQueryOptions(QueryOptions queryOptions) { JArray array = new JArray(); - for (LookupSetting setting : contexts.getSettings()) { + for (Flag setting : queryOptions.flags()) { array.add(setting.name()); } return array; } - private static JObject serializeMetaContextsSettings(MetaContexts metaContexts) { + private static JObject serializeMetaContextsSettings(QueryOptions queryOptions) { return new JObject() - .add("prefixStack", serializeMetaStackData(metaContexts.getPrefixStackDefinition())) - .add("suffixStack", serializeMetaStackData(metaContexts.getSuffixStackDefinition())); + .consume(obj -> { + Optional prefixStack = queryOptions.option(MetaStackDefinition.PREFIX_STACK_KEY); + prefixStack.ifPresent(metaStackDefinition -> obj.add("prefixStack", serializeMetaStackData(metaStackDefinition))); + }) + .consume(obj -> { + Optional suffixStack = queryOptions.option(MetaStackDefinition.SUFFIX_STACK_KEY); + suffixStack.ifPresent(metaStackDefinition -> obj.add("suffixStack", serializeMetaStackData(metaStackDefinition))); + }); } private static JObject serializePermissionsData(PermissionCache permissionData) { @@ -262,15 +266,8 @@ public class DebugCommand extends SingleCommand { return suffixes; }) .add("meta", () -> { - JObject metaMap = new JObject(); - for (Map.Entry entry : metaData.getMeta(MetaCheckEvent.Origin.INTERNAL).entrySet()) { - metaMap.add(entry.getKey(), entry.getValue()); - } - return metaMap; - }) - .add("metaMap", () -> { JObject metaMultimap = new JObject(); - for (Map.Entry> entry : metaData.getMetaMultimap(MetaCheckEvent.Origin.INTERNAL).asMap().entrySet()) { + for (Map.Entry> entry : metaData.getMeta().entrySet()) { JArray values = new JArray(); for (String v : entry.getValue()) { values.add(v); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/misc/SearchCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/misc/SearchCommand.java index 8993175a8..ed0a8345f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/misc/SearchCommand.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/misc/SearchCommand.java @@ -27,8 +27,8 @@ package me.lucko.luckperms.common.commands.misc; import com.google.common.collect.Maps; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.HeldNode; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.bulkupdate.comparison.Comparison; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison; @@ -86,8 +86,8 @@ public class SearchCommand extends SingleCommand { Message.SEARCH_SEARCHING.send(sender, query); - List> matchedUsers = plugin.getStorage().getUsersWithPermission(query).join(); - List> matchedGroups = plugin.getStorage().getGroupsWithPermission(query).join(); + List> matchedUsers = plugin.getStorage().getUsersWithPermission(query).join(); + List> matchedGroups = plugin.getStorage().getGroupsWithPermission(query).join(); int users = matchedUsers.size(); int groups = matchedGroups.size(); @@ -127,56 +127,56 @@ public class SearchCommand extends SingleCommand { .complete(args); } - private static > void sendResult(Sender sender, List> results, Function lookupFunction, Message headerMessage, HolderType holderType, String label, int page, Comparison comparison) { + private static > void sendResult(Sender sender, List> results, Function lookupFunction, Message headerMessage, HolderType holderType, String label, int page, Comparison comparison) { results = new ArrayList<>(results); results.sort(HeldPermissionComparator.normal()); int pageIndex = page - 1; - List>> pages = Iterators.divideIterable(results, 15); + List>> pages = Iterators.divideIterable(results, 15); if (pageIndex < 0 || pageIndex >= pages.size()) { page = 1; pageIndex = 0; } - List> content = pages.get(pageIndex); + List> content = pages.get(pageIndex); - List>> mappedContent = content.stream() + List>> mappedContent = content.stream() .map(hp -> Maps.immutableEntry(lookupFunction.apply(hp.getHolder()), hp)) .collect(Collectors.toList()); // send header headerMessage.send(sender, page, pages.size(), results.size()); - for (Map.Entry> ent : mappedContent) { + for (Map.Entry> ent : mappedContent) { // only show the permission in the results if the comparison isn't equals String permission = ""; if (comparison != StandardComparison.EQUAL) { - permission = "&7 - (" + ent.getValue().getPermission() + ")"; + permission = "&7 - (" + ent.getValue().getNode().getKey() + ")"; } - String s = "&3> &b" + ent.getKey() + permission + "&7 - " + (ent.getValue().getValue() ? "&a" : "&c") + ent.getValue().getValue() + getNodeExpiryString(ent.getValue().asNode()) + MessageUtils.getAppendableNodeContextString(sender.getPlugin().getLocaleManager(), ent.getValue().asNode()); + String s = "&3> &b" + ent.getKey() + permission + "&7 - " + (ent.getValue().getNode().getValue() ? "&a" : "&c") + ent.getValue().getNode().getValue() + getNodeExpiryString(ent.getValue().getNode()) + MessageUtils.getAppendableNodeContextString(sender.getPlugin().getLocaleManager(), ent.getValue().getNode()); TextComponent message = TextUtils.fromLegacy(s, CommandManager.AMPERSAND_CHAR).toBuilder().applyDeep(makeFancy(ent.getKey(), holderType, label, ent.getValue(), sender.getPlugin())).build(); sender.sendMessage(message); } } private static String getNodeExpiryString(Node node) { - if (!node.isTemporary()) { + if (!node.hasExpiry()) { return ""; } - return " &8(&7expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime()) + "&8)"; + return " &8(&7expires in " + DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond()) + "&8)"; } - private static Consumer> makeFancy(String holderName, HolderType holderType, String label, HeldPermission perm, LuckPermsPlugin plugin) { + private static Consumer> makeFancy(String holderName, HolderType holderType, String label, HeldNode perm, LuckPermsPlugin plugin) { HoverEvent hoverEvent = HoverEvent.showText(TextUtils.fromLegacy(TextUtils.joinNewline( - "&3> " + (perm.asNode().getValue() ? "&a" : "&c") + perm.asNode().getPermission(), + "&3> " + (perm.getNode().getValue() ? "&a" : "&c") + perm.getNode().getKey(), " ", "&7Click to remove this node from " + holderName ), CommandManager.AMPERSAND_CHAR)); - String command = "/" + label + " " + NodeFactory.nodeAsCommand(perm.asNode(), holderName, holderType, false, !plugin.getConfiguration().getContextsFile().getDefaultContexts().isEmpty()); + String command = "/" + label + " " + NodeFactory.nodeAsCommand(perm.getNode(), holderName, holderType, false, !plugin.getConfiguration().getContextsFile().getDefaultContexts().isEmpty()); ClickEvent clickEvent = ClickEvent.suggestCommand(command); return component -> { diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/misc/TreeCommand.java b/common/src/main/java/me/lucko/luckperms/common/commands/misc/TreeCommand.java index c475c6392..57f432f20 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/misc/TreeCommand.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/misc/TreeCommand.java @@ -90,7 +90,7 @@ public class TreeCommand extends SingleCommand { } Message.TREE_UPLOAD_START.send(sender); - PermissionCache permissionData = user == null ? null : user.getCachedData().getPermissionData(plugin.getContextForUser(user).orElse(plugin.getContextManager().getStaticContexts())); + PermissionCache permissionData = user == null ? null : user.getCachedData().getPermissionData(plugin.getQueryOptionsForUser(user).orElse(plugin.getContextManager().getStaticQueryOptions())); String id = view.uploadPasteData(plugin.getBytebin(), sender, user, permissionData); String url = plugin.getConfiguration().get(ConfigKeys.TREE_VIEWER_URL_PATTERN) + "#" + id; diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/track/CreateTrack.java b/common/src/main/java/me/lucko/luckperms/common/commands/track/CreateTrack.java index 892ef0bb7..1a0a83307 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/track/CreateTrack.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/track/CreateTrack.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.commands.track; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; @@ -74,7 +74,7 @@ public class CreateTrack extends SingleCommand { Message.CREATE_SUCCESS.send(sender, trackName); - ExtendedLogEntry.build().actor(sender).actedName(trackName).type(LogEntry.Type.TRACK) + ExtendedLogEntry.build().actor(sender).actedName(trackName).type(Action.Type.TRACK) .action("create").build() .submit(plugin, sender); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/track/DeleteTrack.java b/common/src/main/java/me/lucko/luckperms/common/commands/track/DeleteTrack.java index 5d99de3c3..d43d60efa 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/track/DeleteTrack.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/track/DeleteTrack.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.commands.track; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.cause.DeletionCause; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; @@ -72,7 +72,7 @@ public class DeleteTrack extends SingleCommand { Message.DELETE_SUCCESS.send(sender, trackName); - ExtendedLogEntry.build().actor(sender).actedName(trackName).type(LogEntry.Type.TRACK) + ExtendedLogEntry.build().actor(sender).actedName(trackName).type(Action.Type.TRACK) .action("delete") .build().submit(plugin, sender); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackAppend.java b/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackAppend.java index 1420db303..dbbb41bfa 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackAppend.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackAppend.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.commands.track; -import me.lucko.luckperms.api.DataMutateResult; +import me.lucko.luckperms.api.model.DataMutateResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; @@ -66,7 +66,7 @@ public class TrackAppend extends SubCommand { DataMutateResult result = track.appendGroup(group); - if (result.asBoolean()) { + if (result.wasSuccessful()) { Message.TRACK_APPEND_SUCCESS.send(sender, group.getName(), track.getName()); if (track.getGroups().size() > 1) { Message.BLANK.send(sender, MessageUtils.listToArrowSep(track.getGroups(), group.getName())); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackInsert.java b/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackInsert.java index c9adf68e3..ef1f050aa 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackInsert.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackInsert.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.commands.track; -import me.lucko.luckperms.api.DataMutateResult; +import me.lucko.luckperms.api.model.DataMutateResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; @@ -75,7 +75,7 @@ public class TrackInsert extends SubCommand { try { DataMutateResult result = track.insertGroup(group, pos - 1); - if (result.asBoolean()) { + if (result.wasSuccessful()) { Message.TRACK_INSERT_SUCCESS.send(sender, group.getName(), track.getName(), pos); if (track.getGroups().size() > 1) { Message.BLANK.send(sender, MessageUtils.listToArrowSep(track.getGroups(), group.getName())); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackRemove.java b/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackRemove.java index 0a024c7cf..216e5731b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackRemove.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/track/TrackRemove.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.commands.track; -import me.lucko.luckperms.api.DataMutateResult; +import me.lucko.luckperms.api.model.DataMutateResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; @@ -60,7 +60,7 @@ public class TrackRemove extends SubCommand { DataMutateResult result = track.removeGroup(groupName); - if (result.asBoolean()) { + if (result.wasSuccessful()) { Message.TRACK_REMOVE_SUCCESS.send(sender, groupName, track.getName()); if (track.getGroups().size() > 1) { Message.BLANK.send(sender, MessageUtils.listToArrowSep(track.getGroups())); diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserDemote.java b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserDemote.java index 5ff0b2da4..9bf5f5228 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserDemote.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserDemote.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.commands.user; -import me.lucko.luckperms.api.DemotionResult; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.track.DemotionResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserInfo.java b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserInfo.java index 75742fbdb..9e2179693 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserInfo.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserInfo.java @@ -25,11 +25,12 @@ package me.lucko.luckperms.common.commands.user; -import com.google.common.collect.ListMultimap; +import com.google.common.collect.Maps; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.type.MetaCache; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.SubCommand; @@ -47,6 +48,7 @@ import me.lucko.luckperms.common.util.Predicates; import me.lucko.luckperms.common.verbose.event.MetaCheckEvent; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; public class UserInfo extends SubCommand { @@ -71,30 +73,28 @@ public class UserInfo extends SubCommand { user.getPrimaryGroup().getValue() ); - List parents = user.enduringData().asSortedSet().stream() - .filter(Node::isGroupNode) + List parents = user.enduringData().inheritanceAsSortedSet().stream() .filter(Node::getValue) - .filter(Node::isPermanent) + .filter(n -> !n.hasExpiry()) .collect(Collectors.toList()); - List tempParents = user.enduringData().asSortedSet().stream() - .filter(Node::isGroupNode) + List tempParents = user.enduringData().inheritanceAsSortedSet().stream() .filter(Node::getValue) - .filter(Node::isTemporary) + .filter(Node::hasExpiry) .collect(Collectors.toList()); if (!parents.isEmpty()) { Message.INFO_PARENT_HEADER.send(sender); - for (Node node : parents) { + for (InheritanceNode node : parents) { Message.INFO_PARENT_ENTRY.send(sender, node.getGroupName(), MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node)); } } if (!tempParents.isEmpty()) { Message.INFO_TEMP_PARENT_HEADER.send(sender); - for (Node node : tempParents) { + for (InheritanceNode node : tempParents) { Message.INFO_PARENT_ENTRY.send(sender, node.getGroupName(), MessageUtils.getAppendableNodeContextString(plugin.getLocaleManager(), node)); - Message.INFO_PARENT_ENTRY_EXPIRY.send(sender, DurationFormatter.LONG.formatDateDiff(node.getExpiryUnixTime())); + Message.INFO_PARENT_ENTRY_EXPIRY.send(sender, DurationFormatter.LONG.formatDateDiff(node.getExpiry().getEpochSecond())); } } @@ -102,16 +102,16 @@ public class UserInfo extends SubCommand { String prefix = "&bNone"; String suffix = "&bNone"; String meta = "&bNone"; - Contexts contexts = plugin.getContextForUser(user).orElse(null); - if (contexts != null) { - ContextSet contextSet = contexts.getContexts(); - if (!contextSet.isEmpty()) { + QueryOptions queryOptions = plugin.getQueryOptionsForUser(user).orElse(null); + if (queryOptions != null) { + ContextSet contextSet = queryOptions.context(); + if (contextSet != null && !contextSet.isEmpty()) { context = contextSet.toSet().stream() .map(e -> MessageUtils.contextToString(plugin.getLocaleManager(), e.getKey(), e.getValue())) .collect(Collectors.joining(" ")); } - MetaCache data = user.getCachedData().getMetaData(contexts); + MetaCache data = user.getCachedData().getMetaData(queryOptions); String prefixValue = data.getPrefix(MetaCheckEvent.Origin.INTERNAL); if (prefixValue != null) { prefix = "&f\"" + prefixValue + "&f\""; @@ -121,15 +121,16 @@ public class UserInfo extends SubCommand { suffix = "&f\"" + sussexValue + "&f\""; } - ListMultimap metaMap = data.getMetaMultimap(MetaCheckEvent.Origin.INTERNAL); + Map> metaMap = data.getMeta(); if (!metaMap.isEmpty()) { - meta = metaMap.entries().stream() + meta = metaMap.entrySet().stream() + .flatMap(entry -> entry.getValue().stream().map(value -> Maps.immutableEntry(entry.getKey(), value))) .map(e -> MessageUtils.contextToString(plugin.getLocaleManager(), e.getKey(), e.getValue())) .collect(Collectors.joining(" ")); } } - Message.USER_INFO_DATA.send(sender, MessageUtils.formatBoolean(contexts != null), context, prefix, suffix, meta); + Message.USER_INFO_DATA.send(sender, MessageUtils.formatBoolean(queryOptions != null), context, prefix, suffix, meta); return CommandResult.SUCCESS; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserPromote.java b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserPromote.java index 67f697670..9654469c2 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/user/UserPromote.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/user/UserPromote.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.commands.user; -import me.lucko.luckperms.api.PromotionResult; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.track.PromotionResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; diff --git a/common/src/main/java/me/lucko/luckperms/common/config/AbstractConfiguration.java b/common/src/main/java/me/lucko/luckperms/common/config/AbstractConfiguration.java index 25a1e4fb1..28b4c582d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/config/AbstractConfiguration.java +++ b/common/src/main/java/me/lucko/luckperms/common/config/AbstractConfiguration.java @@ -25,7 +25,6 @@ package me.lucko.luckperms.common.config; -import me.lucko.luckperms.common.api.implementation.ApiConfiguration; import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -47,8 +46,6 @@ public class AbstractConfiguration implements LuckPermsConfiguration { private final LuckPermsPlugin plugin; private final ConfigurationAdapter adapter; - // the api delegate - private final ApiConfiguration delegate = new ApiConfiguration(this); // the contextsfile handler private final ContextsFile contextsFile = new ContextsFile(this); @@ -104,11 +101,6 @@ public class AbstractConfiguration implements LuckPermsConfiguration { return this.plugin; } - @Override - public ApiConfiguration getDelegate() { - return this.delegate; - } - @Override public ContextsFile getContextsFile() { return this.contextsFile; diff --git a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java index bff4ff89f..92b96131c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java +++ b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java @@ -28,11 +28,12 @@ package me.lucko.luckperms.common.config; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.TemporaryMergeBehaviour; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.metastacking.DuplicateRemovalFunction; import me.lucko.luckperms.api.metastacking.MetaStackDefinition; +import me.lucko.luckperms.api.model.TemporaryMergeBehaviour; +import me.lucko.luckperms.api.query.Flag; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.command.utils.ArgumentParser; import me.lucko.luckperms.common.defaultassignments.AssignmentRule; import me.lucko.luckperms.common.graph.TraversalAlgorithm; @@ -52,9 +53,11 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.EnumMap; +import java.util.EnumSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Function; import static me.lucko.luckperms.common.config.ConfigKeyTypes.booleanKey; @@ -92,16 +95,21 @@ public final class ConfigKeys { /** * The default global contexts instance */ - public static final ConfigKey GLOBAL_CONTEXTS = customKey(c -> { - return Contexts.of( - ContextSet.empty(), - c.getBoolean("include-global", true), - c.getBoolean("include-global-world", true), - true, - c.getBoolean("apply-global-groups", true), - c.getBoolean("apply-global-world-groups", true), - false - ); + public static final ConfigKey GLOBAL_CONTEXTS = customKey(c -> { + Set flags = EnumSet.of(Flag.RESOLVE_INHERITANCE); + if (c.getBoolean("include-global", true)) { + flags.add(Flag.INCLUDE_NODES_WITHOUT_SERVER_CONTEXT); + } + if (c.getBoolean("include-global-world", true)) { + flags.add(Flag.INCLUDE_NODES_WITHOUT_WORLD_CONTEXT); + } + if (c.getBoolean("apply-global-groups", true)) { + flags.add(Flag.APPLY_INHERITANCE_NODES_WITHOUT_SERVER_CONTEXT); + } + if (c.getBoolean("apply-global-world-groups", true)) { + flags.add(Flag.APPLY_INHERITANCE_NODES_WITHOUT_WORLD_CONTEXT); + } + return QueryOptions.contextual(ImmutableContextSet.empty(), flags); }); /** diff --git a/common/src/main/java/me/lucko/luckperms/common/config/ContextsFile.java b/common/src/main/java/me/lucko/luckperms/common/config/ContextsFile.java index 1e08c2276..246a0b97b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/config/ContextsFile.java +++ b/common/src/main/java/me/lucko/luckperms/common/config/ContextsFile.java @@ -73,16 +73,16 @@ public class ContextsFile { JsonObject data = GsonProvider.normal().fromJson(reader, JsonObject.class); if (data.has("context")) { - this.staticContexts = ContextSetJsonSerializer.deserializeContextSet(data.get("context").getAsJsonObject()).makeImmutable(); + this.staticContexts = ContextSetJsonSerializer.deserializeContextSet(data.get("context").getAsJsonObject()).immutableCopy(); save = true; } if (data.has("static-contexts")) { - this.staticContexts = ContextSetJsonSerializer.deserializeContextSet(data.get("static-contexts").getAsJsonObject()).makeImmutable(); + this.staticContexts = ContextSetJsonSerializer.deserializeContextSet(data.get("static-contexts").getAsJsonObject()).immutableCopy(); } if (data.has("default-contexts")) { - this.defaultContexts = ContextSetJsonSerializer.deserializeContextSet(data.get("default-contexts").getAsJsonObject()).makeImmutable(); + this.defaultContexts = ContextSetJsonSerializer.deserializeContextSet(data.get("default-contexts").getAsJsonObject()).immutableCopy(); } } catch (IOException e) { diff --git a/common/src/main/java/me/lucko/luckperms/common/config/LuckPermsConfiguration.java b/common/src/main/java/me/lucko/luckperms/common/config/LuckPermsConfiguration.java index 4ede6fdc0..c72bd80f4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/config/LuckPermsConfiguration.java +++ b/common/src/main/java/me/lucko/luckperms/common/config/LuckPermsConfiguration.java @@ -25,7 +25,6 @@ package me.lucko.luckperms.common.config; -import me.lucko.luckperms.common.api.implementation.ApiConfiguration; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; /** @@ -33,13 +32,6 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin; */ public interface LuckPermsConfiguration { - /** - * Gets the API delegate for this class. - * - * @return the api delegate - */ - ApiConfiguration getDelegate(); - /** * Gets the main plugin instance. * diff --git a/common/src/main/java/me/lucko/luckperms/common/context/ContextManager.java b/common/src/main/java/me/lucko/luckperms/common/context/ContextManager.java index 1e770b2bf..779456b03 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/ContextManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/ContextManager.java @@ -27,12 +27,10 @@ package me.lucko.luckperms.common.context; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.caching.MetaContexts; import me.lucko.luckperms.api.context.ContextCalculator; import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.api.context.MutableContextSet; import me.lucko.luckperms.api.context.StaticContextCalculator; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cache.ExpiringCache; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -64,105 +62,44 @@ public abstract class ContextManager { this.subjectClass = subjectClass; } - /** - * Gets the calculators registered on the platform - * - * @return the registered calculators - */ public List> getCalculators() { return ImmutableList.copyOf(this.calculators); } - /** - * Gets the static calculators registered on the platform - * - * @return the registered static calculators - */ public List getStaticCalculators() { return ImmutableList.copyOf(this.staticCalculators); } - /** - * Gets the class of the subject handled by this instance - * - * @return the subject class - */ public Class getSubjectClass() { return this.subjectClass; } - /** - * Queries the ContextManager for current context values for the subject. - * - * @param subject the subject - * @return the applicable context for the subject - */ - public ImmutableContextSet getApplicableContext(T subject) { + public abstract QueryOptionsSupplier getCacheFor(T subject); + + public QueryOptions getQueryOptions(T subject) { + return getCacheFor(subject).getQueryOptions(); + } + + public ImmutableContextSet getContext(T subject) { return getCacheFor(subject).getContextSet(); } - /** - * Queries the ContextManager for current context values for the subject. - * - * @param subject the subject - * @return the applicable context for the subject - */ - public Contexts getApplicableContexts(T subject) { - return getCacheFor(subject).getContexts(); - } - - /** - * Gets the cache instance for the given subject. - * - * @param subject the subject - * @return the cache - */ - public abstract ContextsSupplier getCacheFor(T subject); - - /** - * Gets the contexts from the static calculators in this manager. - * - * @return the current active static contexts - */ - public ImmutableContextSet getStaticContext() { - // this is actually already immutable, but the Contexts method signature returns the interface. - // using the makeImmutable method is faster than casting - return getStaticContexts().getContexts().makeImmutable(); - } - - /** - * Gets the contexts from the static calculators in this manager. - * - * @return the current active static contexts - */ - public Contexts getStaticContexts() { + public QueryOptions getStaticQueryOptions() { return this.staticLookupCache.get(); } - /** - * Forms a {@link Contexts} instance from an {@link ImmutableContextSet}. - * - * @param contextSet the context set - * @return a contexts instance - */ - public Contexts formContexts(ImmutableContextSet contextSet) { - return this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_CONTEXTS).setContexts(contextSet); + public ImmutableContextSet getStaticContext() { + return getStaticQueryOptions().context(); } - /** - * Forms a "default" {@link MetaContexts} instance from {@link Contexts}. - * - * @param contexts the contexts - * @return a contexts instance - */ - public MetaContexts formMetaContexts(Contexts contexts) { - return new MetaContexts( - contexts, - this.plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS), - this.plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS) - ); + public QueryOptions formQueryOptions(ImmutableContextSet contextSet) { + return this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_CONTEXTS).toBuilder().context(contextSet).build(); } + public abstract QueryOptions formQueryOptions(T subject, ImmutableContextSet contextSet); + + public abstract void invalidateCache(T subject); + public void registerCalculator(ContextCalculator calculator) { // calculators registered first should have priority (and be checked last.) this.calculators.add(0, calculator); @@ -180,67 +117,43 @@ public abstract class ContextManager { } } - /** - * Invalidates the lookup cache for a given subject - * - * @param subject the subject - */ - public abstract void invalidateCache(T subject); - - protected Contexts calculate(T subject) { - MutableContextSet accumulator = MutableContextSet.create(); + protected QueryOptions calculate(T subject) { + ImmutableContextSet.Builder accumulator = ImmutableContextSet.builder(); for (ContextCalculator calculator : this.calculators) { try { - MutableContextSet ret = calculator.giveApplicableContext(subject, accumulator); - if (ret == null) { - throw new IllegalStateException(calculator.getClass() + " returned a null context set"); - } - accumulator = ret; + calculator.giveApplicableContext(subject, accumulator::add); } catch (Throwable e) { ContextManager.this.plugin.getLogger().warn("An exception was thrown by " + getCalculatorClass(calculator) + " whilst calculating the context of subject " + subject); e.printStackTrace(); } } - return formContexts(subject, accumulator.makeImmutable()); + return formQueryOptions(subject, accumulator.build()); } - Contexts calculateStatic() { - MutableContextSet accumulator = MutableContextSet.create(); + QueryOptions calculateStatic() { + ImmutableContextSet.Builder accumulator = ImmutableContextSet.builder(); for (StaticContextCalculator calculator : this.staticCalculators) { try { - MutableContextSet ret = calculator.giveApplicableContext(accumulator); - if (ret == null) { - throw new IllegalStateException(calculator.getClass() + " returned a null context set"); - } - accumulator = ret; + calculator.giveApplicableContext(accumulator::add); } catch (Throwable e) { this.plugin.getLogger().warn("An exception was thrown by " + getCalculatorClass(calculator) + " whilst calculating static contexts"); e.printStackTrace(); } } - return formContexts(accumulator.makeImmutable()); + return formQueryOptions(accumulator.build()); } - /** - * Forms a {@link Contexts} instance from an {@link ImmutableContextSet}. - * - * @param subject the subject - * @param contextSet the context set - * @return a contexts instance - */ - public abstract Contexts formContexts(T subject, ImmutableContextSet contextSet); - - private final class StaticLookupCache extends ExpiringCache { + private final class StaticLookupCache extends ExpiringCache { StaticLookupCache() { super(50L, TimeUnit.MILLISECONDS); } @Override - public @NonNull Contexts supply() { + public @NonNull QueryOptions supply() { return calculateStatic(); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/context/ContextSetComparator.java b/common/src/main/java/me/lucko/luckperms/common/context/ContextSetComparator.java index 492319180..14f0b9249 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/ContextSetComparator.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/ContextSetComparator.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.context; -import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.context.ImmutableContextSet; import java.util.ArrayList; @@ -53,12 +53,12 @@ public class ContextSetComparator implements Comparator { return 0; } - int result = Boolean.compare(o1.containsKey(Contexts.SERVER_KEY), o2.containsKey(Contexts.SERVER_KEY)); + int result = Boolean.compare(o1.containsKey(DefaultContextKeys.SERVER_KEY), o2.containsKey(DefaultContextKeys.SERVER_KEY)); if (result != 0) { return result; } - result = Boolean.compare(o1.containsKey(Contexts.WORLD_KEY), o2.containsKey(Contexts.WORLD_KEY)); + result = Boolean.compare(o1.containsKey(DefaultContextKeys.WORLD_KEY), o2.containsKey(DefaultContextKeys.WORLD_KEY)); if (result != 0) { return result; } diff --git a/common/src/main/java/me/lucko/luckperms/common/context/ContextSetConfigurateSerializer.java b/common/src/main/java/me/lucko/luckperms/common/context/ContextSetConfigurateSerializer.java index d510aa152..ee31395ae 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/ContextSetConfigurateSerializer.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/ContextSetConfigurateSerializer.java @@ -28,24 +28,25 @@ package me.lucko.luckperms.common.context; import com.google.common.base.Preconditions; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet; import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.SimpleConfigurationNode; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; public final class ContextSetConfigurateSerializer { private ContextSetConfigurateSerializer() {} public static ConfigurationNode serializeContextSet(ContextSet contextSet) { ConfigurationNode data = SimpleConfigurationNode.root(); - Map> map = contextSet.toMultimap().asMap(); + Map> map = contextSet.toMap(); - for (Map.Entry> entry : map.entrySet()) { + for (Map.Entry> entry : map.entrySet()) { List values = new ArrayList<>(entry.getValue()); int size = values.size(); @@ -64,7 +65,7 @@ public final class ContextSetConfigurateSerializer { Map dataMap = data.getChildrenMap(); if (dataMap.isEmpty()) { - return ContextSet.empty(); + return ImmutableContextSet.empty(); } MutableContextSet map = MutableContextSet.create(); diff --git a/common/src/main/java/me/lucko/luckperms/common/context/ContextSetJsonSerializer.java b/common/src/main/java/me/lucko/luckperms/common/context/ContextSetJsonSerializer.java index 9c6b312e2..66dce6ee6 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/ContextSetJsonSerializer.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/ContextSetJsonSerializer.java @@ -33,22 +33,23 @@ import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; public final class ContextSetJsonSerializer { private ContextSetJsonSerializer() {} public static JsonObject serializeContextSet(ContextSet contextSet) { JsonObject data = new JsonObject(); - Map> map = contextSet.toMultimap().asMap(); + Map> map = contextSet.toMap(); - for (Map.Entry> entry : map.entrySet()) { + for (Map.Entry> entry : map.entrySet()) { List values = new ArrayList<>(entry.getValue()); int size = values.size(); @@ -69,12 +70,12 @@ public final class ContextSetJsonSerializer { public static ContextSet deserializeContextSet(Gson gson, String json) { Objects.requireNonNull(json, "json"); if (json.equals("{}")) { - return ContextSet.empty(); + return ImmutableContextSet.empty(); } JsonObject context = gson.fromJson(json, JsonObject.class); if (context == null) { - return ContextSet.empty(); + return ImmutableContextSet.empty(); } return deserializeContextSet(context); @@ -85,7 +86,7 @@ public final class ContextSetJsonSerializer { JsonObject data = element.getAsJsonObject(); if (data.entrySet().isEmpty()) { - return ContextSet.empty(); + return ImmutableContextSet.empty(); } MutableContextSet map = MutableContextSet.create(); diff --git a/common/src/main/java/me/lucko/luckperms/common/context/LPStaticContextsCalculator.java b/common/src/main/java/me/lucko/luckperms/common/context/LPStaticContextsCalculator.java index 4d88ce9fd..0ba25bf23 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/LPStaticContextsCalculator.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/LPStaticContextsCalculator.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.context; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ContextConsumer; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.context.StaticContextCalculator; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.config.LuckPermsConfiguration; @@ -41,15 +41,12 @@ public class LPStaticContextsCalculator implements StaticContextCalculator { } @Override - public @NonNull MutableContextSet giveApplicableContext(@NonNull MutableContextSet accumulator) { + public void giveApplicableContext(@NonNull ContextConsumer consumer) { String server = this.config.get(ConfigKeys.SERVER); if (!server.equals("global")) { - accumulator.add(Contexts.SERVER_KEY, server); + consumer.accept(DefaultContextKeys.SERVER_KEY, server); } - - accumulator.addAll(this.config.getContextsFile().getStaticContexts()); - - return accumulator; + consumer.accept(this.config.getContextsFile().getStaticContexts()); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/context/ContextsCache.java b/common/src/main/java/me/lucko/luckperms/common/context/QueryOptionsCache.java similarity index 77% rename from common/src/main/java/me/lucko/luckperms/common/context/ContextsCache.java rename to common/src/main/java/me/lucko/luckperms/common/context/QueryOptionsCache.java index 844d635fc..d194b6cb8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/ContextsCache.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/QueryOptionsCache.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.context; -import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cache.ExpiringCache; import org.checkerframework.checker.nullness.qual.NonNull; @@ -34,34 +34,32 @@ import org.checkerframework.checker.nullness.qual.NonNull; import java.util.concurrent.TimeUnit; /** - * Implementation of {@link ContextsSupplier} that caches results. + * Implementation of {@link QueryOptionsSupplier} that caches results. * * @param the player type */ -public final class ContextsCache extends ExpiringCache implements ContextsSupplier { +public final class QueryOptionsCache extends ExpiringCache implements QueryOptionsSupplier { private final T subject; private final ContextManager contextManager; - public ContextsCache(T subject, ContextManager contextManager) { + public QueryOptionsCache(T subject, ContextManager contextManager) { super(50L, TimeUnit.MILLISECONDS); // expire roughly every tick this.subject = subject; this.contextManager = contextManager; } @Override - protected @NonNull Contexts supply() { + protected @NonNull QueryOptions supply() { return this.contextManager.calculate(this.subject); } @Override - public Contexts getContexts() { + public QueryOptions getQueryOptions() { return get(); } @Override public ImmutableContextSet getContextSet() { - // this is actually already immutable, but the Contexts method signature returns the interface. - // using the makeImmutable method is faster than casting - return get().getContexts().makeImmutable(); + return get().context(); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/context/ContextsSupplier.java b/common/src/main/java/me/lucko/luckperms/common/context/QueryOptionsSupplier.java similarity index 89% rename from common/src/main/java/me/lucko/luckperms/common/context/ContextsSupplier.java rename to common/src/main/java/me/lucko/luckperms/common/context/QueryOptionsSupplier.java index ce66baa9d..fb0649d6a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/context/ContextsSupplier.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/QueryOptionsSupplier.java @@ -25,18 +25,18 @@ package me.lucko.luckperms.common.context; -import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryOptions; /** * Supplies contexts for a given subject. */ -public interface ContextsSupplier { +public interface QueryOptionsSupplier { - Contexts getContexts(); + QueryOptions getQueryOptions(); default ImmutableContextSet getContextSet() { - return getContexts().getContexts().makeImmutable(); + return getQueryOptions().context(); } } diff --git a/api/src/main/java/me/lucko/luckperms/api/context/AbstractContextSet.java b/common/src/main/java/me/lucko/luckperms/common/context/contextset/AbstractContextSet.java similarity index 94% rename from api/src/main/java/me/lucko/luckperms/api/context/AbstractContextSet.java rename to common/src/main/java/me/lucko/luckperms/common/context/contextset/AbstractContextSet.java index b4ee598a0..60cab96da 100644 --- a/api/src/main/java/me/lucko/luckperms/api/context/AbstractContextSet.java +++ b/common/src/main/java/me/lucko/luckperms/common/context/contextset/AbstractContextSet.java @@ -23,11 +23,13 @@ * SOFTWARE. */ -package me.lucko.luckperms.api.context; +package me.lucko.luckperms.common.context.contextset; import com.google.common.collect.ImmutableSet; import com.google.common.collect.SetMultimap; +import me.lucko.luckperms.api.context.ContextSet; + import org.checkerframework.checker.nullness.qual.NonNull; import java.util.Collection; @@ -52,7 +54,7 @@ abstract class AbstractContextSet implements ContextSet { } @Override - public boolean has(@NonNull String key, @NonNull String value) { + public boolean contains(@NonNull String key, @NonNull String value) { return backing().containsEntry(sanitizeKey(key), sanitizeValue(value)); } diff --git a/common/src/main/java/me/lucko/luckperms/common/context/contextset/ImmutableContextSetImpl.java b/common/src/main/java/me/lucko/luckperms/common/context/contextset/ImmutableContextSetImpl.java new file mode 100644 index 000000000..9d1d25102 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/context/contextset/ImmutableContextSetImpl.java @@ -0,0 +1,205 @@ +/* + * 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.contextset; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.SetMultimap; + +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.context.MutableContextSet; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Iterator; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.Spliterator; + +public final class ImmutableContextSetImpl extends AbstractContextSet implements ImmutableContextSet { + public static final ImmutableContextSetImpl EMPTY = new ImmutableContextSetImpl(ImmutableSetMultimap.of()); + + public static ImmutableContextSet of(String key, String value) { + return new ImmutableContextSetImpl(ImmutableSetMultimap.of(sanitizeKey(key), sanitizeValue(value))); + } + + public static ImmutableContextSet of(String key1, String value1, String key2, String value2) { + return new ImmutableContextSetImpl(ImmutableSetMultimap.of( + sanitizeKey(key1), + sanitizeValue(value1), + sanitizeKey(key2), + sanitizeValue(value2) + )); + } + + private final ImmutableSetMultimap map; + private final int hashCode; + + ImmutableContextSetImpl(ImmutableSetMultimap contexts) { + this.map = contexts; + this.hashCode = this.map.hashCode(); + } + + @Override + protected SetMultimap backing() { + return this.map; + } + + @Override + protected void copyTo(SetMultimap other) { + other.putAll(this.map); + } + + @Override + public boolean isImmutable() { + return true; + } + + @Deprecated + @Override // This set is already immutable! + public @NonNull ImmutableContextSetImpl immutableCopy() { + return this; + } + + @Override + public @NonNull MutableContextSet mutableCopy() { + return new MutableContextSetImpl(this.map); + } + + @Override + public @NonNull Set> toSet() { + return this.map.entries(); + } + + @Override + public @NonNull Map> toMap() { + return Multimaps.asMap(this.map); + } + + @Deprecated + @Override + public @NonNull Map toFlattenedMap() { + ImmutableMap.Builder m = ImmutableMap.builder(); + for (Map.Entry e : this.map.entries()) { + m.put(e.getKey(), e.getValue()); + } + return m.build(); + } + + @Override + public @NonNull Iterator> iterator() { + return this.map.entries().iterator(); + } + + @Override + public Spliterator> spliterator() { + return this.map.entries().spliterator(); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof ContextSet)) return false; + final ContextSet that = (ContextSet) o; + + // fast(er) path for ImmutableContextSet comparisons + if (that instanceof ImmutableContextSetImpl) { + ImmutableContextSetImpl immutableThat = (ImmutableContextSetImpl) that; + if (this.hashCode != immutableThat.hashCode) return false; + } + + final Multimap thatBacking; + if (that instanceof AbstractContextSet) { + thatBacking = ((AbstractContextSet) that).backing(); + } else { + thatBacking = ImmutableSetMultimap.copyOf(that.toSet()); + } + + return backing().equals(thatBacking); + } + + @Override + public int hashCode() { + return this.hashCode; + } + + @Override + public String toString() { + return "ImmutableContextSet(contexts=" + this.map + ")"; + } + + public static final class BuilderImpl implements ImmutableContextSet.Builder { + private ImmutableSetMultimap.Builder builder; + + public BuilderImpl() { + + } + + private synchronized ImmutableSetMultimap.Builder builder() { + if (this.builder == null) { + this.builder = ImmutableSetMultimap.builder(); + } + return this.builder; + } + + private void put(String key, String value) { + builder().put(key, value); + } + + @Override + public @NonNull BuilderImpl add(@NonNull String key, @NonNull String value) { + put(sanitizeKey(key), sanitizeValue(value)); + return this; + } + + @Override + public @NonNull BuilderImpl addAll(@NonNull ContextSet contextSet) { + Objects.requireNonNull(contextSet, "contextSet"); + if (contextSet instanceof AbstractContextSet) { + AbstractContextSet other = ((AbstractContextSet) contextSet); + if (!other.isEmpty()) { + builder().putAll(other.backing()); + } + } else { + addAll(contextSet.toSet()); + } + return this; + } + + @Override + public @NonNull ImmutableContextSet build() { + if (this.builder == null) { + return EMPTY; + } else { + return new ImmutableContextSetImpl(this.builder.build()); + } + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/context/contextset/MutableContextSetImpl.java b/common/src/main/java/me/lucko/luckperms/common/context/contextset/MutableContextSetImpl.java new file mode 100644 index 000000000..8dd7a5f78 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/context/contextset/MutableContextSetImpl.java @@ -0,0 +1,187 @@ +/* + * 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.contextset; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.SetMultimap; + +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.context.MutableContextSet; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.Spliterator; + +public final class MutableContextSetImpl extends AbstractContextSet implements MutableContextSet { + private final SetMultimap map; + + public MutableContextSetImpl() { + this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create()); + } + + MutableContextSetImpl(SetMultimap other) { + this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create(other)); + } + + @Override + protected SetMultimap backing() { + return this.map; + } + + @Override + protected void copyTo(SetMultimap other) { + synchronized (this.map) { + other.putAll(this.map); + } + } + + @Override + public boolean isImmutable() { + return false; + } + + @Override + public @NonNull ImmutableContextSet immutableCopy() { + // if the map is empty, don't create a new instance + if (this.map.isEmpty()) { + return ImmutableContextSet.empty(); + } + synchronized (this.map) { + return new ImmutableContextSetImpl(ImmutableSetMultimap.copyOf(this.map)); + } + } + + @Override + public @NonNull MutableContextSetImpl mutableCopy() { + synchronized (this.map) { + return new MutableContextSetImpl(this.map); + } + } + + @Override + public @NonNull Set> toSet() { + // map.entries() returns immutable Map.Entry instances, so we can just call copyOf + return ImmutableSet.copyOf(this.map.entries()); + } + + @Override + public @NonNull Map> toMap() { + ImmutableMap.Builder> builder = ImmutableMap.builder(); + Map> map = this.map.asMap(); + synchronized (this.map) { + for (Map.Entry> e : map.entrySet()) { + builder.put(e.getKey(), ImmutableSet.copyOf(e.getValue())); + } + } + return builder.build(); + } + + @Deprecated + @Override + public @NonNull Map toFlattenedMap() { + ImmutableMap.Builder builder = ImmutableMap.builder(); + Set> entries = this.map.entries(); + synchronized (this.map) { + for (Map.Entry e : entries) { + builder.put(e.getKey(), e.getValue()); + } + } + return builder.build(); + } + + @Override + public @NonNull Iterator> iterator() { + return toSet().iterator(); + } + + @Override + public Spliterator> spliterator() { + return toSet().spliterator(); + } + + @Override + public void add(@NonNull String key, @NonNull String value) { + this.map.put(sanitizeKey(key), sanitizeValue(value)); + } + + @Override + public void addAll(@NonNull ContextSet contextSet) { + Objects.requireNonNull(contextSet, "contextSet"); + if (contextSet instanceof AbstractContextSet) { + AbstractContextSet other = ((AbstractContextSet) contextSet); + other.copyTo(this.map); + } else { + addAll(contextSet.toSet()); + } + } + + @Override + public void remove(@NonNull String key, @NonNull String value) { + this.map.remove(sanitizeKey(key), sanitizeValue(value)); + } + + @Override + public void removeAll(@NonNull String key) { + this.map.removeAll(sanitizeKey(key)); + } + + @Override + public void clear() { + this.map.clear(); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof ContextSet)) return false; + final ContextSet that = (ContextSet) o; + + final Multimap thatBacking; + if (that instanceof AbstractContextSet) { + thatBacking = ((AbstractContextSet) that).backing(); + } else { + thatBacking = ImmutableSetMultimap.copyOf(that.toSet()); + } + + return backing().equals(thatBacking); + } + + @Override + public String toString() { + return "MutableContextSet(contexts=" + this.map + ")"; + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/defaultassignments/AssignmentExpression.java b/common/src/main/java/me/lucko/luckperms/common/defaultassignments/AssignmentExpression.java index c0322f8ba..fc76e4156 100644 --- a/common/src/main/java/me/lucko/luckperms/common/defaultassignments/AssignmentExpression.java +++ b/common/src/main/java/me/lucko/luckperms/common/defaultassignments/AssignmentExpression.java @@ -27,12 +27,12 @@ package me.lucko.luckperms.common.defaultassignments; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.StandardNodeEquality; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.PermissionHolder; -import me.lucko.luckperms.common.node.factory.LegacyNodeFactory; +import me.lucko.luckperms.common.node.factory.NodeFactory; import me.lucko.luckperms.common.util.Scripting; import java.util.List; @@ -62,7 +62,7 @@ public class AssignmentExpression { throw new NullPointerException("script engine"); } - Predicate checker = node -> holder.hasPermission(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY) == tristate; + Predicate checker = node -> holder.hasPermission(NodeMapType.ENDURING, node, NodeEqualityPredicate.IGNORE_VALUE_OR_IF_TEMPORARY) == tristate; String exp = this.expression.stream().map(t -> t.forExpression(checker)).collect(Collectors.joining()) .replace("&", "&&").replace("|", "||"); @@ -140,7 +140,7 @@ public class AssignmentExpression { private PermissionToken(String permission) { this.permission = permission; - this.node = LegacyNodeFactory.fromLegacyString(permission, true); + this.node = NodeFactory.make(permission); } @Override diff --git a/common/src/main/java/me/lucko/luckperms/common/defaultassignments/AssignmentRule.java b/common/src/main/java/me/lucko/luckperms/common/defaultassignments/AssignmentRule.java index 39a3f2ebe..0bc3ccb49 100644 --- a/common/src/main/java/me/lucko/luckperms/common/defaultassignments/AssignmentRule.java +++ b/common/src/main/java/me/lucko/luckperms/common/defaultassignments/AssignmentRule.java @@ -25,10 +25,10 @@ package me.lucko.luckperms.common.defaultassignments; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.model.User; -import me.lucko.luckperms.common.node.factory.LegacyNodeFactory; +import me.lucko.luckperms.common.node.factory.NodeFactory; import me.lucko.luckperms.common.util.ImmutableCollectors; import java.util.List; @@ -46,8 +46,8 @@ public class AssignmentRule { this.hasTrueExpression = AssignmentExpression.compile(hasTrueExpression); this.hasFalseExpression = AssignmentExpression.compile(hasFalseExpression); this.lacksExpression = AssignmentExpression.compile(lacksExpression); - this.toGive = toGive.stream().map(s -> LegacyNodeFactory.fromLegacyString(s, true)).collect(ImmutableCollectors.toList()); - this.toTake = toTake.stream().map(s -> LegacyNodeFactory.fromLegacyString(s, true)).collect(ImmutableCollectors.toList()); + this.toGive = toGive.stream().map(s -> NodeFactory.make(s, true)).collect(ImmutableCollectors.toList()); + this.toTake = toTake.stream().map(s -> NodeFactory.make(s, true)).collect(ImmutableCollectors.toList()); this.setPrimaryGroup = setPrimaryGroup; } diff --git a/common/src/main/java/me/lucko/luckperms/common/dependencies/DependencyRegistry.java b/common/src/main/java/me/lucko/luckperms/common/dependencies/DependencyRegistry.java index fc7227e6a..a8914a32b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/dependencies/DependencyRegistry.java +++ b/common/src/main/java/me/lucko/luckperms/common/dependencies/DependencyRegistry.java @@ -29,7 +29,7 @@ import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ListMultimap; import com.google.gson.JsonElement; -import me.lucko.luckperms.api.platform.PlatformType; +import me.lucko.luckperms.api.platform.Platform; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.dependencies.relocation.Relocation; import me.lucko.luckperms.common.dependencies.relocation.RelocationHandler; @@ -88,7 +88,7 @@ public class DependencyRegistry { } public void applyRelocationSettings(Dependency dependency, List relocations) { - PlatformType type = this.plugin.getBootstrap().getType(); + Platform.Type type = this.plugin.getBootstrap().getType(); // support for LuckPerms legacy (bukkit 1.7.10) if (!RelocationHandler.DEPENDENCIES.contains(dependency) && JsonElement.class.getName().startsWith("me.lucko")) { @@ -97,7 +97,7 @@ public class DependencyRegistry { } // relocate yaml within configurate when running velocity - if (dependency == Dependency.CONFIGURATE_YAML && type == PlatformType.VELOCITY) { + if (dependency == Dependency.CONFIGURATE_YAML && type == Platform.Type.VELOCITY) { relocations.add(Relocation.of("yaml", "org{}yaml{}snakeyaml")); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java b/common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java index fc20f62f7..a8d5ee3f2 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/AbstractEventBus.java @@ -26,7 +26,7 @@ package me.lucko.luckperms.common.event; import me.lucko.luckperms.api.event.EventBus; -import me.lucko.luckperms.api.event.EventHandler; +import me.lucko.luckperms.api.event.EventSubscription; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -89,21 +89,21 @@ public abstract class AbstractEventBus

    implements EventBus, AutoCloseable { } @Override - public @NonNull EventHandler subscribe(@NonNull Class eventClass, @NonNull Consumer handler) { + public @NonNull EventSubscription subscribe(@NonNull Class eventClass, @NonNull Consumer handler) { Objects.requireNonNull(eventClass, "eventClass"); Objects.requireNonNull(handler, "handler"); return registerSubscription(eventClass, handler, null); } @Override - public @NonNull EventHandler subscribe(Object plugin, @NonNull Class eventClass, @NonNull Consumer handler) { + public @NonNull EventSubscription subscribe(Object plugin, @NonNull Class eventClass, @NonNull Consumer handler) { Objects.requireNonNull(plugin, "plugin"); Objects.requireNonNull(eventClass, "eventClass"); Objects.requireNonNull(handler, "handler"); return registerSubscription(eventClass, handler, checkPlugin(plugin)); } - private EventHandler registerSubscription(Class eventClass, Consumer handler, Object plugin) { + private EventSubscription registerSubscription(Class eventClass, Consumer handler, Object plugin) { if (!eventClass.isInterface()) { throw new IllegalArgumentException("class " + eventClass + " is not an interface"); } @@ -111,14 +111,14 @@ public abstract class AbstractEventBus

    implements EventBus, AutoCloseable { throw new IllegalArgumentException("class " + eventClass.getName() + " does not implement LuckPermsEvent"); } - LuckPermsEventHandler eventHandler = new LuckPermsEventHandler<>(this, eventClass, handler, plugin); + LuckPermsEventSubscription eventHandler = new LuckPermsEventSubscription<>(this, eventClass, handler, plugin); this.bus.register(eventClass, eventHandler); return eventHandler; } @Override - public @NonNull Set> getHandlers(@NonNull Class eventClass) { + public @NonNull Set> getSubscriptions(@NonNull Class eventClass) { return this.bus.getHandlers(eventClass); } @@ -127,7 +127,7 @@ public abstract class AbstractEventBus

    implements EventBus, AutoCloseable { * * @param handler the handler to remove */ - public void unregisterHandler(LuckPermsEventHandler handler) { + public void unregisterHandler(LuckPermsEventSubscription handler) { this.bus.unregister(handler); } @@ -137,7 +137,7 @@ public abstract class AbstractEventBus

    implements EventBus, AutoCloseable { * @param plugin the plugin */ protected void unregisterHandlers(P plugin) { - this.bus.unregister(sub -> ((LuckPermsEventHandler) sub).getPlugin() == plugin); + this.bus.unregister(sub -> ((LuckPermsEventSubscription) sub).getPlugin() == plugin); } @Override @@ -155,11 +155,11 @@ public abstract class AbstractEventBus

    implements EventBus, AutoCloseable { return true; } - public Set> getHandlers(Class eventClass) { + public Set> getHandlers(Class eventClass) { //noinspection unchecked return super.subscribers().values().stream() - .filter(s -> s instanceof EventHandler && ((EventHandler) s).getEventClass().isAssignableFrom(eventClass)) - .map(s -> ((EventHandler) s)) + .filter(s -> s instanceof EventSubscription && ((EventSubscription) s).getEventClass().isAssignableFrom(eventClass)) + .map(s -> ((EventSubscription) s)) .collect(Collectors.toSet()); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java b/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java index f70da34f8..f4ce782f2 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/EventFactory.java @@ -28,11 +28,7 @@ package me.lucko.luckperms.common.event; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import me.lucko.luckperms.api.LogEntry; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.PlayerSaveResult; -import me.lucko.luckperms.api.caching.GroupData; -import me.lucko.luckperms.api.caching.UserData; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.Cancellable; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.cause.CreationCause; @@ -71,11 +67,15 @@ import me.lucko.luckperms.api.event.user.UserFirstLoginEvent; import me.lucko.luckperms.api.event.user.UserLoadEvent; import me.lucko.luckperms.api.event.user.track.UserDemoteEvent; import me.lucko.luckperms.api.event.user.track.UserPromoteEvent; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.api.implementation.ApiPermissionHolder; import me.lucko.luckperms.common.api.implementation.ApiUser; +import me.lucko.luckperms.common.cacheddata.GroupCachedDataManager; +import me.lucko.luckperms.common.cacheddata.UserCachedDataManager; import me.lucko.luckperms.common.event.gen.GeneratedEventSpec; import me.lucko.luckperms.common.event.model.EntitySourceImpl; -import me.lucko.luckperms.common.event.model.SenderEntity; +import me.lucko.luckperms.common.event.model.SenderPlatformEntity; import me.lucko.luckperms.common.event.model.UnknownSource; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.HolderType; @@ -131,7 +131,7 @@ public final class EventFactory { return (T) GeneratedEventSpec.lookup(eventClass).newInstance(this.eventBus.getApiProvider(), params); } - public void handleGroupCacheLoad(Group group, GroupData data) { + public void handleGroupCacheLoad(Group group, GroupCachedDataManager data) { post(GroupCacheLoadEvent.class, () -> generate(GroupCacheLoadEvent.class, group.getApiDelegate(), data)); } @@ -151,7 +151,7 @@ public final class EventFactory { post(GroupLoadEvent.class, () -> generate(GroupLoadEvent.class, group.getApiDelegate())); } - public boolean handleLogBroadcast(boolean initialState, LogEntry entry, LogBroadcastEvent.Origin origin) { + public boolean handleLogBroadcast(boolean initialState, Action entry, LogBroadcastEvent.Origin origin) { if (!shouldPost(LogBroadcastEvent.class)) { return initialState; } @@ -161,7 +161,7 @@ public final class EventFactory { return cancel.get(); } - public boolean handleLogPublish(boolean initialState, LogEntry entry) { + public boolean handleLogPublish(boolean initialState, Action entry) { if (!shouldPost(LogPublishEvent.class)) { return initialState; } @@ -171,7 +171,7 @@ public final class EventFactory { return cancel.get(); } - public boolean handleLogNetworkPublish(boolean initialState, UUID id, LogEntry entry) { + public boolean handleLogNetworkPublish(boolean initialState, UUID id, Action entry) { if (!shouldPost(LogNetworkPublishEvent.class)) { return initialState; } @@ -181,17 +181,17 @@ public final class EventFactory { return cancel.get(); } - public boolean handleLogNotify(boolean initialState, LogEntry entry, LogNotifyEvent.Origin origin, Sender sender) { + public boolean handleLogNotify(boolean initialState, Action entry, LogNotifyEvent.Origin origin, Sender sender) { if (!shouldPost(LogNotifyEvent.class)) { return initialState; } AtomicBoolean cancel = new AtomicBoolean(initialState); - post(generate(LogNotifyEvent.class, cancel, entry, origin, new SenderEntity(sender))); + post(generate(LogNotifyEvent.class, cancel, entry, origin, new SenderPlatformEntity(sender))); return cancel.get(); } - public void handleLogReceive(UUID id, LogEntry entry) { + public void handleLogReceive(UUID id, Action entry) { post(LogReceiveEvent.class, () -> generate(LogReceiveEvent.class, id, entry)); } @@ -263,7 +263,7 @@ public final class EventFactory { post(TrackRemoveGroupEvent.class, () -> generate(TrackRemoveGroupEvent.class, track.getApiDelegate(), ImmutableList.copyOf(before), ImmutableList.copyOf(after), group)); } - public void handleUserCacheLoad(User user, UserData data) { + public void handleUserCacheLoad(User user, UserCachedDataManager data) { post(UserCacheLoadEvent.class, () -> generate(UserCacheLoadEvent.class, new ApiUser(user), data)); } @@ -299,14 +299,14 @@ public final class EventFactory { public void handleUserDemote(User user, Track track, String from, String to, @Nullable Sender source) { post(UserDemoteEvent.class, () -> { - Source s = source == null ? UnknownSource.INSTANCE : new EntitySourceImpl(new SenderEntity(source)); + Source s = source == null ? UnknownSource.INSTANCE : new EntitySourceImpl(new SenderPlatformEntity(source)); return generate(UserDemoteEvent.class, s, track.getApiDelegate(), new ApiUser(user), Optional.ofNullable(from), Optional.ofNullable(to)); }); } public void handleUserPromote(User user, Track track, String from, String to, @Nullable Sender source) { post(UserPromoteEvent.class, () -> { - Source s = source == null ? UnknownSource.INSTANCE : new EntitySourceImpl(new SenderEntity(source)); + Source s = source == null ? UnknownSource.INSTANCE : new EntitySourceImpl(new SenderPlatformEntity(source)); return generate(UserPromoteEvent.class, s, track.getApiDelegate(), new ApiUser(user), Optional.ofNullable(from), Optional.ofNullable(to)); }); } diff --git a/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventHandler.java b/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventSubscription.java similarity index 79% rename from common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventHandler.java rename to common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventSubscription.java index 6dd460e50..6e5dae65c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventHandler.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/LuckPermsEventSubscription.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.event; -import me.lucko.luckperms.api.event.EventHandler; +import me.lucko.luckperms.api.event.EventSubscription; import me.lucko.luckperms.api.event.LuckPermsEvent; import net.kyori.event.EventSubscriber; @@ -34,15 +34,14 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; /** - * Simple implementation of {@link EventHandler}. + * Simple implementation of {@link EventSubscription}. * * @param the event type */ -public class LuckPermsEventHandler implements EventHandler, EventSubscriber { +public class LuckPermsEventSubscription implements EventSubscription, EventSubscriber { /** * The event bus which created this handler @@ -69,12 +68,7 @@ public class LuckPermsEventHandler implements EventHan */ private final AtomicBoolean active = new AtomicBoolean(true); - /** - * How many times this handler has been called - */ - private final AtomicInteger callCount = new AtomicInteger(0); - - public LuckPermsEventHandler(AbstractEventBus eventBus, Class eventClass, Consumer consumer, @Nullable Object plugin) { + public LuckPermsEventSubscription(AbstractEventBus eventBus, Class eventClass, Consumer consumer, @Nullable Object plugin) { this.eventBus = eventBus; this.eventClass = eventClass; this.consumer = consumer; @@ -87,26 +81,19 @@ public class LuckPermsEventHandler implements EventHan } @Override - public boolean unregister() { + public void close() { // already unregistered if (!this.active.getAndSet(false)) { - return false; + return; } this.eventBus.unregisterHandler(this); - return true; - } - - @Override - public int getCallCount() { - return this.callCount.get(); } @Override public void invoke(@NonNull T event) throws Throwable { try { this.consumer.accept(event); - this.callCount.incrementAndGet(); } catch (Throwable t) { this.eventBus.getPlugin().getLogger().warn("Unable to pass event " + event.getEventType().getSimpleName() + " to handler " + this.consumer.getClass().getName()); t.printStackTrace(); @@ -119,7 +106,7 @@ public class LuckPermsEventHandler implements EventHan } @Override - public @NonNull Consumer getConsumer() { + public @NonNull Consumer getHandler() { return this.consumer; } diff --git a/common/src/main/java/me/lucko/luckperms/common/event/gen/GeneratedEventSpec.java b/common/src/main/java/me/lucko/luckperms/common/event/gen/GeneratedEventSpec.java index 1c1b8bf92..06990510c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/gen/GeneratedEventSpec.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/gen/GeneratedEventSpec.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.common.event.gen; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.LuckPerms; import me.lucko.luckperms.api.event.LuckPermsEvent; import me.lucko.luckperms.api.event.Param; import me.lucko.luckperms.common.cache.LoadingMap; @@ -51,14 +51,14 @@ public class GeneratedEventSpec { private static final Method TO_STRING_METHOD; private static final Method EQUALS_METHOD; private static final Method HASHCODE_METHOD; - private static final Method GET_API_METHOD; + private static final Method GET_LUCKPERMS_METHOD; private static final Method GET_EVENT_TYPE_METHOD; static { try { TO_STRING_METHOD = Object.class.getMethod("toString"); EQUALS_METHOD = Object.class.getMethod("equals", Object.class); HASHCODE_METHOD = Object.class.getMethod("hashCode"); - GET_API_METHOD = LuckPermsEvent.class.getMethod("getApi"); + GET_LUCKPERMS_METHOD = LuckPermsEvent.class.getMethod("getLuckPerms"); GET_EVENT_TYPE_METHOD = LuckPermsEvent.class.getMethod("getEventType"); } catch (NoSuchMethodException e) { throw new ExceptionInInitializerError(e); @@ -83,7 +83,7 @@ public class GeneratedEventSpec { if (method.isDefault()) { continue; } - if (GET_API_METHOD.equals(method) || GET_EVENT_TYPE_METHOD.equals(method)) { + if (GET_LUCKPERMS_METHOD.equals(method) || GET_EVENT_TYPE_METHOD.equals(method)) { continue; } @@ -97,7 +97,7 @@ public class GeneratedEventSpec { .collect(ImmutableCollectors.toList()); } - public LuckPermsEvent newInstance(LuckPermsApi api, Object... params) { + public LuckPermsEvent newInstance(LuckPerms api, Object... params) { if (params.length != this.methods.size()) { throw new IllegalStateException("param length differs from number of methods. expected " + this.methods.size() + " - " + this.methods); } @@ -118,10 +118,10 @@ public class GeneratedEventSpec { * An invocation handler bound to a set of parameters, used to implement the event as a proxy. */ private final class EventInvocationHandler implements InvocationHandler { - private final LuckPermsApi api; + private final LuckPerms api; private final Object[] fields; - EventInvocationHandler(LuckPermsApi api, Object[] fields) { + EventInvocationHandler(LuckPerms api, Object[] fields) { this.api = api; this.fields = fields; } @@ -140,7 +140,7 @@ public class GeneratedEventSpec { if (HASHCODE_METHOD.equals(method)) { return System.identityHashCode(proxy); } - if (GET_API_METHOD.equals(method)) { + if (GET_LUCKPERMS_METHOD.equals(method)) { return this.api; } if (GET_EVENT_TYPE_METHOD.equals(method)) { diff --git a/common/src/main/java/me/lucko/luckperms/common/event/model/EntitySourceImpl.java b/common/src/main/java/me/lucko/luckperms/common/event/model/EntitySourceImpl.java index 5c63b229c..515ca6af5 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/model/EntitySourceImpl.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/model/EntitySourceImpl.java @@ -25,20 +25,20 @@ package me.lucko.luckperms.common.event.model; -import me.lucko.luckperms.api.Entity; import me.lucko.luckperms.api.event.source.EntitySource; +import me.lucko.luckperms.api.platform.PlatformEntity; import org.checkerframework.checker.nullness.qual.NonNull; public class EntitySourceImpl implements EntitySource { - private final Entity entity; + private final PlatformEntity entity; - public EntitySourceImpl(Entity entity) { + public EntitySourceImpl(PlatformEntity entity) { this.entity = entity; } @Override - public @NonNull Entity getEntity() { + public @NonNull PlatformEntity getEntity() { return this.entity; } diff --git a/common/src/main/java/me/lucko/luckperms/common/event/model/SenderEntity.java b/common/src/main/java/me/lucko/luckperms/common/event/model/SenderPlatformEntity.java similarity index 92% rename from common/src/main/java/me/lucko/luckperms/common/event/model/SenderEntity.java rename to common/src/main/java/me/lucko/luckperms/common/event/model/SenderPlatformEntity.java index 12e826036..ddbbaa5eb 100644 --- a/common/src/main/java/me/lucko/luckperms/common/event/model/SenderEntity.java +++ b/common/src/main/java/me/lucko/luckperms/common/event/model/SenderPlatformEntity.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.event.model; -import me.lucko.luckperms.api.Entity; +import me.lucko.luckperms.api.platform.PlatformEntity; import me.lucko.luckperms.common.sender.Sender; import org.checkerframework.checker.nullness.qual.NonNull; @@ -33,10 +33,10 @@ import org.checkerframework.checker.nullness.qual.Nullable; import java.util.UUID; -public class SenderEntity implements Entity { +public class SenderPlatformEntity implements PlatformEntity { private final Sender sender; - public SenderEntity(Sender sender) { + public SenderPlatformEntity(Sender sender) { this.sender = sender; } diff --git a/common/src/main/java/me/lucko/luckperms/common/inheritance/InheritanceGraph.java b/common/src/main/java/me/lucko/luckperms/common/inheritance/InheritanceGraph.java index 92e64dbe9..edaaaaac8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/inheritance/InheritanceGraph.java +++ b/common/src/main/java/me/lucko/luckperms/common/inheritance/InheritanceGraph.java @@ -25,19 +25,58 @@ package me.lucko.luckperms.common.inheritance; +import me.lucko.luckperms.api.context.DefaultContextKeys; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.query.Flag; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.config.LuckPermsConfiguration; import me.lucko.luckperms.common.graph.Graph; import me.lucko.luckperms.common.graph.TraversalAlgorithm; +import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.PermissionHolder; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; /** * A {@link Graph} which represents an "inheritance tree". */ -public interface InheritanceGraph extends Graph { +public class InheritanceGraph implements Graph { + private final LuckPermsPlugin plugin; + + /** + * The contexts to resolve inheritance in. + */ + private final QueryOptions queryOptions; + + public InheritanceGraph(LuckPermsPlugin plugin, QueryOptions queryOptions) { + this.plugin = plugin; + this.queryOptions = queryOptions; + } + + @Override + public Iterable successors(PermissionHolder holder) { + Set successors = new LinkedHashSet<>(); + for (InheritanceNode n : holder.getOwnGroupNodes(this.queryOptions)) { + // effectively: if not (we're applying global groups or it's specific anyways) + if (!((this.queryOptions.flag(Flag.APPLY_INHERITANCE_NODES_WITHOUT_SERVER_CONTEXT) || n.getContexts().containsKey(DefaultContextKeys.SERVER_KEY)) && + (this.queryOptions.flag(Flag.APPLY_INHERITANCE_NODES_WITHOUT_WORLD_CONTEXT) || n.getContexts().containsKey(DefaultContextKeys.WORLD_KEY)))) { + continue; + } + + Group g = this.plugin.getGroupManager().getIfLoaded(n.getGroupName()); + if (g != null) { + successors.add(g); + } + } + + List successorsSorted = new ArrayList<>(successors); + successorsSorted.sort(holder.getInheritanceComparator()); + return successorsSorted; + } /** * Returns an iterable which will traverse this inheritance graph using the specified @@ -49,7 +88,7 @@ public interface InheritanceGraph extends Graph { * @param startNode the start node in the inheritance graph * @return an iterable */ - default Iterable traverse(TraversalAlgorithm algorithm, boolean postTraversalSort, PermissionHolder startNode) { + public Iterable traverse(TraversalAlgorithm algorithm, boolean postTraversalSort, PermissionHolder startNode) { Iterable traversal = traverse(algorithm, startNode); // perform post traversal sort if needed @@ -69,14 +108,13 @@ public interface InheritanceGraph extends Graph { /** * Perform a traversal according to the rules defined in the configuration. * - * @param configuration the configuration object * @param startNode the start node in the inheritance graph * @return an iterable */ - default Iterable traverse(LuckPermsConfiguration configuration, PermissionHolder startNode) { + public Iterable traverse(PermissionHolder startNode) { return traverse( - configuration.get(ConfigKeys.INHERITANCE_TRAVERSAL_ALGORITHM), - configuration.get(ConfigKeys.POST_TRAVERSAL_INHERITANCE_SORT), + this.plugin.getConfiguration().get(ConfigKeys.INHERITANCE_TRAVERSAL_ALGORITHM), + this.plugin.getConfiguration().get(ConfigKeys.POST_TRAVERSAL_INHERITANCE_SORT), startNode ); } diff --git a/common/src/main/java/me/lucko/luckperms/common/inheritance/InheritanceHandler.java b/common/src/main/java/me/lucko/luckperms/common/inheritance/InheritanceHandler.java index b0c358345..92218931d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/inheritance/InheritanceHandler.java +++ b/common/src/main/java/me/lucko/luckperms/common/inheritance/InheritanceHandler.java @@ -25,109 +25,34 @@ package me.lucko.luckperms.common.inheritance; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LookupSetting; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.common.model.Group; -import me.lucko.luckperms.common.model.PermissionHolder; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - /** * Provides {@link InheritanceGraph}s. */ public class InheritanceHandler { private final LuckPermsPlugin plugin; - /** - * An inheritance graph which doesn't consider contexts - */ private final InheritanceGraph nonContextualGraph; - - // cached contextual graphs for common Contexts - private final InheritanceGraph globalContextualGraph; + private final InheritanceGraph defaultContextualGraph; public InheritanceHandler(LuckPermsPlugin plugin) { this.plugin = plugin; - this.nonContextualGraph = new NonContextualGraph(plugin); - this.globalContextualGraph = new ContextualGraph(plugin, Contexts.global()); + this.nonContextualGraph = new InheritanceGraph(plugin, QueryOptions.nonContextual()); + this.defaultContextualGraph = new InheritanceGraph(plugin, QueryOptions.defaultContextualOptions()); } - public InheritanceGraph getGraph() { - return this.nonContextualGraph; - } - - public InheritanceGraph getGraph(Contexts contexts) { - if (contexts == Contexts.allowAll()) { - throw new IllegalArgumentException("Contexts#allowAll passed to contextual #getGraph method"); - } - - if (contexts == Contexts.global()) { - return this.globalContextualGraph; + public InheritanceGraph getGraph(QueryOptions queryOptions) { + if (queryOptions == QueryOptions.nonContextual()) { + return this.nonContextualGraph; + } else if (queryOptions == QueryOptions.defaultContextualOptions()) { + return this.defaultContextualGraph; } else { - return new ContextualGraph(this.plugin, contexts); + return new InheritanceGraph(plugin, queryOptions); } } - private static final class NonContextualGraph implements InheritanceGraph { - private final LuckPermsPlugin plugin; - NonContextualGraph(LuckPermsPlugin plugin) { - this.plugin = plugin; - } - - @Override - public Iterable successors(PermissionHolder holder) { - Set successors = new LinkedHashSet<>(); - for (Node n : holder.getOwnGroupNodes()) { - Group g = this.plugin.getGroupManager().getIfLoaded(n.getGroupName()); - if (g != null) { - successors.add(g); - } - } - - List successorsSorted = new ArrayList<>(successors); - successorsSorted.sort(holder.getInheritanceComparator()); - return successorsSorted; - } - } - - private static final class ContextualGraph implements InheritanceGraph { - private final LuckPermsPlugin plugin; - - /** - * The contexts to resolve inheritance in. - */ - private final Contexts context; - - ContextualGraph(LuckPermsPlugin plugin, Contexts context) { - this.plugin = plugin; - this.context = context; - } - - @Override - public Iterable successors(PermissionHolder holder) { - Set successors = new LinkedHashSet<>(); - for (Node n : holder.getOwnGroupNodes(this.context.getContexts())) { - // effectively: if not (we're applying global groups or it's specific anyways) - if (!((this.context.hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER) || n.isServerSpecific()) && (this.context.hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD) || n.isWorldSpecific()))) { - continue; - } - - Group g = this.plugin.getGroupManager().getIfLoaded(n.getGroupName()); - if (g != null) { - successors.add(g); - } - } - - List successorsSorted = new ArrayList<>(successors); - successorsSorted.sort(holder.getInheritanceComparator()); - return successorsSorted; - } - } } diff --git a/common/src/main/java/me/lucko/luckperms/common/inheritance/ResolvedGroup.java b/common/src/main/java/me/lucko/luckperms/common/inheritance/ResolvedGroup.java index 6401dbfa9..a8509289e 100644 --- a/common/src/main/java/me/lucko/luckperms/common/inheritance/ResolvedGroup.java +++ b/common/src/main/java/me/lucko/luckperms/common/inheritance/ResolvedGroup.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.inheritance; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.model.Group; public final class ResolvedGroup { diff --git a/common/src/main/java/me/lucko/luckperms/common/messaging/InternalMessagingService.java b/common/src/main/java/me/lucko/luckperms/common/messaging/InternalMessagingService.java index f8e7559c8..6dcfa332d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/messaging/InternalMessagingService.java +++ b/common/src/main/java/me/lucko/luckperms/common/messaging/InternalMessagingService.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.messaging; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.messenger.Messenger; import me.lucko.luckperms.api.messenger.MessengerProvider; import me.lucko.luckperms.common.cache.BufferedRequest; @@ -74,6 +74,6 @@ public interface InternalMessagingService { * * @param logEntry the log entry */ - void pushLog(LogEntry logEntry); + void pushLog(Action logEntry); } diff --git a/common/src/main/java/me/lucko/luckperms/common/messaging/LuckPermsMessagingService.java b/common/src/main/java/me/lucko/luckperms/common/messaging/LuckPermsMessagingService.java index 8a38ced98..536c94d41 100644 --- a/common/src/main/java/me/lucko/luckperms/common/messaging/LuckPermsMessagingService.java +++ b/common/src/main/java/me/lucko/luckperms/common/messaging/LuckPermsMessagingService.java @@ -28,18 +28,18 @@ package me.lucko.luckperms.common.messaging; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.messenger.IncomingMessageConsumer; import me.lucko.luckperms.api.messenger.Messenger; import me.lucko.luckperms.api.messenger.MessengerProvider; import me.lucko.luckperms.api.messenger.message.Message; -import me.lucko.luckperms.api.messenger.message.type.LogMessage; +import me.lucko.luckperms.api.messenger.message.type.ActionLogMessage; import me.lucko.luckperms.api.messenger.message.type.UpdateMessage; import me.lucko.luckperms.api.messenger.message.type.UserUpdateMessage; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.cache.BufferedRequest; import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.messaging.message.LogMessageImpl; +import me.lucko.luckperms.common.messaging.message.ActionLogMessageImpl; import me.lucko.luckperms.common.messaging.message.UpdateMessageImpl; import me.lucko.luckperms.common.messaging.message.UserUpdateMessageImpl; import me.lucko.luckperms.common.model.User; @@ -126,7 +126,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco } @Override - public void pushLog(LogEntry logEntry) { + public void pushLog(Action logEntry) { this.plugin.getBootstrap().getScheduler().executeAsync(() -> { UUID requestId = generatePingId(); @@ -135,7 +135,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco } this.plugin.getLogger().info("[Messaging] Sending log with id: " + requestId); - this.messenger.sendOutgoingMessage(new LogMessageImpl(requestId, logEntry)); + this.messenger.sendOutgoingMessage(new ActionLogMessageImpl(requestId, logEntry)); }); } @@ -150,7 +150,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco // determine if the message can be handled by us boolean valid = message instanceof UpdateMessage || message instanceof UserUpdateMessage || - message instanceof LogMessage; + message instanceof ActionLogMessage; // instead of throwing an exception here, just return false // it means an instance of LP can gracefully handle messages it doesn't @@ -199,8 +199,8 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco case UserUpdateMessageImpl.TYPE: decoded = UserUpdateMessageImpl.decode(content, id); break; - case LogMessageImpl.TYPE: - decoded = LogMessageImpl.decode(content, id); + case ActionLogMessageImpl.TYPE: + decoded = ActionLogMessageImpl.decode(content, id); break; default: // gracefully return if we just don't recognise the type @@ -240,7 +240,7 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco } else if (message instanceof UserUpdateMessage) { UserUpdateMessage msg = (UserUpdateMessage) message; - User user = this.plugin.getUserManager().getIfLoaded(msg.getUser()); + User user = this.plugin.getUserManager().getIfLoaded(msg.getUserUniqueId()); if (user == null) { return; } @@ -252,11 +252,11 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco } this.plugin.getStorage().loadUser(user.getUuid(), null); - } else if (message instanceof LogMessage) { - LogMessage msg = (LogMessage) message; + } else if (message instanceof ActionLogMessage) { + ActionLogMessage msg = (ActionLogMessage) message; - this.plugin.getEventFactory().handleLogReceive(msg.getId(), msg.getLogEntry()); - this.plugin.getLogDispatcher().dispatchFromRemote((ExtendedLogEntry) msg.getLogEntry()); + this.plugin.getEventFactory().handleLogReceive(msg.getId(), msg.getAction()); + this.plugin.getLogDispatcher().dispatchFromRemote((ExtendedLogEntry) msg.getAction()); } else { throw new IllegalArgumentException("Unknown message type: " + message.getClass().getName()); } diff --git a/common/src/main/java/me/lucko/luckperms/common/messaging/message/LogMessageImpl.java b/common/src/main/java/me/lucko/luckperms/common/messaging/message/ActionLogMessageImpl.java similarity index 80% rename from common/src/main/java/me/lucko/luckperms/common/messaging/message/LogMessageImpl.java rename to common/src/main/java/me/lucko/luckperms/common/messaging/message/ActionLogMessageImpl.java index 35a75c2bf..3850ec322 100644 --- a/common/src/main/java/me/lucko/luckperms/common/messaging/message/LogMessageImpl.java +++ b/common/src/main/java/me/lucko/luckperms/common/messaging/message/ActionLogMessageImpl.java @@ -27,8 +27,8 @@ package me.lucko.luckperms.common.messaging.message; import com.google.gson.JsonElement; -import me.lucko.luckperms.api.LogEntry; -import me.lucko.luckperms.api.messenger.message.type.LogMessage; +import me.lucko.luckperms.api.actionlog.Action; +import me.lucko.luckperms.api.messenger.message.type.ActionLogMessage; import me.lucko.luckperms.common.actionlog.LogEntryJsonSerializer; import me.lucko.luckperms.common.messaging.LuckPermsMessagingService; @@ -37,26 +37,26 @@ import org.checkerframework.checker.nullness.qual.Nullable; import java.util.UUID; -public class LogMessageImpl extends AbstractMessage implements LogMessage { +public class ActionLogMessageImpl extends AbstractMessage implements ActionLogMessage { public static final String TYPE = "log"; - public static LogMessageImpl decode(@Nullable JsonElement content, UUID id) { + public static ActionLogMessageImpl decode(@Nullable JsonElement content, UUID id) { if (content == null) { throw new IllegalStateException("Missing content"); } - return new LogMessageImpl(id, LogEntryJsonSerializer.deserialize(content)); + return new ActionLogMessageImpl(id, LogEntryJsonSerializer.deserialize(content)); } - private final LogEntry logEntry; + private final Action logEntry; - public LogMessageImpl(UUID id, LogEntry logEntry) { + public ActionLogMessageImpl(UUID id, Action logEntry) { super(id); this.logEntry = logEntry; } @Override - public @NonNull LogEntry getLogEntry() { + public @NonNull Action getAction() { return this.logEntry; } diff --git a/common/src/main/java/me/lucko/luckperms/common/messaging/message/UserUpdateMessageImpl.java b/common/src/main/java/me/lucko/luckperms/common/messaging/message/UserUpdateMessageImpl.java index 07afa7151..fb5b9e575 100644 --- a/common/src/main/java/me/lucko/luckperms/common/messaging/message/UserUpdateMessageImpl.java +++ b/common/src/main/java/me/lucko/luckperms/common/messaging/message/UserUpdateMessageImpl.java @@ -62,7 +62,7 @@ public class UserUpdateMessageImpl extends AbstractMessage implements UserUpdate } @Override - public @NonNull UUID getUser() { + public @NonNull UUID getUserUniqueId() { return this.userUuid; } diff --git a/common/src/main/java/me/lucko/luckperms/common/metastacking/FluentMetaStackElement.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/FluentMetaStackElement.java index b1a2d38b9..74cc4741b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/metastacking/FluentMetaStackElement.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/FluentMetaStackElement.java @@ -28,9 +28,9 @@ package me.lucko.luckperms.common.metastacking; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.metastacking.MetaStackElement; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.types.ChatMetaNode; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -54,9 +54,9 @@ public final class FluentMetaStackElement implements MetaStackElement { } @Override - public boolean shouldAccumulate(@NonNull LocalizedNode node, @NonNull ChatMetaType type, Map.@Nullable Entry current) { + public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode node, @Nullable ChatMetaNode current) { for (MetaStackElement element : this.subElements) { - if (!element.shouldAccumulate(node, type, current)) { + if (!element.shouldAccumulate(type, node, current)) { return false; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStack.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStack.java index e61937d0d..2b1fe3590 100644 --- a/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStack.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStack.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.metastacking; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.metastacking.MetaStackDefinition; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.types.ChatMetaNode; /** * A live stack of {@link MetaStackEntry} instances, formed from a @@ -65,6 +65,6 @@ public interface MetaStack { * * @param node the node to accumulate */ - void accumulateToAll(LocalizedNode node); + void accumulateToAll(ChatMetaNode node); } diff --git a/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStackEntry.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStackEntry.java index 092b4f7e2..ad4e038eb 100644 --- a/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStackEntry.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStackEntry.java @@ -25,10 +25,9 @@ package me.lucko.luckperms.common.metastacking; -import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.metastacking.MetaStackElement; +import me.lucko.luckperms.api.node.types.ChatMetaNode; -import java.util.Map; import java.util.Optional; /** @@ -56,7 +55,7 @@ public interface MetaStackEntry { * * @return the entry */ - Optional> getCurrentValue(); + Optional> getCurrentValue(); /** * Accumulates a node to this entry @@ -64,6 +63,6 @@ public interface MetaStackEntry { * @param node the node to accumulate * @return if the node was accepted */ - boolean accumulateNode(LocalizedNode node); + boolean accumulateNode(ChatMetaNode node); } diff --git a/common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStack.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStack.java index 9118c8bc0..478aa98d0 100644 --- a/common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStack.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStack.java @@ -25,14 +25,13 @@ package me.lucko.luckperms.common.metastacking; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.metastacking.MetaStackDefinition; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.types.ChatMetaNode; import me.lucko.luckperms.common.util.ImmutableCollectors; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @@ -57,7 +56,7 @@ public final class SimpleMetaStack implements MetaStack { .map(MetaStackEntry::getCurrentValue) .filter(Optional::isPresent) .map(Optional::get) - .map(Map.Entry::getValue) + .map(ChatMetaNode::getMetaValue) .collect(Collectors.toCollection(LinkedList::new)); if (elements.isEmpty()) { @@ -80,7 +79,7 @@ public final class SimpleMetaStack implements MetaStack { } @Override - public void accumulateToAll(LocalizedNode node) { + public void accumulateToAll(ChatMetaNode node) { this.entries.forEach(e -> e.accumulateNode(node)); } diff --git a/common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStackEntry.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStackEntry.java index 65e4d03c7..895bc1011 100644 --- a/common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStackEntry.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStackEntry.java @@ -25,13 +25,12 @@ package me.lucko.luckperms.common.metastacking; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.metastacking.MetaStackElement; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.types.ChatMetaNode; import org.checkerframework.checker.nullness.qual.Nullable; -import java.util.Map; import java.util.Optional; final class SimpleMetaStackEntry implements MetaStackEntry { @@ -39,7 +38,7 @@ final class SimpleMetaStackEntry implements MetaStackEntry { private final MetaStackElement element; private final ChatMetaType type; - private Map.@Nullable Entry current = null; + private @Nullable ChatMetaNode current = null; public SimpleMetaStackEntry(MetaStack parentStack, MetaStackElement element, ChatMetaType type) { this.parentStack = parentStack; @@ -48,14 +47,14 @@ final class SimpleMetaStackEntry implements MetaStackEntry { } @Override - public Optional> getCurrentValue() { + public Optional> getCurrentValue() { return Optional.ofNullable(this.current); } @Override - public boolean accumulateNode(LocalizedNode node) { - if (this.element.shouldAccumulate(node, this.type, this.current)) { - this.current = this.type.getEntry(node); + public boolean accumulateNode(ChatMetaNode node) { + if (this.element.shouldAccumulate(this.type, node, this.current)) { + this.current = node; return true; } return false; diff --git a/common/src/main/java/me/lucko/luckperms/common/metastacking/StandardStackElements.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/StandardStackElements.java index b99a01fb5..9390b6d8f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/metastacking/StandardStackElements.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/StandardStackElements.java @@ -25,9 +25,10 @@ package me.lucko.luckperms.common.metastacking; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.metastacking.MetaStackElement; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.metadata.types.InheritanceOriginMetadata; +import me.lucko.luckperms.api.node.types.ChatMetaNode; import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.util.ImmutableCollectors; @@ -37,7 +38,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; -import java.util.Map; import java.util.Objects; /** @@ -93,11 +93,11 @@ public final class StandardStackElements { // utility functions, used in combination with FluentMetaStackElement for form full MetaStackElements - private static final MetaStackElement TYPE_CHECK = (node, type, current) -> type.matches(node); - private static final MetaStackElement HIGHEST_CHECK = (node, type, current) -> current == null || type.getEntry(node).getKey() > current.getKey(); - private static final MetaStackElement LOWEST_CHECK = (node, type, current) -> current == null || type.getEntry(node).getKey() < current.getKey(); - private static final MetaStackElement OWN_CHECK = (node, type, current) -> Uuids.fromString(node.getLocation()) != null; - private static final MetaStackElement INHERITED_CHECK = (node, type, current) -> Uuids.fromString(node.getLocation()) == null; + private static final MetaStackElement TYPE_CHECK = (type, node, current) -> type.nodeType().matches(node); + private static final MetaStackElement HIGHEST_CHECK = (type, node, current) -> current == null || node.getPriority() > current.getPriority(); + private static final MetaStackElement LOWEST_CHECK = (type, node, current) -> current == null || node.getPriority() < current.getPriority(); + private static final MetaStackElement OWN_CHECK = (type, node, current) -> Uuids.fromString(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()) != null; + private static final MetaStackElement INHERITED_CHECK = (type, node, current) -> Uuids.fromString(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()) == null; // implementations @@ -218,9 +218,9 @@ public final class StandardStackElements { } @Override - public boolean shouldAccumulate(@NonNull LocalizedNode node, @NonNull ChatMetaType type, Map.@Nullable Entry current) { + public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode node, @Nullable ChatMetaNode current) { Track t = this.plugin.getTrackManager().getIfLoaded(this.trackName); - return t != null && t.containsGroup(node.getLocation()); + return t != null && t.containsGroup(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()); } @Override @@ -247,9 +247,9 @@ public final class StandardStackElements { } @Override - public boolean shouldAccumulate(@NonNull LocalizedNode node, @NonNull ChatMetaType type, Map.@Nullable Entry current) { + public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode node, @Nullable ChatMetaNode current) { Track t = this.plugin.getTrackManager().getIfLoaded(this.trackName); - return t != null && !t.containsGroup(node.getLocation()); + return t != null && !t.containsGroup(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()); } @Override @@ -274,8 +274,8 @@ public final class StandardStackElements { } @Override - public boolean shouldAccumulate(@NonNull LocalizedNode node, @NonNull ChatMetaType type, Map.@Nullable Entry current) { - return this.groupName.equals(node.getLocation()); + public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode node, @Nullable ChatMetaNode current) { + return this.groupName.equals(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()); } @Override @@ -300,8 +300,8 @@ public final class StandardStackElements { } @Override - public boolean shouldAccumulate(@NonNull LocalizedNode node, @NonNull ChatMetaType type, Map.@Nullable Entry current) { - return !this.groupName.equals(node.getLocation()); + public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode node, @Nullable ChatMetaNode current) { + return !this.groupName.equals(node.metadata(InheritanceOriginMetadata.KEY).getOrigin()); } @Override diff --git a/common/src/main/java/me/lucko/luckperms/common/model/DemotionResults.java b/common/src/main/java/me/lucko/luckperms/common/model/DemotionResults.java index 0440e3084..6ab8746b5 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/DemotionResults.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/DemotionResults.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.model; -import me.lucko.luckperms.api.DemotionResult; +import me.lucko.luckperms.api.track.DemotionResult; import org.checkerframework.checker.nullness.qual.NonNull; diff --git a/common/src/main/java/me/lucko/luckperms/common/model/DisplayNameCache.java b/common/src/main/java/me/lucko/luckperms/common/model/DisplayNameCache.java index cdc661144..cd4db61d7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/DisplayNameCache.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/DisplayNameCache.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.model; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.nodetype.types.DisplayNameType; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.DisplayNameNode; import me.lucko.luckperms.common.cache.Cache; import me.lucko.luckperms.common.config.ConfigKeys; @@ -47,10 +47,10 @@ public class DisplayNameCache extends Cache> { @Override protected @NonNull Optional supply() { // query for a displayname node - for (Node n : this.group.getOwnNodes(this.group.getPlugin().getContextManager().getStaticContext())) { - Optional displayName = n.getTypeData(DisplayNameType.KEY); - if (displayName.isPresent()) { - return Optional.of(displayName.get().getDisplayName()); + for (Node n : this.group.getOwnNodes(this.group.getPlugin().getContextManager().getStaticQueryOptions())) { + if (n instanceof DisplayNameNode) { + DisplayNameNode displayNameNode = (DisplayNameNode) n; + return Optional.of(displayNameNode.getDisplayName()); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/model/Group.java b/common/src/main/java/me/lucko/luckperms/common/model/Group.java index 1fa827359..0e8e38952 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/Group.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/Group.java @@ -25,12 +25,12 @@ package me.lucko.luckperms.common.model; -import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.context.ContextSet; -import me.lucko.luckperms.api.nodetype.types.DisplayNameType; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.DisplayNameNode; import me.lucko.luckperms.common.api.implementation.ApiGroup; import me.lucko.luckperms.common.cache.Cache; -import me.lucko.luckperms.common.cacheddata.GroupCachedData; +import me.lucko.luckperms.common.cacheddata.GroupCachedDataManager; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import java.util.Optional; @@ -57,13 +57,13 @@ public class Group extends PermissionHolder implements Identifiable { /** * The groups data cache instance */ - private final GroupCachedData cachedData; + private final GroupCachedDataManager cachedData; public Group(String name, LuckPermsPlugin plugin) { super(plugin); this.name = name.toLowerCase(); - this.cachedData = new GroupCachedData(this); + this.cachedData = new GroupCachedDataManager(this); getPlugin().getEventFactory().handleGroupCacheLoad(this, this.cachedData); } @@ -115,10 +115,9 @@ public class Group extends PermissionHolder implements Identifiable { * @return the display name */ public Optional getDisplayName(ContextSet contextSet) { - for (Node n : getData(NodeMapType.ENDURING).immutable().get(contextSet.makeImmutable())) { - Optional displayName = n.getTypeData(DisplayNameType.KEY); - if (displayName.isPresent()) { - return Optional.of(displayName.get().getDisplayName()); + for (Node n : getData(NodeMapType.ENDURING).immutable().get(contextSet.immutableCopy())) { + if (n instanceof DisplayNameNode) { + return Optional.of(((DisplayNameNode) n).getDisplayName()); } } return Optional.empty(); @@ -129,7 +128,7 @@ public class Group extends PermissionHolder implements Identifiable { } @Override - public GroupCachedData getCachedData() { + public GroupCachedDataManager getCachedData() { return this.cachedData; } diff --git a/common/src/main/java/me/lucko/luckperms/common/model/NodeMap.java b/common/src/main/java/me/lucko/luckperms/common/model/NodeMap.java index ad69b9659..5dc22ca2f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/NodeMap.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/NodeMap.java @@ -30,29 +30,30 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.Multimap; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.StandardNodeEquality; import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; +import me.lucko.luckperms.api.node.metadata.types.InheritanceOriginMetadata; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cache.Cache; import me.lucko.luckperms.common.context.ContextSetComparator; import me.lucko.luckperms.common.node.comparator.NodeComparator; import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator; -import me.lucko.luckperms.common.node.model.ImmutableLocalizedNode; +import me.lucko.luckperms.common.node.model.InheritanceOrigin; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedHashSet; -import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; @@ -72,8 +73,8 @@ import java.util.function.Predicate; *

    Each holder has two of these maps, one for enduring and transient nodes.

    */ public final class NodeMap { - private static final Function> VALUE_SET_SUPPLIER = k -> new ConcurrentSkipListSet<>(NodeComparator.reverse()); - + private static final Function> VALUE_SET_SUPPLIER = k -> new ConcurrentSkipListSet<>(NodeComparator.reverse()); + private static final Function> INHERITANCE_VALUE_SET_SUPPLIER = k -> new ConcurrentSkipListSet<>(NodeComparator.reverse()); /** * The holder which this map is for */ @@ -82,18 +83,18 @@ public final class NodeMap { /** * The backing data map. * - *

    Nodes are mapped by the result of {@link Node#getFullContexts()}, and keys are sorted by the weight of the + *

    Nodes are mapped by the result of {@link Node#getContexts()}, and keys are sorted by the weight of the * ContextSet. ContextSets are ordered first by the presence of a server key, then by the presence of a world * key, and finally by the overall size of the set. Nodes are ordered according to the priority rules * defined in {@link NodeComparator}.

    */ - private final SortedMap> map = new ConcurrentSkipListMap<>(ContextSetComparator.reverse()); + private final SortedMap> map = new ConcurrentSkipListMap<>(ContextSetComparator.reverse()); /** * Copy of {@link #map} which only contains group nodes - * @see Node#isGroupNode() + * @see InheritanceNode */ - private final SortedMap> inheritanceMap = new ConcurrentSkipListMap<>(ContextSetComparator.reverse()); + private final SortedMap> inheritanceMap = new ConcurrentSkipListMap<>(ContextSetComparator.reverse()); /** * A cache which holds an immutable copy of the backing map @@ -104,47 +105,41 @@ public final class NodeMap { this.holder = holder; } - public List asList() { - List list = new ArrayList<>(); - copyTo(list); - return list; - } - - public LinkedHashSet asSet() { - LinkedHashSet set = new LinkedHashSet<>(); - copyTo(set); + public LinkedHashSet asSet() { + LinkedHashSet set = new LinkedHashSet<>(); + copyTo(set, QueryOptions.nonContextual()); return set; } - public SortedSet asSortedSet() { - SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse()); - copyTo(ret); + public SortedSet asSortedSet() { + SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse()); + copyTo(ret, QueryOptions.nonContextual()); return ret; } - public void copyTo(Collection collection) { - for (SortedSet nodes : this.map.values()) { - collection.addAll(nodes); - } + public LinkedHashSet inheritanceAsSet() { + LinkedHashSet set = new LinkedHashSet<>(); + copyInheritanceNodesTo(set, QueryOptions.nonContextual()); + return set; } - public void copyTo(Collection collection, ContextSet filter) { - for (Map.Entry> e : this.map.entrySet()) { - if (e.getKey().isSatisfiedBy(filter)) { + public SortedSet inheritanceAsSortedSet() { + SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse()); + copyInheritanceNodesTo(ret, QueryOptions.nonContextual()); + return ret; + } + + public void copyTo(Collection collection, QueryOptions filter) { + for (Map.Entry> e : this.map.entrySet()) { + if (filter.satisfies(e.getKey())) { collection.addAll(e.getValue()); } } } - public void copyGroupNodesTo(Collection collection) { - for (SortedSet nodes : this.inheritanceMap.values()) { - collection.addAll(nodes); - } - } - - public void copyGroupNodesTo(Collection collection, ContextSet filter) { - for (Map.Entry> e : this.inheritanceMap.entrySet()) { - if (e.getKey().isSatisfiedBy(filter)) { + public void copyInheritanceNodesTo(Collection collection, QueryOptions filter) { + for (Map.Entry> e : this.inheritanceMap.entrySet()) { + if (filter.satisfies(e.getKey())) { collection.addAll(e.getValue()); } } @@ -155,7 +150,7 @@ public final class NodeMap { * * @return an immutable copy */ - public ImmutableSetMultimap immutable() { + public ImmutableSetMultimap immutable() { return this.cache.get(); } @@ -166,64 +161,57 @@ public final class NodeMap { this.cache.invalidate(); } - private LocalizedNode localise(Node node) { - while (node instanceof LocalizedNode) { - LocalizedNode localizedNode = (LocalizedNode) node; - if (this.holder.getObjectName().equals(localizedNode.getLocation())) { - return localizedNode; - } else { - node = localizedNode.getNode(); - } + private Node localise(Node node) { + Optional metadata = node.getMetadata(InheritanceOriginMetadata.KEY); + if (metadata.map(InheritanceOriginMetadata::getOrigin).equals(Optional.of(this.holder.getObjectName()))) { + return node; } - // localise - return ImmutableLocalizedNode.of(node, this.holder.getObjectName()); + return node.toBuilder().withMetadata(InheritanceOriginMetadata.KEY, new InheritanceOrigin(this.holder.getObjectName())).build(); } void add(Node node) { - ImmutableContextSet context = node.getFullContexts().makeImmutable(); - LocalizedNode n = localise(node); + ImmutableContextSet context = node.getContexts(); + Node n = localise(node); - SortedSet nodesInContext = this.map.computeIfAbsent(context, VALUE_SET_SUPPLIER); - nodesInContext.removeIf(e -> e.equals(node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE)); + SortedSet nodesInContext = this.map.computeIfAbsent(context, VALUE_SET_SUPPLIER); + nodesInContext.removeIf(e -> e.equals(node, NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE)); nodesInContext.add(n); - if (node.isGroupNode()) { - SortedSet groupNodesInContext = this.inheritanceMap.computeIfAbsent(context, VALUE_SET_SUPPLIER); - groupNodesInContext.removeIf(e -> e.equals(node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE)); - if (node.getValue()) { - groupNodesInContext.add(n); + if (n instanceof InheritanceNode) { + SortedSet groupNodesInContext = this.inheritanceMap.computeIfAbsent(context, INHERITANCE_VALUE_SET_SUPPLIER); + groupNodesInContext.removeIf(e -> e.equals(node, NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE)); + if (n.getValue()) { + groupNodesInContext.add((InheritanceNode) n); } } } void remove(Node node) { - ImmutableContextSet context = node.getFullContexts().makeImmutable(); - SortedSet nodesInContext = this.map.get(context); + ImmutableContextSet context = node.getContexts(); + SortedSet nodesInContext = this.map.get(context); if (nodesInContext != null) { - nodesInContext.removeIf(e -> e.equals(node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE)); + nodesInContext.removeIf(e -> e.equals(node, NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE)); } - if (node.isGroupNode()) { - SortedSet groupNodesInContext = this.inheritanceMap.get(context); + if (node instanceof InheritanceNode) { + SortedSet groupNodesInContext = this.inheritanceMap.get(context); if (groupNodesInContext != null) { - groupNodesInContext.removeIf(e -> e.equals(node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE)); + groupNodesInContext.removeIf(e -> e.equals(node, NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE)); } } } private void removeExact(Node node) { - ImmutableContextSet context = node.getFullContexts().makeImmutable(); - SortedSet nodesInContext = this.map.get(context); + ImmutableContextSet context = node.getContexts(); + SortedSet nodesInContext = this.map.get(context); if (nodesInContext != null) { - //noinspection SuspiciousMethodCalls nodesInContext.remove(node); } - if (node.isGroupNode() && node.getValue()) { - SortedSet groupNodesInContext = this.inheritanceMap.get(context); + if (node instanceof InheritanceNode && node.getValue()) { + SortedSet groupNodesInContext = this.inheritanceMap.get(context); if (groupNodesInContext != null) { - //noinspection SuspiciousMethodCalls groupNodesInContext.remove(node); } } @@ -240,7 +228,7 @@ public final class NodeMap { } void clear(ContextSet contextSet) { - ImmutableContextSet context = contextSet.makeImmutable(); + ImmutableContextSet context = contextSet.immutableCopy(); this.map.remove(context); this.inheritanceMap.remove(context); } @@ -257,30 +245,30 @@ public final class NodeMap { setContent(multimap.values()); } - boolean removeIf(Predicate predicate) { + boolean removeIf(Predicate predicate) { boolean ret = false; - for (SortedSet valueSet : this.map.values()) { + for (SortedSet valueSet : this.map.values()) { if (valueSet.removeIf(predicate)) { ret = true; } } - for (SortedSet valueSet : this.inheritanceMap.values()) { + for (SortedSet valueSet : this.inheritanceMap.values()) { valueSet.removeIf(predicate); } return ret; } - boolean removeIf(ContextSet contextSet, Predicate predicate) { - ImmutableContextSet context = contextSet.makeImmutable(); + boolean removeIf(ContextSet contextSet, Predicate predicate) { + ImmutableContextSet context = contextSet.immutableCopy(); boolean ret = false; - SortedSet nodesInContext = this.map.get(context); + SortedSet nodesInContext = this.map.get(context); if (nodesInContext != null) { ret = nodesInContext.removeIf(predicate); } - SortedSet groupNodesInContext = this.inheritanceMap.get(context); + SortedSet groupNodesInContext = this.inheritanceMap.get(context); if (groupNodesInContext != null) { groupNodesInContext.removeIf(predicate); } @@ -288,13 +276,13 @@ public final class NodeMap { return ret; } - boolean auditTemporaryNodes(@Nullable Set removed) { + boolean auditTemporaryNodes(@Nullable Set removed) { boolean work = false; - for (SortedSet valueSet : this.map.values()) { - Iterator it = valueSet.iterator(); + for (SortedSet valueSet : this.map.values()) { + Iterator it = valueSet.iterator(); while (it.hasNext()) { - LocalizedNode entry = it.next(); + Node entry = it.next(); if (!entry.hasExpired()) { continue; } @@ -303,8 +291,8 @@ public final class NodeMap { if (removed != null) { removed.add(entry); } - if (entry.isGroupNode() && entry.getValue()) { - SortedSet groupNodesInContext = this.inheritanceMap.get(entry.getFullContexts().makeImmutable()); + if (entry instanceof InheritanceNode && entry.getValue()) { + SortedSet groupNodesInContext = this.inheritanceMap.get(entry.getContexts()); if (groupNodesInContext != null) { groupNodesInContext.remove(entry); } @@ -317,7 +305,7 @@ public final class NodeMap { return work; } - private static final class NodeMapCache extends Cache> { + private static final class NodeMapCache extends Cache> { private static final Constructor IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR; static { try { @@ -335,13 +323,13 @@ public final class NodeMap { } @Override - protected @NonNull ImmutableSetMultimap supply() { - ImmutableMap.Builder> builder = ImmutableMap.builder(); + protected @NonNull ImmutableSetMultimap supply() { + ImmutableMap.Builder> builder = ImmutableMap.builder(); int size = 0; - for (Map.Entry> entry : this.handle.map.entrySet()) { + for (Map.Entry> entry : this.handle.map.entrySet()) { ImmutableContextSet key = entry.getKey(); - ImmutableSet values = ImmutableSet.copyOf(entry.getValue()); + ImmutableSet values = ImmutableSet.copyOf(entry.getValue()); if (!values.isEmpty()) { builder.put(key, values); size += values.size(); diff --git a/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java b/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java index 319fc2531..fc0702a0f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java @@ -29,30 +29,33 @@ import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Multimap; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.DataMutateResult; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.LookupSetting; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.NodeEqualityPredicate; -import me.lucko.luckperms.api.StandardNodeEquality; -import me.lucko.luckperms.api.TemporaryDataMutateResult; -import me.lucko.luckperms.api.TemporaryMergeBehaviour; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.common.cacheddata.HolderCachedData; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.model.TemporaryDataMutateResult; +import me.lucko.luckperms.api.model.TemporaryMergeBehaviour; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; +import me.lucko.luckperms.api.node.NodeType; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.query.Flag; +import me.lucko.luckperms.api.query.QueryOptions; +import me.lucko.luckperms.common.cacheddata.HolderCachedDataManager; import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; import me.lucko.luckperms.common.inheritance.InheritanceComparator; import me.lucko.luckperms.common.inheritance.InheritanceGraph; import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator; import me.lucko.luckperms.common.node.utils.InheritanceInfo; -import me.lucko.luckperms.common.node.utils.MetaType; import me.lucko.luckperms.common.node.utils.NodeTools; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import org.checkerframework.checker.nullness.qual.NonNull; +import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; @@ -202,7 +205,7 @@ public abstract class PermissionHolder { * * @return the holders cached data */ - public abstract HolderCachedData getCachedData(); + public abstract HolderCachedDataManager getCachedData(); /** * Returns the type of this PermissionHolder. @@ -229,46 +232,39 @@ public abstract class PermissionHolder { invalidateCache(); } - public List getOwnNodes() { - List ret = new ArrayList<>(); - this.transientNodes.copyTo(ret); - this.enduringNodes.copyTo(ret); + public List getOwnNodes() { + List ret = new ArrayList<>(); + this.transientNodes.copyTo(ret, QueryOptions.nonContextual()); + this.enduringNodes.copyTo(ret, QueryOptions.nonContextual()); return ret; } - public List getOwnNodes(ContextSet filter) { - List ret = new ArrayList<>(); - this.transientNodes.copyTo(ret, filter); - this.enduringNodes.copyTo(ret, filter); + public List getOwnNodes(QueryOptions queryOptions) { + List ret = new ArrayList<>(); + this.transientNodes.copyTo(ret, queryOptions); + this.enduringNodes.copyTo(ret, queryOptions); return ret; } - public List getOwnGroupNodes() { - List ret = new ArrayList<>(); - this.transientNodes.copyGroupNodesTo(ret); - this.enduringNodes.copyGroupNodesTo(ret); + public List getOwnGroupNodes(QueryOptions queryOptions) { + List ret = new ArrayList<>(); + this.transientNodes.copyInheritanceNodesTo(ret, queryOptions); + this.enduringNodes.copyInheritanceNodesTo(ret, queryOptions); return ret; } - public List getOwnGroupNodes(ContextSet filter) { - List ret = new ArrayList<>(); - this.transientNodes.copyGroupNodesTo(ret, filter); - this.enduringNodes.copyGroupNodesTo(ret, filter); + public SortedSet getOwnNodesSorted() { + SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse()); + this.transientNodes.copyTo(ret, QueryOptions.nonContextual()); + this.enduringNodes.copyTo(ret, QueryOptions.nonContextual()); return ret; } - public SortedSet getOwnNodesSorted() { - SortedSet ret = new TreeSet<>(NodeWithContextComparator.reverse()); - this.transientNodes.copyTo(ret); - this.enduringNodes.copyTo(ret); - return ret; + public boolean removeIfEnduring(Predicate predicate) { + return removeIfEnduring(predicate, null); } - public boolean removeIf(Predicate predicate) { - return removeIf(predicate, null); - } - - public boolean removeIf(Predicate predicate, Runnable taskIfSuccess) { + public boolean removeIfEnduring(Predicate predicate, Runnable taskIfSuccess) { ImmutableCollection before = enduringData().immutable().values(); if (!this.enduringNodes.removeIf(predicate)) { return false; @@ -283,11 +279,11 @@ public abstract class PermissionHolder { return true; } - public boolean removeIf(ContextSet contextSet, Predicate predicate) { - return removeIf(contextSet, predicate, null); + public boolean removeIfEnduring(ContextSet contextSet, Predicate predicate) { + return removeIfEnduring(contextSet, predicate, null); } - public boolean removeIf(ContextSet contextSet, Predicate predicate, Runnable taskIfSuccess) { + public boolean removeIfEnduring(ContextSet contextSet, Predicate predicate, Runnable taskIfSuccess) { ImmutableCollection before = enduringData().immutable().values(); if (!this.enduringNodes.removeIf(contextSet, predicate)) { return false; @@ -302,7 +298,7 @@ public abstract class PermissionHolder { return true; } - public boolean removeIfTransient(Predicate predicate) { + public boolean removeIfTransient(Predicate predicate) { boolean result = this.transientNodes.removeIf(predicate); if (result) { invalidateCache(); @@ -310,71 +306,59 @@ public abstract class PermissionHolder { return result; } - public void accumulateInheritancesTo(List accumulator, Contexts context) { - InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(context); - Iterable traversal = graph.traverse(this.plugin.getConfiguration(), this); + public boolean removeIfTransient(ContextSet contextSet, Predicate predicate) { + boolean result = this.transientNodes.removeIf(contextSet, predicate); + if (result) { + invalidateCache(); + } + return result; + } + + public void accumulateInheritancesTo(List accumulator, QueryOptions queryOptions) { + InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(queryOptions); + Iterable traversal = graph.traverse(this); for (PermissionHolder holder : traversal) { - List nodes = holder.getOwnNodes(context.getContexts()); + List nodes = holder.getOwnNodes(queryOptions); accumulator.addAll(nodes); } } - public List resolveInheritances(Contexts context) { - List accumulator = new ArrayList<>(); - accumulateInheritancesTo(accumulator, context); + public List resolveInheritances(QueryOptions queryOptions) { + List accumulator = new ArrayList<>(); + accumulateInheritancesTo(accumulator, queryOptions); return accumulator; } - public void accumulateInheritancesTo(List accumulator) { - InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(); - Iterable traversal = graph.traverse(this.plugin.getConfiguration(), this); - for (PermissionHolder holder : traversal) { - List nodes = holder.getOwnNodes(); - accumulator.addAll(nodes); - } - } - - public List resolveInheritances() { - List accumulator = new ArrayList<>(); - accumulateInheritancesTo(accumulator); - return accumulator; - } - - public List getAllEntries(Contexts context) { - List entries = new LinkedList<>(); - if (context.hasSetting(LookupSetting.RESOLVE_INHERITANCE)) { - accumulateInheritancesTo(entries, context); + public List getAllEntries(QueryOptions queryOptions) { + List entries = new LinkedList<>(); + if (queryOptions.flag(Flag.RESOLVE_INHERITANCE)) { + accumulateInheritancesTo(entries, queryOptions); } else { - entries.addAll(getOwnNodes(context.getContexts())); + entries.addAll(getOwnNodes(queryOptions)); } - if (!context.hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER)) { - entries.removeIf(n -> !n.isGroupNode() && !n.isServerSpecific()); + if (!queryOptions.flag(Flag.INCLUDE_NODES_WITHOUT_SERVER_CONTEXT)) { + entries.removeIf(n -> !(n instanceof InheritanceNode) && !n.getContexts().containsKey(DefaultContextKeys.SERVER_KEY)); } - if (!context.hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD)) { - entries.removeIf(n -> !n.isGroupNode() && !n.isWorldSpecific()); + if (!queryOptions.flag(Flag.INCLUDE_NODES_WITHOUT_WORLD_CONTEXT)) { + entries.removeIf(n -> !(n instanceof InheritanceNode) && !n.getContexts().containsKey(DefaultContextKeys.WORLD_KEY)); } return entries; } - public Map exportPermissions(Contexts context, boolean convertToLowercase, boolean resolveShorthand) { - List entries = getAllEntries(context); + public Map exportPermissions(QueryOptions queryOptions, boolean convertToLowercase, boolean resolveShorthand) { + List entries = getAllEntries(queryOptions); return processExportedPermissions(entries, convertToLowercase, resolveShorthand); } - public Map exportPermissions(boolean convertToLowercase, boolean resolveShorthand) { - List entries = resolveInheritances(); - return processExportedPermissions(entries, convertToLowercase, resolveShorthand); - } - - private static ImmutableMap processExportedPermissions(List entries, boolean convertToLowercase, boolean resolveShorthand) { + private static ImmutableMap processExportedPermissions(List entries, boolean convertToLowercase, boolean resolveShorthand) { Map perms = new HashMap<>(entries.size()); for (Node node : entries) { if (convertToLowercase) { - perms.putIfAbsent(node.getPermission().toLowerCase(), node.getValue()); + perms.putIfAbsent(node.getKey().toLowerCase(), node.getValue()); } else { - perms.putIfAbsent(node.getPermission(), node.getValue()); + perms.putIfAbsent(node.getKey(), node.getValue()); } } @@ -394,20 +378,22 @@ public abstract class PermissionHolder { return ImmutableMap.copyOf(perms); } - public MetaAccumulator accumulateMeta(MetaAccumulator accumulator, Contexts context) { + public MetaAccumulator accumulateMeta(MetaAccumulator accumulator, QueryOptions queryOptions) { if (accumulator == null) { accumulator = MetaAccumulator.makeFromConfig(this.plugin); } - InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(context); - Iterable traversal = graph.traverse(this.plugin.getConfiguration(), this); + InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(queryOptions); + Iterable traversal = graph.traverse(this); for (PermissionHolder holder : traversal) { - List nodes = holder.getOwnNodes(context.getContexts()); - for (LocalizedNode node : nodes) { + List nodes = holder.getOwnNodes(queryOptions); + for (Node node : nodes) { if (!node.getValue()) continue; - if (!node.isMeta() && !node.isPrefix() && !node.isSuffix()) continue; + if (!NodeType.META_OR_CHAT_META.matches(node)) continue; - if (!((context.hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER) || node.isServerSpecific()) && (context.hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD) || node.isWorldSpecific()))) { + // effectively: if not (we're applying global groups or it's specific anyways) + if (!((queryOptions.flag(Flag.APPLY_INHERITANCE_NODES_WITHOUT_SERVER_CONTEXT) || node.getContexts().containsKey(DefaultContextKeys.SERVER_KEY)) && + (queryOptions.flag(Flag.APPLY_INHERITANCE_NODES_WITHOUT_WORLD_CONTEXT) || node.getContexts().containsKey(DefaultContextKeys.WORLD_KEY)))) { continue; } @@ -423,31 +409,6 @@ public abstract class PermissionHolder { return accumulator; } - public MetaAccumulator accumulateMeta(MetaAccumulator accumulator) { - if (accumulator == null) { - accumulator = MetaAccumulator.makeFromConfig(this.plugin); - } - - InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(); - Iterable traversal = graph.traverse(this.plugin.getConfiguration(), this); - for (PermissionHolder holder : traversal) { - List nodes = holder.getOwnNodes(); - for (LocalizedNode node : nodes) { - if (!node.getValue()) continue; - if (!node.isMeta() && !node.isPrefix() && !node.isSuffix()) continue; - - accumulator.accumulateNode(node); - } - - OptionalInt w = getWeight(); - if (w.isPresent()) { - accumulator.accumulateWeight(w.getAsInt()); - } - } - - return accumulator; - } - /** * Removes temporary permissions that have expired * @@ -458,7 +419,7 @@ public abstract class PermissionHolder { // we don't call events for transient nodes boolean transientWork = this.transientNodes.auditTemporaryNodes(null); - ImmutableCollection before = enduringData().immutable().values(); + ImmutableCollection before = enduringData().immutable().values(); Set removed = new HashSet<>(); boolean enduringWork = this.enduringNodes.auditTemporaryNodes(removed); @@ -480,8 +441,8 @@ public abstract class PermissionHolder { return transientWork || enduringWork; } - private Optional searchForMatch(NodeMapType type, Node node, NodeEqualityPredicate equalityPredicate) { - for (LocalizedNode n : getData(type).immutable().values()) { + private Optional searchForMatch(NodeMapType type, Node node, NodeEqualityPredicate equalityPredicate) { + for (Node n : getData(type).immutable().values()) { if (n.equals(node, equalityPredicate)) { return Optional.of(n); } @@ -493,28 +454,28 @@ public abstract class PermissionHolder { * Check if the holder has a permission node * * @param type which backing map to check - * @param node the node to check + * @param node the Node to check * @param equalityPredicate how to match * @return a tristate, returns undefined if no match */ public Tristate hasPermission(NodeMapType type, Node node, NodeEqualityPredicate equalityPredicate) { - if (this.getType() == HolderType.GROUP && node.isGroupNode() && node.getGroupName().equalsIgnoreCase(getObjectName())) { + if (this.getType() == HolderType.GROUP && node instanceof InheritanceNode && ((InheritanceNode) node).getGroupName().equalsIgnoreCase(getObjectName())) { return Tristate.TRUE; } - return searchForMatch(type, node, equalityPredicate).map(Node::getTristate).orElse(Tristate.UNDEFINED); + return searchForMatch(type, node, equalityPredicate).map(n -> Tristate.of(n.getValue())).orElse(Tristate.UNDEFINED); } /** * Check if the holder inherits a node * - * @param node the node to check + * @param node the Node to check * @param equalityPredicate how to match * @return the result of the lookup */ public InheritanceInfo searchForInheritedMatch(Node node, NodeEqualityPredicate equalityPredicate) { - for (LocalizedNode n : resolveInheritances()) { - if (n.getNode().equals(node, equalityPredicate)) { + for (Node n : resolveInheritances(QueryOptions.nonContextual())) { + if (n.equals(node, equalityPredicate)) { return InheritanceInfo.of(n); } } @@ -531,7 +492,7 @@ public abstract class PermissionHolder { } public DataMutateResult setPermission(Node node, boolean callEvent) { - if (hasPermission(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_EXPIRY_TIME) != Tristate.UNDEFINED) { + if (hasPermission(NodeMapType.ENDURING, node, NodeEqualityPredicate.IGNORE_EXPIRY_TIME) != Tristate.UNDEFINED) { return DataMutateResult.ALREADY_HAS; } @@ -557,7 +518,7 @@ public abstract class PermissionHolder { } public DataMutateResult setTransientPermission(Node node) { - if (hasPermission(NodeMapType.TRANSIENT, node, StandardNodeEquality.IGNORE_EXPIRY_TIME) != Tristate.UNDEFINED) { + if (hasPermission(NodeMapType.TRANSIENT, node, NodeEqualityPredicate.IGNORE_EXPIRY_TIME) != Tristate.UNDEFINED) { return DataMutateResult.ALREADY_HAS; } @@ -578,12 +539,12 @@ public abstract class PermissionHolder { } private TemporaryDataMutateResult handleTemporaryMergeBehaviour(NodeMapType nodeMapType, Node node, TemporaryMergeBehaviour mergeBehaviour) { - // If the node is temporary, we should take note of the modifier - if (!node.isTemporary() || mergeBehaviour == TemporaryMergeBehaviour.FAIL_WITH_ALREADY_HAS) { + // If the Node is temporary, we should take note of the modifier + if (!node.hasExpiry() || mergeBehaviour == TemporaryMergeBehaviour.FAIL_WITH_ALREADY_HAS) { return null; } - Node previous = searchForMatch(nodeMapType, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE).orElse(null); + Node previous = searchForMatch(nodeMapType, node, NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE).orElse(null); if (previous == null) { return null; } @@ -593,10 +554,10 @@ public abstract class PermissionHolder { switch (mergeBehaviour) { case ADD_NEW_DURATION_TO_EXISTING: { - // Create a new node with the same properties, but add the expiry dates together - Node newNode = node.toBuilder().setExpiry(previous.getExpiryUnixTime() + node.getSecondsTilExpiry()).build(); + // Create a new Node with the same properties, but add the expiry dates together + Node newNode = node.toBuilder().expiry(previous.getExpiry().plus(Duration.between(Instant.now(), node.getExpiry())).getEpochSecond()).build(); - // Remove the old node & add the new one. + // Remove the old Node & add the new one. ImmutableCollection before = null; if (callEvents) { before = data.immutable().values(); @@ -614,7 +575,7 @@ public abstract class PermissionHolder { } case REPLACE_EXISTING_IF_DURATION_LONGER: { // Only replace if the new expiry time is greater than the old one. - if (node.getExpiryUnixTime() <= previous.getExpiryUnixTime()) { + if (node.getExpiry().getEpochSecond() <= previous.getExpiry().getEpochSecond()) { break; } @@ -640,7 +601,7 @@ public abstract class PermissionHolder { } public DataMutateResult unsetPermission(Node node) { - if (hasPermission(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE) == Tristate.UNDEFINED) { + if (hasPermission(NodeMapType.ENDURING, node, NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE) == Tristate.UNDEFINED) { return DataMutateResult.LACKS; } @@ -654,7 +615,7 @@ public abstract class PermissionHolder { } public DataMutateResult unsetTransientPermission(Node node) { - if (hasPermission(NodeMapType.TRANSIENT, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE) == Tristate.UNDEFINED) { + if (hasPermission(NodeMapType.TRANSIENT, node, NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE) == Tristate.UNDEFINED) { return DataMutateResult.LACKS; } @@ -667,7 +628,7 @@ public abstract class PermissionHolder { /** * Clear all of the holders permission nodes */ - public boolean clearNodes() { + public boolean clearEnduringNodes() { ImmutableCollection before = enduringData().immutable().values(); this.enduringNodes.clear(); invalidateCache(); @@ -681,7 +642,7 @@ public abstract class PermissionHolder { return true; } - public boolean clearNodes(ContextSet contextSet) { + public boolean clearEnduringNodes(ContextSet contextSet) { ImmutableCollection before = enduringData().immutable().values(); this.enduringNodes.clear(contextSet); invalidateCache(); @@ -695,44 +656,36 @@ public abstract class PermissionHolder { return true; } - public boolean clearPermissions() { - return removeIf(node -> !node.hasTypeData()); - } - - public boolean clearPermissions(ContextSet contextSet) { - return removeIf(contextSet, node -> !node.hasTypeData()); - } - - public boolean clearParents(boolean giveDefault) { - return removeIf(Node::isGroupNode, () -> { + public boolean clearEnduringParents(boolean giveDefault) { + return removeIfEnduring(n -> n instanceof InheritanceNode, () -> { if (this.getType() == HolderType.USER && giveDefault) { this.plugin.getUserManager().giveDefaultIfNeeded((User) this, false); } }); } - public boolean clearParents(ContextSet contextSet, boolean giveDefault) { - return removeIf(contextSet, Node::isGroupNode, () -> { + public boolean clearEnduringParents(ContextSet contextSet, boolean giveDefault) { + return removeIfEnduring(contextSet, n -> n instanceof InheritanceNode, () -> { if (this.getType() == HolderType.USER && giveDefault) { this.plugin.getUserManager().giveDefaultIfNeeded((User) this, false); } }); } - public boolean clearMeta(MetaType type) { - return removeIf(type::matches); + public boolean clearMeta(NodeType type) { + return removeIfEnduring(type::matches); } - public boolean clearMeta(MetaType type, ContextSet contextSet) { - return removeIf(contextSet, type::matches); + public boolean clearMeta(NodeType type, ContextSet contextSet) { + return removeIfEnduring(contextSet, type::matches); } public boolean clearMetaKeys(String key, boolean temp) { - return removeIf(n -> n.isMeta() && (n.isTemporary() == temp) && n.getMeta().getKey().equalsIgnoreCase(key)); + return removeIfEnduring(n -> n instanceof MetaNode && (n.hasExpiry() == temp) && ((MetaNode) n).getMetaKey().equalsIgnoreCase(key)); } public boolean clearMetaKeys(String key, ContextSet contextSet, boolean temp) { - return removeIf(contextSet, n -> n.isMeta() && (n.isTemporary() == temp) && n.getMeta().getKey().equalsIgnoreCase(key)); + return removeIfEnduring(contextSet, n -> n instanceof MetaNode && (n.hasExpiry() == temp) && ((MetaNode) n).getMetaKey().equalsIgnoreCase(key)); } public boolean clearTransientNodes() { @@ -741,6 +694,12 @@ public abstract class PermissionHolder { return true; } + public boolean clearTransientNodes(ContextSet contextSet) { + this.transientNodes.clear(); + invalidateCache(); + return true; + } + public OptionalInt getWeight() { return OptionalInt.empty(); } diff --git a/common/src/main/java/me/lucko/luckperms/common/model/PromotionResults.java b/common/src/main/java/me/lucko/luckperms/common/model/PromotionResults.java index 10b96253c..1c951cd0f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/PromotionResults.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/PromotionResults.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.model; -import me.lucko.luckperms.api.PromotionResult; +import me.lucko.luckperms.api.track.PromotionResult; import org.checkerframework.checker.nullness.qual.NonNull; diff --git a/common/src/main/java/me/lucko/luckperms/common/model/Track.java b/common/src/main/java/me/lucko/luckperms/common/model/Track.java index 6617184cd..a7b224a22 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/Track.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/Track.java @@ -27,11 +27,13 @@ package me.lucko.luckperms.common.model; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.DataMutateResult; -import me.lucko.luckperms.api.DemotionResult; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.PromotionResult; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeType; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.track.DemotionResult; +import me.lucko.luckperms.api.track.PromotionResult; import me.lucko.luckperms.common.api.implementation.ApiTrack; import me.lucko.luckperms.common.node.factory.NodeFactory; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -274,8 +276,9 @@ public final class Track implements Identifiable { } // find all groups that are inherited by the user in the exact contexts given and applicable to this track - List nodes = user.enduringData().immutable().get(context.makeImmutable()).stream() - .filter(Node::isGroupNode) + List nodes = user.enduringData().immutable().get(context.immutableCopy()).stream() + .filter(NodeType.INHERITANCE::matches) + .map(NodeType.INHERITANCE::cast) .filter(Node::getValue) .filter(node -> containsGroup(node.getGroupName())) .distinct() @@ -297,7 +300,7 @@ public final class Track implements Identifiable { return PromotionResults.undefinedFailure(); } - user.setPermission(NodeFactory.buildGroupNode(nextGroup.getId()).withExtraContext(context).build()); + user.setPermission(NodeFactory.buildGroupNode(nextGroup.getId()).withContext(context).build()); this.plugin.getEventFactory().handleUserPromote(user, this, null, first, sender); return PromotionResults.addedToFirst(first); } @@ -306,7 +309,7 @@ public final class Track implements Identifiable { return PromotionResults.ambiguousCall(); } - Node oldNode = nodes.get(0); + InheritanceNode oldNode = nodes.get(0); String old = oldNode.getGroupName(); String next = getNext(old); @@ -324,7 +327,7 @@ public final class Track implements Identifiable { } user.unsetPermission(oldNode); - user.setPermission(NodeFactory.buildGroupNode(nextGroup.getName()).withExtraContext(context).build()); + user.setPermission(NodeFactory.buildGroupNode(nextGroup.getName()).withContext(context).build()); if (context.isEmpty() && user.getPrimaryGroup().getStoredValue().orElse(NodeFactory.DEFAULT_GROUP_NAME).equalsIgnoreCase(old)) { user.getPrimaryGroup().setStoredValue(nextGroup.getName()); @@ -340,8 +343,9 @@ public final class Track implements Identifiable { } // find all groups that are inherited by the user in the exact contexts given and applicable to this track - List nodes = user.enduringData().immutable().get(context.makeImmutable()).stream() - .filter(Node::isGroupNode) + List nodes = user.enduringData().immutable().get(context.immutableCopy()).stream() + .filter(NodeType.INHERITANCE::matches) + .map(NodeType.INHERITANCE::cast) .filter(Node::getValue) .filter(node -> containsGroup(node.getGroupName())) .distinct() @@ -355,7 +359,7 @@ public final class Track implements Identifiable { return DemotionResults.ambiguousCall(); } - Node oldNode = nodes.get(0); + InheritanceNode oldNode = nodes.get(0); String old = oldNode.getGroupName(); String previous = getPrevious(old); @@ -379,7 +383,7 @@ public final class Track implements Identifiable { } user.unsetPermission(oldNode); - user.setPermission(NodeFactory.buildGroupNode(previousGroup.getName()).withExtraContext(context).build()); + user.setPermission(NodeFactory.buildGroupNode(previousGroup.getName()).withContext(context).build()); if (context.isEmpty() && user.getPrimaryGroup().getStoredValue().orElse(NodeFactory.DEFAULT_GROUP_NAME).equalsIgnoreCase(old)) { user.getPrimaryGroup().setStoredValue(previousGroup.getName()); diff --git a/common/src/main/java/me/lucko/luckperms/common/model/User.java b/common/src/main/java/me/lucko/luckperms/common/model/User.java index 2dd9e05ec..5e4167eae 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/User.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/User.java @@ -26,7 +26,7 @@ package me.lucko.luckperms.common.model; import me.lucko.luckperms.common.api.implementation.ApiUser; -import me.lucko.luckperms.common.cacheddata.UserCachedData; +import me.lucko.luckperms.common.cacheddata.UserCachedDataManager; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.primarygroup.ContextualHolder; @@ -58,7 +58,7 @@ public class User extends PermissionHolder implements Identifiable { protected @NonNull OptionalInt supply() { boolean seen = false; int best = 0; - for (Node n : this.group.getOwnNodes(ImmutableContextSet.empty())) { - Optional weight = n.getTypeData(WeightType.KEY); - if (!weight.isPresent()) { - continue; - } + for (Node n : this.group.getOwnNodes(QueryOptions.nonContextual())) { + if (n instanceof WeightNode) { + WeightNode weightNode = (WeightNode) n; + int value = weightNode.getWeight(); - int value = weight.get().getWeight(); - - if (!seen || value > best) { - seen = true; - best = value; + if (!seen || value > best) { + seen = true; + best = value; + } } } + OptionalInt weight = seen ? OptionalInt.of(best) : OptionalInt.empty(); if (!weight.isPresent()) { diff --git a/common/src/main/java/me/lucko/luckperms/common/model/manager/user/AbstractUserManager.java b/common/src/main/java/me/lucko/luckperms/common/model/manager/user/AbstractUserManager.java index 86c0852b7..728e73ac4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/manager/user/AbstractUserManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/manager/user/AbstractUserManager.java @@ -27,9 +27,10 @@ package me.lucko.luckperms.common.model.manager.user; import com.google.common.collect.ImmutableCollection; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeType; +import me.lucko.luckperms.api.node.types.InheritanceNode; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.UserIdentifier; @@ -89,7 +90,7 @@ public abstract class AbstractUserManager extends AbstractManage boolean has = false; for (Node node : user.enduringData().immutable().get(ImmutableContextSet.empty())) { - if (node.isGroupNode() && node.getGroupName().equalsIgnoreCase(pg)) { + if (node instanceof InheritanceNode && ((InheritanceNode) node).getGroupName().equalsIgnoreCase(pg)) { has = true; break; } @@ -98,9 +99,10 @@ public abstract class AbstractUserManager extends AbstractManage // need to find a new primary group for the user. if (!has) { String group = user.enduringData().immutable().get(ImmutableContextSet.empty()).stream() - .filter(Node::isGroupNode) + .filter(NodeType.INHERITANCE::matches) + .map(NodeType.INHERITANCE::cast) .findFirst() - .map(Node::getGroupName) + .map(InheritanceNode::getGroupName) .orElse(null); // if the group is null, it'll be resolved in the next step @@ -115,11 +117,11 @@ public abstract class AbstractUserManager extends AbstractManage boolean hasGroup = false; if (user.getPrimaryGroup().getStoredValue().isPresent()) { for (Node node : user.enduringData().immutable().values()) { - if (node.hasSpecificContext()) { + if (!node.getContexts().isEmpty()) { continue; } - if (node.isGroupNode()) { + if (node instanceof InheritanceNode) { hasGroup = true; break; } @@ -180,21 +182,21 @@ public abstract class AbstractUserManager extends AbstractManage */ @Override public boolean shouldSave(User user) { - ImmutableCollection nodes = user.enduringData().immutable().values(); + ImmutableCollection nodes = user.enduringData().immutable().values(); if (nodes.size() != 1) { return true; } - LocalizedNode onlyNode = nodes.iterator().next(); - if (!onlyNode.isGroupNode()) { + Node onlyNode = nodes.iterator().next(); + if (!(onlyNode instanceof InheritanceNode)) { return true; } - if (onlyNode.isTemporary() || onlyNode.isServerSpecific() || onlyNode.isWorldSpecific()) { + if (onlyNode.hasExpiry() || !onlyNode.getContexts().isEmpty()) { return true; } - if (!onlyNode.getGroupName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) { + if (!((InheritanceNode) onlyNode).getGroupName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) { // The user's only node is not the default group one. return true; } diff --git a/common/src/main/java/me/lucko/luckperms/common/node/AbstractNode.java b/common/src/main/java/me/lucko/luckperms/common/node/AbstractNode.java new file mode 100644 index 000000000..284695ac5 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/AbstractNode.java @@ -0,0 +1,237 @@ +/* + * 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.node; + +import com.google.common.collect.ImmutableList; + +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; +import me.lucko.luckperms.api.node.ScopedNode; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.node.types.RegexPermissionNode; +import me.lucko.luckperms.common.node.utils.ShorthandParser; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public abstract class AbstractNode, B extends NodeBuilder> implements ScopedNode { + + /** + * The character which separates each part of a permission node + */ + public static final char NODE_SEPARATOR = '.'; + + /** + * The numeric value of {@link #NODE_SEPARATOR} + */ + public static final int NODE_SEPARATOR_CODE = Character.getNumericValue(NODE_SEPARATOR); + + // node attributes + protected final String key; + protected final boolean value; + protected final long expireAt; // 0L for no expiry + protected final ImmutableContextSet contexts; + protected final Map, NodeMetadata> metadata; + + private final List resolvedShorthand; + + // this class is immutable, so we can cache the hashcode calculation + private final int hashCode; + + protected AbstractNode(String key, boolean value, long expireAt, ImmutableContextSet contexts, Map, NodeMetadata> metadata) { + this.key = key; + this.value = value; + this.expireAt = expireAt; + this.contexts = contexts; + this.metadata = metadata; + + this.resolvedShorthand = this instanceof RegexPermissionNode ? ImmutableList.of() : ImmutableList.copyOf(ShorthandParser.parseShorthand(this.key)); + + this.hashCode = calculateHashCode(); + } + + @Override + public @NonNull String getKey() { + return this.key; + } + + @Override + public boolean getValue() { + return this.value; + } + + @Override + public @NonNull ImmutableContextSet getContexts() { + return this.contexts; + } + + @Override + public Optional getMetadata(NodeMetadataKey key) { + //noinspection unchecked + T value = (T) this.metadata.get(key); + return Optional.ofNullable(value); + } + + @Override + public boolean appliesGlobally() { + return this.contexts.isEmpty(); + } + + @Override + public boolean shouldApplyWithContext(@NonNull ContextSet contextSet) { + return this.contexts.isSatisfiedBy(contextSet); + } + + @Override + public boolean hasExpiry() { + return this.expireAt != 0L; + } + + @Override + public @Nullable Instant getExpiry() { + return hasExpiry() ? Instant.ofEpochSecond(this.expireAt) : null; + } + + @Override + public boolean hasExpired() { + return hasExpiry() && this.expireAt < System.currentTimeMillis() / 1000L; + } + + @Override + public @NonNull List resolveShorthand() { + return this.resolvedShorthand; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof Node)) return false; + return Equality.EXACT.areEqual(this, ((AbstractNode) o)); + } + + @Override + public boolean equals(@NonNull Node o, @NonNull NodeEqualityPredicate equalityPredicate) { + AbstractNode other = (AbstractNode) o; + if (equalityPredicate == NodeEqualityPredicate.EXACT) { + return Equality.EXACT.areEqual(this, other); + } else if (equalityPredicate == NodeEqualityPredicate.IGNORE_VALUE) { + return Equality.IGNORE_VALUE.areEqual(this, other); + } else if (equalityPredicate == NodeEqualityPredicate.IGNORE_EXPIRY_TIME) { + return Equality.IGNORE_EXPIRY_TIME.areEqual(this, other); + } else if (equalityPredicate == NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE) { + return Equality.IGNORE_EXPIRY_TIME_AND_VALUE.areEqual(this, other); + } else if (equalityPredicate == NodeEqualityPredicate.IGNORE_VALUE_OR_IF_TEMPORARY) { + return Equality.IGNORE_VALUE_OR_IF_TEMPORARY.areEqual(this, other); + } else { + return equalityPredicate.areEqual(this, o); + } + } + + @Override + public int hashCode() { + return this.hashCode; + } + + private int calculateHashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.key.hashCode(); + result = result * PRIME + (this.value ? 79 : 97); + result = result * PRIME + (int) (this.expireAt >>> 32 ^ this.expireAt); + result = result * PRIME + this.contexts.hashCode(); + return result; + } + + @SuppressWarnings("StringEquality") + private enum Equality { + EXACT { + @Override + public boolean areEqual(@NonNull AbstractNode o1, @NonNull AbstractNode o2) { + return o1 == o2 || + o1.key == o2.key && + o1.value == o2.value && + o1.expireAt == o2.expireAt && + o1.getContexts().equals(o2.getContexts()); + } + }, + IGNORE_VALUE { + @Override + public boolean areEqual(@NonNull AbstractNode o1, @NonNull AbstractNode o2) { + return o1 == o2 || + o1.key == o2.key && + o1.expireAt == o2.expireAt && + o1.getContexts().equals(o2.getContexts()); + } + }, + IGNORE_EXPIRY_TIME { + @Override + public boolean areEqual(@NonNull AbstractNode o1, @NonNull AbstractNode o2) { + return o1 == o2 || + o1.key == o2.key && + o1.value == o2.value && + o1.hasExpiry() == o2.hasExpiry() && + o1.getContexts().equals(o2.getContexts()); + } + }, + IGNORE_EXPIRY_TIME_AND_VALUE { + @Override + public boolean areEqual(@NonNull AbstractNode o1, @NonNull AbstractNode o2) { + return o1 == o2 || + o1.key == o2.key && + o1.hasExpiry() == o2.hasExpiry() && + o1.getContexts().equals(o2.getContexts()); + } + }, + IGNORE_VALUE_OR_IF_TEMPORARY { + @Override + public boolean areEqual(@NonNull AbstractNode o1, @NonNull AbstractNode o2) { + return o1 == o2 || + o1.key == o2.key && + o1.getContexts().equals(o2.getContexts()); + } + }; + + public abstract boolean areEqual(@NonNull AbstractNode o1, @NonNull AbstractNode o2); + } + + @Override + public String toString() { + return "ImmutableNode(" + + "key=" + this.key + ", " + + "value=" + this.value + ", " + + "expireAt=" + this.expireAt + ", " + + "contexts=" + this.contexts + ")"; + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/AbstractNodeBuilder.java b/common/src/main/java/me/lucko/luckperms/common/node/AbstractNodeBuilder.java new file mode 100644 index 000000000..f5e5b4634 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/AbstractNodeBuilder.java @@ -0,0 +1,121 @@ +/* + * 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.node; + +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.DefaultContextKeys; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.ScopedNode; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Objects; + +public abstract class AbstractNodeBuilder, B extends NodeBuilder> implements NodeBuilder { + protected boolean value; + protected long expireAt; + protected ImmutableContextSet.Builder context; + protected Map, NodeMetadata> metadata; + + protected AbstractNodeBuilder() { + this.value = true; + this.expireAt = 0L; + this.context = ImmutableContextSet.builder(); + this.metadata = new IdentityHashMap<>(); + } + + protected AbstractNodeBuilder(boolean value, long expireAt, ImmutableContextSet context, Map, NodeMetadata> metadata) { + this.value = value; + this.expireAt = expireAt; + this.context = ImmutableContextSet.builder().addAll(context); + this.metadata = new IdentityHashMap<>(metadata); + } + + @Override + public @NonNull B value(boolean value) { + this.value = value; + return (B) this; + } + + @Override + public @NonNull B negated(boolean negated) { + this.value = !negated; + return (B) this; + } + + @Override + public @NonNull B expiry(long expiryUnixTimestamp) { + this.expireAt = expiryUnixTimestamp; + return (B) this; + } + + @Override + public @NonNull B clearExpiry() { + this.expireAt = 0L; + return (B) this; + } + + @Override + public @NonNull B context(@NonNull ContextSet contextSet) { + Objects.requireNonNull(contextSet, "contextSet"); + this.context = ImmutableContextSet.builder().addAll(contextSet); + return (B) this; + } + + @Override + public @NonNull B withContext(@NonNull String key, @NonNull String value) { + // TODO reconsider a better place to insert / avoid this special case + if ((key.equalsIgnoreCase(DefaultContextKeys.SERVER_KEY) || key.equalsIgnoreCase(DefaultContextKeys.WORLD_KEY)) && value.equalsIgnoreCase("global")) { + return (B) this; + } + this.context.add(key, value); + return (B) this; + } + + @Override + public @NonNull B withContext(@NonNull ContextSet contextSet) { + this.context.addAll(contextSet); + return (B) this; + } + + @Override + public @NonNull B withMetadata(@NonNull NodeMetadataKey key, @Nullable T metadata) { + Objects.requireNonNull(key, "key"); + if (metadata == null) { + this.metadata.remove(key); + } else { + this.metadata.put(key, metadata); + } + return (B) this; + } + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/comparator/HeldPermissionComparator.java b/common/src/main/java/me/lucko/luckperms/common/node/comparator/HeldPermissionComparator.java index 0b5cb5cd0..15ca22c56 100644 --- a/common/src/main/java/me/lucko/luckperms/common/node/comparator/HeldPermissionComparator.java +++ b/common/src/main/java/me/lucko/luckperms/common/node/comparator/HeldPermissionComparator.java @@ -25,23 +25,23 @@ package me.lucko.luckperms.common.node.comparator; -import me.lucko.luckperms.api.HeldPermission; +import me.lucko.luckperms.api.node.HeldNode; import java.util.Comparator; -public class HeldPermissionComparator> implements Comparator> { +public class HeldPermissionComparator> implements Comparator> { - public static > Comparator> normal() { + public static > Comparator> normal() { return new HeldPermissionComparator<>(); } - public static > Comparator> reverse() { + public static > Comparator> reverse() { return HeldPermissionComparator.normal().reversed(); } @Override - public int compare(HeldPermission o1, HeldPermission o2) { - int i = NodeWithContextComparator.normal().compare(o1.asNode(), o2.asNode()); + public int compare(HeldNode o1, HeldNode o2) { + int i = NodeWithContextComparator.normal().compare(o1.getNode(), o2.getNode()); if (i != 0) { return i; } diff --git a/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeComparator.java b/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeComparator.java index d193462f1..cd9e233eb 100644 --- a/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeComparator.java +++ b/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeComparator.java @@ -25,8 +25,11 @@ package me.lucko.luckperms.common.node.comparator; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.types.PermissionNode; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.Comparator; public class NodeComparator implements Comparator { @@ -48,38 +51,36 @@ public class NodeComparator implements Comparator { return 0; } - int result = Boolean.compare(o1.isOverride(), o2.isOverride()); + int result = Boolean.compare(o1.hasExpiry(), o2.hasExpiry()); if (result != 0) { return result; } - result = Boolean.compare(o1.isTemporary(), o2.isTemporary()); + result = Boolean.compare( + o1 instanceof PermissionNode && ((PermissionNode) o1).isWildcard(), + o2 instanceof PermissionNode && ((PermissionNode) o2).isWildcard() + ); if (result != 0) { return result; } - result = Boolean.compare(o1.isWildcard(), o2.isWildcard()); - if (result != 0) { - return result; - } - - if (o1.isTemporary()) { + if (o1.hasExpiry()) { // note vvv - result = -Long.compare(o1.getSecondsTilExpiry(), o2.getSecondsTilExpiry()); + result = -Long.compare(ChronoUnit.MILLIS.between(Instant.now(), o1.getExpiry()), ChronoUnit.MILLIS.between(Instant.now(), o2.getExpiry())); if (result != 0) { return result; } } - if (o1.isWildcard()) { - result = Integer.compare(o1.getWildcardLevel(), o2.getWildcardLevel()); + if (o1 instanceof PermissionNode && ((PermissionNode) o1).isWildcard()) { + result = Integer.compare(((PermissionNode) o1).getWildcardLevel().getAsInt(), ((PermissionNode) o2).getWildcardLevel().getAsInt()); if (result != 0) { return result; } } // note vvv - result = -o1.getPermission().compareTo(o2.getPermission()); + result = -o1.getKey().compareTo(o2.getKey()); if (result != 0) { return result; } diff --git a/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeWithContextComparator.java b/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeWithContextComparator.java index 29b3c3ba4..336a8ea04 100644 --- a/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeWithContextComparator.java +++ b/common/src/main/java/me/lucko/luckperms/common/node/comparator/NodeWithContextComparator.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.node.comparator; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.context.ContextSetComparator; import java.util.Comparator; @@ -53,14 +53,9 @@ public class NodeWithContextComparator implements Comparator { return 0; } - int result = Boolean.compare(o1.isOverride(), o2.isOverride()); - if (result != 0) { - return result; - } - - result = ContextSetComparator.normal().compare( - o1.getFullContexts().makeImmutable(), - o2.getFullContexts().makeImmutable() + int result = ContextSetComparator.normal().compare( + o1.getContexts(), + o2.getContexts() ); if (result != 0) { diff --git a/common/src/main/java/me/lucko/luckperms/common/node/factory/Delimiters.java b/common/src/main/java/me/lucko/luckperms/common/node/factory/Delimiters.java new file mode 100644 index 000000000..9f60d9bd8 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/factory/Delimiters.java @@ -0,0 +1,74 @@ +/* + * 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.node.factory; + +public final class Delimiters { + private Delimiters() {} + + /** + * The characters which are delimited when serializing meta/prefix/suffix strings + */ + private static final String[] GENERIC_DELIMITERS = new String[]{".", "/", "-", "$"}; + + static String escapeCharacters(String s) { + if (s == null) { + throw new NullPointerException(); + } + + return escapeDelimiters(s, GENERIC_DELIMITERS); + } + + public static String unescapeCharacters(String s) { + if (s == null) { + throw new NullPointerException(); + } + + return unescapeDelimiters(s, GENERIC_DELIMITERS); + } + + private static String escapeDelimiters(String s, String... delimiters) { + if (s == null) { + return null; + } + + for (String d : delimiters) { + s = s.replace(d, "\\" + d); + } + return s; + } + + private static String unescapeDelimiters(String s, String... delimiters) { + if (s == null) { + return null; + } + + for (String d : delimiters) { + s = s.replace("\\" + d, d); + } + return s; + } + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/factory/LegacyNodeFactory.java b/common/src/main/java/me/lucko/luckperms/common/node/factory/LegacyNodeFactory.java deleted file mode 100644 index 6dc25e9a0..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/node/factory/LegacyNodeFactory.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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.node.factory; - -import com.google.common.base.Splitter; - -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.common.cache.PatternCache; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -public final class LegacyNodeFactory { - private LegacyNodeFactory() {} - - /** - * The characters which are delimited when serializing a context set - */ - private static final String[] CONTEXT_DELIMITERS = new String[]{"=", "(", ")", ","}; - - /** - * The characters which are delimited when serializing meta/prefix/suffix strings - */ - private static final String[] GENERIC_DELIMITERS = new String[]{".", "/", "-", "$"}; - - // legacy node format delimiters - private static final Pattern LEGACY_SERVER_DELIM = PatternCache.compileDelimiterPattern("/", "\\"); - private static final Splitter LEGACY_SERVER_SPLITTER = Splitter.on(LEGACY_SERVER_DELIM).limit(2); - private static final Pattern LEGACY_WORLD_DELIM = PatternCache.compileDelimiterPattern("-", "\\"); - private static final Splitter LEGACY_WORLD_SPLITTER = Splitter.on(LEGACY_WORLD_DELIM).limit(2); - private static final Pattern LEGACY_EXPIRY_DELIM = PatternCache.compileDelimiterPattern("$", "\\"); - private static final Splitter LEGACY_EXPIRY_SPLITTER = Splitter.on(LEGACY_EXPIRY_DELIM).limit(2); - private static final Pattern LEGACY_CONTEXT_DELIM = PatternCache.compileDelimiterPattern(")", "\\"); - private static final Splitter CONTEXT_SPLITTER = Splitter.on(LEGACY_CONTEXT_DELIM).limit(2); - private static final Pattern LEGACY_CONTEXT_PAIR_DELIM = PatternCache.compileDelimiterPattern(",", "\\"); - private static final Pattern LEGACY_CONTEXT_PAIR_PART_DELIM = PatternCache.compileDelimiterPattern("=", "\\"); - private static final Splitter.MapSplitter LEGACY_CONTEXT_PART_SPLITTER = Splitter.on(LEGACY_CONTEXT_PAIR_DELIM) - .withKeyValueSeparator(Splitter.on(LEGACY_CONTEXT_PAIR_PART_DELIM)); - - public static Node fromLegacyString(String s, boolean b) { - if (b) { - return builderFromLegacyString(s, true).build(); - } else { - return builderFromLegacyString(s, false).build(); - } - } - - private static Node.Builder builderFromLegacyString(String s, boolean b) { - // if contains / - if (LEGACY_SERVER_DELIM.matcher(s).find()) { - // 0=server(+world) 1=node - Iterator parts = LEGACY_SERVER_SPLITTER.split(s).iterator(); - String parts0 = parts.next(); - String parts1 = parts.next(); - - // WORLD SPECIFIC - // if parts[0] contains - - if (LEGACY_WORLD_DELIM.matcher(parts0).find()) { - // 0=server 1=world - Iterator serverParts = LEGACY_WORLD_SPLITTER.split(parts0).iterator(); - String serverParts0 = serverParts.next(); - String serverParts1 = serverParts.next(); - - // if parts[1] contains $ - if (LEGACY_EXPIRY_DELIM.matcher(parts1).find()) { - // 0=node 1=expiry - Iterator tempParts = LEGACY_EXPIRY_SPLITTER.split(parts1).iterator(); - String tempParts0 = tempParts.next(); - String tempParts1 = tempParts.next(); - - return new LegacyNodeBuilder(tempParts0).setServer(serverParts0).setWorld(serverParts1).setExpiry(Long.parseLong(tempParts1)).setValue(b); - } else { - return new LegacyNodeBuilder(parts1).setServer(serverParts0).setWorld(serverParts1).setValue(b); - } - } else { - // SERVER BUT NOT WORLD SPECIFIC - - // if parts[1] contains $ - if (LEGACY_EXPIRY_DELIM.matcher(parts1).find()) { - // 0=node 1=expiry - Iterator tempParts = LEGACY_EXPIRY_SPLITTER.split(parts1).iterator(); - String tempParts0 = tempParts.next(); - String tempParts1 = tempParts.next(); - - return new LegacyNodeBuilder(tempParts0).setServer(parts0).setExpiry(Long.parseLong(tempParts1)).setValue(b); - } else { - return new LegacyNodeBuilder(parts1).setServer(parts0).setValue(b); - } - } - } else { - // NOT SERVER SPECIFIC - - // if s contains $ - if (LEGACY_EXPIRY_DELIM.matcher(s).find()) { - // 0=node 1=expiry - Iterator tempParts = LEGACY_EXPIRY_SPLITTER.split(s).iterator(); - String tempParts0 = tempParts.next(); - String tempParts1 = tempParts.next(); - - return new LegacyNodeBuilder(tempParts0).setExpiry(Long.parseLong(tempParts1)).setValue(b); - } else { - return new LegacyNodeBuilder(s).setValue(b); - } - } - } - - static String escapeCharacters(String s) { - if (s == null) { - throw new NullPointerException(); - } - - return escapeDelimiters(s, GENERIC_DELIMITERS); - } - - public static String unescapeCharacters(String s) { - if (s == null) { - throw new NullPointerException(); - } - - // super old hack - this format is no longer used for escaping, - // but we'll keep supporting it when unescaping - s = s.replace("{SEP}", "."); - s = s.replace("{FSEP}", "/"); - s = s.replace("{DSEP}", "$"); - s = unescapeDelimiters(s, GENERIC_DELIMITERS); - - return s; - } - - private static String escapeDelimiters(String s, String... delimiters) { - if (s == null) { - return null; - } - - for (String d : delimiters) { - s = s.replace(d, "\\" + d); - } - return s; - } - - public static String unescapeDelimiters(String s, String... delimiters) { - if (s == null) { - return null; - } - - for (String d : delimiters) { - s = s.replace("\\" + d, d); - } - return s; - } - - private static final class LegacyNodeBuilder extends NodeBuilder { - private static final Pattern NODE_CONTEXTS_PATTERN = Pattern.compile("\\(.+\\).*"); - - LegacyNodeBuilder(String permission) { - if (!NODE_CONTEXTS_PATTERN.matcher(permission).matches()) { - this.permission = permission; - } else { - List contextParts = CONTEXT_SPLITTER.splitToList(permission.substring(1)); - // 0 = context, 1 = node - - this.permission = contextParts.get(1); - try { - Map map = LEGACY_CONTEXT_PART_SPLITTER.split(contextParts.get(0)); - for (Map.Entry e : map.entrySet()) { - this.withExtraContext( - unescapeDelimiters(e.getKey(), CONTEXT_DELIMITERS), - unescapeDelimiters(e.getValue(), CONTEXT_DELIMITERS) - ); - } - - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } - } - - } - } - -} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeBuilder.java b/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeBuilder.java deleted file mode 100644 index 034271fd6..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeBuilder.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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.node.factory; - -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.context.ContextSet; -import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.common.node.model.ImmutableNode; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -/** - * Builds node instances - */ -public class NodeBuilder implements Node.Builder { - protected String permission; - private ImmutableContextSet.Builder extraContexts = ImmutableContextSet.builder(); - private Boolean value = true; - private boolean override = false; - private String server = null; - private String world = null; - private long expireAt = 0L; - - NodeBuilder() { - - } - - NodeBuilder(String permission) { - this.permission = permission; - } - - public NodeBuilder(Node other) { - this.permission = other.getPermission(); - copyFrom(other); - } - - @Override - public Node.Builder copyFrom(@NonNull Node node) { - Objects.requireNonNull(node, "node"); - this.value = node.getValue(); - this.override = node.isOverride(); - this.server = node.getServer().orElse(null); - this.world = node.getWorld().orElse(null); - this.expireAt = node.isPermanent() ? 0L : node.getExpiryUnixTime(); - this.extraContexts = ImmutableContextSet.builder().addAll(node.getContexts()); - return this; - } - - @Override - public Node.@NonNull Builder setNegated(boolean negated) { - this.value = !negated; - return this; - } - - @Override - public Node.@NonNull Builder setValue(boolean value) { - this.value = value; - return this; - } - - @Override - public Node.@NonNull Builder setOverride(boolean override) { - this.override = override; - return this; - } - - @Override - public Node.@NonNull Builder setExpiry(long expireAt) { - this.expireAt = expireAt; - return this; - } - - @Override - public Node.@NonNull Builder clearExpiry() { - this.expireAt = 0L; - return this; - } - - @Override - public Node.@NonNull Builder setWorld(String world) { - this.world = world; - return this; - } - - @Override - public Node.@NonNull Builder setServer(String server) { - this.server = server; - return this; - } - - @Override - public Node.@NonNull Builder withExtraContext(@NonNull String key, @NonNull String value) { - Objects.requireNonNull(key, "key"); - Objects.requireNonNull(value, "value"); - switch (key.toLowerCase()) { - case Contexts.SERVER_KEY: - setServer(value); - break; - case Contexts.WORLD_KEY: - setWorld(value); - break; - default: - this.extraContexts.add(key, value); - break; - } - - return this; - } - - @Override - public Node.@NonNull Builder withExtraContext(Map.@NonNull Entry entry) { - Objects.requireNonNull(entry, "entry"); - withExtraContext(entry.getKey(), entry.getValue()); - return this; - } - - @Override - public Node.@NonNull Builder withExtraContext(@NonNull Map map) { - Objects.requireNonNull(map, "map"); - withExtraContext(ContextSet.fromMap(map)); - return this; - } - - @Override - public Node.@NonNull Builder withExtraContext(@NonNull Set> context) { - Objects.requireNonNull(context, "context"); - withExtraContext(ContextSet.fromEntries(context)); - return this; - } - - @Override - public Node.@NonNull Builder withExtraContext(@NonNull ContextSet set) { - Objects.requireNonNull(set, "set"); - set.toSet().forEach(this::withExtraContext); - return this; - } - - @Override - public Node.@NonNull Builder setExtraContext(@NonNull ContextSet contextSet) { - this.extraContexts = ImmutableContextSet.builder().addAll(contextSet); - return this; - } - - @Override - public @NonNull Node build() { - return new ImmutableNode(this.permission, this.value, this.override, this.expireAt, this.server, this.world, this.extraContexts.build()); - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeFactory.java b/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeFactory.java index 28db72d14..ee262d13f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeFactory.java @@ -25,12 +25,16 @@ package me.lucko.luckperms.common.node.factory; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.DefaultContextKeys; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.types.ChatMetaNode; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.node.types.MetaNode; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.HolderType; -import me.lucko.luckperms.common.node.model.NodeTypes; import java.util.Map; @@ -42,116 +46,124 @@ public final class NodeFactory { public static final String DEFAULT_GROUP_NAME = "default"; - public static Node.Builder builder(String s) { - return new NodeBuilder(s); + public static NodeBuilder builder(String s) { + return NodeTypes.newBuilder(s); } - public static Node.Builder buildGroupNode(String groupName) { - return new NodeBuilder(groupNode(groupName)); + public static NodeBuilder buildGroupNode(String groupName) { + return builder(groupNode(groupName)); } - public static Node.Builder buildGroupNode(Group group) { - return new NodeBuilder(groupNode(group.getName())); + public static NodeBuilder buildGroupNode(Group group) { + return builder(groupNode(group.getName())); } - public static Node.Builder buildMetaNode(String key, String value) { - return new NodeBuilder(metaNode(key, value)); + public static NodeBuilder buildMetaNode(String key, String value) { + return builder(metaNode(key, value)); } - public static Node.Builder buildChatMetaNode(ChatMetaType type, int priority, String s) { + public static NodeBuilder buildChatMetaNode(ChatMetaType type, int priority, String s) { return type == ChatMetaType.PREFIX ? buildPrefixNode(priority, s) : buildSuffixNode(priority, s); } - public static Node.Builder buildPrefixNode(int priority, String prefix) { - return new NodeBuilder(prefixNode(priority, prefix)); + public static NodeBuilder buildPrefixNode(int priority, String prefix) { + return builder(prefixNode(priority, prefix)); } - public static Node.Builder buildSuffixNode(int priority, String suffix) { - return new NodeBuilder(suffixNode(priority, suffix)); + public static NodeBuilder buildSuffixNode(int priority, String suffix) { + return builder(suffixNode(priority, suffix)); } - public static Node.Builder buildWeightNode(int weight) { - return new NodeBuilder(weightNode(weight)); + public static NodeBuilder buildWeightNode(int weight) { + return builder(weightNode(weight)); } public static String groupNode(String groupName) { return NodeTypes.GROUP_NODE_MARKER + groupName; } + public static String displayName(String displayName) { + return NodeTypes.DISPLAY_NAME_NODE_MARKER + displayName; + } + public static String chatMetaNode(ChatMetaType type, int priority, String value) { return type == ChatMetaType.PREFIX ? prefixNode(priority, value) : suffixNode(priority, value); } public static String prefixNode(int priority, String prefix) { - return NodeTypes.PREFIX_NODE_MARKER + priority + "." + LegacyNodeFactory.escapeCharacters(prefix); + return NodeTypes.PREFIX_NODE_MARKER + priority + "." + Delimiters.escapeCharacters(prefix); } public static String suffixNode(int priority, String suffix) { - return NodeTypes.SUFFIX_NODE_MARKER + priority + "." + LegacyNodeFactory.escapeCharacters(suffix); + return NodeTypes.SUFFIX_NODE_MARKER + priority + "." + Delimiters.escapeCharacters(suffix); } public static String metaNode(String key, String value) { - return NodeTypes.META_NODE_MARKER + LegacyNodeFactory.escapeCharacters(key) + "." + LegacyNodeFactory.escapeCharacters(value); + return NodeTypes.META_NODE_MARKER + Delimiters.escapeCharacters(key) + "." + Delimiters.escapeCharacters(value); } public static String weightNode(int weight) { return NodeTypes.WEIGHT_NODE_MARKER + weight; } + public static String regexNode(String pattern) { + return NodeTypes.REGEX_MARKER_1 + pattern; + } + public static Node make(String node) { return builder(node).build(); } public static Node make(String node, boolean value) { - return builder(node).setValue(value).build(); + return builder(node).value(value).build(); } public static Node make(String node, boolean value, String server) { - return builder(node).setValue(value).setServer(server).build(); + return builder(node).value(value).withContext(DefaultContextKeys.SERVER_KEY, server).build(); } public static Node make(String node, boolean value, String server, String world) { - return builder(node).setValue(value).setServer(server).setWorld(world).build(); + return builder(node).value(value).withContext(DefaultContextKeys.SERVER_KEY, server).withContext(DefaultContextKeys.WORLD_KEY, world).build(); } public static Node make(String node, String server) { - return builder(node).setServer(server).build(); + return builder(node).withContext(DefaultContextKeys.SERVER_KEY, server).build(); } public static Node make(String node, String server, String world) { - return builder(node).setServer(server).setWorld(world).build(); + return builder(node).withContext(DefaultContextKeys.SERVER_KEY, server).withContext(DefaultContextKeys.WORLD_KEY, world).build(); } public static Node make(String node, boolean value, boolean temporary) { - return builder(node).setValue(value).setExpiry(temporary ? 10L : 0L).build(); + return builder(node).value(value).expiry(temporary ? 10L : 0L).build(); } public static Node make(String node, boolean value, String server, boolean temporary) { - return builder(node).setValue(value).setServer(server).setExpiry(temporary ? 10L : 0L).build(); + return builder(node).value(value).withContext(DefaultContextKeys.SERVER_KEY, server).expiry(temporary ? 10L : 0L).build(); } public static Node make(String node, boolean value, String server, String world, boolean temporary) { - return builder(node).setValue(value).setServer(server).setWorld(world).setExpiry(temporary ? 10L : 0L).build(); + return builder(node).value(value).withContext(DefaultContextKeys.SERVER_KEY, server).withContext(DefaultContextKeys.WORLD_KEY, world).expiry(temporary ? 10L : 0L).build(); } public static Node make(String node, String server, boolean temporary) { - return builder(node).setServer(server).setExpiry(temporary ? 10L : 0L).build(); + return builder(node).withContext(DefaultContextKeys.SERVER_KEY, server).expiry(temporary ? 10L : 0L).build(); } public static Node make(String node, String server, String world, boolean temporary) { - return builder(node).setServer(server).setWorld(world).setExpiry(temporary ? 10L : 0L).build(); + return builder(node).withContext(DefaultContextKeys.SERVER_KEY, server).withContext(DefaultContextKeys.WORLD_KEY, world).expiry(temporary ? 10L : 0L).build(); } public static Node make(String node, boolean value, long expireAt) { - return builder(node).setValue(value).setExpiry(expireAt).build(); + return builder(node).value(value).expiry(expireAt).build(); } public static Node make(String node, boolean value, String server, long expireAt) { - return builder(node).setValue(value).setServer(server).setExpiry(expireAt).build(); + return builder(node).value(value).withContext(DefaultContextKeys.SERVER_KEY, server).expiry(expireAt).build(); } public static Node make(String node, boolean value, String server, String world, long expireAt) { - return builder(node).setValue(value).setServer(server).setWorld(world).setExpiry(expireAt).build(); + return builder(node).value(value).withContext(DefaultContextKeys.SERVER_KEY, server).withContext(DefaultContextKeys.WORLD_KEY, world).expiry(expireAt).build(); } public static Node make(Group group, long expireAt) { @@ -194,7 +206,7 @@ public final class NodeFactory { StringBuilder sb = new StringBuilder(32); sb.append(type.toString()).append(" ").append(id).append(" "); - if (node.isGroupNode()) { + if (node instanceof InheritanceNode) { sb.append("parent "); if (set) { @@ -203,21 +215,21 @@ public final class NodeFactory { sb.append("remove"); } - if (node.isTemporary()) { + if (node.hasExpiry()) { sb.append("temp"); } - sb.append(" ").append(node.getGroupName()); + sb.append(" ").append(((InheritanceNode) node).getGroupName()); - if (node.isTemporary() && set) { - sb.append(" ").append(node.getExpiryUnixTime()); + if (node.hasExpiry() && set) { + sb.append(" ").append(node.getExpiry().getEpochSecond()); } return appendContextToCommand(sb, node, explicitGlobalContext).toString(); } - if (node.getValue() && (node.isPrefix() || node.isSuffix())) { - ChatMetaType chatMetaType = node.isPrefix() ? ChatMetaType.PREFIX : ChatMetaType.SUFFIX; + if (node.getValue() && (node instanceof ChatMetaNode)) { + ChatMetaNode cmNode = (ChatMetaNode) node; sb.append("meta "); @@ -227,16 +239,16 @@ public final class NodeFactory { sb.append("remove"); } - if (node.isTemporary()) { + if (node.hasExpiry()) { sb.append("temp"); } - sb.append(chatMetaType) + sb.append(cmNode.getType().toString()) .append(" ") - .append(chatMetaType.getEntry(node).getKey()) // weight + .append(cmNode.getPriority()) // weight .append(" "); - String value = chatMetaType.getEntry(node).getValue(); + String value = cmNode.getMetaValue(); if (value.contains(" ")) { // wrap value in quotes sb.append("\"").append(value).append("\""); @@ -244,14 +256,14 @@ public final class NodeFactory { sb.append(value); } - if (set && node.isTemporary()) { - sb.append(" ").append(node.getExpiryUnixTime()); + if (set && node.hasExpiry()) { + sb.append(" ").append(node.getExpiry().getEpochSecond()); } return appendContextToCommand(sb, node, explicitGlobalContext).toString(); } - if (node.getValue() && node.isMeta()) { + if (node.getValue() && node instanceof MetaNode) { sb.append("meta "); if (set) { @@ -260,14 +272,15 @@ public final class NodeFactory { sb.append("unset"); } - if (node.isTemporary()) { + if (node.hasExpiry()) { sb.append("temp"); } sb.append(" "); - String key = node.getMeta().getKey(); + MetaNode metaNode = (MetaNode) node; + String key = metaNode.getMetaKey(); if (key.contains(" ")) { sb.append("\"").append(key).append("\""); } else { @@ -277,15 +290,15 @@ public final class NodeFactory { if (set) { sb.append(" "); - String value = node.getMeta().getValue(); + String value = metaNode.getMetaValue(); if (value.contains(" ")) { sb.append("\"").append(value).append("\""); } else { sb.append(value); } - if (node.isTemporary()) { - sb.append(" ").append(node.getExpiryUnixTime()); + if (node.hasExpiry()) { + sb.append(" ").append(node.getExpiry().getEpochSecond()); } } @@ -300,13 +313,13 @@ public final class NodeFactory { sb.append("unset"); } - if (node.isTemporary()) { + if (node.hasExpiry()) { sb.append("temp"); } sb.append(" "); - String perm = node.getPermission(); + String perm = node.getKey(); if (perm.contains(" ")) { sb.append("\"").append(perm).append("\""); } else { @@ -315,8 +328,8 @@ public final class NodeFactory { if (set) { sb.append(" ").append(node.getValue()); - if (node.isTemporary()) { - sb.append(" ").append(node.getExpiryUnixTime()); + if (node.hasExpiry()) { + sb.append(" ").append(node.getExpiry().getEpochSecond()); } } @@ -324,22 +337,15 @@ public final class NodeFactory { } private static StringBuilder appendContextToCommand(StringBuilder sb, Node node, boolean explicitGlobalContext) { - if (node.getFullContexts().isEmpty()) { + if (node.getContexts().isEmpty()) { if (explicitGlobalContext) { sb.append(" global"); } return sb; } - if (node.getServer().isPresent()) { - sb.append(" server=").append(node.getServer().get()); - } - if (node.getWorld().isPresent()) { - sb.append(" world=").append(node.getWorld().get()); - } - ContextSet contexts = node.getContexts(); - for (Map.Entry context : contexts.toSet()) { + for (Map.Entry context : contexts) { sb.append(" ").append(context.getKey()).append("=").append(context.getValue()); } diff --git a/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeTypes.java b/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeTypes.java new file mode 100644 index 000000000..45d3faa9c --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/factory/NodeTypes.java @@ -0,0 +1,264 @@ +/* + * 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.node.factory; + +import com.google.common.base.Splitter; + +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.DefaultContextKeys; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.types.DisplayNameNode; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.node.types.PrefixNode; +import me.lucko.luckperms.api.node.types.RegexPermissionNode; +import me.lucko.luckperms.api.node.types.SuffixNode; +import me.lucko.luckperms.api.node.types.WeightNode; +import me.lucko.luckperms.common.cache.PatternCache; +import me.lucko.luckperms.common.node.types.DisplayName; +import me.lucko.luckperms.common.node.types.Inheritance; +import me.lucko.luckperms.common.node.types.Meta; +import me.lucko.luckperms.common.node.types.Permission; +import me.lucko.luckperms.common.node.types.Prefix; +import me.lucko.luckperms.common.node.types.RegexPermission; +import me.lucko.luckperms.common.node.types.Suffix; +import me.lucko.luckperms.common.node.types.Weight; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Iterator; + +public final class NodeTypes { + private NodeTypes() {} + + public static final String GROUP_KEY = "group"; + public static final String PREFIX_KEY = "prefix"; + public static final String SUFFIX_KEY = "suffix"; + public static final String META_KEY = "meta"; + public static final String WEIGHT_KEY = "weight"; + public static final String DISPLAY_NAME_KEY = "displayname"; + + public static final String GROUP_NODE_MARKER = GROUP_KEY + "."; + public static final String PREFIX_NODE_MARKER = PREFIX_KEY + "."; + public static final String SUFFIX_NODE_MARKER = SUFFIX_KEY + "."; + public static final String META_NODE_MARKER = META_KEY + "."; + public static final String WEIGHT_NODE_MARKER = WEIGHT_KEY + "."; + public static final String DISPLAY_NAME_NODE_MARKER = DISPLAY_NAME_KEY + "."; + public static final String REGEX_MARKER_1 = "r="; + public static final String REGEX_MARKER_2 = "R="; + + // used to split prefix/suffix/meta nodes + private static final Splitter META_SPLITTER = Splitter.on(PatternCache.compileDelimiterPattern(".", "\\")).limit(2); + + public static Node makeNode(String key, boolean value, long expireAt, String server, String world, ContextSet contexts) { + if (key == null || key.isEmpty()) { + throw new IllegalArgumentException("Empty permission"); + } + + server = standardizeServerWorld(server); + world = standardizeServerWorld(world); + key = key.intern(); + contexts = formContextSet(contexts, server, world); + + return newBuilder(key).value(value).expiry(expireAt).context(contexts).build(); + } + + private static String standardizeServerWorld(String s) { + if (s != null) { + s = s.toLowerCase(); + + if (s.equals("global") || s.isEmpty()) { + s = null; + } + } + + return s; + } + + private static ImmutableContextSet formContextSet(ContextSet contexts, String server, String world) { + if ((contexts == null || contexts.isEmpty()) && server == null && world == null) { + return ImmutableContextSet.empty(); + } + + ImmutableContextSet.Builder builder = ImmutableContextSet.builder(); + + if (contexts != null) { + builder.addAll(contexts); + } + if (server != null) { + builder.add(DefaultContextKeys.SERVER_KEY, server); + } + if (world != null) { + builder.add(DefaultContextKeys.WORLD_KEY, world); + } + + return builder.build(); + } + + public static @NonNull NodeBuilder newBuilder(String s) { + NodeBuilder b = parseInheritanceType(s); + if (b != null) { + return b; + } + + b = parseMetaType(s); + if (b != null) { + return b; + } + + b = parsePrefixType(s); + if (b != null) { + return b; + } + + b = parseSuffixType(s); + if (b != null) { + return b; + } + + b = parseWeightType(s); + if (b != null) { + return b; + } + + b = parseDisplayNameType(s); + if (b != null) { + return b; + } + + b = parseRegexType(s); + if (b != null) { + return b; + } + + return new Permission.Builder().permission(s); + } + + private static InheritanceNode.@Nullable Builder parseInheritanceType(String s) { + s = s.toLowerCase(); + if (!s.startsWith(GROUP_NODE_MARKER)) { + return null; + } + + String groupName = s.substring(GROUP_NODE_MARKER.length()).intern(); + return new Inheritance.Builder().group(groupName); + } + + private static MetaNode.@Nullable Builder parseMetaType(String s) { + if (!s.toLowerCase().startsWith(META_NODE_MARKER)) { + return null; + } + + Iterator metaParts = META_SPLITTER.split(s.substring(META_NODE_MARKER.length())).iterator(); + + if (!metaParts.hasNext()) return null; + String key = metaParts.next(); + + if (!metaParts.hasNext()) return null; + String value = metaParts.next(); + + return new Meta.Builder() + .key(Delimiters.unescapeCharacters(key).intern()) + .value(Delimiters.unescapeCharacters(value).intern()); + } + + private static PrefixNode.@Nullable Builder parsePrefixType(String s) { + if (!s.toLowerCase().startsWith(PREFIX_NODE_MARKER)) { + return null; + } + + Iterator metaParts = META_SPLITTER.split(s.substring(PREFIX_NODE_MARKER.length())).iterator(); + + if (!metaParts.hasNext()) return null; + String priority = metaParts.next(); + + if (!metaParts.hasNext()) return null; + String value = metaParts.next(); + + try { + int p = Integer.parseInt(priority); + String v = Delimiters.unescapeCharacters(value).intern(); + return new Prefix.Builder().priority(p).prefix(v); + } catch (NumberFormatException e) { + return null; + } + } + + private static SuffixNode.@Nullable Builder parseSuffixType(String s) { + if (!s.toLowerCase().startsWith(SUFFIX_NODE_MARKER)) { + return null; + } + + Iterator metaParts = META_SPLITTER.split(s.substring(SUFFIX_NODE_MARKER.length())).iterator(); + + if (!metaParts.hasNext()) return null; + String priority = metaParts.next(); + + if (!metaParts.hasNext()) return null; + String value = metaParts.next(); + + try { + int p = Integer.parseInt(priority); + String v = Delimiters.unescapeCharacters(value).intern(); + return new Suffix.Builder().priority(p).suffix(v); + } catch (NumberFormatException e) { + return null; + } + } + + private static WeightNode.@Nullable Builder parseWeightType(String s) { + String lower = s.toLowerCase(); + if (!lower.startsWith(WEIGHT_NODE_MARKER)) { + return null; + } + String i = lower.substring(WEIGHT_NODE_MARKER.length()); + try { + return new Weight.Builder().weight(Integer.parseInt(i)); + } catch (NumberFormatException e) { + return null; + } + } + + private static DisplayNameNode.@Nullable Builder parseDisplayNameType(String s) { + if (!s.toLowerCase().startsWith(DISPLAY_NAME_NODE_MARKER)) { + return null; + } + + return new DisplayName.Builder().displayName(s.substring(DISPLAY_NAME_NODE_MARKER.length())); + } + + private static RegexPermissionNode.@Nullable Builder parseRegexType(String s) { + if (!s.startsWith(REGEX_MARKER_1) && !s.startsWith(REGEX_MARKER_2)) { + return null; + } + + return new RegexPermission.Builder().pattern(s.substring(2)); + } + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/model/ForwardingNode.java b/common/src/main/java/me/lucko/luckperms/common/node/model/ForwardingNode.java deleted file mode 100644 index 6a25e94f9..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/node/model/ForwardingNode.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 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.node.model; - -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.NodeEqualityPredicate; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.context.ContextSet; -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -public abstract class ForwardingNode implements Node { - - static ImmutableNode unwrapForwarding(Node node) { - while (node instanceof ForwardingNode) { - node = ((ForwardingNode) node).delegate(); - } - if (!(node instanceof ImmutableNode)) { - throw new IllegalArgumentException("Node type cannot be casted to ImmutableNode: " + node.getClass()); - } - return ((ImmutableNode) node); - } - - public abstract Node delegate(); - - @Override - public int hashCode() { - return delegate().hashCode(); - } - - @Override - public boolean equals(Object obj) { - return this == obj || delegate().equals(obj); - } - - @Override - public @NonNull String getPermission() { - return delegate().getPermission(); - } - - @Override - public boolean getValue() { - return delegate().getValue(); - } - - @Override - public @NonNull Tristate getTristate() { - return delegate().getTristate(); - } - - @Override - public boolean isNegated() { - return delegate().isNegated(); - } - - @Override - public boolean isOverride() { - return delegate().isOverride(); - } - - @Override - public @NonNull Optional getServer() { - return delegate().getServer(); - } - - @Override - public @NonNull Optional getWorld() { - return delegate().getWorld(); - } - - @Override - public boolean isServerSpecific() { - return delegate().isServerSpecific(); - } - - @Override - public boolean isWorldSpecific() { - return delegate().isWorldSpecific(); - } - - @Override - public boolean appliesGlobally() { - return delegate().appliesGlobally(); - } - - @Override - public boolean hasSpecificContext() { - return delegate().hasSpecificContext(); - } - - @Override - public boolean shouldApplyWithContext(@NonNull ContextSet contextSet) { - return delegate().shouldApplyWithContext(contextSet); - } - - @Override - public @NonNull List resolveShorthand() { - return delegate().resolveShorthand(); - } - - @Override - public boolean isTemporary() { - return delegate().isTemporary(); - } - - @Override - public boolean isPermanent() { - return delegate().isPermanent(); - } - - @Override - public long getExpiryUnixTime() throws IllegalStateException { - return delegate().getExpiryUnixTime(); - } - - @Override - public @NonNull Date getExpiry() throws IllegalStateException { - return delegate().getExpiry(); - } - - @Override - public long getSecondsTilExpiry() throws IllegalStateException { - return delegate().getSecondsTilExpiry(); - } - - @Override - public boolean hasExpired() { - return delegate().hasExpired(); - } - - @Override - public @NonNull ContextSet getContexts() { - return delegate().getContexts(); - } - - @Override - public @NonNull ContextSet getFullContexts() { - return delegate().getFullContexts(); - } - - @Override - public boolean isGroupNode() { - return delegate().isGroupNode(); - } - - @Override - public @NonNull String getGroupName() throws IllegalStateException { - return delegate().getGroupName(); - } - - @Override - public boolean isWildcard() { - return delegate().isWildcard(); - } - - @Override - public int getWildcardLevel() throws IllegalStateException { - return delegate().getWildcardLevel(); - } - - @Override - public boolean hasTypeData() { - return delegate().hasTypeData(); - } - - @Override - public Optional getTypeData(NodeTypeKey key) { - return delegate().getTypeData(key); - } - - @Override - public T typeData(NodeTypeKey key) throws IllegalStateException { - return delegate().typeData(key); - } - - @Override - public boolean isMeta() { - return delegate().isMeta(); - } - - @Override - public Map.@NonNull Entry getMeta() throws IllegalStateException { - return delegate().getMeta(); - } - - @Override - public boolean isPrefix() { - return delegate().isPrefix(); - } - - @Override - public Map.@NonNull Entry getPrefix() throws IllegalStateException { - return delegate().getPrefix(); - } - - @Override - public boolean isSuffix() { - return delegate().isSuffix(); - } - - @Override - public Map.@NonNull Entry getSuffix() throws IllegalStateException { - return delegate().getSuffix(); - } - - @Override - public boolean equals(Node other, NodeEqualityPredicate equalityPredicate) { - return delegate().equals(other, equalityPredicate); - } - - @Override - public Builder toBuilder() { - return delegate().toBuilder(); - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableLocalizedNode.java b/common/src/main/java/me/lucko/luckperms/common/node/model/HeldNodeImpl.java similarity index 61% rename from common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableLocalizedNode.java rename to common/src/main/java/me/lucko/luckperms/common/node/model/HeldNodeImpl.java index 0b67082f4..75848e622 100644 --- a/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableLocalizedNode.java +++ b/common/src/main/java/me/lucko/luckperms/common/node/model/HeldNodeImpl.java @@ -25,35 +25,23 @@ package me.lucko.luckperms.common.node.model; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.HeldNode; +import me.lucko.luckperms.api.node.Node; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.Objects; +public final class HeldNodeImpl> implements HeldNode { -/** - * Holds a Node and where it was inherited from. All calls are passed onto the contained Node instance. - */ -public final class ImmutableLocalizedNode extends ForwardingNode implements LocalizedNode { - public static ImmutableLocalizedNode of(Node node, String location) { - Objects.requireNonNull(node, "node"); - Objects.requireNonNull(location, "location"); - - return new ImmutableLocalizedNode(node, location); + public static > HeldNodeImpl of(T holder, Node node) { + return new HeldNodeImpl<>(holder, node); } + private final T holder; private final Node node; - private final String location; - private ImmutableLocalizedNode(Node node, String location) { + private HeldNodeImpl(T holder, Node node) { + this.holder = holder; this.node = node; - this.location = location; - } - - @Override - public Node delegate() { - return this.node; } @Override @@ -62,12 +50,24 @@ public final class ImmutableLocalizedNode extends ForwardingNode implements Loca } @Override - public @NonNull String getLocation() { - return this.location; + public @NonNull T getHolder() { + return this.holder; } @Override - public String toString() { - return "ImmutableLocalizedNode(node=" + this.getNode() + ", location=" + this.getLocation() + ")"; + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof HeldNodeImpl)) return false; + final HeldNodeImpl other = (HeldNodeImpl) o; + return this.getHolder().equals(other.getHolder()) && this.getNode().equals(other.getNode()); + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.getHolder().hashCode(); + result = result * PRIME + this.getNode().hashCode(); + return result; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableNode.java b/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableNode.java deleted file mode 100644 index f27498e3d..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/node/model/ImmutableNode.java +++ /dev/null @@ -1,415 +0,0 @@ -/* - * 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.node.model; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; - -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.NodeEqualityPredicate; -import me.lucko.luckperms.api.StandardNodeEquality; -import me.lucko.luckperms.api.context.ContextSet; -import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.api.context.MutableContextSet; -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; -import me.lucko.luckperms.api.nodetype.types.RegexType; -import me.lucko.luckperms.common.calculator.processor.WildcardProcessor; -import me.lucko.luckperms.common.node.factory.NodeBuilder; -import me.lucko.luckperms.common.node.utils.ShorthandParser; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -/** - * An immutable implementation of {@link Node}. - */ -@SuppressWarnings("OptionalUsedAsFieldOrParameterType") -public final class ImmutableNode implements Node { - - /** - * The character which separates each part of a permission node - */ - public static final char NODE_SEPARATOR = '.'; - - /** - * The numeric value of {@link #NODE_SEPARATOR} - */ - public static final int NODE_SEPARATOR_CODE = Character.getNumericValue(NODE_SEPARATOR); - - // node attributes - - private final String permission; - private final boolean value; - private boolean override; - - private final @Nullable String server; - private final @Nullable String world; - - private final long expireAt; // 0L for no expiry - private final ImmutableContextSet contexts; - private final ImmutableContextSet fullContexts; - - - - // cached state - private final Optional optServer; - private final Optional optWorld; - - // this class is immutable, so we can cache the hashcode calculation - private final int hashCode; - - private final int wildcardLevel; - private final Map, NodeType> resolvedTypes; - private final List resolvedShorthand; - - /** - * Make an immutable node instance - * - * @param permission the actual permission node - * @param value the value (if it's *not* negated) - * @param expireAt the time when the node will expire - * @param server the server this node applies on - * @param world the world this node applies on - * @param contexts any additional contexts applying to this node - */ - public ImmutableNode(String permission, boolean value, boolean override, long expireAt, String server, String world, ContextSet contexts) { - if (permission == null || permission.isEmpty()) { - throw new IllegalArgumentException("Empty permission"); - } - - // standardize server/world values. - server = standardizeServerWorld(server); - world = standardizeServerWorld(world); - - // define core attributes - this.permission = permission.intern(); - this.value = value; - this.override = override; - this.expireAt = expireAt; - this.server = internString(server); - this.world = internString(world); - this.contexts = contexts == null ? ContextSet.empty() : contexts.makeImmutable(); - - // define cached state - this.wildcardLevel = this.permission.endsWith(WildcardProcessor.WILDCARD_SUFFIX) ? this.permission.chars().filter(num -> num == NODE_SEPARATOR_CODE).sum() : -1; - this.resolvedTypes = NodeTypes.parseTypes(this.permission); - this.resolvedShorthand = this.resolvedTypes.containsKey(RegexType.KEY) ? ImmutableList.of() : ImmutableList.copyOf(ShorthandParser.parseShorthand(getPermission())); - this.optServer = Optional.ofNullable(this.server); - this.optWorld = Optional.ofNullable(this.world); - - // calculate the "full" context set - if (this.server != null || this.world != null) { - MutableContextSet fullContexts = this.contexts.mutableCopy(); - if (this.server != null) { - fullContexts.add(Contexts.SERVER_KEY, this.server); - } - if (this.world != null) { - fullContexts.add(Contexts.WORLD_KEY, this.world); - } - - this.fullContexts = fullContexts.makeImmutable(); - } else { - this.fullContexts = this.contexts; - } - - this.hashCode = calculateHashCode(); - } - - @Override - public Builder toBuilder() { - return new NodeBuilder(this); - } - - @Override - public @NonNull String getPermission() { - return this.permission; - } - - @Override - public boolean getValue() { - return this.value; - } - - @Override - public boolean isOverride() { - return this.override; - } - - @Override - public @NonNull Optional getServer() { - return this.optServer; - } - - @Override - public @NonNull Optional getWorld() { - return this.optWorld; - } - - @Override - public boolean isServerSpecific() { - return this.server != null; - } - - @Override - public boolean isWorldSpecific() { - return this.world != null; - } - - @Override - public @NonNull ImmutableContextSet getContexts() { - return this.contexts; - } - - @Override - public @NonNull ImmutableContextSet getFullContexts() { - return this.fullContexts; - } - - @Override - public boolean appliesGlobally() { - return this.server == null && this.world == null && this.contexts.isEmpty(); - } - - @Override - public boolean hasSpecificContext() { - return this.server != null || this.world != null || !this.contexts.isEmpty(); - } - - @Override - public boolean shouldApplyWithContext(@NonNull ContextSet contextSet) { - return getFullContexts().isSatisfiedBy(contextSet); - } - - @Override - public boolean isTemporary() { - return this.expireAt != 0L; - } - - @Override - public long getExpiryUnixTime() { - Preconditions.checkState(isTemporary(), "Node does not have an expiry time."); - return this.expireAt; - } - - @Override - public @NonNull Date getExpiry() { - Preconditions.checkState(isTemporary(), "Node does not have an expiry time."); - return new Date(this.expireAt * 1000L); - } - - @Override - public long getSecondsTilExpiry() { - Preconditions.checkState(isTemporary(), "Node does not have an expiry time."); - return this.expireAt - System.currentTimeMillis() / 1000L; - } - - @Override - public boolean hasExpired() { - return isTemporary() && this.expireAt < System.currentTimeMillis() / 1000L; - } - - @Override - public boolean isWildcard() { - return this.wildcardLevel != -1; - } - - @Override - public int getWildcardLevel() { - Preconditions.checkState(isWildcard(), "Node is not a wildcard"); - return this.wildcardLevel; - } - - @Override - public boolean hasTypeData() { - return !this.resolvedTypes.isEmpty(); - } - - @Override - public Optional getTypeData(NodeTypeKey key) { - Objects.requireNonNull(key, "key"); - - //noinspection unchecked - T result = (T) this.resolvedTypes.get(key); - return Optional.ofNullable(result); - } - - @Override - public @NonNull List resolveShorthand() { - return this.resolvedShorthand; - } - - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof Node)) return false; - return Equality.EXACT.areEqual(this, ForwardingNode.unwrapForwarding((Node) o)); - } - - @Override - public boolean equals(Node o, NodeEqualityPredicate equalityPredicate) { - if (equalityPredicate instanceof StandardNodeEquality) { - StandardNodeEquality stdEqualityPredicate = (StandardNodeEquality) equalityPredicate; - ImmutableNode other = ForwardingNode.unwrapForwarding(o); - switch (stdEqualityPredicate) { - case EXACT: - return Equality.EXACT.areEqual(this, other); - case IGNORE_VALUE: - return Equality.IGNORE_VALUE.areEqual(this, other); - case IGNORE_EXPIRY_TIME: - return Equality.IGNORE_EXPIRY_TIME.areEqual(this, other); - case IGNORE_EXPIRY_TIME_AND_VALUE: - return Equality.IGNORE_EXPIRY_TIME_AND_VALUE.areEqual(this, other); - case IGNORE_VALUE_OR_IF_TEMPORARY: - return Equality.IGNORE_VALUE_OR_IF_TEMPORARY.areEqual(this, other); - default: - throw new AssertionError(); - } - } - - return equalityPredicate.areEqual(this, o); - } - - @Override - public int hashCode() { - return this.hashCode; - } - - private int calculateHashCode() { - final int PRIME = 59; - int result = 1; - result = result * PRIME + this.permission.hashCode(); - result = result * PRIME + (this.value ? 79 : 97); - result = result * PRIME + (this.override ? 79 : 97); - result = result * PRIME + (this.server == null ? 43 : this.server.hashCode()); - result = result * PRIME + (this.world == null ? 43 : this.world.hashCode()); - result = result * PRIME + (int) (this.expireAt >>> 32 ^ this.expireAt); - result = result * PRIME + this.contexts.hashCode(); - return result; - } - - @SuppressWarnings("StringEquality") - private enum Equality { - EXACT { - @Override - public boolean areEqual(@NonNull ImmutableNode o1, @NonNull ImmutableNode o2) { - return o1 == o2 || - o1.permission == o2.permission && - o1.value == o2.value && - o1.override == o2.override && - Objects.equals(o1.server, o2.server) && - Objects.equals(o1.world, o2.world) && - o1.expireAt == o2.expireAt && - o1.getContexts().equals(o2.getContexts()); - } - }, - IGNORE_VALUE { - @Override - public boolean areEqual(@NonNull ImmutableNode o1, @NonNull ImmutableNode o2) { - return o1 == o2 || - o1.permission == o2.permission && - o1.override == o2.override && - Objects.equals(o1.server, o2.server) && - Objects.equals(o1.world, o2.world) && - o1.expireAt == o2.expireAt && - o1.getContexts().equals(o2.getContexts()); - } - }, - IGNORE_EXPIRY_TIME { - @Override - public boolean areEqual(@NonNull ImmutableNode o1, @NonNull ImmutableNode o2) { - return o1 == o2 || - o1.permission == o2.permission && - o1.value == o2.value && - o1.override == o2.override && - Objects.equals(o1.server, o2.server) && - Objects.equals(o1.world, o2.world) && - o1.isTemporary() == o2.isTemporary() && - o1.getContexts().equals(o2.getContexts()); - } - }, - IGNORE_EXPIRY_TIME_AND_VALUE { - @Override - public boolean areEqual(@NonNull ImmutableNode o1, @NonNull ImmutableNode o2) { - return o1 == o2 || - o1.permission == o2.permission && - o1.override == o2.override && - Objects.equals(o1.server, o2.server) && - Objects.equals(o1.world, o2.world) && - o1.isTemporary() == o2.isTemporary() && - o1.getContexts().equals(o2.getContexts()); - } - }, - IGNORE_VALUE_OR_IF_TEMPORARY { - @Override - public boolean areEqual(@NonNull ImmutableNode o1, @NonNull ImmutableNode o2) { - return o1 == o2 || - o1.permission == o2.permission && - o1.override == o2.override && - Objects.equals(o1.server, o2.server) && - Objects.equals(o1.world, o2.world) && - o1.getContexts().equals(o2.getContexts()); - } - }; - - public abstract boolean areEqual(@NonNull ImmutableNode o1, @NonNull ImmutableNode o2); - } - - private static String internString(String s) { - return s == null ? null : s.intern(); - } - - private static String standardizeServerWorld(String s) { - if (s != null) { - s = s.toLowerCase(); - - if (s.equals("global") || s.isEmpty()) { - s = null; - } - } - - return s; - } - - @Override - public String toString() { - return "ImmutableNode(" + - "permission=" + this.permission + ", " + - "value=" + this.value + ", " + - "override=" + this.override + ", " + - "server=" + this.getServer() + ", " + - "world=" + this.getWorld() + ", " + - "expireAt=" + this.expireAt + ", " + - "contexts=" + this.contexts + ")"; - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/model/InheritanceOrigin.java b/common/src/main/java/me/lucko/luckperms/common/node/model/InheritanceOrigin.java new file mode 100644 index 000000000..56475870e --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/model/InheritanceOrigin.java @@ -0,0 +1,43 @@ +/* + * 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.node.model; + +import me.lucko.luckperms.api.node.metadata.types.InheritanceOriginMetadata; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public class InheritanceOrigin implements InheritanceOriginMetadata { + private final String location; + + public InheritanceOrigin(String location) { + this.location = location; + } + + @Override + public @NonNull String getOrigin() { + return this.location; + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/model/NodeDataContainer.java b/common/src/main/java/me/lucko/luckperms/common/node/model/NodeDataContainer.java index b84cf03b9..fd4cf2d14 100644 --- a/common/src/main/java/me/lucko/luckperms/common/node/model/NodeDataContainer.java +++ b/common/src/main/java/me/lucko/luckperms/common/node/model/NodeDataContainer.java @@ -25,11 +25,16 @@ package me.lucko.luckperms.common.node.model; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.node.factory.NodeFactory; import java.util.Objects; +import java.util.Optional; +import java.util.Set; /** * An stripped down version of {@link Node}, without methods and cached values @@ -40,14 +45,36 @@ import java.util.Objects; public final class NodeDataContainer { public static NodeDataContainer fromNode(Node node) { - NodeDataContainer model = of( - node.getPermission(), - node.getValue(), - node.getServer().orElse("global"), - node.getWorld().orElse("global"), - node.isTemporary() ? node.getExpiryUnixTime() : 0L, - node.getContexts().makeImmutable() - ); + ContextSet contexts = node.getContexts(); + + Set servers = contexts.getValues(DefaultContextKeys.SERVER_KEY); + Optional firstServer = servers.stream().sorted().findFirst(); + + String server; + if (firstServer.isPresent()) { + server = firstServer.get(); + MutableContextSet mutableContextSet = contexts.mutableCopy(); + mutableContextSet.remove(DefaultContextKeys.SERVER_KEY, server); + contexts = mutableContextSet; + } else { + server = "global"; + } + + Set worlds = contexts.getValues(DefaultContextKeys.WORLD_KEY); + Optional firstWorld = worlds.stream().sorted().findFirst(); + + String world; + if (firstWorld.isPresent()) { + world = firstWorld.get(); + MutableContextSet mutableContextSet = contexts instanceof MutableContextSet ? (MutableContextSet) contexts : contexts.mutableCopy(); + mutableContextSet.remove(DefaultContextKeys.WORLD_KEY, world); + contexts = mutableContextSet; + } else { + world = "global"; + } + + + NodeDataContainer model = of(node.getKey(), node.getValue(), server, world, node.hasExpiry() ? node.getExpiry().getEpochSecond() : 0L, contexts.immutableCopy()); model.node = node; return model; } @@ -80,11 +107,11 @@ public final class NodeDataContainer { public synchronized Node toNode() { if (this.node == null) { this.node = NodeFactory.builder(this.permission) - .setValue(this.value) - .setServer(this.server) - .setWorld(this.world) - .setExpiry(this.expiry) - .withExtraContext(this.contexts) + .value(this.value) + .withContext(DefaultContextKeys.SERVER_KEY, this.server) + .withContext(DefaultContextKeys.WORLD_KEY, this.world) + .expiry(this.expiry) + .withContext(this.contexts) .build(); } diff --git a/common/src/main/java/me/lucko/luckperms/common/node/model/NodeHeldPermission.java b/common/src/main/java/me/lucko/luckperms/common/node/model/NodeHeldPermission.java deleted file mode 100644 index 7554e0911..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/node/model/NodeHeldPermission.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.node.model; - -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.context.ContextSet; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.Optional; -import java.util.OptionalLong; - -public final class NodeHeldPermission> implements HeldPermission { - public static > NodeHeldPermission of(T holder, NodeDataContainer node) { - return of(holder, node.toNode()); - } - - public static > NodeHeldPermission of(T holder, Node node) { - return new NodeHeldPermission<>(holder, node); - } - - private final T holder; - private final Node node; - - private NodeHeldPermission(T holder, Node node) { - this.holder = holder; - this.node = node; - } - - @Override - public @NonNull String getPermission() { - return this.node.getPermission(); - } - - @Override - public boolean getValue() { - return this.node.getValue(); - } - - @Override - public @NonNull Optional getServer() { - return this.node.getServer(); - } - - @Override - public @NonNull Optional getWorld() { - return this.node.getWorld(); - } - - @Override - public @NonNull OptionalLong getExpiry() { - return this.node.isTemporary() ? OptionalLong.of(this.node.getExpiryUnixTime()) : OptionalLong.empty(); - } - - @Override - public @NonNull ContextSet getContexts() { - return this.node.getContexts(); - } - - @Override - public @NonNull Node asNode() { - return this.node; - } - - @Override - public @NonNull T getHolder() { - return this.holder; - } - - public Node getNode() { - return this.node; - } - - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof NodeHeldPermission)) return false; - final NodeHeldPermission other = (NodeHeldPermission) o; - return this.getHolder().equals(other.getHolder()) && this.getNode().equals(other.getNode()); - } - - @Override - public int hashCode() { - final int PRIME = 59; - int result = 1; - result = result * PRIME + this.getHolder().hashCode(); - result = result * PRIME + this.getNode().hashCode(); - return result; - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/model/NodeTypes.java b/common/src/main/java/me/lucko/luckperms/common/node/model/NodeTypes.java deleted file mode 100644 index 4c00f0bc5..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/node/model/NodeTypes.java +++ /dev/null @@ -1,513 +0,0 @@ -/* - * 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.node.model; - -import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableMap; - -import me.lucko.luckperms.api.nodetype.NodeType; -import me.lucko.luckperms.api.nodetype.NodeTypeKey; -import me.lucko.luckperms.api.nodetype.types.DisplayNameType; -import me.lucko.luckperms.api.nodetype.types.InheritanceType; -import me.lucko.luckperms.api.nodetype.types.MetaType; -import me.lucko.luckperms.api.nodetype.types.PrefixType; -import me.lucko.luckperms.api.nodetype.types.RegexType; -import me.lucko.luckperms.api.nodetype.types.SuffixType; -import me.lucko.luckperms.api.nodetype.types.WeightType; -import me.lucko.luckperms.common.cache.Cache; -import me.lucko.luckperms.common.cache.PatternCache; -import me.lucko.luckperms.common.node.factory.LegacyNodeFactory; - -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.regex.Pattern; - -public final class NodeTypes { - private NodeTypes() {} - - public static final String PREFIX_KEY = "prefix"; - public static final String SUFFIX_KEY = "suffix"; - public static final String META_KEY = "meta"; - public static final String WEIGHT_KEY = "weight"; - public static final String DISPLAY_NAME_KEY = "displayname"; - - public static final String GROUP_NODE_MARKER = "group."; - public static final String PREFIX_NODE_MARKER = PREFIX_KEY + "."; - public static final String SUFFIX_NODE_MARKER = SUFFIX_KEY + "."; - public static final String META_NODE_MARKER = META_KEY + "."; - public static final String WEIGHT_NODE_MARKER = WEIGHT_KEY + "."; - public static final String DISPLAY_NAME_NODE_MARKER = DISPLAY_NAME_KEY + "."; - public static final String REGEX_MARKER_1 = "r="; - public static final String REGEX_MARKER_2 = "R="; - - // used to split prefix/suffix/meta nodes - private static final Splitter META_SPLITTER = Splitter.on(PatternCache.compileDelimiterPattern(".", "\\")).limit(2); - - public static @NonNull Map, NodeType> parseTypes(String s) { - Map, NodeType> results = new IdentityHashMap<>(); - - NodeType type = parseInheritanceType(s); - if (type != null) { - results.put(InheritanceType.KEY, type); - } - - type = parseMetaType(s); - if (type != null) { - results.put(MetaType.KEY, type); - } - - type = parsePrefixType(s); - if (type != null) { - results.put(PrefixType.KEY, type); - } - - type = parseSuffixType(s); - if (type != null) { - results.put(SuffixType.KEY, type); - } - - type = parseWeightType(s); - if (type != null) { - results.put(WeightType.KEY, type); - } - - type = parseDisplayNameType(s); - if (type != null) { - results.put(DisplayNameType.KEY, type); - } - - type = parseRegexType(s); - if (type != null) { - results.put(RegexType.KEY, type); - } - - if (results.isEmpty()) { - return ImmutableMap.of(); - } - - return results; - } - - public static @Nullable InheritanceType parseInheritanceType(String s) { - s = s.toLowerCase(); - if (!s.startsWith(GROUP_NODE_MARKER)) { - return null; - } - - String groupName = s.substring(GROUP_NODE_MARKER.length()).intern(); - return new Inheritance(groupName); - } - - public static @Nullable MetaType parseMetaType(String s) { - if (!s.toLowerCase().startsWith(META_NODE_MARKER)) { - return null; - } - - Iterator metaParts = META_SPLITTER.split(s.substring(META_NODE_MARKER.length())).iterator(); - - if (!metaParts.hasNext()) return null; - String key = metaParts.next(); - - if (!metaParts.hasNext()) return null; - String value = metaParts.next(); - - return new Meta( - LegacyNodeFactory.unescapeCharacters(key).intern(), - LegacyNodeFactory.unescapeCharacters(value).intern() - ); - } - - public static @Nullable PrefixType parsePrefixType(String s) { - if (!s.toLowerCase().startsWith(PREFIX_NODE_MARKER)) { - return null; - } - - Iterator metaParts = META_SPLITTER.split(s.substring(PREFIX_NODE_MARKER.length())).iterator(); - - if (!metaParts.hasNext()) return null; - String priority = metaParts.next(); - - if (!metaParts.hasNext()) return null; - String value = metaParts.next(); - - try { - int p = Integer.parseInt(priority); - String v = LegacyNodeFactory.unescapeCharacters(value).intern(); - return new Prefix(p, v); - } catch (NumberFormatException e) { - return null; - } - } - - public static @Nullable SuffixType parseSuffixType(String s) { - if (!s.toLowerCase().startsWith(SUFFIX_NODE_MARKER)) { - return null; - } - - Iterator metaParts = META_SPLITTER.split(s.substring(SUFFIX_NODE_MARKER.length())).iterator(); - - if (!metaParts.hasNext()) return null; - String priority = metaParts.next(); - - if (!metaParts.hasNext()) return null; - String value = metaParts.next(); - - try { - int p = Integer.parseInt(priority); - String v = LegacyNodeFactory.unescapeCharacters(value).intern(); - return new Suffix(p, v); - } catch (NumberFormatException e) { - return null; - } - } - - public static @Nullable WeightType parseWeightType(String s) { - String lower = s.toLowerCase(); - if (!lower.startsWith(WEIGHT_NODE_MARKER)) { - return null; - } - String i = lower.substring(WEIGHT_NODE_MARKER.length()); - try { - return new Weight(Integer.parseInt(i)); - } catch (NumberFormatException e) { - return null; - } - } - - public static @Nullable DisplayNameType parseDisplayNameType(String s) { - if (!s.toLowerCase().startsWith(DISPLAY_NAME_NODE_MARKER)) { - return null; - } - - return new DisplayName(s.substring(DISPLAY_NAME_NODE_MARKER.length())); - } - - public static @Nullable RegexType parseRegexType(String s) { - if (!s.startsWith(REGEX_MARKER_1) && !s.startsWith(REGEX_MARKER_2)) { - return null; - } - - return new Regex(s.substring(2)); - } - - private static final class Inheritance implements InheritanceType { - private final String groupName; - - private Inheritance(String groupName) { - this.groupName = groupName; - } - - @Override - public @NonNull String getGroupName() { - return this.groupName; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Inheritance that = (Inheritance) o; - return Objects.equals(this.groupName, that.groupName); - } - - @Override - public int hashCode() { - return Objects.hash(this.groupName); - } - - @Override - public String toString() { - return "InheritanceType{groupName='" + this.groupName + "'}"; - } - } - - private static final class Meta implements MetaType { - private final String key; - private final String value; - - private Meta(String key, String value) { - this.key = key; - this.value = value; - } - - @Override - public @NonNull String getKey() { - return this.key; - } - - @Override - public @NonNull String getValue() { - return this.value; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Meta that = (Meta) o; - return Objects.equals(this.key, that.key) && - Objects.equals(this.value, that.value); - } - - @Override - public int hashCode() { - return Objects.hash(this.key, this.value); - } - - @Override - public String toString() { - return "MetaType{key='" + this.key + "', value='" + this.value + "'}"; - } - } - - private static final class Prefix implements PrefixType, Map.Entry { - private final int priority; - private final String prefix; - - private Prefix(int priority, String prefix) { - this.priority = priority; - this.prefix = prefix; - } - - @Override - public int getPriority() { - return this.priority; - } - - @Override - public @NonNull String getPrefix() { - return this.prefix; - } - - @Override - public Map.@NonNull Entry getAsEntry() { - return this; - } - - @Override - public Integer getKey() { - return getPriority(); - } - - @Override - public String getValue() { - return getPrefix(); - } - - @Override - public String setValue(String value) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Prefix that = (Prefix) o; - return this.priority == that.priority && - Objects.equals(this.prefix, that.prefix); - } - - @Override - public int hashCode() { - return Objects.hash(this.priority, this.prefix); - } - - @Override - public String toString() { - return "PrefixType{priority=" + this.priority + ", prefix='" + this.prefix + "'}"; - } - } - - private static final class Suffix implements SuffixType, Map.Entry { - private final int priority; - private final String suffix; - - private Suffix(int priority, String suffix) { - this.priority = priority; - this.suffix = suffix; - } - - @Override - public int getPriority() { - return this.priority; - } - - @Override - public @NonNull String getSuffix() { - return this.suffix; - } - - @Override - public Map.@NonNull Entry getAsEntry() { - return this; - } - - @Override - public Integer getKey() { - return getPriority(); - } - - @Override - public String getValue() { - return getSuffix(); - } - - @Override - public String setValue(String value) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Suffix that = (Suffix) o; - return this.priority == that.priority && - Objects.equals(this.suffix, that.suffix); - } - - @Override - public int hashCode() { - return Objects.hash(this.priority, this.suffix); - } - - @Override - public String toString() { - return "SuffixType{priority=" + this.priority + ", suffix='" + this.suffix + "'}"; - } - } - - private static final class Weight implements WeightType { - private final int weight; - - private Weight(int weight) { - this.weight = weight; - } - - @Override - public int getWeight() { - return this.weight; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Weight that = (Weight) o; - return this.weight == that.weight; - } - - @Override - public int hashCode() { - return Objects.hash(this.weight); - } - - @Override - public String toString() { - return "WeightType{weight=" + this.weight + '}'; - } - } - - private static final class DisplayName implements DisplayNameType { - private final String displayName; - - private DisplayName(String displayName) { - this.displayName = displayName; - } - - @Override - public @NonNull String getDisplayName() { - return this.displayName; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - DisplayName that = (DisplayName) o; - return Objects.equals(this.displayName, that.displayName); - } - - @Override - public int hashCode() { - return Objects.hash(this.displayName); - } - - @Override - public String toString() { - return "DisplayName{displayName='" + this.displayName + '\'' + '}'; - } - } - - private static final class Regex extends Cache implements RegexType { - private final String patternString; - - private Regex(String patternString) { - this.patternString = patternString; - } - - @Override - protected PatternCache.@NonNull CachedPattern supply() { - return PatternCache.lookup(this.patternString); - } - - @Override - public @NonNull String getPatternString() { - return this.patternString; - } - - @Override - public @NonNull Optional getPattern() { - return Optional.ofNullable(get().getPattern()); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Regex that = (Regex) o; - return Objects.equals(this.patternString, that.patternString); - } - - @Override - public int hashCode() { - return Objects.hash(this.patternString); - } - - @Override - public String toString() { - return "Regex{pattern=" + this.patternString + '}'; - } - } - -} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/types/DisplayName.java b/common/src/main/java/me/lucko/luckperms/common/node/types/DisplayName.java new file mode 100644 index 000000000..11480e734 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/types/DisplayName.java @@ -0,0 +1,83 @@ +/* + * 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.node.types; + +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.node.types.DisplayNameNode; +import me.lucko.luckperms.common.node.AbstractNode; +import me.lucko.luckperms.common.node.AbstractNodeBuilder; +import me.lucko.luckperms.common.node.factory.NodeFactory; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Map; +import java.util.Objects; + +public class DisplayName extends AbstractNode implements DisplayNameNode { + private final String displayName; + + public DisplayName(String displayName, boolean value, long expireAt, ImmutableContextSet contexts, Map, NodeMetadata> metadata) { + super(NodeFactory.displayName(displayName), value, expireAt, contexts, metadata); + this.displayName = displayName; + } + + @Override + public @NonNull String getDisplayName() { + return this.displayName; + } + + @Override + public @NonNull Builder toBuilder() { + return new Builder(this.displayName, this.value, this.expireAt, this.contexts, this.metadata); + } + + public static final class Builder extends AbstractNodeBuilder implements DisplayNameNode.Builder { + private String displayName; + + public Builder() { + this.displayName = null; + } + + public Builder(String displayName, boolean value, long expireAt, ImmutableContextSet context, Map, NodeMetadata> metadata) { + super(value, expireAt, context, metadata); + this.displayName = displayName; + } + + @Override + public @NonNull Builder displayName(@NonNull String displayName) { + this.displayName = displayName; + return this; + } + + @Override + public @NonNull DisplayName build() { + Objects.requireNonNull(this.displayName, "displayName"); + return new DisplayName(this.displayName, this.value, this.expireAt, this.context.build(), this.metadata); + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/types/Inheritance.java b/common/src/main/java/me/lucko/luckperms/common/node/types/Inheritance.java new file mode 100644 index 000000000..f84ca37e2 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/types/Inheritance.java @@ -0,0 +1,90 @@ +/* + * 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.node.types; + +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.model.group.Group; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.common.node.AbstractNode; +import me.lucko.luckperms.common.node.AbstractNodeBuilder; +import me.lucko.luckperms.common.node.factory.NodeFactory; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Map; +import java.util.Objects; + +public class Inheritance extends AbstractNode implements InheritanceNode { + private final String groupName; + + public Inheritance(String groupName, boolean value, long expireAt, ImmutableContextSet contexts, Map, NodeMetadata> metadata) { + super(NodeFactory.groupNode(groupName), value, expireAt, contexts, metadata); + this.groupName = groupName; + } + + @Override + public @NonNull String getGroupName() { + return this.groupName; + } + + @Override + public @NonNull Builder toBuilder() { + return new Builder(this.groupName, this.value, this.expireAt, this.contexts, this.metadata); + } + + public static final class Builder extends AbstractNodeBuilder implements InheritanceNode.Builder { + private String groupName; + + public Builder() { + this.groupName = null; + } + + public Builder(String groupName, boolean value, long expireAt, ImmutableContextSet context, Map, NodeMetadata> metadata) { + super(value, expireAt, context, metadata); + this.groupName = groupName; + } + + @Override + public @NonNull Builder group(@NonNull String group) { + this.groupName = Objects.requireNonNull(group, "group"); + return this; + } + + @Override + public @NonNull Builder group(@NonNull Group group) { + this.groupName = Objects.requireNonNull(group, "group").getName(); + return this; + } + + @Override + public @NonNull Inheritance build() { + Objects.requireNonNull(this.groupName, "groupName"); + return new Inheritance(this.groupName, this.value, this.expireAt, this.context.build(), this.metadata); + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/types/Meta.java b/common/src/main/java/me/lucko/luckperms/common/node/types/Meta.java new file mode 100644 index 000000000..b9238de1a --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/types/Meta.java @@ -0,0 +1,100 @@ +/* + * 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.node.types; + +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.common.node.AbstractNode; +import me.lucko.luckperms.common.node.AbstractNodeBuilder; +import me.lucko.luckperms.common.node.factory.NodeFactory; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Map; +import java.util.Objects; + +public class Meta extends AbstractNode implements MetaNode { + private final String metaKey; + private final String metaValue; + + public Meta(String metaKey, String metaValue, boolean value, long expireAt, ImmutableContextSet contexts, Map, NodeMetadata> metadata) { + super(NodeFactory.metaNode(metaKey, metaValue), value, expireAt, contexts, metadata); + this.metaKey = metaKey; + this.metaValue = metaValue; + } + + @Override + public @NonNull String getMetaKey() { + return this.metaKey; + } + + @Override + public @NonNull String getMetaValue() { + return this.metaValue; + } + + @Override + public @NonNull Builder toBuilder() { + return new Builder(this.metaKey, this.metaValue, this.value, this.expireAt, this.contexts, this.metadata); + } + + public static final class Builder extends AbstractNodeBuilder implements MetaNode.Builder { + private String metaKey; + private String metaValue; + + public Builder() { + this.metaKey = null; + this.metaValue = null; + } + + public Builder(String metaKey, String metaValue, boolean value, long expireAt, ImmutableContextSet context, Map, NodeMetadata> metadata) { + super(value, expireAt, context, metadata); + this.metaKey = metaKey; + this.metaValue = metaValue; + } + + @Override + public @NonNull Builder key(@NonNull String key) { + this.metaKey = Objects.requireNonNull(key, "key"); + return this; + } + + @Override + public @NonNull Builder value(@NonNull String value) { + this.metaKey = Objects.requireNonNull(value, "value"); + return this; + } + + @Override + public @NonNull Meta build() { + Objects.requireNonNull(this.metaKey, "metaKey"); + Objects.requireNonNull(this.metaValue, "metaValue"); + return new Meta(this.metaKey, this.metaValue, this.value, this.expireAt, this.context.build(), this.metadata); + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/types/Permission.java b/common/src/main/java/me/lucko/luckperms/common/node/types/Permission.java new file mode 100644 index 000000000..f0491581e --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/types/Permission.java @@ -0,0 +1,103 @@ +/* + * 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.node.types; + +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.NodeBuilder; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.node.types.PermissionNode; +import me.lucko.luckperms.common.calculator.processor.WildcardProcessor; +import me.lucko.luckperms.common.node.AbstractNode; +import me.lucko.luckperms.common.node.AbstractNodeBuilder; +import me.lucko.luckperms.common.node.factory.NodeTypes; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Map; +import java.util.Objects; +import java.util.OptionalInt; + +public class Permission extends AbstractNode implements PermissionNode { + private final int wildcardLevel; + + public Permission(String permission, boolean value, long expireAt, ImmutableContextSet contexts, Map, NodeMetadata> metadata) { + super(permission, value, expireAt, contexts, metadata); + this.wildcardLevel = permission.endsWith(WildcardProcessor.WILDCARD_SUFFIX) ? permission.chars().filter(num -> num == NODE_SEPARATOR_CODE).sum() : -1; + } + + @Override + public @NonNull String getPermission() { + return getKey(); + } + + @Override + public boolean isWildcard() { + return this.wildcardLevel != -1; + } + + @Override + public @NonNull OptionalInt getWildcardLevel() { + return isWildcard() ? OptionalInt.of(this.wildcardLevel) : OptionalInt.empty(); + } + + @Override + public PermissionNode.@NonNull Builder toBuilder() { + return new Builder(this.key, this.value, this.expireAt, this.contexts, this.metadata); + } + + public static final class Builder extends AbstractNodeBuilder implements PermissionNode.Builder { + private String permission; + + public Builder() { + this.permission = null; + } + + public Builder(String permission, boolean value, long expireAt, ImmutableContextSet context, Map, NodeMetadata> metadata) { + super(value, expireAt, context, metadata); + this.permission = permission; + } + + @Override + public @NonNull Builder permission(@NonNull String permission) { + this.permission = Objects.requireNonNull(permission, "permission"); + return this; + } + + @Override + public @NonNull Permission build() { + Objects.requireNonNull(this.permission, "permission"); + + NodeBuilder testBuilder = NodeTypes.newBuilder(this.permission); + if (!(testBuilder instanceof Builder)) { + throw new IllegalArgumentException("Attempting to build non-permission node with PermissionNode.Builder. permission = '" + this.permission + "', correct builder type = " + testBuilder.getClass().getName()); + } + + return new Permission(this.permission, this.value, this.expireAt, this.context.build(), this.metadata); + } + } + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/types/Prefix.java b/common/src/main/java/me/lucko/luckperms/common/node/types/Prefix.java new file mode 100644 index 000000000..a0c5a5622 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/types/Prefix.java @@ -0,0 +1,106 @@ +/* + * 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.node.types; + +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.node.types.PrefixNode; +import me.lucko.luckperms.common.node.AbstractNode; +import me.lucko.luckperms.common.node.AbstractNodeBuilder; +import me.lucko.luckperms.common.node.factory.NodeFactory; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Map; +import java.util.Objects; + +public class Prefix extends AbstractNode implements PrefixNode { + private final String prefix; + private final int priority; + + public Prefix(String prefix, int priority, boolean value, long expireAt, ImmutableContextSet contexts, Map, NodeMetadata> metadata) { + super(NodeFactory.prefixNode(priority, prefix), value, expireAt, contexts, metadata); + this.prefix = prefix; + this.priority = priority; + } + + @Override + public int getPriority() { + return this.priority; + } + + @Override + public @NonNull String getMetaValue() { + return this.prefix; + } + + @Override + public @NonNull ChatMetaType getType() { + return ChatMetaType.PREFIX; + } + + @Override + public @NonNull Builder toBuilder() { + return new Builder(this.prefix, this.priority, this.value, this.expireAt, this.contexts, this.metadata); + } + + public static final class Builder extends AbstractNodeBuilder implements PrefixNode.Builder { + private String prefix; + private Integer priority; + + public Builder() { + this.prefix = null; + this.priority = null; + } + + public Builder(String prefix, int priority, boolean value, long expireAt, ImmutableContextSet context, Map, NodeMetadata> metadata) { + super(value, expireAt, context, metadata); + this.prefix = prefix; + this.priority = priority; + } + + @Override + public @NonNull Builder prefix(@NonNull String prefix) { + this.prefix = prefix; + return this; + } + + @Override + public @NonNull Builder priority(int priority) { + this.priority = priority; + return this; + } + + @Override + public @NonNull Prefix build() { + Objects.requireNonNull(this.prefix, "prefix"); + Objects.requireNonNull(this.priority, "priority"); + return new Prefix(this.prefix, this.priority, this.value, this.expireAt, this.context.build(), this.metadata); + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/types/RegexPermission.java b/common/src/main/java/me/lucko/luckperms/common/node/types/RegexPermission.java new file mode 100644 index 000000000..a4fed047d --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/types/RegexPermission.java @@ -0,0 +1,105 @@ +/* + * 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.node.types; + +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.node.types.RegexPermissionNode; +import me.lucko.luckperms.common.cache.Cache; +import me.lucko.luckperms.common.cache.PatternCache; +import me.lucko.luckperms.common.node.AbstractNode; +import me.lucko.luckperms.common.node.AbstractNodeBuilder; +import me.lucko.luckperms.common.node.factory.NodeFactory; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.regex.Pattern; + +public class RegexPermission extends AbstractNode implements RegexPermissionNode { + private final String pattern; + + private final Cache cache = new Cache() { + @Override + protected PatternCache.@NonNull CachedPattern supply() { + return PatternCache.lookup(RegexPermission.this.pattern); + } + }; + + public RegexPermission(String pattern, boolean value, long expireAt, ImmutableContextSet contexts, Map, NodeMetadata> metadata) { + super(NodeFactory.regexNode(pattern), value, expireAt, contexts, metadata); + this.pattern = pattern; + } + + @Override + public @NonNull String getPatternString() { + return this.pattern; + } + + @Override + public @NonNull Optional getPattern() { + return Optional.ofNullable(this.cache.get().getPattern()); + } + + @Override + public @NonNull Builder toBuilder() { + return new Builder(this.pattern, this.value, this.expireAt, this.contexts, this.metadata); + } + + public static final class Builder extends AbstractNodeBuilder implements RegexPermissionNode.Builder { + private String pattern; + + public Builder() { + this.pattern = null; + } + + public Builder(String pattern, boolean value, long expireAt, ImmutableContextSet context, Map, NodeMetadata> metadata) { + super(value, expireAt, context, metadata); + this.pattern = pattern; + } + + @Override + public @NonNull Builder pattern(@NonNull String pattern) { + this.pattern = Objects.requireNonNull(pattern, "pattern"); + return this; + } + + @Override + public @NonNull Builder pattern(@NonNull Pattern pattern) { + this.pattern = Objects.requireNonNull(pattern, "pattern").pattern(); + return this; + } + + @Override + public @NonNull RegexPermission build() { + Objects.requireNonNull(this.pattern, "pattern"); + return new RegexPermission(this.pattern, this.value, this.expireAt, this.context.build(), this.metadata); + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/types/Suffix.java b/common/src/main/java/me/lucko/luckperms/common/node/types/Suffix.java new file mode 100644 index 000000000..800625af5 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/types/Suffix.java @@ -0,0 +1,106 @@ +/* + * 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.node.types; + +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.node.types.SuffixNode; +import me.lucko.luckperms.common.node.AbstractNode; +import me.lucko.luckperms.common.node.AbstractNodeBuilder; +import me.lucko.luckperms.common.node.factory.NodeFactory; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Map; +import java.util.Objects; + +public class Suffix extends AbstractNode implements SuffixNode { + private final String suffix; + private final int priority; + + public Suffix(String suffix, int priority, boolean value, long expireAt, ImmutableContextSet contexts, Map, NodeMetadata> metadata) { + super(NodeFactory.suffixNode(priority, suffix), value, expireAt, contexts, metadata); + this.suffix = suffix; + this.priority = priority; + } + + @Override + public int getPriority() { + return this.priority; + } + + @Override + public @NonNull String getMetaValue() { + return this.suffix; + } + + @Override + public @NonNull ChatMetaType getType() { + return ChatMetaType.SUFFIX; + } + + @Override + public @NonNull Builder toBuilder() { + return new Builder(this.suffix, this.priority, this.value, this.expireAt, this.contexts, this.metadata); + } + + public static final class Builder extends AbstractNodeBuilder implements SuffixNode.Builder { + private String suffix; + private Integer priority; + + public Builder() { + this.suffix = null; + this.priority = null; + } + + public Builder(String suffix, int priority, boolean value, long expireAt, ImmutableContextSet context, Map, NodeMetadata> metadata) { + super(value, expireAt, context, metadata); + this.suffix = suffix; + this.priority = priority; + } + + @Override + public @NonNull Builder suffix(@NonNull String suffix) { + this.suffix = suffix; + return this; + } + + @Override + public @NonNull Builder priority(int priority) { + this.priority = priority; + return this; + } + + @Override + public @NonNull Suffix build() { + Objects.requireNonNull(this.suffix, "suffix"); + Objects.requireNonNull(this.priority, "priority"); + return new Suffix(this.suffix, this.priority, this.value, this.expireAt, this.context.build(), this.metadata); + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/types/Weight.java b/common/src/main/java/me/lucko/luckperms/common/node/types/Weight.java new file mode 100644 index 000000000..84a989395 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/node/types/Weight.java @@ -0,0 +1,83 @@ +/* + * 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.node.types; + +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.node.types.WeightNode; +import me.lucko.luckperms.common.node.AbstractNode; +import me.lucko.luckperms.common.node.AbstractNodeBuilder; +import me.lucko.luckperms.common.node.factory.NodeFactory; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Map; +import java.util.Objects; + +public class Weight extends AbstractNode implements WeightNode { + private final int weight; + + public Weight(int weight, boolean value, long expireAt, ImmutableContextSet contexts, Map, NodeMetadata> metadata) { + super(NodeFactory.weightNode(weight), value, expireAt, contexts, metadata); + this.weight = weight; + } + + @Override + public int getWeight() { + return this.weight; + } + + @Override + public @NonNull Builder toBuilder() { + return new Builder(this.weight, this.value, this.expireAt, this.contexts, this.metadata); + } + + public static final class Builder extends AbstractNodeBuilder implements WeightNode.Builder { + private Integer weight; + + public Builder() { + this.weight = null; + } + + public Builder(int weight, boolean value, long expireAt, ImmutableContextSet context, Map, NodeMetadata> metadata) { + super(value, expireAt, context, metadata); + this.weight = weight; + } + + @Override + public @NonNull Builder weight(int weight) { + this.weight = weight; + return this; + } + + @Override + public @NonNull Weight build() { + Objects.requireNonNull(this.weight, "weight"); + return new Weight(this.weight, this.value, this.expireAt, this.context.build(), this.metadata); + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/utils/InheritanceInfo.java b/common/src/main/java/me/lucko/luckperms/common/node/utils/InheritanceInfo.java index f5768df13..2d84b7f99 100644 --- a/common/src/main/java/me/lucko/luckperms/common/node/utils/InheritanceInfo.java +++ b/common/src/main/java/me/lucko/luckperms/common/node/utils/InheritanceInfo.java @@ -25,8 +25,9 @@ package me.lucko.luckperms.common.node.utils; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.node.metadata.types.InheritanceOriginMetadata; import java.util.Objects; import java.util.Optional; @@ -35,9 +36,9 @@ import java.util.Optional; * The result of an inheritance lookup */ public final class InheritanceInfo { - public static InheritanceInfo of(LocalizedNode node) { + public static InheritanceInfo of(Node node) { Objects.requireNonNull(node, "node"); - return new InheritanceInfo(node.getTristate(), node.getLocation()); + return new InheritanceInfo(Tristate.of(node.getValue()), node.metadata(InheritanceOriginMetadata.KEY).getOrigin()); } public static InheritanceInfo empty() { diff --git a/common/src/main/java/me/lucko/luckperms/common/node/utils/MetaType.java b/common/src/main/java/me/lucko/luckperms/common/node/utils/MetaType.java deleted file mode 100644 index 08126d0f8..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/node/utils/MetaType.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.node.utils; - -import me.lucko.luckperms.api.Node; - -/** - * Represents a type of meta - */ -public enum MetaType { - - /** - * Represents any meta type - */ - ANY { - @Override - public boolean matches(Node node) { - return META.matches(node) || PREFIX.matches(node) || SUFFIX.matches(node); - } - }, - - /** - * Represents any chat meta type - */ - CHAT { - @Override - public boolean matches(Node node) { - return PREFIX.matches(node) || SUFFIX.matches(node); - } - }, - - /** - * Represents a meta key-value pair - */ - META { - @Override - public boolean matches(Node node) { - return node.isMeta(); - } - }, - - /** - * Represents a prefix - */ - PREFIX { - @Override - public boolean matches(Node node) { - return node.isPrefix(); - } - }, - - /** - * Represents a suffix - */ - SUFFIX { - @Override - public boolean matches(Node node) { - return node.isSuffix(); - } - }; - - /** - * Returns if the passed node matches the type - * - * @param node the node to test - * @return true if the node has the same type - */ - public abstract boolean matches(Node node); - -} diff --git a/common/src/main/java/me/lucko/luckperms/common/node/utils/NodeTools.java b/common/src/main/java/me/lucko/luckperms/common/node/utils/NodeTools.java index df194b7a3..7e4aaa2da 100644 --- a/common/src/main/java/me/lucko/luckperms/common/node/utils/NodeTools.java +++ b/common/src/main/java/me/lucko/luckperms/common/node/utils/NodeTools.java @@ -25,16 +25,14 @@ package me.lucko.luckperms.common.node.utils; -import me.lucko.luckperms.api.LocalizedNode; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.NodeEqualityPredicate; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeEqualityPredicate; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; -import java.util.function.Predicate; public final class NodeTools { private NodeTools() {} @@ -61,22 +59,10 @@ public final class NodeTools { Set alreadyIn = new HashSet<>(); while (it.hasNext()) { T next = it.next(); - if (!alreadyIn.add(next.getPermission())) { + if (!alreadyIn.add(next.getKey())) { it.remove(); } } } - /** - * Returns a predicate which unwraps the localised node parameter before delegating - * the handling to the provided predicate. - * - * @param delegate the delegate predicate. - * @return the composed predicate - * @since 4.3 - */ - public static Predicate localizedNodeComposedPredicate(Predicate delegate) { - return localizedNode -> delegate.test(localizedNode.getNode()); - } - } diff --git a/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java b/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java index 9dfe4fd45..d31be4091 100644 --- a/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java +++ b/common/src/main/java/me/lucko/luckperms/common/plugin/AbstractLuckPermsPlugin.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.plugin; -import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.LuckPerms; import me.lucko.luckperms.common.actionlog.LogDispatcher; import me.lucko.luckperms.common.api.ApiRegistrationUtil; import me.lucko.luckperms.common.api.LuckPermsApiProvider; @@ -243,7 +243,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin { protected abstract void setupContextManager(); protected abstract void setupPlatformHooks(); protected abstract AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider); - protected abstract void registerApiOnPlatform(LuckPermsApi api); + protected abstract void registerApiOnPlatform(LuckPerms api); protected abstract void registerHousekeepingTasks(); protected abstract void performFinalSetup(); diff --git a/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java b/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java index 9b9f50fbf..a76a8b3ef 100644 --- a/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java +++ b/common/src/main/java/me/lucko/luckperms/common/plugin/LuckPermsPlugin.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.plugin; -import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.actionlog.LogDispatcher; import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.calculator.CalculatorFactory; @@ -236,7 +236,7 @@ public interface LuckPermsPlugin { * @param user the user instance * @return a contexts object, or null if one couldn't be generated */ - Optional getContextForUser(User user); + Optional getQueryOptionsForUser(User user); /** * Gets a list of online Senders on the platform diff --git a/common/src/main/java/me/lucko/luckperms/common/plugin/bootstrap/LuckPermsBootstrap.java b/common/src/main/java/me/lucko/luckperms/common/plugin/bootstrap/LuckPermsBootstrap.java index af542d6f7..7cdf973ab 100644 --- a/common/src/main/java/me/lucko/luckperms/common/plugin/bootstrap/LuckPermsBootstrap.java +++ b/common/src/main/java/me/lucko/luckperms/common/plugin/bootstrap/LuckPermsBootstrap.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.plugin.bootstrap; -import me.lucko.luckperms.api.platform.PlatformType; +import me.lucko.luckperms.api.platform.Platform; import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader; import me.lucko.luckperms.common.plugin.logging.PluginLogger; import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter; @@ -105,7 +105,7 @@ public interface LuckPermsBootstrap { * * @return the platform type */ - PlatformType getType(); + Platform.Type getType(); /** * Gets the name or "brand" of the running platform diff --git a/common/src/main/java/me/lucko/luckperms/common/plugin/util/AbstractConnectionListener.java b/common/src/main/java/me/lucko/luckperms/common/plugin/util/AbstractConnectionListener.java index df4f89632..78eee10cd 100644 --- a/common/src/main/java/me/lucko/luckperms/common/plugin/util/AbstractConnectionListener.java +++ b/common/src/main/java/me/lucko/luckperms/common/plugin/util/AbstractConnectionListener.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.plugin.util; -import me.lucko.luckperms.api.PlayerSaveResult; -import me.lucko.luckperms.api.platform.PlatformType; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.platform.Platform; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.defaultassignments.AssignmentRule; import me.lucko.luckperms.common.model.User; @@ -70,22 +70,22 @@ public abstract class AbstractConnectionListener { PlayerSaveResult saveResult = this.plugin.getStorage().savePlayerData(uuid, username).join(); // fire UserFirstLogin event - if (saveResult.includes(PlayerSaveResult.Status.CLEAN_INSERT)) { + if (saveResult.includes(PlayerSaveResult.Outcome.CLEAN_INSERT)) { this.plugin.getEventFactory().handleUserFirstLogin(uuid, username); } // most likely because ip forwarding is not setup correctly // print a warning to the console - if (saveResult.includes(PlayerSaveResult.Status.OTHER_UUIDS_PRESENT_FOR_USERNAME)) { - Set otherUuids = saveResult.getOtherUuids(); + if (saveResult.includes(PlayerSaveResult.Outcome.OTHER_UNIQUE_IDS_PRESENT_FOR_USERNAME)) { + Set otherUuids = saveResult.getOtherUniqueIds(); this.plugin.getLogger().warn("LuckPerms already has data for player '" + username + "' - but this data is stored under a different UUID."); this.plugin.getLogger().warn("'" + username + "' has previously used the unique ids " + otherUuids + " but is now connecting with '" + uuid + "'"); if (uuid.version() == 4) { - if (this.plugin.getBootstrap().getType() == PlatformType.BUNGEE) { + if (this.plugin.getBootstrap().getType() == Platform.Type.BUNGEECORD) { this.plugin.getLogger().warn("The UUID the player is connecting with now is Mojang-assigned (type 4). This implies that BungeeCord's IP-Forwarding has not been setup correctly on one (or more) of the backend servers."); - } if (this.plugin.getBootstrap().getType() == PlatformType.VELOCITY) { + } if (this.plugin.getBootstrap().getType() == Platform.Type.VELOCITY) { this.plugin.getLogger().warn("The UUID the player is connecting with now is Mojang-assigned (type 4). This implies that Velocity's IP-Forwarding has not been setup correctly on one (or more) of the backend servers."); } else { this.plugin.getLogger().warn("The UUID the player is connecting with now is Mojang-assigned (type 4). This implies that one of the other servers in your network is not authenticating correctly."); diff --git a/common/src/main/java/me/lucko/luckperms/common/primarygroup/AllParentsByWeightHolder.java b/common/src/main/java/me/lucko/luckperms/common/primarygroup/AllParentsByWeightHolder.java index 83284c117..99b52c3a7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/primarygroup/AllParentsByWeightHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/primarygroup/AllParentsByWeightHolder.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.primarygroup; -import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.inheritance.InheritanceGraph; import me.lucko.luckperms.common.model.Group; @@ -42,8 +42,8 @@ public class AllParentsByWeightHolder extends ContextualHolder { } @Override - protected @NonNull Optional calculateValue(Contexts contexts) { - InheritanceGraph graph = this.user.getPlugin().getInheritanceHandler().getGraph(contexts); + protected @NonNull Optional calculateValue(QueryOptions queryOptions) { + InheritanceGraph graph = this.user.getPlugin().getInheritanceHandler().getGraph(queryOptions); // fully traverse the graph, obtain a list of permission holders the user inherits from in weight order. Iterable traversal = graph.traverse(this.user.getPlugin().getConfiguration().get(ConfigKeys.INHERITANCE_TRAVERSAL_ALGORITHM), true, this.user); diff --git a/common/src/main/java/me/lucko/luckperms/common/primarygroup/ContextualHolder.java b/common/src/main/java/me/lucko/luckperms/common/primarygroup/ContextualHolder.java index aea5a2e7e..b86da83f3 100644 --- a/common/src/main/java/me/lucko/luckperms/common/primarygroup/ContextualHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/primarygroup/ContextualHolder.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.common.primarygroup; import com.github.benmanes.caffeine.cache.LoadingCache; -import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.factory.NodeFactory; import me.lucko.luckperms.common.util.CaffeineFactory; @@ -44,7 +44,7 @@ import java.util.concurrent.TimeUnit; public abstract class ContextualHolder extends StoredHolder { // cache lookups - private final LoadingCache> cache = CaffeineFactory.newBuilder() + private final LoadingCache> cache = CaffeineFactory.newBuilder() .expireAfterAccess(1, TimeUnit.MINUTES) .build(this::calculateValue); @@ -52,7 +52,7 @@ public abstract class ContextualHolder extends StoredHolder { super(user); } - protected abstract @NonNull Optional calculateValue(Contexts contexts); + protected abstract @NonNull Optional calculateValue(QueryOptions queryOptions); public void invalidateCache() { this.cache.invalidateAll(); @@ -60,12 +60,12 @@ public abstract class ContextualHolder extends StoredHolder { @Override public final String getValue() { - Contexts contexts = this.user.getPlugin().getContextForUser(this.user).orElse(null); - if (contexts == null) { - contexts = this.user.getPlugin().getContextManager().getStaticContexts(); + QueryOptions queryOptions = this.user.getPlugin().getQueryOptionsForUser(this.user).orElse(null); + if (queryOptions == null) { + queryOptions = this.user.getPlugin().getContextManager().getStaticQueryOptions(); } - return Objects.requireNonNull(this.cache.get(contexts)) + return Objects.requireNonNull(this.cache.get(queryOptions)) .orElseGet(() -> getStoredValue().orElse(NodeFactory.DEFAULT_GROUP_NAME)); } diff --git a/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java b/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java index 64db7e199..8ffda99e1 100644 --- a/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.common.primarygroup; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.User; @@ -42,9 +42,9 @@ public class ParentsByWeightHolder extends ContextualHolder { } @Override - protected @NonNull Optional calculateValue(Contexts contexts) { + protected @NonNull Optional calculateValue(QueryOptions queryOptions) { Set groups = new LinkedHashSet<>(); - for (Node node : this.user.getOwnGroupNodes(contexts.getContexts())) { + for (InheritanceNode node : this.user.getOwnGroupNodes(queryOptions)) { Group group = this.user.getPlugin().getGroupManager().getIfLoaded(node.getGroupName()); if (group != null) { groups.add(group); diff --git a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiCachedDataManager.java b/common/src/main/java/me/lucko/luckperms/common/query/FlagUtils.java similarity index 61% rename from common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiCachedDataManager.java rename to common/src/main/java/me/lucko/luckperms/common/query/FlagUtils.java index 1ee3cedbb..41900aec8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/implementation/ApiCachedDataManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/query/FlagUtils.java @@ -23,29 +23,38 @@ * SOFTWARE. */ -package me.lucko.luckperms.common.api.implementation; +package me.lucko.luckperms.common.query; -import me.lucko.luckperms.api.manager.CachedDataManager; -import me.lucko.luckperms.common.model.manager.group.GroupManager; -import me.lucko.luckperms.common.model.manager.user.UserManager; +import me.lucko.luckperms.api.query.Flag; -public class ApiCachedDataManager implements CachedDataManager { - private final UserManager userManager; - private final GroupManager groupManager; +import java.util.EnumSet; +import java.util.Set; - public ApiCachedDataManager(UserManager userManager, GroupManager groupManager) { - this.userManager = userManager; - this.groupManager = groupManager; +final class FlagUtils { + private FlagUtils() {} + + /* bitwise utility methods */ + + static boolean read(byte b, Flag setting) { + return ((b >> setting.ordinal()) & 1) == 1; } - - @Override - public void invalidateAllUserCaches() { - this.userManager.invalidateAllUserCaches(); + static byte createFlag(Set settings) { + byte b = 0; + for (Flag setting : settings) { + b |= (1 << setting.ordinal()); + } + return b; } - @Override - public void invalidateAllGroupCaches() { - this.groupManager.invalidateAllGroupCaches(); + static Set createSetFromFlag(byte b) { + EnumSet settings = EnumSet.noneOf(Flag.class); + for (Flag setting : Flag.values()) { + if (((b >> setting.ordinal()) & 1) == 1) { + settings.add(setting); + } + } + return settings; } + } diff --git a/common/src/main/java/me/lucko/luckperms/common/query/QueryOptionsBuilderImpl.java b/common/src/main/java/me/lucko/luckperms/common/query/QueryOptionsBuilderImpl.java new file mode 100644 index 000000000..45ac0fd5b --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/query/QueryOptionsBuilderImpl.java @@ -0,0 +1,169 @@ +/* + * 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.query; + +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.Flag; +import me.lucko.luckperms.api.query.OptionKey; +import me.lucko.luckperms.api.query.QueryMode; +import me.lucko.luckperms.api.query.QueryOptions; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.EnumSet; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +public class QueryOptionsBuilderImpl implements QueryOptions.Builder { + private QueryMode mode; + private ImmutableContextSet context; + private byte flags; + private Set flagsSet; + private Map, Object> options; + private boolean copyOptions; + + public QueryOptionsBuilderImpl(QueryMode mode) { + this.mode = mode; + this.context = mode == QueryMode.CONTEXTUAL ? ImmutableContextSet.empty() : null; + this.flags = 0; + this.flagsSet = null; + this.options = null; + this.copyOptions = false; + } + + QueryOptionsBuilderImpl(QueryMode mode, ImmutableContextSet context, byte flags, Map, Object> options) { + this.mode = mode; + this.context = context; + this.flags = flags; + this.flagsSet = null; + this.options = options; + this.copyOptions = true; + } + + @Override + public QueryOptions.@NonNull Builder mode(@NonNull QueryMode mode) { + if (this.mode == mode) { + return this; + } + + this.mode = mode; + this.context = this.mode == QueryMode.CONTEXTUAL ? ImmutableContextSet.empty() : null; + return this; + } + + @Override + public QueryOptions.@NonNull Builder context(@NonNull ContextSet context) { + if (this.mode != QueryMode.CONTEXTUAL) { + throw new IllegalStateException("Mode is not CONTEXTUAL"); + } + + this.context = Objects.requireNonNull(context, "context").immutableCopy(); + return this; + } + + @Override + public QueryOptions.@NonNull Builder flag(@NonNull Flag flag, boolean value) { + Objects.requireNonNull(flag, "flag"); + + // already set + if (this.flagsSet == null && FlagUtils.read(this.flags, flag) == value) { + return this; + } + + if (this.flagsSet == null) { + this.flagsSet = FlagUtils.createSetFromFlag(this.flags); + } + if (value) { + this.flagsSet.add(flag); + } else { + this.flagsSet.remove(flag); + } + + return this; + } + + @Override + public QueryOptions.@NonNull Builder flags(@NonNull Set flags) { + Objects.requireNonNull(flags, "flags"); + this.flagsSet = EnumSet.copyOf(flags); + return this; + } + + @Override + public QueryOptions.@NonNull Builder option(@NonNull OptionKey key, @Nullable O value) { + Objects.requireNonNull(key, "key"); + + if (this.options == null || this.copyOptions) { + if (this.options != null) { + this.options = new IdentityHashMap<>(this.options); + } else { + this.options = new IdentityHashMap<>(); + } + this.copyOptions = false; + } + + if (value == null) { + this.options.remove(key); + } else { + this.options.put(key, value); + } + + if (this.options.isEmpty()) { + this.options = null; + } + + return this; + } + + @Override + public @NonNull QueryOptions build() { + byte flags = this.flagsSet != null ? FlagUtils.createFlag(this.flagsSet) : this.flags; + + if (this.options == null) { + if (this.mode == QueryMode.NON_CONTEXTUAL) { + QueryOptionsImpl defaults = (QueryOptionsImpl) QueryOptions.nonContextual(); + if (defaults.getFlagsByte() == flags) { + // mode same, contexts null, flags same, options null + // so therefore, equal to default - return that instead! + return defaults; + } + } else if (this.mode == QueryMode.CONTEXTUAL) { + QueryOptionsImpl defaults = (QueryOptionsImpl) QueryOptions.defaultContextualOptions(); + if (defaults.getFlagsByte() == flags && this.context.isEmpty()) { + // mode same, contexts empty, flags same, options null + // so therefore, equal to default - return that instead! + return defaults; + } + } + } + + return new QueryOptionsImpl(this.mode, this.context, flags, this.options); + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/query/QueryOptionsImpl.java b/common/src/main/java/me/lucko/luckperms/common/query/QueryOptionsImpl.java new file mode 100644 index 000000000..d7ed124d2 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/query/QueryOptionsImpl.java @@ -0,0 +1,149 @@ +/* + * 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.query; + +import com.google.common.collect.ImmutableSet; + +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.Flag; +import me.lucko.luckperms.api.query.OptionKey; +import me.lucko.luckperms.api.query.QueryMode; +import me.lucko.luckperms.api.query.QueryOptions; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +public class QueryOptionsImpl implements QueryOptions { + private final QueryMode mode; + private final ImmutableContextSet context; + private final byte flags; + private final Map, Object> options; + private final int hashCode; + + private Set flagsSet = null; + + QueryOptionsImpl(QueryMode mode, ImmutableContextSet context, byte flags, Map, Object> options) { + this.mode = mode; + this.context = context; + this.flags = flags; + this.options = options; + this.hashCode = calculateHashCode(); + } + + byte getFlagsByte() { + return this.flags; + } + + @Override + public @NonNull QueryMode mode() { + return this.mode; + } + + @Override + public @NonNull ImmutableContextSet context() { + if (this.mode != QueryMode.CONTEXTUAL) { + throw new IllegalStateException("Mode is not CONTEXTUAL"); + } + return this.context; + } + + @Override + public boolean flag(@NonNull Flag flag) { + Objects.requireNonNull(flag, "flag"); + return FlagUtils.read(this.flags, flag); + } + + @Override + public @NonNull Set flags() { + if (this.flagsSet != null) { + return this.flagsSet; + } + Set set = ImmutableSet.copyOf(FlagUtils.createSetFromFlag(this.flags)); + this.flagsSet = set; + return set; + } + + @Override + public @NonNull Optional option(@NonNull OptionKey key) { + if (this.options == null) { + return Optional.empty(); + } + + //noinspection unchecked + return Optional.ofNullable((O) this.options.get(key)); + } + + @Override + public @NonNull Map, Object> options() { + return this.options; + } + + @Override + public boolean satisfies(@NonNull ContextSet contextSet) { + switch (this.mode) { + case CONTEXTUAL: + return contextSet.isSatisfiedBy(this.context); + case NON_CONTEXTUAL: + return true; + default: + throw new AssertionError(); + } + } + + @Override + public @NonNull Builder toBuilder() { + return new QueryOptionsBuilderImpl(this.mode, this.context, this.flags, this.options); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + QueryOptionsImpl that = (QueryOptionsImpl) o; + return this.flags == that.flags && + this.mode == that.mode && + Objects.equals(this.context, that.context) && + Objects.equals(this.options, that.options); + } + + @Override + public int hashCode() { + return this.hashCode; + } + + private int calculateHashCode() { + int result = this.mode.hashCode(); + result = 31 * result + (this.context != null ? this.context.hashCode() : 0); + result = 31 * result + (int) this.flags; + result = 31 * result + (this.options != null ? this.options.hashCode() : 0); + return result; + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/sender/AbstractSender.java b/common/src/main/java/me/lucko/luckperms/common/sender/AbstractSender.java index 4ca86472e..90d859cc3 100644 --- a/common/src/main/java/me/lucko/luckperms/common/sender/AbstractSender.java +++ b/common/src/main/java/me/lucko/luckperms/common/sender/AbstractSender.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.common.sender; import com.google.common.base.Splitter; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.util.TextUtils; diff --git a/common/src/main/java/me/lucko/luckperms/common/sender/DummySender.java b/common/src/main/java/me/lucko/luckperms/common/sender/DummySender.java index 304409ef6..0c02a0358 100644 --- a/common/src/main/java/me/lucko/luckperms/common/sender/DummySender.java +++ b/common/src/main/java/me/lucko/luckperms/common/sender/DummySender.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.sender; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.util.TextUtils; diff --git a/common/src/main/java/me/lucko/luckperms/common/sender/Sender.java b/common/src/main/java/me/lucko/luckperms/common/sender/Sender.java index 278cff57d..ce4365a2a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/sender/Sender.java +++ b/common/src/main/java/me/lucko/luckperms/common/sender/Sender.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.sender; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.command.CommandManager; import me.lucko.luckperms.common.command.access.CommandPermission; import me.lucko.luckperms.common.context.ContextManager; @@ -89,7 +89,7 @@ public interface Sender { } else if (staticContext.size() == 1) { location = staticContext.iterator().next().getValue(); } else { - Set servers = staticContext.getValues(Contexts.SERVER_KEY); + Set servers = staticContext.getValues(DefaultContextKeys.SERVER_KEY); if (servers.size() == 1) { location = servers.iterator().next(); } else { diff --git a/common/src/main/java/me/lucko/luckperms/common/sender/SenderFactory.java b/common/src/main/java/me/lucko/luckperms/common/sender/SenderFactory.java index 992047bc7..7e6b5272d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/sender/SenderFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/sender/SenderFactory.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.sender; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import net.kyori.text.Component; diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/Storage.java b/common/src/main/java/me/lucko/luckperms/common/storage/Storage.java index 40d4a879b..909c33025 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/Storage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/Storage.java @@ -27,11 +27,11 @@ package me.lucko.luckperms.common.storage; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.LogEntry; -import me.lucko.luckperms.api.PlayerSaveResult; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.api.event.cause.DeletionCause; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.node.HeldNode; import me.lucko.luckperms.common.actionlog.Log; import me.lucko.luckperms.common.bulkupdate.BulkUpdate; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; @@ -119,7 +119,7 @@ public class Storage { return this.implementation.getMeta(); } - public CompletableFuture logAction(LogEntry entry) { + public CompletableFuture logAction(Action entry) { return makeFuture(() -> this.implementation.logAction(entry)); } @@ -149,10 +149,10 @@ public class Storage { return makeFuture(this.implementation::getUniqueUsers); } - public CompletableFuture>> getUsersWithPermission(Constraint constraint) { + public CompletableFuture>> getUsersWithPermission(Constraint constraint) { return makeFuture(() -> { - List> result = this.implementation.getUsersWithPermission(constraint); - result.removeIf(entry -> entry.asNode().hasExpired()); + List> result = this.implementation.getUsersWithPermission(constraint); + result.removeIf(entry -> entry.getNode().hasExpired()); return ImmutableList.copyOf(result); }); } @@ -195,10 +195,10 @@ public class Storage { }); } - public CompletableFuture>> getGroupsWithPermission(Constraint constraint) { + public CompletableFuture>> getGroupsWithPermission(Constraint constraint) { return makeFuture(() -> { - List> result = this.implementation.getGroupsWithPermission(constraint); - result.removeIf(entry -> entry.asNode().hasExpired()); + List> result = this.implementation.getGroupsWithPermission(constraint); + result.removeIf(entry -> entry.getNode().hasExpired()); return ImmutableList.copyOf(result); }); } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/StorageImplementation.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/StorageImplementation.java index 79d02248e..0a14b5896 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/StorageImplementation.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/StorageImplementation.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.common.storage.implementation; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.LogEntry; -import me.lucko.luckperms.api.PlayerSaveResult; +import me.lucko.luckperms.api.actionlog.Action; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.node.HeldNode; import me.lucko.luckperms.common.actionlog.Log; import me.lucko.luckperms.common.bulkupdate.BulkUpdate; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; @@ -58,7 +58,7 @@ public interface StorageImplementation { return Collections.emptyMap(); } - void logAction(LogEntry entry) throws Exception; + void logAction(Action entry) throws Exception; Log getLog() throws Exception; @@ -70,7 +70,7 @@ public interface StorageImplementation { Set getUniqueUsers() throws Exception; - List> getUsersWithPermission(Constraint constraint) throws Exception; + List> getUsersWithPermission(Constraint constraint) throws Exception; Group createAndLoadGroup(String name) throws Exception; @@ -82,7 +82,7 @@ public interface StorageImplementation { void deleteGroup(Group group) throws Exception; - List> getGroupsWithPermission(Constraint constraint) throws Exception; + List> getGroupsWithPermission(Constraint constraint) throws Exception; Track createAndLoadTrack(String name) throws Exception; diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/AbstractConfigurateStorage.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/AbstractConfigurateStorage.java index e8102bd45..ac2d4bb61 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/AbstractConfigurateStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/AbstractConfigurateStorage.java @@ -29,11 +29,15 @@ import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.LogEntry; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.PlayerSaveResult; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeType; +import me.lucko.luckperms.api.node.types.ChatMetaNode; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.node.types.MetaNode; import me.lucko.luckperms.common.actionlog.Log; import me.lucko.luckperms.common.bulkupdate.BulkUpdate; import me.lucko.luckperms.common.context.ContextSetConfigurateSerializer; @@ -44,7 +48,6 @@ import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.UserIdentifier; import me.lucko.luckperms.common.node.factory.NodeFactory; import me.lucko.luckperms.common.node.model.NodeDataContainer; -import me.lucko.luckperms.common.node.utils.MetaType; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.storage.implementation.StorageImplementation; import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader; @@ -161,7 +164,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio } @Override - public void logAction(LogEntry entry) { + public void logAction(Action entry) { this.actionLogger.logAction(entry); } @@ -209,7 +212,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio } } else { if (this.plugin.getUserManager().shouldSave(user)) { - user.clearNodes(); + user.clearEnduringNodes(); user.getPrimaryGroup().setStoredValue(null); this.plugin.getUserManager().giveDefaultIfNeeded(user, false); } @@ -461,7 +464,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio ImmutableContextSet context = ImmutableContextSet.empty(); ConfigurationNode contextMap = attributes.getNode("context"); if (!contextMap.isVirtual() && contextMap.hasMapChildren()) { - context = ContextSetConfigurateSerializer.deserializeContextSet(contextMap).makeImmutable(); + context = ContextSetConfigurateSerializer.deserializeContextSet(contextMap).immutableCopy(); } return NodeDataContainer.of(permissionFunction.apply(attributes), true, server, world, expiry, context); @@ -476,7 +479,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio ImmutableContextSet context = ImmutableContextSet.empty(); ConfigurationNode contextMap = attributes.getNode("context"); if (!contextMap.isVirtual() && contextMap.hasMapChildren()) { - context = ContextSetConfigurateSerializer.deserializeContextSet(contextMap).makeImmutable(); + context = ContextSetConfigurateSerializer.deserializeContextSet(contextMap).immutableCopy(); } ConfigurationNode batchAttribute = attributes.getNode("permissions"); @@ -644,56 +647,57 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio // just add a string to the list. if (this.loader instanceof YamlLoader && isPlain(node)) { - if (n.isGroupNode()) { - parentsSection.getAppendedNode().setValue(n.getGroupName()); + if (n instanceof InheritanceNode) { + parentsSection.getAppendedNode().setValue(((InheritanceNode) n).getGroupName()); continue; } - if (!MetaType.ANY.matches(n)) { + if (!NodeType.META_OR_CHAT_META.matches(n)) { permissionsSection.getAppendedNode().setValue(node.getPermission()); continue; } } - ChatMetaType chatMetaType = ChatMetaType.ofNode(n).orElse(null); - if (chatMetaType != null && n.getValue()) { + if (n instanceof ChatMetaNode && n.getValue()) { // handle prefixes / suffixes - Map.Entry entry = chatMetaType.getEntry(n); + ChatMetaNode chatMeta = (ChatMetaNode) n; ConfigurationNode attributes = SimpleConfigurationNode.root(); - attributes.getNode("priority").setValue(entry.getKey()); + attributes.getNode("priority").setValue(chatMeta.getPriority()); writeAttributesTo(attributes, node, false); - switch (chatMetaType) { + switch (chatMeta.getType()) { case PREFIX: - appendNode(prefixesSection, entry.getValue(), attributes, "prefix"); + appendNode(prefixesSection, chatMeta.getMetaValue(), attributes, "prefix"); break; case SUFFIX: - appendNode(suffixesSection, entry.getValue(), attributes, "suffix"); + appendNode(suffixesSection, chatMeta.getMetaValue(), attributes, "suffix"); break; default: throw new AssertionError(); } - } else if (n.isMeta() && n.getValue()) { + } else if (n instanceof MetaNode && n.getValue()) { // handle meta nodes - Map.Entry meta = n.getMeta(); + MetaNode meta = (MetaNode) n; ConfigurationNode attributes = SimpleConfigurationNode.root(); - attributes.getNode("value").setValue(meta.getValue()); + attributes.getNode("value").setValue(meta.getMetaValue()); writeAttributesTo(attributes, node, false); - appendNode(metaSection, meta.getKey(), attributes, "key"); - } else if (n.isGroupNode() && n.getValue()) { + appendNode(metaSection, meta.getMetaKey(), attributes, "key"); + } else if (n instanceof InheritanceNode && n.getValue()) { // handle group nodes + InheritanceNode inheritance = (InheritanceNode) n; + ConfigurationNode attributes = SimpleConfigurationNode.root(); writeAttributesTo(attributes, node, false); - appendNode(parentsSection, n.getGroupName(), attributes, "group"); + appendNode(parentsSection, inheritance.getGroupName(), attributes, "group"); } else { // handle regular permissions and negated meta+prefixes+suffixes ConfigurationNode attributes = SimpleConfigurationNode.root(); writeAttributesTo(attributes, node, true); - appendNode(permissionsSection, n.getPermission(), attributes, "permission"); + appendNode(permissionsSection, n.getKey(), attributes, "permission"); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/CombinedConfigurateStorage.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/CombinedConfigurateStorage.java index a4cbf2d75..6b05be271 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/CombinedConfigurateStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/CombinedConfigurateStorage.java @@ -25,13 +25,13 @@ package me.lucko.luckperms.common.storage.implementation.file; -import me.lucko.luckperms.api.HeldPermission; +import me.lucko.luckperms.api.node.HeldNode; import me.lucko.luckperms.common.bulkupdate.BulkUpdate; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; import me.lucko.luckperms.common.model.manager.group.GroupManager; import me.lucko.luckperms.common.model.manager.track.TrackManager; +import me.lucko.luckperms.common.node.model.HeldNodeImpl; import me.lucko.luckperms.common.node.model.NodeDataContainer; -import me.lucko.luckperms.common.node.model.NodeHeldPermission; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader; @@ -262,8 +262,8 @@ public class CombinedConfigurateStorage extends AbstractConfigurateStorage { } @Override - public List> getUsersWithPermission(Constraint constraint) throws Exception { - List> held = new ArrayList<>(); + public List> getUsersWithPermission(Constraint constraint) throws Exception { + List> held = new ArrayList<>(); this.usersLoader.apply(false, true, root -> { for (Map.Entry entry : root.getChildrenMap().entrySet()) { try { @@ -275,7 +275,7 @@ public class CombinedConfigurateStorage extends AbstractConfigurateStorage { if (!constraint.eval(e.getPermission())) { continue; } - held.add(NodeHeldPermission.of(holder, e)); + held.add(HeldNodeImpl.of(holder, e.toNode())); } } catch (Exception e) { e.printStackTrace(); @@ -316,8 +316,8 @@ public class CombinedConfigurateStorage extends AbstractConfigurateStorage { } @Override - public List> getGroupsWithPermission(Constraint constraint) throws Exception { - List> held = new ArrayList<>(); + public List> getGroupsWithPermission(Constraint constraint) throws Exception { + List> held = new ArrayList<>(); this.groupsLoader.apply(false, true, root -> { for (Map.Entry entry : root.getChildrenMap().entrySet()) { try { @@ -329,7 +329,7 @@ public class CombinedConfigurateStorage extends AbstractConfigurateStorage { if (!constraint.eval(e.getPermission())) { continue; } - held.add(NodeHeldPermission.of(holder, e)); + held.add(HeldNodeImpl.of(holder, e.toNode())); } } catch (Exception e) { e.printStackTrace(); diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/FileActionLogger.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/FileActionLogger.java index a62718da2..cf5e68ff4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/FileActionLogger.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/FileActionLogger.java @@ -30,7 +30,7 @@ import com.google.gson.JsonElement; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; -import me.lucko.luckperms.api.LogEntry; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.common.actionlog.Log; import me.lucko.luckperms.common.actionlog.LogEntryJsonSerializer; import me.lucko.luckperms.common.cache.BufferedRequest; @@ -61,7 +61,7 @@ public class FileActionLogger { /** * The queue of entries pending save to the file */ - private final Queue entryQueue = new ConcurrentLinkedQueue<>(); + private final Queue entryQueue = new ConcurrentLinkedQueue<>(); private final SaveBuffer saveBuffer; @@ -73,7 +73,7 @@ public class FileActionLogger { this.contentFile = contentFile; } - public void logAction(LogEntry entry) { + public void logAction(Action entry) { this.entryQueue.add(entry); this.saveBuffer.request(); } @@ -102,7 +102,7 @@ public class FileActionLogger { } // poll the queue for new entries - for (LogEntry e; (e = this.entryQueue.poll()) != null; ) { + for (Action e; (e = this.entryQueue.poll()) != null; ) { array.add(LogEntryJsonSerializer.serialize(e)); } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/FileUuidCache.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/FileUuidCache.java index fa90e05d3..b4f593bb7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/FileUuidCache.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/FileUuidCache.java @@ -30,7 +30,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Multimaps; import com.google.common.collect.SetMultimap; -import me.lucko.luckperms.api.PlayerSaveResult; +import me.lucko.luckperms.api.model.PlayerSaveResult; import me.lucko.luckperms.common.storage.misc.PlayerSaveResultImpl; import me.lucko.luckperms.common.util.Uuids; diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/SeparatedConfigurateStorage.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/SeparatedConfigurateStorage.java index d0bd6346f..dcb8839bf 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/SeparatedConfigurateStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/file/SeparatedConfigurateStorage.java @@ -25,14 +25,14 @@ package me.lucko.luckperms.common.storage.implementation.file; -import me.lucko.luckperms.api.HeldPermission; +import me.lucko.luckperms.api.node.HeldNode; import me.lucko.luckperms.common.bulkupdate.BulkUpdate; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.manager.group.GroupManager; import me.lucko.luckperms.common.model.manager.track.TrackManager; +import me.lucko.luckperms.common.node.model.HeldNodeImpl; import me.lucko.luckperms.common.node.model.NodeDataContainer; -import me.lucko.luckperms.common.node.model.NodeHeldPermission; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader; import me.lucko.luckperms.common.util.MoreFiles; @@ -253,8 +253,8 @@ public class SeparatedConfigurateStorage extends AbstractConfigurateStorage { } @Override - public List> getUsersWithPermission(Constraint constraint) throws Exception { - List> held = new ArrayList<>(); + public List> getUsersWithPermission(Constraint constraint) throws Exception { + List> held = new ArrayList<>(); try (Stream stream = Files.list(getDirectory(StorageLocation.USER))) { stream.filter(getFileTypeFilter()) .forEach(file -> { @@ -268,7 +268,7 @@ public class SeparatedConfigurateStorage extends AbstractConfigurateStorage { if (!constraint.eval(e.getPermission())) { continue; } - held.add(NodeHeldPermission.of(holder, e)); + held.add(HeldNodeImpl.of(holder, e.toNode())); } } catch (Exception e) { throw reportException(file.getFileName().toString(), e); @@ -309,8 +309,8 @@ public class SeparatedConfigurateStorage extends AbstractConfigurateStorage { } @Override - public List> getGroupsWithPermission(Constraint constraint) throws Exception { - List> held = new ArrayList<>(); + public List> getGroupsWithPermission(Constraint constraint) throws Exception { + List> held = new ArrayList<>(); try (Stream stream = Files.list(getDirectory(StorageLocation.GROUP))) { stream.filter(getFileTypeFilter()) .forEach(file -> { @@ -324,7 +324,7 @@ public class SeparatedConfigurateStorage extends AbstractConfigurateStorage { if (!constraint.eval(e.getPermission())) { continue; } - held.add(NodeHeldPermission.of(holder, e)); + held.add(HeldNodeImpl.of(holder, e.toNode())); } } catch (Exception e) { throw reportException(file.getFileName().toString(), e); diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java index b183d03ac..787275805 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java @@ -35,15 +35,15 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; -import com.mongodb.client.model.UpdateOptions; +import com.mongodb.client.model.ReplaceOptions; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.LogEntry; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.PlayerSaveResult; +import me.lucko.luckperms.api.actionlog.Action; import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.node.HeldNode; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.actionlog.Log; import me.lucko.luckperms.common.bulkupdate.BulkUpdate; @@ -55,10 +55,9 @@ import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.UserIdentifier; import me.lucko.luckperms.common.model.manager.group.GroupManager; import me.lucko.luckperms.common.model.manager.track.TrackManager; -import me.lucko.luckperms.common.node.factory.LegacyNodeFactory; import me.lucko.luckperms.common.node.factory.NodeFactory; +import me.lucko.luckperms.common.node.model.HeldNodeImpl; import me.lucko.luckperms.common.node.model.NodeDataContainer; -import me.lucko.luckperms.common.node.model.NodeHeldPermission; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.storage.implementation.StorageImplementation; import me.lucko.luckperms.common.storage.misc.PlayerSaveResultImpl; @@ -163,7 +162,7 @@ public class MongoStorage implements StorageImplementation { } @Override - public void logAction(LogEntry entry) { + public void logAction(Action entry) { MongoCollection c = this.database.getCollection(this.prefix + "action"); Document doc = new Document() .append("timestamp", entry.getTimestamp()) @@ -197,7 +196,7 @@ public class MongoStorage implements StorageImplementation { .timestamp(d.getLong("timestamp")) .actor(d.get("actor", UUID.class)) .actorName(d.getString("actorName")) - .type(LogEntry.Type.valueOf(d.getString("type").charAt(0))) + .type(Action.Type.valueOf(d.getString("type").charAt(0))) .acted(actedUuid) .actedName(d.getString("actedName")) .action(d.getString("action")) @@ -290,7 +289,7 @@ public class MongoStorage implements StorageImplementation { } } else { if (this.plugin.getUserManager().shouldSave(user)) { - user.clearNodes(); + user.clearEnduringNodes(); user.getPrimaryGroup().setStoredValue(null); this.plugin.getUserManager().giveDefaultIfNeeded(user, false); } @@ -310,7 +309,7 @@ public class MongoStorage implements StorageImplementation { if (!this.plugin.getUserManager().shouldSave(user)) { c.deleteOne(new Document("_id", user.getUuid())); } else { - c.replaceOne(new Document("_id", user.getUuid()), userToDoc(user), new UpdateOptions().upsert(true)); + c.replaceOne(new Document("_id", user.getUuid()), userToDoc(user), new ReplaceOptions().upsert(true)); } } finally { user.getIoLock().unlock(); @@ -331,8 +330,8 @@ public class MongoStorage implements StorageImplementation { } @Override - public List> getUsersWithPermission(Constraint constraint) { - List> held = new ArrayList<>(); + public List> getUsersWithPermission(Constraint constraint) { + List> held = new ArrayList<>(); MongoCollection c = this.database.getCollection(this.prefix + "users"); try (MongoCursor cursor = c.find().iterator()) { while (cursor.hasNext()) { @@ -344,7 +343,7 @@ public class MongoStorage implements StorageImplementation { if (!constraint.eval(e.getPermission())) { continue; } - held.add(NodeHeldPermission.of(holder, e)); + held.add(HeldNodeImpl.of(holder, e.toNode())); } } } @@ -438,7 +437,7 @@ public class MongoStorage implements StorageImplementation { group.getIoLock().lock(); try { MongoCollection c = this.database.getCollection(this.prefix + "groups"); - c.replaceOne(new Document("_id", group.getName()), groupToDoc(group), new UpdateOptions().upsert(true)); + c.replaceOne(new Document("_id", group.getName()), groupToDoc(group), new ReplaceOptions().upsert(true)); } finally { group.getIoLock().unlock(); } @@ -456,8 +455,8 @@ public class MongoStorage implements StorageImplementation { } @Override - public List> getGroupsWithPermission(Constraint constraint) { - List> held = new ArrayList<>(); + public List> getGroupsWithPermission(Constraint constraint) { + List> held = new ArrayList<>(); MongoCollection c = this.database.getCollection(this.prefix + "groups"); try (MongoCursor cursor = c.find().iterator()) { while (cursor.hasNext()) { @@ -469,7 +468,7 @@ public class MongoStorage implements StorageImplementation { if (!constraint.eval(e.getPermission())) { continue; } - held.add(NodeHeldPermission.of(holder, e)); + held.add(HeldNodeImpl.of(holder, e.toNode())); } } } @@ -591,7 +590,7 @@ public class MongoStorage implements StorageImplementation { // do the insert if (!username.equalsIgnoreCase(oldUsername)) { - c.replaceOne(new Document("_id", uuid), new Document("_id", uuid).append("name", username), new UpdateOptions().upsert(true)); + c.replaceOne(new Document("_id", uuid), new Document("_id", uuid).append("name", username), new ReplaceOptions().upsert(true)); } PlayerSaveResultImpl result = PlayerSaveResultImpl.determineBaseResult(username, oldUsername); @@ -647,19 +646,6 @@ public class MongoStorage implements StorageImplementation { private static List nodesFromDoc(Document document) { List nodes = new ArrayList<>(); - - // legacy - if (document.containsKey("perms") && document.get("perms") instanceof Map) { - //noinspection unchecked - Map permsMap = (Map) document.get("perms"); - for (Map.Entry e : permsMap.entrySet()) { - // legacy permission key deserialisation - String permission = e.getKey().replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$"); - nodes.add(NodeDataContainer.fromNode(LegacyNodeFactory.fromLegacyString(permission, e.getValue()))); - } - } - - // new format if (document.containsKey("permissions") && document.get("permissions") instanceof List) { //noinspection unchecked List permsList = (List) document.get("permissions"); @@ -667,7 +653,6 @@ public class MongoStorage implements StorageImplementation { nodes.add(nodeFromDoc(d)); } } - return nodes; } @@ -733,7 +718,7 @@ public class MongoStorage implements StorageImplementation { if (document.containsKey("context") && document.get("context") instanceof List) { //noinspection unchecked List contexts = (List) document.get("context"); - context = docsToContextSet(contexts).makeImmutable(); + context = docsToContextSet(contexts).immutableCopy(); } return NodeDataContainer.of(permission, value, server, world, expiry, context); diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/split/SplitStorage.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/split/SplitStorage.java index 34522ff59..408a9b1a4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/split/SplitStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/split/SplitStorage.java @@ -27,9 +27,9 @@ package me.lucko.luckperms.common.storage.implementation.split; import com.google.common.collect.ImmutableMap; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.LogEntry; -import me.lucko.luckperms.api.PlayerSaveResult; +import me.lucko.luckperms.api.actionlog.Action; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.node.HeldNode; import me.lucko.luckperms.common.actionlog.Log; import me.lucko.luckperms.common.bulkupdate.BulkUpdate; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; @@ -106,7 +106,7 @@ public class SplitStorage implements StorageImplementation { } @Override - public void logAction(LogEntry entry) throws Exception { + public void logAction(Action entry) throws Exception { this.backing.get(this.types.get(SplitStorageType.LOG)).logAction(entry); } @@ -144,7 +144,7 @@ public class SplitStorage implements StorageImplementation { } @Override - public List> getUsersWithPermission(Constraint constraint) throws Exception { + public List> getUsersWithPermission(Constraint constraint) throws Exception { return this.backing.get(this.types.get(SplitStorageType.USER)).getUsersWithPermission(constraint); } @@ -174,7 +174,7 @@ public class SplitStorage implements StorageImplementation { } @Override - public List> getGroupsWithPermission(Constraint constraint) throws Exception { + public List> getGroupsWithPermission(Constraint constraint) throws Exception { return this.backing.get(this.types.get(SplitStorageType.GROUP)).getGroupsWithPermission(constraint); } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/SqlStorage.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/SqlStorage.java index 3b8e8122b..de1924741 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/SqlStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/SqlStorage.java @@ -28,10 +28,10 @@ package me.lucko.luckperms.common.storage.implementation.sql; import com.google.common.collect.Maps; import com.google.gson.reflect.TypeToken; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.LogEntry; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.PlayerSaveResult; +import me.lucko.luckperms.api.actionlog.Action; +import me.lucko.luckperms.api.model.PlayerSaveResult; +import me.lucko.luckperms.api.node.HeldNode; +import me.lucko.luckperms.api.node.Node; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.actionlog.Log; import me.lucko.luckperms.common.bulkupdate.BulkUpdate; @@ -46,8 +46,8 @@ import me.lucko.luckperms.common.model.UserIdentifier; import me.lucko.luckperms.common.model.manager.group.GroupManager; import me.lucko.luckperms.common.model.manager.track.TrackManager; import me.lucko.luckperms.common.node.factory.NodeFactory; +import me.lucko.luckperms.common.node.model.HeldNodeImpl; import me.lucko.luckperms.common.node.model.NodeDataContainer; -import me.lucko.luckperms.common.node.model.NodeHeldPermission; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.storage.implementation.StorageImplementation; import me.lucko.luckperms.common.storage.implementation.sql.connection.ConnectionFactory; @@ -263,7 +263,7 @@ public class SqlStorage implements StorageImplementation { } @Override - public void logAction(LogEntry entry) throws SQLException { + public void logAction(Action entry) throws SQLException { try (Connection c = this.connectionFactory.getConnection()) { try (PreparedStatement ps = c.prepareStatement(this.statementProcessor.apply(ACTION_INSERT))) { ps.setLong(1, entry.getTimestamp()); @@ -290,7 +290,7 @@ public class SqlStorage implements StorageImplementation { .timestamp(rs.getLong("time")) .actor(UUID.fromString(rs.getString("actor_uuid"))) .actorName(rs.getString("actor_name")) - .type(LogEntry.Type.valueOf(rs.getString("type").toCharArray()[0])) + .type(Action.Type.valueOf(rs.getString("type").toCharArray()[0])) .acted(actedUuid.equals("null") ? null : UUID.fromString(actedUuid)) .actedName(rs.getString("acted_name")) .action(rs.getString("action")) @@ -388,7 +388,7 @@ public class SqlStorage implements StorageImplementation { } else { // User has no data in storage. if (this.plugin.getUserManager().shouldSave(user)) { - user.clearNodes(); + user.clearEnduringNodes(); user.getPrimaryGroup().setStoredValue(null); this.plugin.getUserManager().giveDefaultIfNeeded(user, false); } @@ -532,11 +532,11 @@ public class SqlStorage implements StorageImplementation { } @Override - public List> getUsersWithPermission(Constraint constraint) throws SQLException { + public List> getUsersWithPermission(Constraint constraint) throws SQLException { PreparedStatementBuilder builder = new PreparedStatementBuilder().append(USER_PERMISSIONS_SELECT_PERMISSION); constraint.appendSql(builder, "permission"); - List> held = new ArrayList<>(); + List> held = new ArrayList<>(); try (Connection c = this.connectionFactory.getConnection()) { try (PreparedStatement ps = builder.build(c, this.statementProcessor)) { try (ResultSet rs = ps.executeQuery()) { @@ -550,7 +550,7 @@ public class SqlStorage implements StorageImplementation { String contexts = rs.getString("contexts"); NodeDataContainer data = deserializeNode(perm, value, server, world, expiry, contexts); - held.add(NodeHeldPermission.of(holder, data)); + held.add(HeldNodeImpl.of(holder, data.toNode())); } } } @@ -632,7 +632,7 @@ public class SqlStorage implements StorageImplementation { Set nodes = data.stream().map(NodeDataContainer::toNode).collect(Collectors.toSet()); group.setNodes(NodeMapType.ENDURING, nodes); } else { - group.clearNodes(); + group.clearEnduringNodes(); } } finally { group.getIoLock().unlock(); @@ -778,11 +778,11 @@ public class SqlStorage implements StorageImplementation { } @Override - public List> getGroupsWithPermission(Constraint constraint) throws SQLException { + public List> getGroupsWithPermission(Constraint constraint) throws SQLException { PreparedStatementBuilder builder = new PreparedStatementBuilder().append(GROUP_PERMISSIONS_SELECT_PERMISSION); constraint.appendSql(builder, "permission"); - List> held = new ArrayList<>(); + List> held = new ArrayList<>(); try (Connection c = this.connectionFactory.getConnection()) { try (PreparedStatement ps = builder.build(c, this.statementProcessor)) { try (ResultSet rs = ps.executeQuery()) { @@ -796,7 +796,7 @@ public class SqlStorage implements StorageImplementation { String contexts = rs.getString("contexts"); NodeDataContainer data = deserializeNode(perm, value, server, world, expiry, contexts); - held.add(NodeHeldPermission.of(holder, data)); + held.add(HeldNodeImpl.of(holder, data.toNode())); } } } @@ -1053,6 +1053,6 @@ public class SqlStorage implements StorageImplementation { } private NodeDataContainer deserializeNode(String permission, boolean value, String server, String world, long expiry, String contexts) { - return NodeDataContainer.of(permission, value, server, world, expiry, ContextSetJsonSerializer.deserializeContextSet(GsonProvider.normal(), contexts).makeImmutable()); + return NodeDataContainer.of(permission, value, server, world, expiry, ContextSetJsonSerializer.deserializeContextSet(GsonProvider.normal(), contexts).immutableCopy()); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/misc/PlayerSaveResultImpl.java b/common/src/main/java/me/lucko/luckperms/common/storage/misc/PlayerSaveResultImpl.java index 941854056..ec06165a6 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/misc/PlayerSaveResultImpl.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/misc/PlayerSaveResultImpl.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.common.storage.misc; import com.google.common.collect.ImmutableSet; -import me.lucko.luckperms.api.PlayerSaveResult; +import me.lucko.luckperms.api.model.PlayerSaveResult; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -41,8 +41,8 @@ import java.util.UUID; * Represents the result to a player history save operation */ public final class PlayerSaveResultImpl implements PlayerSaveResult { - private static final PlayerSaveResultImpl CLEAN_INSERT = new PlayerSaveResultImpl(Status.CLEAN_INSERT); - private static final PlayerSaveResultImpl NO_CHANGE = new PlayerSaveResultImpl(Status.NO_CHANGE); + private static final PlayerSaveResultImpl CLEAN_INSERT = new PlayerSaveResultImpl(Outcome.CLEAN_INSERT); + private static final PlayerSaveResultImpl NO_CHANGE = new PlayerSaveResultImpl(Outcome.NO_CHANGE); public static PlayerSaveResultImpl cleanInsert() { return CLEAN_INSERT; @@ -53,7 +53,7 @@ public final class PlayerSaveResultImpl implements PlayerSaveResult { } public static PlayerSaveResultImpl usernameUpdated(String oldUsername) { - return new PlayerSaveResultImpl(EnumSet.of(Status.USERNAME_UPDATED), oldUsername, null); + return new PlayerSaveResultImpl(EnumSet.of(Outcome.USERNAME_UPDATED), oldUsername, null); } public static PlayerSaveResultImpl determineBaseResult(String username, String oldUsername) { @@ -68,36 +68,36 @@ public final class PlayerSaveResultImpl implements PlayerSaveResult { return result; } - private final Set status; + private final Set outcomes; private final @Nullable String oldUsername; private final @Nullable Set otherUuids; - private PlayerSaveResultImpl(EnumSet status, @Nullable String oldUsername, @Nullable Set otherUuids) { - this.status = ImmutableSet.copyOf(status); + private PlayerSaveResultImpl(EnumSet outcomes, @Nullable String oldUsername, @Nullable Set otherUuids) { + this.outcomes = ImmutableSet.copyOf(outcomes); this.oldUsername = oldUsername; this.otherUuids = otherUuids; } - private PlayerSaveResultImpl(Status status) { - this(EnumSet.of(status), null, null); + private PlayerSaveResultImpl(Outcome outcome) { + this(EnumSet.of(outcome), null, null); } /** - * Returns a new {@link PlayerSaveResultImpl} with the {@link Status#OTHER_UUIDS_PRESENT_FOR_USERNAME} + * Returns a new {@link PlayerSaveResultImpl} with the {@link Outcome#OTHER_UNIQUE_IDS_PRESENT_FOR_USERNAME} * status attached to the state of this result. * * @param otherUuids the other uuids * @return a new result */ public PlayerSaveResultImpl withOtherUuidsPresent(@NonNull Set otherUuids) { - EnumSet status = EnumSet.copyOf(this.status); - status.add(Status.OTHER_UUIDS_PRESENT_FOR_USERNAME); - return new PlayerSaveResultImpl(status, this.oldUsername, ImmutableSet.copyOf(otherUuids)); + EnumSet outcomes = EnumSet.copyOf(this.outcomes); + outcomes.add(Outcome.OTHER_UNIQUE_IDS_PRESENT_FOR_USERNAME); + return new PlayerSaveResultImpl(outcomes, this.oldUsername, ImmutableSet.copyOf(otherUuids)); } @Override - public @NonNull Set getStatus() { - return this.status; + public @NonNull Set getOutcomes() { + return this.outcomes; } @Override @@ -106,7 +106,7 @@ public final class PlayerSaveResultImpl implements PlayerSaveResult { } @Override - public @Nullable Set getOtherUuids() { + public @Nullable Set getOtherUniqueIds() { return this.otherUuids; } @@ -115,18 +115,18 @@ public final class PlayerSaveResultImpl implements PlayerSaveResult { if (this == that) return true; if (that == null || getClass() != that.getClass()) return false; PlayerSaveResultImpl result = (PlayerSaveResultImpl) that; - return Objects.equals(this.status, result.status) && + return Objects.equals(this.outcomes, result.outcomes) && Objects.equals(this.oldUsername, result.oldUsername) && Objects.equals(this.otherUuids, result.otherUuids); } @Override public int hashCode() { - return Objects.hash(this.status, this.oldUsername, this.otherUuids); + return Objects.hash(this.outcomes, this.oldUsername, this.otherUuids); } @Override public String toString() { - return "PlayerSaveResult(status=" + this.status + ", oldUsername=" + this.oldUsername + ", otherUuids=" + this.otherUuids + ")"; + return "PlayerSaveResult(outcomes=" + this.outcomes + ", oldUsername=" + this.oldUsername + ", otherUuids=" + this.otherUuids + ")"; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/treeview/TreeView.java b/common/src/main/java/me/lucko/luckperms/common/treeview/TreeView.java index 198d43a9e..1a95c2ea4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/treeview/TreeView.java +++ b/common/src/main/java/me/lucko/luckperms/common/treeview/TreeView.java @@ -151,7 +151,7 @@ public class TreeView { checks = new JObject(); for (Map.Entry node : this.view.getNodeEndings()) { String permission = prefix + node.getValue(); - checks.add(permission, checker.getPermissionValue(permission, PermissionCheckEvent.Origin.INTERNAL).result().name().toLowerCase()); + checks.add(permission, checker.checkPermission(permission, PermissionCheckEvent.Origin.INTERNAL).result().name().toLowerCase()); } } else { checks = null; diff --git a/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseHandler.java b/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseHandler.java index ca753c2cb..7e0a40d9c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseHandler.java +++ b/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseHandler.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.verbose; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.calculator.result.TristateResult; import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter; import me.lucko.luckperms.common.sender.Sender; @@ -69,11 +69,11 @@ public class VerboseHandler extends RepeatingTask { * * @param origin the origin of the check * @param checkTarget the target of the permission check - * @param checkContext the contexts where the check occurred + * @param checkQueryOptions the query options used for the check * @param permission the permission which was checked for * @param result the result of the permission check */ - public void offerPermissionCheckEvent(PermissionCheckEvent.Origin origin, String checkTarget, ContextSet checkContext, String permission, TristateResult result) { + public void offerPermissionCheckEvent(PermissionCheckEvent.Origin origin, String checkTarget, QueryOptions checkQueryOptions, String permission, TristateResult result) { // don't bother even processing the check if there are no listeners registered if (!this.listening) { return; @@ -82,7 +82,7 @@ public class VerboseHandler extends RepeatingTask { StackTraceElement[] trace = new Exception().getStackTrace(); // add the check data to a queue to be processed later. - this.queue.offer(new PermissionCheckEvent(origin, checkTarget, checkContext.makeImmutable(), trace, permission, result)); + this.queue.offer(new PermissionCheckEvent(origin, checkTarget, checkQueryOptions, trace, permission, result)); } /** @@ -93,11 +93,11 @@ public class VerboseHandler extends RepeatingTask { * * @param origin the origin of the check * @param checkTarget the target of the meta check - * @param checkContext the contexts where the check occurred + * @param checkQueryOptions the query options used for the check * @param key the meta key which was checked for * @param result the result of the meta check */ - public void offerMetaCheckEvent(MetaCheckEvent.Origin origin, String checkTarget, ContextSet checkContext, String key, String result) { + public void offerMetaCheckEvent(MetaCheckEvent.Origin origin, String checkTarget, QueryOptions checkQueryOptions, String key, String result) { // don't bother even processing the check if there are no listeners registered if (!this.listening) { return; @@ -106,7 +106,7 @@ public class VerboseHandler extends RepeatingTask { StackTraceElement[] trace = new Exception().getStackTrace(); // add the check data to a queue to be processed later. - this.queue.offer(new MetaCheckEvent(origin, checkTarget, checkContext.makeImmutable(), trace, key, result)); + this.queue.offer(new MetaCheckEvent(origin, checkTarget, checkQueryOptions, trace, key, result)); } /** diff --git a/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseListener.java b/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseListener.java index b85de96dd..31e3f5c8a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseListener.java +++ b/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseListener.java @@ -27,7 +27,8 @@ package me.lucko.luckperms.common.verbose; import com.google.gson.JsonObject; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryMode; import me.lucko.luckperms.common.calculator.result.TristateResult; import me.lucko.luckperms.common.command.CommandManager; import me.lucko.luckperms.common.command.utils.MessageUtils; @@ -206,7 +207,9 @@ public class VerboseListener { hover.add("&bOrigin: &2" + metaEvent.getOrigin().name()); } - hover.add("&bContext: &r" + MessageUtils.contextSetToString(this.notifiedSender.getPlugin().getLocaleManager(), event.getCheckContext())); + if (event.getCheckQueryOptions().mode() == QueryMode.CONTEXTUAL) { + hover.add("&bContext: &r" + MessageUtils.contextSetToString(this.notifiedSender.getPlugin().getLocaleManager(), event.getCheckQueryOptions().context())); + } hover.add("&bTrace: &r"); Consumer printer = StackTracePrinter.elementToString(str -> hover.add("&7" + str)); diff --git a/common/src/main/java/me/lucko/luckperms/common/verbose/event/MetaCheckEvent.java b/common/src/main/java/me/lucko/luckperms/common/verbose/event/MetaCheckEvent.java index 0beba16e0..459ad19b9 100644 --- a/common/src/main/java/me/lucko/luckperms/common/verbose/event/MetaCheckEvent.java +++ b/common/src/main/java/me/lucko/luckperms/common/verbose/event/MetaCheckEvent.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.verbose.event; -import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.util.gson.JObject; public class MetaCheckEvent extends VerboseEvent { @@ -45,8 +45,8 @@ public class MetaCheckEvent extends VerboseEvent { */ private final String result; - public MetaCheckEvent(Origin origin, String checkTarget, ImmutableContextSet checkContext, StackTraceElement[] checkTrace, String key, String result) { - super(checkTarget, checkContext, checkTrace); + public MetaCheckEvent(Origin origin, String checkTarget, QueryOptions checkQueryOptions, StackTraceElement[] checkTrace, String key, String result) { + super(checkTarget, checkQueryOptions, checkTrace); this.origin = origin; this.key = key; this.result = result; diff --git a/common/src/main/java/me/lucko/luckperms/common/verbose/event/PermissionCheckEvent.java b/common/src/main/java/me/lucko/luckperms/common/verbose/event/PermissionCheckEvent.java index 6b5a38853..159f3ad75 100644 --- a/common/src/main/java/me/lucko/luckperms/common/verbose/event/PermissionCheckEvent.java +++ b/common/src/main/java/me/lucko/luckperms/common/verbose/event/PermissionCheckEvent.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.common.verbose.event; -import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.calculator.result.TristateResult; import me.lucko.luckperms.common.util.gson.JObject; @@ -46,8 +46,8 @@ public class PermissionCheckEvent extends VerboseEvent { */ private final TristateResult result; - public PermissionCheckEvent(Origin origin, String checkTarget, ImmutableContextSet checkContext, StackTraceElement[] checkTrace, String permission, TristateResult result) { - super(checkTarget, checkContext, checkTrace); + public PermissionCheckEvent(Origin origin, String checkTarget, QueryOptions checkQueryOptions, StackTraceElement[] checkTrace, String permission, TristateResult result) { + super(checkTarget, checkQueryOptions, checkTrace); this.origin = origin; this.permission = permission; this.result = result; diff --git a/common/src/main/java/me/lucko/luckperms/common/verbose/event/VerboseEvent.java b/common/src/main/java/me/lucko/luckperms/common/verbose/event/VerboseEvent.java index 592fd4600..dd8a56d03 100644 --- a/common/src/main/java/me/lucko/luckperms/common/verbose/event/VerboseEvent.java +++ b/common/src/main/java/me/lucko/luckperms/common/verbose/event/VerboseEvent.java @@ -27,12 +27,14 @@ package me.lucko.luckperms.common.verbose.event; import com.google.gson.JsonObject; -import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryMode; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.util.StackTracePrinter; import me.lucko.luckperms.common.util.gson.JArray; import me.lucko.luckperms.common.util.gson.JObject; import java.util.Map; +import java.util.Objects; /** * Represents a verbose event. @@ -45,18 +47,18 @@ public abstract class VerboseEvent { private final String checkTarget; /** - * The contexts where the check took place + * The query options used for the check */ - private final ImmutableContextSet checkContext; + private final QueryOptions checkQueryOptions; /** * The stack trace when the check took place */ private final StackTraceElement[] checkTrace; - protected VerboseEvent(String checkTarget, ImmutableContextSet checkContext, StackTraceElement[] checkTrace) { + protected VerboseEvent(String checkTarget, QueryOptions checkQueryOptions, StackTraceElement[] checkTrace) { this.checkTarget = checkTarget; - this.checkContext = checkContext; + this.checkQueryOptions = checkQueryOptions; this.checkTrace = checkTrace; } @@ -64,8 +66,8 @@ public abstract class VerboseEvent { return this.checkTarget; } - public ImmutableContextSet getCheckContext() { - return this.checkContext; + public QueryOptions getCheckQueryOptions() { + return this.checkQueryOptions; } public StackTraceElement[] getCheckTrace() { @@ -79,13 +81,18 @@ public abstract class VerboseEvent { .add("who", new JObject() .add("identifier", this.checkTarget) ) - .add("context", new JArray() - .consume(arr -> { - for (Map.Entry contextPair : this.checkContext.toSet()) { - arr.add(new JObject().add("key", contextPair.getKey()).add("value", contextPair.getValue())); - } - }) - ) + .add("queryMode", this.checkQueryOptions.mode().name().toLowerCase()) + .consume(obj -> { + if (this.checkQueryOptions.mode() == QueryMode.CONTEXTUAL) { + obj.add("context", new JArray() + .consume(arr -> { + for (Map.Entry contextPair : Objects.requireNonNull(this.checkQueryOptions.context())) { + arr.add(new JObject().add("key", contextPair.getKey()).add("value", contextPair.getValue())); + } + }) + ); + } + }) .consume(this::serializeTo); } diff --git a/common/src/main/java/me/lucko/luckperms/common/web/WebEditor.java b/common/src/main/java/me/lucko/luckperms/common/web/WebEditor.java index 332417d5f..132819b06 100644 --- a/common/src/main/java/me/lucko/luckperms/common/web/WebEditor.java +++ b/common/src/main/java/me/lucko/luckperms/common/web/WebEditor.java @@ -229,7 +229,7 @@ public final class WebEditor { if (data.has("context") && data.get("context").isJsonObject()) { JsonObject contexts = data.get("context").getAsJsonObject(); - context = ContextSetJsonSerializer.deserializeContextSet(contexts).makeImmutable(); + context = ContextSetJsonSerializer.deserializeContextSet(contexts).immutableCopy(); } nodes.add(NodeDataContainer.of(permission, value, server, world, expiry, context)); diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitBootstrap.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitBootstrap.java index 719958706..55d22192f 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitBootstrap.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitBootstrap.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.nukkit; -import me.lucko.luckperms.api.platform.PlatformType; +import me.lucko.luckperms.api.platform.Platform; import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader; import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader; import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap; @@ -154,8 +154,8 @@ public class LPNukkitBootstrap extends PluginBase implements LuckPermsBootstrap // provide information about the platform @Override - public PlatformType getType() { - return PlatformType.NUKKIT; + public Platform.Type getType() { + return Platform.Type.NUKKIT; } @Override diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitPlugin.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitPlugin.java index 080965e0e..c55040b98 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitPlugin.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/LPNukkitPlugin.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.nukkit; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.LuckPerms; import me.lucko.luckperms.api.event.user.UserDataRecalculateEvent; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.api.implementation.ApiUser; import me.lucko.luckperms.common.calculator.CalculatorFactory; @@ -172,8 +172,8 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin { } @Override - protected void registerApiOnPlatform(LuckPermsApi api) { - this.bootstrap.getServer().getServiceManager().register(LuckPermsApi.class, api, this.bootstrap, ServicePriority.NORMAL); + protected void registerApiOnPlatform(LuckPerms api) { + this.bootstrap.getServer().getServiceManager().register(LuckPerms.class, api, this.bootstrap, ServicePriority.NORMAL); } @Override @@ -270,7 +270,7 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin { boolean value; if (user != null) { - Map permData = user.getCachedData().getPermissionData(this.contextManager.getApplicableContexts(player)).getImmutableBacking(); + Map permData = user.getCachedData().getPermissionData(this.contextManager.getQueryOptions(player)).getPermissionMap(); value = permData.getOrDefault("luckperms.autoop", false); } else { value = false; @@ -289,8 +289,8 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin { } @Override - public Optional getContextForUser(User user) { - return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getApplicableContexts(player)); + public Optional getQueryOptionsForUser(User user) { + return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getQueryOptions(player)); } @Override diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitSenderFactory.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitSenderFactory.java index 15bde06fd..742579c22 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitSenderFactory.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/NukkitSenderFactory.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.nukkit; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.SenderFactory; @@ -83,7 +83,7 @@ public class NukkitSenderFactory extends SenderFactory { boolean isSet = sender.isPermissionSet(node); boolean val = sender.hasPermission(node); - return !isSet ? val ? Tristate.TRUE : Tristate.UNDEFINED : Tristate.fromBoolean(val); + return !isSet ? val ? Tristate.TRUE : Tristate.UNDEFINED : Tristate.of(val); } @Override diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/ChildProcessor.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/ChildProcessor.java index 188f3239c..f3c12de18 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/ChildProcessor.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/ChildProcessor.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.nukkit.calculator; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.calculator.processor.AbstractPermissionProcessor; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; import me.lucko.luckperms.common.calculator.result.TristateResult; @@ -42,7 +42,7 @@ public class ChildProcessor extends AbstractPermissionProcessor implements Permi private static final TristateResult.Factory RESULT_FACTORY = new TristateResult.Factory(ChildProcessor.class); private final LPNukkitPlugin plugin; - private Map childPermissions = Collections.emptyMap(); + private Map childPermissions = Collections.emptyMap(); public ChildProcessor(LPNukkitPlugin plugin) { this.plugin = plugin; @@ -50,16 +50,16 @@ public class ChildProcessor extends AbstractPermissionProcessor implements Permi @Override public TristateResult hasPermission(String permission) { - return RESULT_FACTORY.result(Tristate.fromNullableBoolean(this.childPermissions.get(permission))); + return this.childPermissions.getOrDefault(permission, TristateResult.UNDEFINED); } @Override public void refresh() { - Map builder = new ConcurrentHashMap<>(); + Map builder = new ConcurrentHashMap<>(); for (Map.Entry e : this.sourceMap.entrySet()) { Map children = this.plugin.getPermissionMap().getChildPermissions(e.getKey(), e.getValue()); - if (children != null) { - builder.putAll(children); + for (Map.Entry child : children.entrySet()) { + builder.put(child.getKey(), RESULT_FACTORY.result(Tristate.of(child.getValue()), "parent: " + e.getKey())); } } this.childPermissions = builder; diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/DefaultsProcessor.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/DefaultsProcessor.java index 4a1c485de..be9e63486 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/DefaultsProcessor.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/DefaultsProcessor.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.nukkit.calculator; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; import me.lucko.luckperms.common.calculator.result.TristateResult; import me.lucko.luckperms.nukkit.LPNukkitPlugin; @@ -57,6 +57,6 @@ public class DefaultsProcessor implements PermissionProcessor { if (def == null) { return TristateResult.UNDEFINED; } - return PERMISSION_MAP_RESULT_FACTORY.result(Tristate.fromBoolean(def.getValue(this.isOp))); + return PERMISSION_MAP_RESULT_FACTORY.result(Tristate.of(def.getValue(this.isOp))); } } diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/NukkitCalculatorFactory.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/NukkitCalculatorFactory.java index 48548e94e..9f73838a2 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/NukkitCalculatorFactory.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/calculator/NukkitCalculatorFactory.java @@ -27,8 +27,7 @@ package me.lucko.luckperms.nukkit.calculator; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LookupSetting; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.CacheMetadata; import me.lucko.luckperms.common.calculator.CalculatorFactory; import me.lucko.luckperms.common.calculator.PermissionCalculator; @@ -39,6 +38,7 @@ import me.lucko.luckperms.common.calculator.processor.WildcardProcessor; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.model.HolderType; import me.lucko.luckperms.nukkit.LPNukkitPlugin; +import me.lucko.luckperms.nukkit.context.NukkitContextManager; public class NukkitCalculatorFactory implements CalculatorFactory { private final LPNukkitPlugin plugin; @@ -48,7 +48,7 @@ public class NukkitCalculatorFactory implements CalculatorFactory { } @Override - public PermissionCalculator build(Contexts contexts, CacheMetadata metadata) { + public PermissionCalculator build(QueryOptions queryOptions, CacheMetadata metadata) { ImmutableList.Builder processors = ImmutableList.builder(); processors.add(new MapProcessor()); @@ -66,7 +66,7 @@ public class NukkitCalculatorFactory implements CalculatorFactory { } if (this.plugin.getConfiguration().get(ConfigKeys.APPLY_NUKKIT_DEFAULT_PERMISSIONS) && metadata.getHolderType() == HolderType.USER) { - processors.add(new DefaultsProcessor(this.plugin, contexts.hasSetting(LookupSetting.IS_OP))); + processors.add(new DefaultsProcessor(this.plugin, queryOptions.option(NukkitContextManager.OP_OPTION).orElse(false))); } return new PermissionCalculator(this.plugin, metadata, processors.build()); diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/NukkitContextManager.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/NukkitContextManager.java index 796f1baf6..5994e1006 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/NukkitContextManager.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/NukkitContextManager.java @@ -27,36 +27,37 @@ package me.lucko.luckperms.nukkit.context; import com.github.benmanes.caffeine.cache.LoadingCache; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LookupSetting; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.OptionKey; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cache.LoadingMap; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.context.ContextManager; -import me.lucko.luckperms.common.context.ContextsCache; -import me.lucko.luckperms.common.context.ContextsSupplier; +import me.lucko.luckperms.common.context.QueryOptionsCache; +import me.lucko.luckperms.common.context.QueryOptionsSupplier; import me.lucko.luckperms.common.util.CaffeineFactory; import me.lucko.luckperms.nukkit.LPNukkitPlugin; import cn.nukkit.Player; -import java.util.EnumSet; import java.util.concurrent.TimeUnit; public class NukkitContextManager extends ContextManager { + public static final OptionKey OP_OPTION = new OptionKey(){}; + // cache the creation of ContextsCache instances for online players with no expiry - private final LoadingMap> onlineSubjectCaches = LoadingMap.of(key -> new ContextsCache<>(key, this)); + 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() + private final LoadingCache> offlineSubjectCaches = CaffeineFactory.newBuilder() .expireAfterAccess(1, TimeUnit.MINUTES) .build(key -> { - ContextsCache cache = this.onlineSubjectCaches.getIfPresent(key); + QueryOptionsCache cache = this.onlineSubjectCaches.getIfPresent(key); if (cache != null) { return cache; } - return new ContextsCache<>(key, this); + return new QueryOptionsCache<>(key, this); }); public NukkitContextManager(LPNukkitPlugin plugin) { @@ -68,7 +69,7 @@ public class NukkitContextManager extends ContextManager { } @Override - public ContextsSupplier getCacheFor(Player subject) { + public QueryOptionsSupplier getCacheFor(Player subject) { if (subject == null) { throw new NullPointerException("subject"); } @@ -86,7 +87,7 @@ public class NukkitContextManager extends ContextManager { throw new NullPointerException("subject"); } - ContextsCache cache = this.onlineSubjectCaches.getIfPresent(subject); + QueryOptionsCache cache = this.onlineSubjectCaches.getIfPresent(subject); if (cache != null) { cache.invalidate(); } @@ -98,14 +99,12 @@ public class NukkitContextManager extends ContextManager { } @Override - public Contexts formContexts(Player subject, ImmutableContextSet contextSet) { - Contexts contexts = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_CONTEXTS); + public QueryOptions formQueryOptions(Player subject, ImmutableContextSet contextSet) { + QueryOptions.Builder queryOptions = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_CONTEXTS).toBuilder(); if (subject.isOp()) { - EnumSet settings = EnumSet.copyOf(contexts.getSettings()); - settings.add(LookupSetting.IS_OP); - contexts = contexts.setSettings(settings); + queryOptions.option(OP_OPTION, true); } - return contexts.setContexts(contextSet); + return queryOptions.context(contextSet).build(); } } diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/WorldCalculator.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/WorldCalculator.java index 34d5e1c42..18e29497f 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/WorldCalculator.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/context/WorldCalculator.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.nukkit.context; -import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ContextCalculator; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ContextConsumer; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -35,6 +35,9 @@ import org.checkerframework.checker.nullness.qual.NonNull; import cn.nukkit.Player; +import java.util.HashSet; +import java.util.Set; + public class WorldCalculator implements ContextCalculator { private final LuckPermsPlugin plugin; @@ -43,13 +46,12 @@ public class WorldCalculator implements ContextCalculator { } @Override - public @NonNull MutableContextSet giveApplicableContext(@NonNull Player subject, @NonNull MutableContextSet accumulator) { + public void giveApplicableContext(@NonNull Player subject, @NonNull ContextConsumer consumer) { + Set seen = new HashSet<>(); String world = subject.getLevel().getName().toLowerCase(); - while (!accumulator.has(Contexts.WORLD_KEY, world)) { - accumulator.add(Contexts.WORLD_KEY, world); + while (seen.add(world)) { + consumer.accept(DefaultContextKeys.WORLD_KEY, world); world = this.plugin.getConfiguration().get(ConfigKeys.WORLD_REWRITES).getOrDefault(world, world).toLowerCase(); } - - return accumulator; } } diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LPPermissible.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LPPermissible.java index 7e024b8dc..f7cdf2a47 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LPPermissible.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LPPermissible.java @@ -27,10 +27,10 @@ package me.lucko.luckperms.nukkit.inject.permissible; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.calculator.result.TristateResult; import me.lucko.luckperms.common.config.ConfigKeys; -import me.lucko.luckperms.common.context.ContextsSupplier; +import me.lucko.luckperms.common.context.QueryOptionsSupplier; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.util.ImmutableCollectors; import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent; @@ -93,7 +93,7 @@ public class LPPermissible extends PermissibleBase { private final LPNukkitPlugin plugin; // caches context lookups for the player - private final ContextsSupplier contextsSupplier; + 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 LPPermissible extends PermissibleBase { this.user = Objects.requireNonNull(user, "user"); this.player = Objects.requireNonNull(player, "player"); this.plugin = Objects.requireNonNull(plugin, "plugin"); - this.contextsSupplier = plugin.getContextManager().getCacheFor(player); + this.queryOptionsSupplier = plugin.getContextManager().getCacheFor(player); injectFakeAttachmentsList(); } @@ -139,7 +139,7 @@ public class LPPermissible extends PermissibleBase { throw new NullPointerException("permission"); } - TristateResult result = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission, PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK); + TristateResult result = this.user.getCachedData().getPermissionData(this.queryOptionsSupplier.getQueryOptions()).checkPermission(permission, PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK); if (result.result() == Tristate.UNDEFINED) { return false; } @@ -167,7 +167,7 @@ public class LPPermissible extends PermissibleBase { throw new NullPointerException("permission"); } - Tristate ts = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission, PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result(); + Tristate ts = this.user.getCachedData().getPermissionData(this.queryOptionsSupplier.getQueryOptions()).checkPermission(permission, PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result(); return ts != Tristate.UNDEFINED ? ts.asBoolean() : PermissionDefault.OP.getValue(isOp()); } @@ -177,7 +177,7 @@ public class LPPermissible extends PermissibleBase { throw new NullPointerException("permission"); } - Tristate ts = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission.getName(), PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result(); + Tristate ts = this.user.getCachedData().getPermissionData(this.queryOptionsSupplier.getQueryOptions()).checkPermission(permission.getName(), PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result(); if (ts != Tristate.UNDEFINED) { return ts.asBoolean(); } @@ -208,7 +208,7 @@ public class LPPermissible extends PermissibleBase { @Override public Map getEffectivePermissions() { - return this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getImmutableBacking().entrySet().stream() + return this.user.getCachedData().getPermissionData(this.queryOptionsSupplier.getQueryOptions()).getPermissionMap().entrySet().stream() .collect(ImmutableCollectors.toMap(Map.Entry::getKey, entry -> new PermissionAttachmentInfo(this.player, entry.getKey(), null, entry.getValue()))); } diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LPPermissionAttachment.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LPPermissionAttachment.java index 340f7bcb7..c6a467b19 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LPPermissionAttachment.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/LPPermissionAttachment.java @@ -27,12 +27,13 @@ package me.lucko.luckperms.nukkit.inject.permissible; import com.google.common.base.Preconditions; -import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.metadata.NodeMetadata; +import me.lucko.luckperms.api.node.metadata.NodeMetadataKey; +import me.lucko.luckperms.api.util.Result; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.ImmutableTransientNode; -import me.lucko.luckperms.common.node.utils.NodeTools; import me.lucko.luckperms.nukkit.inject.dummy.DummyPlugin; import cn.nukkit.permission.Permission; @@ -54,7 +55,9 @@ import java.util.Set; * * Applies all permissions directly to the backing user instance via transient nodes. */ -public class LPPermissionAttachment extends PermissionAttachment { +public class LPPermissionAttachment extends PermissionAttachment implements NodeMetadata { + + public static final NodeMetadataKey TRANSIENT_SOURCE_KEY = NodeMetadataKey.of("TransientSource", LPPermissionAttachment.class); /** * The field in PermissionAttachment where the attachments applied permissions @@ -181,32 +184,30 @@ public class LPPermissionAttachment extends PermissionAttachment { // construct a node for the permission being set // we use the servers static context to *try* to ensure that the node will apply Node node = NodeFactory.builder(name) - .setValue(value) - .withExtraContext(this.permissible.getPlugin().getContextManager().getStaticContext()) + .value(value) + .withContext(this.permissible.getPlugin().getContextManager().getStaticContext()) + .withMetadata(TRANSIENT_SOURCE_KEY, this) .build(); - // convert the constructed node to a transient node instance to refer back to this attachment - ImmutableTransientNode transientNode = ImmutableTransientNode.of(node, this); - // set the transient node User user = this.permissible.getUser(); - user.setTransientPermission(transientNode).asBoolean(); + ((Result) user.setTransientPermission(node)).wasSuccessful(); } private void unsetPermissionInternal(String name) { - if (!this.permissible.getPlugin().getConfiguration().get(ConfigKeys.APPLY_NUKKIT_ATTACHMENT_PERMISSIONS)) { + if (!this.permissible.getPlugin().getConfiguration().get(ConfigKeys.APPLY_BUKKIT_ATTACHMENT_PERMISSIONS)) { return; } // remove transient permissions from the holder which were added by this attachment & equal the permission User user = this.permissible.getUser(); - user.removeIfTransient(NodeTools.localizedNodeComposedPredicate(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this && n.getPermission().equals(name))); + user.removeIfTransient(n -> n.getMetadata(TRANSIENT_SOURCE_KEY).orElse(null) == this && n.getKey().equals(name)); } private void clearInternal() { // remove all transient permissions added by this attachment User user = this.permissible.getUser(); - user.removeIfTransient(NodeTools.localizedNodeComposedPredicate(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this)); + user.removeIfTransient(n -> n.getMetadata(TRANSIENT_SOURCE_KEY).orElse(null) == this); } @Override diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/MonitoredPermissibleBase.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/MonitoredPermissibleBase.java index e4bea4140..7f439bc33 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/MonitoredPermissibleBase.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/permissible/MonitoredPermissibleBase.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.nukkit.inject.permissible; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.calculator.result.TristateResult; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.verbose.VerboseHandler; @@ -68,7 +68,7 @@ public class MonitoredPermissibleBase extends PermissibleBase { } private void logCheck(PermissionCheckEvent.Origin origin, String permission, boolean result) { - this.plugin.getVerboseHandler().offerPermissionCheckEvent(origin, this.name, ContextSet.empty(), permission, TristateResult.of(Tristate.fromBoolean(result))); + this.plugin.getVerboseHandler().offerPermissionCheckEvent(origin, this.name, QueryOptions.defaultContextualOptions(), permission, TristateResult.of(Tristate.of(result))); this.plugin.getPermissionRegistry().offer(permission); } diff --git a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/server/LPDefaultsMap.java b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/server/LPDefaultsMap.java index 18916f502..5e8d0f465 100644 --- a/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/server/LPDefaultsMap.java +++ b/nukkit/src/main/java/me/lucko/luckperms/nukkit/inject/server/LPDefaultsMap.java @@ -28,7 +28,7 @@ package me.lucko.luckperms.nukkit.inject.server; import com.google.common.collect.ForwardingMap; import com.google.common.collect.ImmutableMap; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.cache.Cache; import me.lucko.luckperms.nukkit.LPNukkitPlugin; @@ -101,7 +101,7 @@ public final class LPDefaultsMap { */ public Tristate lookupDefaultPermission(String permission, boolean isOp) { Map map = getCache(isOp).get(); - return Tristate.fromNullableBoolean(map.get(permission)); + return Tristate.of(map.get(permission)); } final class DefaultPermissionSet extends ForwardingMap { diff --git a/sponge/sponge-service-api6/src/main/java/me/lucko/luckperms/sponge/service/proxy/api6/DescriptionBuilder.java b/sponge/sponge-service-api6/src/main/java/me/lucko/luckperms/sponge/service/proxy/api6/DescriptionBuilder.java index b22885eef..b10ace7fa 100644 --- a/sponge/sponge-service-api6/src/main/java/me/lucko/luckperms/sponge/service/proxy/api6/DescriptionBuilder.java +++ b/sponge/sponge-service-api6/src/main/java/me/lucko/luckperms/sponge/service/proxy/api6/DescriptionBuilder.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.sponge.service.proxy.api6; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.sponge.service.model.LPPermissionDescription; import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubject; @@ -80,7 +80,7 @@ public final class DescriptionBuilder implements PermissionDescription.Builder, @Override public PermissionDescription.@NonNull Builder assign(@NonNull String role, boolean value) { Objects.requireNonNull(role, "role"); - this.roles.put(role, Tristate.fromBoolean(value)); + this.roles.put(role, Tristate.of(value)); return this; } @@ -96,7 +96,7 @@ public final class DescriptionBuilder implements PermissionDescription.Builder, LPSubjectCollection subjects = this.service.getCollection(PermissionService.SUBJECTS_ROLE_TEMPLATE); for (Map.Entry assignment : this.roles.entrySet()) { LPSubject roleSubject = subjects.loadSubject(assignment.getKey()).join(); - roleSubject.getTransientSubjectData().setPermission(ContextSet.empty(), this.id, assignment.getValue()); + roleSubject.getTransientSubjectData().setPermission(ImmutableContextSet.empty(), this.id, assignment.getValue()); } // null stuff so this instance can be reused diff --git a/sponge/sponge-service-api6/src/main/java/me/lucko/luckperms/sponge/service/proxy/api6/SubjectProxy.java b/sponge/sponge-service-api6/src/main/java/me/lucko/luckperms/sponge/service/proxy/api6/SubjectProxy.java index 345a37612..7c9fa9cd1 100644 --- a/sponge/sponge-service-api6/src/main/java/me/lucko/luckperms/sponge/service/proxy/api6/SubjectProxy.java +++ b/sponge/sponge-service-api6/src/main/java/me/lucko/luckperms/sponge/service/proxy/api6/SubjectProxy.java @@ -26,7 +26,7 @@ package me.lucko.luckperms.sponge.service.proxy.api6; import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.common.context.ContextsSupplier; +import me.lucko.luckperms.common.context.QueryOptionsSupplier; import me.lucko.luckperms.common.util.ImmutableCollectors; import me.lucko.luckperms.sponge.service.CompatibilityUtil; import me.lucko.luckperms.sponge.service.model.LPPermissionService; @@ -53,7 +53,7 @@ public final class SubjectProxy implements Subject, ProxiedSubject, ProxiedServi private final LPPermissionService service; private final LPSubjectReference ref; - private ContextsSupplier contextsSupplier = null; + private QueryOptionsSupplier queryOptionsSupplier = null; public SubjectProxy(LPPermissionService service, LPSubjectReference ref) { this.service = service; @@ -65,11 +65,11 @@ public final class SubjectProxy implements Subject, ProxiedSubject, ProxiedServi } // lazy init - private ContextsSupplier getContextsCache() { - if (this.contextsSupplier == null) { - this.contextsSupplier = this.service.getContextManager().getCacheFor(this); + private QueryOptionsSupplier getContextsCache() { + if (this.queryOptionsSupplier == null) { + this.queryOptionsSupplier = this.service.getContextManager().getCacheFor(this); } - return this.contextsSupplier; + return this.queryOptionsSupplier; } @Override diff --git a/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/DescriptionBuilder.java b/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/DescriptionBuilder.java index 8b843a2a2..dbc378931 100644 --- a/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/DescriptionBuilder.java +++ b/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/DescriptionBuilder.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.sponge.service.proxy.api7; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.sponge.service.model.LPPermissionDescription; import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubject; @@ -79,7 +79,7 @@ public final class DescriptionBuilder implements PermissionDescription.Builder, @Override public PermissionDescription.@NonNull Builder assign(@NonNull String role, boolean value) { Objects.requireNonNull(role, "role"); - this.roles.put(role, Tristate.fromBoolean(value)); + this.roles.put(role, Tristate.of(value)); return this; } @@ -95,7 +95,7 @@ public final class DescriptionBuilder implements PermissionDescription.Builder, LPSubjectCollection subjects = this.service.getCollection(PermissionService.SUBJECTS_ROLE_TEMPLATE); for (Map.Entry assignment : this.roles.entrySet()) { LPSubject roleSubject = subjects.loadSubject(assignment.getKey()).join(); - roleSubject.getTransientSubjectData().setPermission(ContextSet.empty(), this.id, assignment.getValue()); + roleSubject.getTransientSubjectData().setPermission(ImmutableContextSet.empty(), this.id, assignment.getValue()); } // null stuff so this instance can be reused diff --git a/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectProxy.java b/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectProxy.java index af9edd420..f06973a81 100644 --- a/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectProxy.java +++ b/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectProxy.java @@ -26,7 +26,7 @@ package me.lucko.luckperms.sponge.service.proxy.api7; import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.common.context.ContextsSupplier; +import me.lucko.luckperms.common.context.QueryOptionsSupplier; import me.lucko.luckperms.sponge.service.CompatibilityUtil; import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubject; @@ -53,7 +53,7 @@ public final class SubjectProxy implements Subject, ProxiedSubject, ProxiedServi private final LPPermissionService service; private final LPSubjectReference ref; - private ContextsSupplier contextsSupplier; + private QueryOptionsSupplier queryOptionsSupplier; public SubjectProxy(LPPermissionService service, LPSubjectReference ref) { this.service = service; @@ -65,11 +65,11 @@ public final class SubjectProxy implements Subject, ProxiedSubject, ProxiedServi } // lazy init - private ContextsSupplier getContextsCache() { - if (this.contextsSupplier == null) { - this.contextsSupplier = this.service.getContextManager().getCacheFor(this); + private QueryOptionsSupplier getContextsCache() { + if (this.queryOptionsSupplier == null) { + this.queryOptionsSupplier = this.service.getContextManager().getCacheFor(this); } - return this.contextsSupplier; + return this.queryOptionsSupplier; } @Override diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/CompatibilityUtil.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/CompatibilityUtil.java index 71dcdac4e..5dde8f0a7 100644 --- a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/CompatibilityUtil.java +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/CompatibilityUtil.java @@ -27,9 +27,9 @@ package me.lucko.luckperms.sponge.service; import com.google.common.collect.ImmutableSet; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.sponge.service.context.DelegatingContextSet; import me.lucko.luckperms.sponge.service.context.DelegatingImmutableContextSet; @@ -50,7 +50,7 @@ public final class CompatibilityUtil { Objects.requireNonNull(contexts, "contexts"); if (contexts instanceof DelegatingContextSet) { - return ((DelegatingContextSet) contexts).getDelegate().makeImmutable(); + return ((DelegatingContextSet) contexts).getDelegate().immutableCopy(); } if (contexts.isEmpty()) { @@ -67,7 +67,7 @@ public final class CompatibilityUtil { return EMPTY; } - return new DelegatingImmutableContextSet(contexts.makeImmutable()); + return new DelegatingImmutableContextSet(contexts.immutableCopy()); } public static org.spongepowered.api.util.Tristate convertTristate(Tristate tristate) { diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/context/AbstractDelegatingContextSet.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/context/AbstractDelegatingContextSet.java index 8b02cae9a..6351ded79 100644 --- a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/context/AbstractDelegatingContextSet.java +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/context/AbstractDelegatingContextSet.java @@ -46,7 +46,7 @@ abstract class AbstractDelegatingContextSet extends AbstractSet impleme public boolean contains(Object o) { if (o instanceof Context) { Context context = (Context) o; - return !context.getKey().isEmpty() && !context.getValue().isEmpty() && getDelegate().has(context); + return !context.getKey().isEmpty() && !context.getValue().isEmpty() && getDelegate().contains(context); } return false; } diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/context/DelegatingMutableContextSet.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/context/DelegatingMutableContextSet.java index cfff1d0b0..13154c48b 100644 --- a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/context/DelegatingMutableContextSet.java +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/context/DelegatingMutableContextSet.java @@ -63,7 +63,7 @@ public class DelegatingMutableContextSet extends AbstractDelegatingContextSet { return false; } - boolean has = this.delegate.has(context); + boolean has = this.delegate.contains(context); this.delegate.add(context); return !has; } @@ -75,7 +75,7 @@ public class DelegatingMutableContextSet extends AbstractDelegatingContextSet { if (context.getKey().isEmpty() || context.getValue().isEmpty()) { return false; } - boolean had = this.delegate.has(context); + boolean had = this.delegate.contains(context); this.delegate.remove(context.getKey(), context.getValue()); return had; } diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubject.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubject.java index 524f137a9..81547e036 100644 --- a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubject.java +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubject.java @@ -27,8 +27,9 @@ package me.lucko.luckperms.sponge.service.model; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.service.permission.Subject; @@ -66,6 +67,8 @@ public interface LPSubject { LPSubjectData getTransientSubjectData(); + Tristate getPermissionValue(QueryOptions options, String permission); + Tristate getPermissionValue(ImmutableContextSet contexts, String permission); boolean isChildOf(ImmutableContextSet contexts, LPSubjectReference parent); diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubjectData.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubjectData.java index d0628496e..219ca7957 100644 --- a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubjectData.java +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubjectData.java @@ -28,8 +28,8 @@ package me.lucko.luckperms.sponge.service.model; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.model.NodeMapType; import org.spongepowered.api.service.permission.SubjectData; diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongeBootstrap.java b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongeBootstrap.java index 48d479eec..b31c40bb1 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongeBootstrap.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongeBootstrap.java @@ -27,7 +27,6 @@ package me.lucko.luckperms.sponge; import com.google.inject.Inject; -import me.lucko.luckperms.api.platform.PlatformType; import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader; import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader; import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap; @@ -226,8 +225,8 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap { // provide information about the platform @Override - public PlatformType getType() { - return PlatformType.SPONGE; + public me.lucko.luckperms.api.platform.Platform.Type getType() { + return me.lucko.luckperms.api.platform.Platform.Type.SPONGE; } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java index dab83c420..b08f4fda5 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.sponge; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.LuckPerms; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.calculator.CalculatorFactory; import me.lucko.luckperms.common.command.abstraction.Command; @@ -53,7 +53,6 @@ import me.lucko.luckperms.sponge.listeners.SpongePlatformListener; import me.lucko.luckperms.sponge.messaging.SpongeMessagingFactory; import me.lucko.luckperms.sponge.model.manager.SpongeGroupManager; import me.lucko.luckperms.sponge.model.manager.SpongeUserManager; -import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.ProxyFactory; import me.lucko.luckperms.sponge.service.events.UpdateEventHandler; import me.lucko.luckperms.sponge.service.model.LPPermissionService; @@ -91,7 +90,7 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin { private SpongeGroupManager groupManager; private StandardTrackManager trackManager; private ContextManager contextManager; - private LuckPermsService service; + private me.lucko.luckperms.sponge.service.LuckPermsService service; private UpdateEventHandler updateEventHandler; private boolean lateLoad = false; @@ -165,7 +164,7 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin { protected void setupPlatformHooks() { getLogger().info("Registering PermissionService..."); this.updateEventHandler = UpdateEventHandler.obtain(this); - this.service = new LuckPermsService(this); + this.service = new me.lucko.luckperms.sponge.service.LuckPermsService(this); PermissionService oldService = this.bootstrap.getGame().getServiceManager().provide(PermissionService.class).orElse(null); if (oldService != null && !(oldService instanceof ProxiedServiceObject)) { @@ -196,8 +195,8 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin { } @Override - protected void registerApiOnPlatform(LuckPermsApi api) { - this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, LuckPermsApi.class, api); + protected void registerApiOnPlatform(LuckPerms api) { + this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, LuckPerms.class, api); } @Override @@ -250,8 +249,8 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin { } @Override - public Optional getContextForUser(User user) { - return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getApplicableContexts(player)); + public Optional getQueryOptionsForUser(User user) { + return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getQueryOptions(player)); } @Override @@ -318,7 +317,7 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin { return this.contextManager; } - public LuckPermsService getService() { + public me.lucko.luckperms.sponge.service.LuckPermsService getService() { return this.service; } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeSenderFactory.java b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeSenderFactory.java index fab7dd0df..edd05211e 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeSenderFactory.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeSenderFactory.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.sponge; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.SenderFactory; diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/DefaultsProcessor.java b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/DefaultsProcessor.java index 72553346b..19e25d775 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/DefaultsProcessor.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/DefaultsProcessor.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.sponge.calculator; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; import me.lucko.luckperms.common.calculator.result.TristateResult; import me.lucko.luckperms.sponge.service.model.LPPermissionService; @@ -37,23 +37,23 @@ public abstract class DefaultsProcessor implements PermissionProcessor { private static final TristateResult.Factory ROOT_DEFAULTS_RESULT_FACTORY = new TristateResult.Factory(DefaultsProcessor.class, "root defaults"); protected final LPPermissionService service; - private final ImmutableContextSet contexts; + private final QueryOptions queryOptions; - public DefaultsProcessor(LPPermissionService service, ImmutableContextSet contexts) { + public DefaultsProcessor(LPPermissionService service, QueryOptions queryOptions) { this.service = service; - this.contexts = contexts; + this.queryOptions = queryOptions; } protected abstract LPSubject getTypeDefaults(); @Override public TristateResult hasPermission(String permission) { - Tristate t = getTypeDefaults().getPermissionValue(this.contexts, permission); + Tristate t = getTypeDefaults().getPermissionValue(this.queryOptions, permission); if (t != Tristate.UNDEFINED) { return TYPE_DEFAULTS_RESULT_FACTORY.result(t); } - t = this.service.getRootDefaults().getPermissionValue(this.contexts, permission); + t = this.service.getRootDefaults().getPermissionValue(this.queryOptions, permission); if (t != Tristate.UNDEFINED) { return ROOT_DEFAULTS_RESULT_FACTORY.result(t); } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/FixedDefaultsProcessor.java b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/FixedDefaultsProcessor.java index 2ae56eaca..0644be8af 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/FixedDefaultsProcessor.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/FixedDefaultsProcessor.java @@ -25,15 +25,15 @@ package me.lucko.luckperms.sponge.calculator; -import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubject; public class FixedDefaultsProcessor extends DefaultsProcessor { private final LPSubject defaultsSubject; - public FixedDefaultsProcessor(LPPermissionService service, ImmutableContextSet contexts, LPSubject defaultsSubject) { - super(service, contexts); + public FixedDefaultsProcessor(LPPermissionService service, QueryOptions queryOptions, LPSubject defaultsSubject) { + super(service, queryOptions); this.defaultsSubject = defaultsSubject; } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/GroupDefaultsProcessor.java b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/GroupDefaultsProcessor.java index 826c93bd1..3b05d71bd 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/GroupDefaultsProcessor.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/GroupDefaultsProcessor.java @@ -25,14 +25,14 @@ package me.lucko.luckperms.sponge.calculator; -import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubject; public class GroupDefaultsProcessor extends DefaultsProcessor implements PermissionProcessor { - public GroupDefaultsProcessor(LPPermissionService service, ImmutableContextSet contexts) { - super(service, contexts); + public GroupDefaultsProcessor(LPPermissionService service, QueryOptions queryOptions) { + super(service, queryOptions); } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/SpongeCalculatorFactory.java b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/SpongeCalculatorFactory.java index c82a2fef9..23067752b 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/SpongeCalculatorFactory.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/SpongeCalculatorFactory.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.sponge.calculator; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.CacheMetadata; import me.lucko.luckperms.common.calculator.CalculatorFactory; import me.lucko.luckperms.common.calculator.PermissionCalculator; @@ -47,7 +47,7 @@ public class SpongeCalculatorFactory implements CalculatorFactory { } @Override - public PermissionCalculator build(Contexts contexts, CacheMetadata metadata) { + public PermissionCalculator build(QueryOptions queryOptions, CacheMetadata metadata) { ImmutableList.Builder processors = ImmutableList.builder(); processors.add(new MapProcessor()); @@ -66,9 +66,9 @@ public class SpongeCalculatorFactory implements CalculatorFactory { if (this.plugin.getConfiguration().get(ConfigKeys.APPLY_SPONGE_DEFAULT_SUBJECTS)) { if (metadata.getHolderType() == HolderType.USER) { - processors.add(new UserDefaultsProcessor(this.plugin.getService(), contexts.getContexts().makeImmutable())); + processors.add(new UserDefaultsProcessor(this.plugin.getService(), queryOptions)); } else if (metadata.getHolderType() == HolderType.GROUP) { - processors.add(new GroupDefaultsProcessor(this.plugin.getService(), contexts.getContexts().makeImmutable())); + processors.add(new GroupDefaultsProcessor(this.plugin.getService(), queryOptions)); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/SpongeWildcardProcessor.java b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/SpongeWildcardProcessor.java index d4b20452a..c58289de7 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/SpongeWildcardProcessor.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/SpongeWildcardProcessor.java @@ -25,11 +25,11 @@ package me.lucko.luckperms.sponge.calculator; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.calculator.processor.AbstractPermissionProcessor; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; import me.lucko.luckperms.common.calculator.result.TristateResult; -import me.lucko.luckperms.common.node.model.ImmutableNode; +import me.lucko.luckperms.common.node.AbstractNode; public class SpongeWildcardProcessor extends AbstractPermissionProcessor implements PermissionProcessor { private static final TristateResult.Factory RESULT_FACTORY = new TristateResult.Factory(SpongeWildcardProcessor.class); @@ -39,14 +39,14 @@ public class SpongeWildcardProcessor extends AbstractPermissionProcessor impleme String node = permission; while (true) { - int endIndex = node.lastIndexOf(ImmutableNode.NODE_SEPARATOR); + int endIndex = node.lastIndexOf(AbstractNode.NODE_SEPARATOR); if (endIndex == -1) { break; } node = node.substring(0, endIndex); if (!node.isEmpty()) { - Tristate t = Tristate.fromNullableBoolean(this.sourceMap.get(node)); + Tristate t = Tristate.of(this.sourceMap.get(node)); if (t != Tristate.UNDEFINED) { return RESULT_FACTORY.result(t, "match: " + node); } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/UserDefaultsProcessor.java b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/UserDefaultsProcessor.java index 27d0bf828..6ed7f8312 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/UserDefaultsProcessor.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/calculator/UserDefaultsProcessor.java @@ -25,14 +25,14 @@ package me.lucko.luckperms.sponge.calculator; -import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.calculator.processor.PermissionProcessor; import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubject; public class UserDefaultsProcessor extends DefaultsProcessor implements PermissionProcessor { - public UserDefaultsProcessor(LPPermissionService service, ImmutableContextSet contexts) { - super(service, contexts); + public UserDefaultsProcessor(LPPermissionService service, QueryOptions queryOptions) { + super(service, queryOptions); } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/commands/PermissionSet.java b/sponge/src/main/java/me/lucko/luckperms/sponge/commands/PermissionSet.java index 936c53af6..04f6f5cff 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/commands/PermissionSet.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/commands/PermissionSet.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.sponge.commands; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.command.CommandResult; import me.lucko.luckperms.common.command.abstraction.CommandException; import me.lucko.luckperms.common.command.abstraction.SubCommand; diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/commands/SpongeCommandUtils.java b/sponge/src/main/java/me/lucko/luckperms/sponge/commands/SpongeCommandUtils.java index 1d7ea5849..933861844 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/commands/SpongeCommandUtils.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/commands/SpongeCommandUtils.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.sponge.commands; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.command.utils.ArgumentParser; import me.lucko.luckperms.common.command.utils.MessageUtils; import me.lucko.luckperms.common.locale.LocaleManager; 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 eccb34923..994bf2206 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 @@ -27,11 +27,11 @@ package me.lucko.luckperms.sponge.context; import com.github.benmanes.caffeine.cache.LoadingCache; -import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.context.ContextManager; -import me.lucko.luckperms.common.context.ContextsCache; -import me.lucko.luckperms.common.context.ContextsSupplier; +import me.lucko.luckperms.common.context.QueryOptionsCache; +import me.lucko.luckperms.common.context.QueryOptionsSupplier; import me.lucko.luckperms.common.util.CaffeineFactory; import me.lucko.luckperms.sponge.LPSpongePlugin; @@ -41,16 +41,16 @@ import java.util.concurrent.TimeUnit; public class SpongeContextManager extends ContextManager { - private final LoadingCache> subjectCaches = CaffeineFactory.newBuilder() + private final LoadingCache> subjectCaches = CaffeineFactory.newBuilder() .expireAfterAccess(1, TimeUnit.MINUTES) - .build(key -> new ContextsCache<>(key, this)); + .build(key -> new QueryOptionsCache<>(key, this)); public SpongeContextManager(LPSpongePlugin plugin) { super(plugin, Subject.class); } @Override - public ContextsSupplier getCacheFor(Subject subject) { + public QueryOptionsSupplier getCacheFor(Subject subject) { if (subject == null) { throw new NullPointerException("subject"); } @@ -64,14 +64,14 @@ public class SpongeContextManager extends ContextManager { throw new NullPointerException("subject"); } - ContextsCache cache = this.subjectCaches.getIfPresent(subject); + QueryOptionsCache cache = this.subjectCaches.getIfPresent(subject); if (cache != null) { cache.invalidate(); } } @Override - public Contexts formContexts(Subject subject, ImmutableContextSet contextSet) { - return formContexts(contextSet); + public QueryOptions formQueryOptions(Subject subject, ImmutableContextSet contextSet) { + return formQueryOptions(contextSet); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/context/SpongeProxiedContextCalculator.java b/sponge/src/main/java/me/lucko/luckperms/sponge/context/SpongeProxiedContextCalculator.java index c3b6c194a..c752d979d 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/context/SpongeProxiedContextCalculator.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/context/SpongeProxiedContextCalculator.java @@ -25,15 +25,16 @@ package me.lucko.luckperms.sponge.context; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ContextConsumer; import me.lucko.luckperms.common.context.ProxiedContextCalculator; -import me.lucko.luckperms.sponge.service.context.DelegatingMutableContextSet; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.context.ContextCalculator; import org.spongepowered.api.service.permission.Subject; +import java.util.Collection; +import java.util.Iterator; import java.util.Set; public class SpongeProxiedContextCalculator implements ProxiedContextCalculator { @@ -44,10 +45,8 @@ public class SpongeProxiedContextCalculator implements ProxiedContextCalculator< } @Override - public @NonNull MutableContextSet giveApplicableContext(@NonNull Subject subject, @NonNull MutableContextSet accumulator) { - Set contexts = new DelegatingMutableContextSet(accumulator); - this.delegate.accumulateContexts(subject, contexts); - return accumulator; + public void giveApplicableContext(@NonNull Subject subject, @NonNull ContextConsumer consumer) { + this.delegate.accumulateContexts(subject, new ProxiedContextSet(consumer)); } @Override @@ -55,4 +54,41 @@ public class SpongeProxiedContextCalculator implements ProxiedContextCalculator< return this.delegate; } + private static final class ProxiedContextSet implements Set { + private final ContextConsumer consumer; + + private ProxiedContextSet(ContextConsumer consumer) { + this.consumer = consumer; + } + + @Override + public boolean add(Context context) { + if (context.getKey().isEmpty() || context.getValue().isEmpty()) { + return false; + } + this.consumer.accept(context.getKey(), context.getValue()); + return true; + } + + @Override + public boolean addAll(@NonNull Collection c) { + for (Context context : c) { + add(context); + } + return true; + } + + @Override public int size() { throw new UnsupportedOperationException(); } + @Override public boolean isEmpty() { throw new UnsupportedOperationException(); } + @Override public boolean contains(Object o) { throw new UnsupportedOperationException(); } + @Override public @NonNull Iterator iterator() { throw new UnsupportedOperationException(); } + @Override public @NonNull Object[] toArray() { throw new UnsupportedOperationException(); } + @Override public @NonNull T[] toArray(T[] a) { throw new UnsupportedOperationException(); } + @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } + @Override public boolean containsAll(Collection c) { throw new UnsupportedOperationException(); } + @Override public boolean retainAll(Collection c) { throw new UnsupportedOperationException(); } + @Override public boolean removeAll(Collection c) { throw new UnsupportedOperationException(); } + @Override public void clear() { throw new UnsupportedOperationException(); } + } + } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/context/WorldCalculator.java b/sponge/src/main/java/me/lucko/luckperms/sponge/context/WorldCalculator.java index 827c9c6ac..a2ef62dce 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/context/WorldCalculator.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/context/WorldCalculator.java @@ -25,9 +25,9 @@ package me.lucko.luckperms.sponge.context; -import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ContextCalculator; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ContextConsumer; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; @@ -36,6 +36,9 @@ import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.service.permission.Subject; +import java.util.HashSet; +import java.util.Set; + public class WorldCalculator implements ContextCalculator { private final LuckPermsPlugin plugin; @@ -44,20 +47,21 @@ public class WorldCalculator implements ContextCalculator { } @Override - public @NonNull MutableContextSet giveApplicableContext(@NonNull Subject subject, @NonNull MutableContextSet accumulator) { + public void giveApplicableContext(@NonNull Subject subject, @NonNull ContextConsumer consumer) { CommandSource source = subject.getCommandSource().orElse(null); if (source == null || !(source instanceof Player)) { - return accumulator; + return; } Player p = ((Player) source); + + Set seen = new HashSet<>(); String world = p.getWorld().getName().toLowerCase(); - while (!accumulator.has(Contexts.WORLD_KEY, world)) { - accumulator.add(Contexts.WORLD_KEY, world); + while (seen.add(world)) { + consumer.accept(DefaultContextKeys.WORLD_KEY, world); world = this.plugin.getConfiguration().get(ConfigKeys.WORLD_REWRITES).getOrDefault(world, world).toLowerCase(); } - return accumulator; } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/model/manager/SpongeGroupManager.java b/sponge/src/main/java/me/lucko/luckperms/sponge/model/manager/SpongeGroupManager.java index 84e15a36f..b8405d439 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/model/manager/SpongeGroupManager.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/model/manager/SpongeGroupManager.java @@ -32,10 +32,10 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.event.cause.CreationCause; +import me.lucko.luckperms.api.node.HeldNode; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison; import me.lucko.luckperms.common.model.manager.group.AbstractGroupManager; @@ -191,10 +191,10 @@ public class SpongeGroupManager extends AbstractGroupManager implem return CompletableFuture.supplyAsync(() -> { ImmutableMap.Builder ret = ImmutableMap.builder(); - List> lookup = this.plugin.getStorage().getGroupsWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join(); - for (HeldPermission holder : lookup) { - if (holder.asNode().getFullContexts().equals(ImmutableContextSet.empty())) { - ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder()), holder.getValue()); + List> lookup = this.plugin.getStorage().getGroupsWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join(); + for (HeldNode holder : lookup) { + if (holder.getNode().getContexts().equals(ImmutableContextSet.empty())) { + ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder()), holder.getNode().getValue()); } } @@ -207,10 +207,10 @@ public class SpongeGroupManager extends AbstractGroupManager implem return CompletableFuture.supplyAsync(() -> { ImmutableMap.Builder ret = ImmutableMap.builder(); - List> lookup = this.plugin.getStorage().getGroupsWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join(); - for (HeldPermission holder : lookup) { - if (holder.asNode().getFullContexts().equals(contexts)) { - ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder()), holder.getValue()); + List> lookup = this.plugin.getStorage().getGroupsWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join(); + for (HeldNode holder : lookup) { + if (holder.getNode().getContexts().equals(contexts)) { + ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder()), holder.getNode().getValue()); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/model/manager/SpongeUserManager.java b/sponge/src/main/java/me/lucko/luckperms/sponge/model/manager/SpongeUserManager.java index 88c80fdc4..802d714d6 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/model/manager/SpongeUserManager.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/model/manager/SpongeUserManager.java @@ -32,9 +32,9 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; -import me.lucko.luckperms.api.HeldPermission; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.HeldNode; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.bulkupdate.comparison.Constraint; import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison; import me.lucko.luckperms.common.model.UserIdentifier; @@ -213,10 +213,10 @@ public class SpongeUserManager extends AbstractUserManager implement return CompletableFuture.supplyAsync(() -> { ImmutableMap.Builder ret = ImmutableMap.builder(); - List> lookup = this.plugin.getStorage().getUsersWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join(); - for (HeldPermission holder : lookup) { - if (holder.asNode().getFullContexts().equals(ImmutableContextSet.empty())) { - ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder().toString()), holder.getValue()); + List> lookup = this.plugin.getStorage().getUsersWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join(); + for (HeldNode holder : lookup) { + if (holder.getNode().getContexts().equals(ImmutableContextSet.empty())) { + ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder().toString()), holder.getNode().getValue()); } } @@ -229,10 +229,10 @@ public class SpongeUserManager extends AbstractUserManager implement return CompletableFuture.supplyAsync(() -> { ImmutableMap.Builder ret = ImmutableMap.builder(); - List> lookup = this.plugin.getStorage().getUsersWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join(); - for (HeldPermission holder : lookup) { - if (holder.asNode().getFullContexts().equals(contexts)) { - ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder().toString()), holder.getValue()); + List> lookup = this.plugin.getStorage().getUsersWithPermission(Constraint.of(StandardComparison.EQUAL, permission)).join(); + for (HeldNode holder : lookup) { + if (holder.getNode().getContexts().equals(contexts)) { + ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder().toString()), holder.getNode().getValue()); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/inheritance/SubjectInheritanceGraph.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/inheritance/SubjectInheritanceGraph.java index 0b88ddff8..96ac5e822 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/inheritance/SubjectInheritanceGraph.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/inheritance/SubjectInheritanceGraph.java @@ -25,12 +25,33 @@ package me.lucko.luckperms.sponge.service.inheritance; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.graph.Graph; import me.lucko.luckperms.sponge.service.model.calculated.CalculatedSubject; +import java.util.stream.Collectors; + /** * A {@link Graph} which represents an "inheritance tree" for subjects. */ -public interface SubjectInheritanceGraph extends Graph { +public class SubjectInheritanceGraph implements Graph { + + /** + * The contexts to resolve inheritance in. + */ + private final QueryOptions queryOptions; + + public SubjectInheritanceGraph(QueryOptions queryOptions) { + this.queryOptions = queryOptions; + } + + @Override + public Iterable successors(CalculatedSubject subject) { + return subject.getCombinedParents(this.queryOptions).stream() + .map(ref -> ref.resolveLp().join()) + .filter(p -> p instanceof CalculatedSubject) + .map(p -> ((CalculatedSubject) p)) + .collect(Collectors.toList()); + } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/inheritance/SubjectInheritanceGraphs.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/inheritance/SubjectInheritanceGraphs.java deleted file mode 100644 index c20322a46..000000000 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/inheritance/SubjectInheritanceGraphs.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.sponge.service.inheritance; - -import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.sponge.service.model.calculated.CalculatedSubject; - -import java.util.stream.Collectors; - -public final class SubjectInheritanceGraphs { - private SubjectInheritanceGraphs() {} - - private static final SubjectInheritanceGraph NON_CONTEXTUAL = new NonContextual(); - - public static SubjectInheritanceGraph getGraph() { - return NON_CONTEXTUAL; - } - - public static SubjectInheritanceGraph getGraph(ImmutableContextSet contextSet) { - return new Contextual(contextSet); - } - - private static final class NonContextual implements SubjectInheritanceGraph { - @Override - public Iterable successors(CalculatedSubject subject) { - return subject.getCombinedParents().stream() - .map(ref -> ref.resolveLp().join()) - .filter(p -> p instanceof CalculatedSubject) - .map(p -> ((CalculatedSubject) p)) - .collect(Collectors.toList()); - } - } - - private static final class Contextual implements SubjectInheritanceGraph { - - /** - * The contexts to resolve inheritance in. - */ - private final ImmutableContextSet contextSet; - - private Contextual(ImmutableContextSet contextSet) { - this.contextSet = contextSet; - } - - @Override - public Iterable successors(CalculatedSubject subject) { - return subject.getCombinedParents(this.contextSet).stream() - .map(ref -> ref.resolveLp().join()) - .filter(p -> p instanceof CalculatedSubject) - .map(p -> ((CalculatedSubject) p)) - .collect(Collectors.toList()); - } - } -} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubject.java index 345de4cba..890e5f4b1 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubject.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubject.java @@ -27,17 +27,15 @@ package me.lucko.luckperms.sponge.service.model.calculated; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; import me.lucko.luckperms.common.graph.TraversalAlgorithm; import me.lucko.luckperms.common.verbose.event.MetaCheckEvent; import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent; import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.service.inheritance.SubjectInheritanceGraph; -import me.lucko.luckperms.sponge.service.inheritance.SubjectInheritanceGraphs; import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubjectReference; @@ -49,11 +47,11 @@ import java.util.Set; public abstract class CalculatedSubject implements LPSubject { private final LPSpongePlugin plugin; - private final CalculatedSubjectCachedData cachedData; + private final CalculatedSubjectCachedDataManager cachedData; protected CalculatedSubject(LPSpongePlugin plugin) { this.plugin = plugin; - this.cachedData = new CalculatedSubjectCachedData(this, plugin); + this.cachedData = new CalculatedSubjectCachedDataManager(this, plugin); } @Override @@ -64,7 +62,7 @@ public abstract class CalculatedSubject implements LPSubject { public abstract CalculatedSubjectData getSubjectData(); public abstract CalculatedSubjectData getTransientSubjectData(); - public Map getCombinedPermissions(ContextSet filter) { + public Map getCombinedPermissions(QueryOptions filter) { Map permissions; Map merging; switch (getParentCollection().getResolutionOrder()) { @@ -86,30 +84,8 @@ public abstract class CalculatedSubject implements LPSubject { return permissions; } - public Map getCombinedPermissions() { - Map permissions; - Map merging; - switch (getParentCollection().getResolutionOrder()) { - case TRANSIENT_FIRST: - permissions = getTransientSubjectData().resolvePermissions(); - merging = getSubjectData().resolvePermissions(); - break; - case TRANSIENT_LAST: - permissions = getSubjectData().resolvePermissions(); - merging = getTransientSubjectData().resolvePermissions(); - break; - default: - throw new AssertionError(); - } - - for (Map.Entry entry : merging.entrySet()) { - permissions.putIfAbsent(entry.getKey(), entry.getValue()); - } - return permissions; - } - - public Map resolveAllPermissions(ImmutableContextSet filter) { - SubjectInheritanceGraph graph = SubjectInheritanceGraphs.getGraph(filter); + public Map resolveAllPermissions(QueryOptions filter) { + SubjectInheritanceGraph graph = new SubjectInheritanceGraph(filter); Map result = new HashMap<>(); Iterable traversal = graph.traverse(TraversalAlgorithm.DEPTH_FIRST_PRE_ORDER, this); @@ -122,21 +98,7 @@ public abstract class CalculatedSubject implements LPSubject { return result; } - public Map resolveAllPermissions() { - SubjectInheritanceGraph graph = SubjectInheritanceGraphs.getGraph(); - Map result = new HashMap<>(); - - Iterable traversal = graph.traverse(TraversalAlgorithm.DEPTH_FIRST_PRE_ORDER, this); - for (CalculatedSubject subject : traversal) { - for (Map.Entry entry : subject.getCombinedPermissions().entrySet()) { - result.putIfAbsent(entry.getKey(), entry.getValue()); - } - } - - return result; - } - - public Set getCombinedParents(ContextSet filter) { + public Set getCombinedParents(QueryOptions filter) { Set parents; Set merging; switch (getParentCollection().getResolutionOrder()) { @@ -156,28 +118,8 @@ public abstract class CalculatedSubject implements LPSubject { return parents; } - public Set getCombinedParents() { - Set parents; - Set merging; - switch (getParentCollection().getResolutionOrder()) { - case TRANSIENT_FIRST: - parents = getTransientSubjectData().resolveParents(); - merging = getSubjectData().resolveParents(); - break; - case TRANSIENT_LAST: - parents = getSubjectData().resolveParents(); - merging = getTransientSubjectData().resolveParents(); - break; - default: - throw new AssertionError(); - } - - parents.addAll(merging); - return parents; - } - - public Set resolveAllParents(ImmutableContextSet filter) { - SubjectInheritanceGraph graph = SubjectInheritanceGraphs.getGraph(filter); + public Set resolveAllParents(QueryOptions filter) { + SubjectInheritanceGraph graph = new SubjectInheritanceGraph(filter); Set result = new LinkedHashSet<>(); Iterable traversal = graph.traverse(TraversalAlgorithm.DEPTH_FIRST_PRE_ORDER, this); @@ -188,19 +130,7 @@ public abstract class CalculatedSubject implements LPSubject { return result; } - public Set resolveAllParents() { - SubjectInheritanceGraph graph = SubjectInheritanceGraphs.getGraph(); - Set result = new LinkedHashSet<>(); - - Iterable traversal = graph.traverse(TraversalAlgorithm.DEPTH_FIRST_PRE_ORDER, this); - for (CalculatedSubject subject : traversal) { - result.addAll(subject.getCombinedParents()); - } - - return result; - } - - public Map getCombinedOptions(ContextSet filter) { + public Map getCombinedOptions(QueryOptions filter) { Map options; Map merging; switch (getParentCollection().getResolutionOrder()) { @@ -222,30 +152,8 @@ public abstract class CalculatedSubject implements LPSubject { return options; } - public Map getCombinedOptions() { - Map options; - Map merging; - switch (getParentCollection().getResolutionOrder()) { - case TRANSIENT_FIRST: - options = getTransientSubjectData().resolveOptions(); - merging = getSubjectData().resolveOptions(); - break; - case TRANSIENT_LAST: - options = getSubjectData().resolveOptions(); - merging = getTransientSubjectData().resolveOptions(); - break; - default: - throw new AssertionError(); - } - - for (Map.Entry entry : merging.entrySet()) { - options.putIfAbsent(entry.getKey(), entry.getValue()); - } - return options; - } - - public Map resolveAllOptions(ImmutableContextSet filter) { - SubjectInheritanceGraph graph = SubjectInheritanceGraphs.getGraph(filter); + public Map resolveAllOptions(QueryOptions filter) { + SubjectInheritanceGraph graph = new SubjectInheritanceGraph(filter); Map result = new HashMap<>(); Iterable traversal = graph.traverse(TraversalAlgorithm.DEPTH_FIRST_PRE_ORDER, this); @@ -258,22 +166,8 @@ public abstract class CalculatedSubject implements LPSubject { return result; } - public Map resolveAllOptions() { - SubjectInheritanceGraph graph = SubjectInheritanceGraphs.getGraph(); - Map result = new HashMap<>(); - - Iterable traversal = graph.traverse(TraversalAlgorithm.DEPTH_FIRST_PRE_ORDER, this); - for (CalculatedSubject subject : traversal) { - for (Map.Entry entry : subject.getCombinedOptions().entrySet()) { - result.putIfAbsent(entry.getKey(), entry.getValue()); - } - } - - return result; - } - - public void resolveAllOptions(MetaAccumulator accumulator, ImmutableContextSet filter) { - SubjectInheritanceGraph graph = SubjectInheritanceGraphs.getGraph(filter); + public void resolveAllOptions(MetaAccumulator accumulator, QueryOptions filter) { + SubjectInheritanceGraph graph = new SubjectInheritanceGraph(filter); Iterable traversal = graph.traverse(TraversalAlgorithm.DEPTH_FIRST_PRE_ORDER, this); for (CalculatedSubject subject : traversal) { for (Map.Entry entry : subject.getCombinedOptions(filter).entrySet()) { @@ -282,34 +176,29 @@ public abstract class CalculatedSubject implements LPSubject { } } - public void resolveAllOptions(MetaAccumulator accumulator) { - SubjectInheritanceGraph graph = SubjectInheritanceGraphs.getGraph(); - Iterable traversal = graph.traverse(TraversalAlgorithm.DEPTH_FIRST_PRE_ORDER, this); - for (CalculatedSubject subject : traversal) { - for (Map.Entry entry : subject.getCombinedOptions().entrySet()) { - accumulator.accumulateMeta(entry.getKey(), entry.getValue()); - } - } + @Override + public Tristate getPermissionValue(QueryOptions options, String permission) { + return this.cachedData.getPermissionData(options).checkPermission(permission, PermissionCheckEvent.Origin.INTERNAL).result(); } @Override public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) { - return this.cachedData.getPermissionData(Contexts.global().setContexts(contexts)).getPermissionValue(permission, PermissionCheckEvent.Origin.INTERNAL).result(); + return getPermissionValue(QueryOptions.defaultContextualOptions().toBuilder().context(contexts).build(), permission); } @Override public boolean isChildOf(ImmutableContextSet contexts, LPSubjectReference parent) { - return resolveAllParents(contexts).contains(parent); + return resolveAllParents(QueryOptions.defaultContextualOptions().toBuilder().context(contexts).build()).contains(parent); } @Override public ImmutableList getParents(ImmutableContextSet contexts) { - return ImmutableList.copyOf(resolveAllParents(contexts)); + return ImmutableList.copyOf(resolveAllParents(QueryOptions.defaultContextualOptions().toBuilder().context(contexts).build())); } @Override public Optional getOption(ImmutableContextSet contexts, String key) { - return Optional.ofNullable(this.cachedData.getMetaData(Contexts.global().setContexts(contexts)).getMeta(MetaCheckEvent.Origin.PLATFORM_API).get(key)); + return Optional.ofNullable(this.cachedData.getMetaData(QueryOptions.defaultContextualOptions().toBuilder().context(contexts).build()).getMetaValue(key, MetaCheckEvent.Origin.PLATFORM_API)); } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubjectCachedData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubjectCachedDataManager.java similarity index 71% rename from sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubjectCachedData.java rename to sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubjectCachedDataManager.java index 8f1b1786c..c85ea76c8 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubjectCachedData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubjectCachedDataManager.java @@ -27,11 +27,11 @@ package me.lucko.luckperms.sponge.service.model.calculated; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.caching.MetaContexts; import me.lucko.luckperms.api.metastacking.DuplicateRemovalFunction; import me.lucko.luckperms.api.metastacking.MetaStackDefinition; -import me.lucko.luckperms.common.cacheddata.AbstractCachedData; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.query.QueryOptions; +import me.lucko.luckperms.common.cacheddata.AbstractCachedDataManager; import me.lucko.luckperms.common.cacheddata.CacheMetadata; import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; import me.lucko.luckperms.common.calculator.CalculatorFactory; @@ -47,7 +47,7 @@ import me.lucko.luckperms.sponge.calculator.SpongeWildcardProcessor; import java.util.Map; -public class CalculatedSubjectCachedData extends AbstractCachedData implements CalculatorFactory { +public class CalculatedSubjectCachedDataManager extends AbstractCachedDataManager implements CalculatorFactory { private static final MetaStackDefinition DEFAULT_META_STACK = new SimpleMetaStackDefinition( ImmutableList.of(StandardStackElements.HIGHEST), DuplicateRemovalFunction.RETAIN_ALL, @@ -56,14 +56,14 @@ public class CalculatedSubjectCachedData extends AbstractCachedData implements C private final CalculatedSubject subject; - CalculatedSubjectCachedData(CalculatedSubject subject, LuckPermsPlugin plugin) { + CalculatedSubjectCachedDataManager(CalculatedSubject subject, LuckPermsPlugin plugin) { super(plugin); this.subject = subject; } @Override - protected CacheMetadata getMetadataForContexts(Contexts contexts) { - return new CacheMetadata(this, null, this.subject.getParentCollection().getIdentifier() + "/" + this.subject.getIdentifier(), contexts.getContexts()); + protected CacheMetadata getMetadataForQueryOptions(QueryOptions queryOptions) { + return new CacheMetadata(this, null, this.subject.getParentCollection().getIdentifier() + "/" + this.subject.getIdentifier(), queryOptions); } @Override @@ -72,39 +72,29 @@ public class CalculatedSubjectCachedData extends AbstractCachedData implements C } @Override - protected MetaContexts getDefaultMetaContexts(Contexts contexts) { - return MetaContexts.of(contexts, DEFAULT_META_STACK, DEFAULT_META_STACK); + protected MetaStackDefinition getDefaultMetaStackDefinition(ChatMetaType type) { + return DEFAULT_META_STACK; } @Override - protected Map resolvePermissions() { - return this.subject.resolveAllPermissions(); + protected Map resolvePermissions(QueryOptions queryOptions) { + return this.subject.resolveAllPermissions(queryOptions); } @Override - protected Map resolvePermissions(Contexts contexts) { - return this.subject.resolveAllPermissions(contexts.getContexts().makeImmutable()); + protected void resolveMeta(MetaAccumulator accumulator, QueryOptions queryOptions) { + this.subject.resolveAllOptions(accumulator, queryOptions); } @Override - protected void resolveMeta(MetaAccumulator accumulator) { - this.subject.resolveAllOptions(accumulator); - } - - @Override - protected void resolveMeta(MetaAccumulator accumulator, MetaContexts contexts) { - this.subject.resolveAllOptions(accumulator, contexts.getContexts().getContexts().makeImmutable()); - } - - @Override - public PermissionCalculator build(Contexts contexts, CacheMetadata metadata) { + public PermissionCalculator build(QueryOptions queryOptions, CacheMetadata metadata) { ImmutableList.Builder processors = ImmutableList.builder(); processors.add(new MapProcessor()); processors.add(new SpongeWildcardProcessor()); processors.add(new WildcardProcessor()); if (!this.subject.getParentCollection().isDefaultsCollection()) { - processors.add(new FixedDefaultsProcessor(this.subject.getService(), contexts.getContexts().makeImmutable(), this.subject.getDefaults())); + processors.add(new FixedDefaultsProcessor(this.subject.getService(), queryOptions, this.subject.getDefaults())); } return new PermissionCalculator(getPlugin(), metadata, processors.build()); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubjectData.java index bbe512d2a..01299b8f9 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/CalculatedSubjectData.java @@ -29,9 +29,9 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.context.ContextSetComparator; import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.sponge.service.ProxyFactory; @@ -126,11 +126,11 @@ public class CalculatedSubjectData implements LPSubjectData { return ImmutableMap.copyOf(this.permissions.getOrDefault(contexts, ImmutableMap.of())); } - public Map resolvePermissions(ContextSet filter) { + public Map resolvePermissions(QueryOptions filter) { // get relevant entries SortedMap> sorted = new TreeMap<>(ContextSetComparator.reverse()); for (Map.Entry> entry : this.permissions.entrySet()) { - if (!entry.getKey().isSatisfiedBy(filter)) { + if (!filter.satisfies(entry.getKey())) { continue; } @@ -148,24 +148,6 @@ public class CalculatedSubjectData implements LPSubjectData { return result; } - public Map resolvePermissions() { - // get relevant entries - SortedMap> sorted = new TreeMap<>(ContextSetComparator.reverse()); - for (Map.Entry> entry : this.permissions.entrySet()) { - sorted.put(entry.getKey(), entry.getValue()); - } - - // flatten - Map result = new HashMap<>(); - for (Map map : sorted.values()) { - for (Map.Entry e : map.entrySet()) { - result.putIfAbsent(e.getKey(), e.getValue()); - } - } - - return result; - } - @Override public CompletableFuture setPermission(ImmutableContextSet contexts, String permission, Tristate value) { boolean b; @@ -222,11 +204,11 @@ public class CalculatedSubjectData implements LPSubjectData { return ImmutableList.copyOf(this.parents.getOrDefault(contexts, ImmutableSet.of())); } - public Set resolveParents(ContextSet filter) { + public Set resolveParents(QueryOptions filter) { // get relevant entries SortedMap> sorted = new TreeMap<>(ContextSetComparator.reverse()); for (Map.Entry> entry : this.parents.entrySet()) { - if (!entry.getKey().isSatisfiedBy(filter)) { + if (!filter.satisfies(entry.getKey())) { continue; } @@ -241,21 +223,6 @@ public class CalculatedSubjectData implements LPSubjectData { return result; } - public Set resolveParents() { - // get relevant entries - SortedMap> sorted = new TreeMap<>(ContextSetComparator.reverse()); - for (Map.Entry> entry : this.parents.entrySet()) { - sorted.put(entry.getKey(), entry.getValue()); - } - - // flatten - Set result = new LinkedHashSet<>(); - for (Set set : sorted.values()) { - result.addAll(set); - } - return result; - } - @Override public CompletableFuture addParent(ImmutableContextSet contexts, LPSubjectReference parent) { Set set = this.parents.computeIfAbsent(contexts, c -> ConcurrentHashMap.newKeySet()); @@ -313,11 +280,11 @@ public class CalculatedSubjectData implements LPSubjectData { return ImmutableMap.copyOf(this.options.getOrDefault(contexts, ImmutableMap.of())); } - public Map resolveOptions(ContextSet filter) { + public Map resolveOptions(QueryOptions filter) { // get relevant entries SortedMap> sorted = new TreeMap<>(ContextSetComparator.reverse()); for (Map.Entry> entry : this.options.entrySet()) { - if (!entry.getKey().isSatisfiedBy(filter)) { + if (!filter.satisfies(entry.getKey())) { continue; } @@ -335,24 +302,6 @@ public class CalculatedSubjectData implements LPSubjectData { return result; } - public Map resolveOptions() { - // get relevant entries - SortedMap> sorted = new TreeMap<>(ContextSetComparator.reverse()); - for (Map.Entry> entry : this.options.entrySet()) { - sorted.put(entry.getKey(), entry.getValue()); - } - - // flatten - Map result = new HashMap<>(); - for (Map map : sorted.values()) { - for (Map.Entry e : map.entrySet()) { - result.putIfAbsent(e.getKey(), e.getValue()); - } - } - - return result; - } - @Override public CompletableFuture setOption(ImmutableContextSet contexts, String key, String value) { Map options = this.options.computeIfAbsent(contexts, c -> new ConcurrentHashMap<>()); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/MonitoredSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/MonitoredSubjectData.java index d070fc5e4..fae6865df 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/MonitoredSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/calculated/MonitoredSubjectData.java @@ -25,8 +25,8 @@ package me.lucko.luckperms.sponge.service.model.calculated; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.model.LPSubject; diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubject.java index 7ba2cadde..1094bc208 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubject.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubject.java @@ -27,9 +27,9 @@ package me.lucko.luckperms.sponge.service.model.permissionholder; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.type.MetaCache; import me.lucko.luckperms.common.graph.TraversalAlgorithm; import me.lucko.luckperms.common.inheritance.InheritanceGraph; @@ -37,7 +37,7 @@ import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; +import me.lucko.luckperms.common.node.factory.NodeTypes; import me.lucko.luckperms.common.verbose.event.MetaCheckEvent; import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent; import me.lucko.luckperms.sponge.LPSpongePlugin; @@ -108,10 +108,15 @@ public abstract class PermissionHolderSubject implem return this.transientSubjectData; } + @Override + public Tristate getPermissionValue(QueryOptions options, String permission) { + return this.parent.getCachedData().getPermissionData(options).checkPermission(permission, PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK).result(); + } + @Override public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) { - Contexts lookupContexts = this.plugin.getContextManager().formContexts(contexts); - return this.parent.getCachedData().getPermissionData(lookupContexts).getPermissionValue(permission, PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK).result(); + QueryOptions queryOptions = this.plugin.getContextManager().formQueryOptions(contexts); + return getPermissionValue(queryOptions, permission); } @Override @@ -122,7 +127,7 @@ public abstract class PermissionHolderSubject implem @Override public ImmutableList getParents(ImmutableContextSet contexts) { - InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(this.plugin.getContextManager().formContexts(contexts)); + InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(this.plugin.getContextManager().formQueryOptions(contexts)); Iterable traversal = graph.traverse(TraversalAlgorithm.DEPTH_FIRST_PRE_ORDER, this.parent); ImmutableList.Builder subjects = ImmutableList.builder(); @@ -138,7 +143,7 @@ public abstract class PermissionHolderSubject implem @Override public Optional getOption(ImmutableContextSet contexts, String s) { - MetaCache data = this.parent.getCachedData().getMetaData(this.plugin.getContextManager().formContexts(contexts)); + MetaCache data = this.parent.getCachedData().getMetaData(this.plugin.getContextManager().formQueryOptions(contexts)); if (s.equalsIgnoreCase(NodeTypes.PREFIX_KEY)) { String prefix = data.getPrefix(MetaCheckEvent.Origin.PLATFORM_API); if (prefix != null) { @@ -153,7 +158,7 @@ public abstract class PermissionHolderSubject implem } } - String val = data.getMeta(MetaCheckEvent.Origin.PLATFORM_API).get(s); + String val = data.getMetaValue(s, MetaCheckEvent.Origin.PLATFORM_API); if (val != null) { return Optional.of(val); } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubjectData.java index c025a9a0e..8970e3695 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/permissionholder/PermissionHolderSubjectData.java @@ -28,12 +28,17 @@ package me.lucko.luckperms.sponge.service.model.permissionholder; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import me.lucko.luckperms.api.ChatMetaType; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.DataMutateResult; -import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.model.DataMutateResult; +import me.lucko.luckperms.api.node.ChatMetaType; +import me.lucko.luckperms.api.node.Node; +import me.lucko.luckperms.api.node.NodeType; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.node.types.InheritanceNode; +import me.lucko.luckperms.api.node.types.MetaNode; +import me.lucko.luckperms.api.node.types.PrefixNode; +import me.lucko.luckperms.api.node.types.SuffixNode; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.HolderType; @@ -41,7 +46,7 @@ import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.factory.NodeFactory; -import me.lucko.luckperms.common.node.model.NodeTypes; +import me.lucko.luckperms.common.node.factory.NodeTypes; import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.ProxyFactory; import me.lucko.luckperms.sponge.service.model.LPSubject; @@ -99,7 +104,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { for (Map.Entry> entry : this.holder.getData(this.type).immutable().asMap().entrySet()) { ImmutableMap.Builder builder = ImmutableMap.builder(); for (Node n : entry.getValue()) { - builder.put(n.getPermission(), n.getValue()); + builder.put(n.getKey(), n.getValue()); } ret.put(entry.getKey(), builder.build()); } @@ -110,7 +115,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { public ImmutableMap getPermissions(ImmutableContextSet contexts) { ImmutableMap.Builder builder = ImmutableMap.builder(); for (Node n : this.holder.getData(this.type).immutable().get(contexts)) { - builder.put(n.getPermission(), n.getValue()); + builder.put(n.getKey(), n.getValue()); } return builder.build(); } @@ -123,7 +128,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { if (tristate == Tristate.UNDEFINED) { // Unset - Node node = NodeFactory.builder(permission).withExtraContext(contexts).build(); + Node node = NodeFactory.builder(permission).withContext(contexts).build(); this.type.run( () -> this.holder.unsetPermission(node), () -> this.holder.unsetTransientPermission(node) @@ -131,7 +136,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { return save(this.holder).thenApply(v -> true); } - Node node = NodeFactory.builder(permission).setValue(tristate.asBoolean()).withExtraContext(contexts).build(); + Node node = NodeFactory.builder(permission).value(tristate.asBoolean()).withContext(contexts).build(); this.type.run( () -> { // unset the inverse, to allow false -> true, true -> false overrides. @@ -150,7 +155,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { @Override public CompletableFuture clearPermissions() { boolean ret = this.type.supply( - this.holder::clearNodes, + this.holder::clearEnduringNodes, this.holder::clearTransientNodes ); @@ -169,10 +174,10 @@ public class PermissionHolderSubjectData implements LPSubjectData { public CompletableFuture clearPermissions(ImmutableContextSet contexts) { Objects.requireNonNull(contexts, "contexts"); boolean ret = this.type.supply( - () -> this.holder.clearNodes(contexts), + () -> this.holder.clearEnduringNodes(contexts), () -> { List toRemove = streamNodes() - .filter(n -> n.getFullContexts().equals(contexts)) + .filter(n -> n.getContexts().equals(contexts)) .collect(Collectors.toList()); toRemove.forEach(this.holder::unsetTransientPermission); @@ -197,8 +202,8 @@ public class PermissionHolderSubjectData implements LPSubjectData { for (Map.Entry> entry : this.holder.getData(this.type).immutable().asMap().entrySet()) { ImmutableList.Builder builder = ImmutableList.builder(); for (Node n : entry.getValue()) { - if (n.isGroupNode()) { - builder.add(this.service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference()); + if (n instanceof InheritanceNode) { + builder.add(this.service.getGroupSubjects().loadSubject(((InheritanceNode) n).getGroupName()).join().toReference()); } } ret.put(entry.getKey(), builder.build()); @@ -210,8 +215,8 @@ public class PermissionHolderSubjectData implements LPSubjectData { public ImmutableList getParents(ImmutableContextSet contexts) { ImmutableList.Builder builder = ImmutableList.builder(); for (Node n : this.holder.getData(this.type).immutable().get(contexts)) { - if (n.isGroupNode()) { - builder.add(this.service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference()); + if (n instanceof InheritanceNode) { + builder.add(this.service.getGroupSubjects().loadSubject(((InheritanceNode) n).getGroupName()).join().toReference()); } } return builder.build(); @@ -227,7 +232,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { } Node node = NodeFactory.buildGroupNode(subject.getSubjectIdentifier()) - .withExtraContext(contexts) + .withContext(contexts) .build(); DataMutateResult result = this.type.supply( @@ -235,7 +240,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { () -> this.holder.setTransientPermission(node) ); - if (!result.asBoolean()) { + if (!result.wasSuccessful()) { return CompletableFuture.completedFuture(false); } @@ -252,7 +257,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { } Node node = NodeFactory.buildGroupNode(subject.getSubjectIdentifier()) - .withExtraContext(contexts) + .withContext(contexts) .build(); DataMutateResult result = this.type.supply( @@ -260,7 +265,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { () -> this.holder.unsetTransientPermission(node) ); - if (!result.asBoolean()) { + if (!result.wasSuccessful()) { return CompletableFuture.completedFuture(false); } @@ -270,10 +275,10 @@ public class PermissionHolderSubjectData implements LPSubjectData { @Override public CompletableFuture clearParents() { boolean ret = this.type.supply( - () -> this.holder.clearParents(true), + () -> this.holder.clearEnduringParents(true), () -> { List toRemove = streamNodes() - .filter(Node::isGroupNode) + .filter(n -> n instanceof InheritanceNode) .collect(Collectors.toList()); toRemove.forEach(this.holder::unsetTransientPermission); @@ -292,11 +297,11 @@ public class PermissionHolderSubjectData implements LPSubjectData { public CompletableFuture clearParents(ImmutableContextSet contexts) { Objects.requireNonNull(contexts, "contexts"); boolean ret = this.type.supply( - () -> this.holder.clearParents(contexts, true), + () -> this.holder.clearEnduringParents(contexts, true), () -> { List toRemove = streamNodes() - .filter(Node::isGroupNode) - .filter(n -> n.getFullContexts().equals(contexts)) + .filter(n -> n instanceof InheritanceNode) + .filter(n -> n.getContexts().equals(contexts)) .collect(Collectors.toList()); toRemove.forEach(this.holder::unsetTransientPermission); @@ -332,29 +337,29 @@ public class PermissionHolderSubjectData implements LPSubjectData { for (Node n : nodes) { if (!n.getValue()) continue; - if (!n.isMeta() && !n.isPrefix() && !n.isSuffix()) continue; + if (!NodeType.META_OR_CHAT_META.matches(n)) continue; - if (n.isPrefix()) { - Map.Entry value = n.getPrefix(); - if (value.getKey() > maxPrefixPriority) { - builder.put(NodeTypes.PREFIX_KEY, value.getValue()); - maxPrefixPriority = value.getKey(); + if (n instanceof PrefixNode) { + PrefixNode pn = (PrefixNode) n; + if (pn.getPriority() > maxPrefixPriority) { + builder.put(NodeTypes.PREFIX_KEY, pn.getMetaValue()); + maxPrefixPriority = pn.getPriority(); } continue; } - if (n.isSuffix()) { - Map.Entry value = n.getSuffix(); - if (value.getKey() > maxSuffixPriority) { - builder.put(NodeTypes.SUFFIX_KEY, value.getValue()); - maxSuffixPriority = value.getKey(); + if (n instanceof SuffixNode) { + SuffixNode sn = (SuffixNode) n; + if (sn.getPriority() > maxSuffixPriority) { + builder.put(NodeTypes.SUFFIX_KEY, sn.getMetaValue()); + maxSuffixPriority = sn.getPriority(); } continue; } - if (n.isMeta()) { - Map.Entry meta = n.getMeta(); - builder.put(meta.getKey(), meta.getValue()); + if (n instanceof MetaNode) { + MetaNode mn = (MetaNode) n; + builder.put(mn.getMetaKey(), mn.getMetaValue()); } } @@ -374,30 +379,30 @@ public class PermissionHolderSubjectData implements LPSubjectData { // remove all prefixes/suffixes from the user streamNodes() - .filter(type::matches) - .filter(n -> n.getFullContexts().equals(contexts)) + .filter(node1 -> type.nodeType().matches(node1)) + .filter(n -> ((Node) n).getContexts().equals(contexts)) .forEach(n -> this.type.run( () -> this.holder.unsetPermission(n), () -> this.holder.unsetTransientPermission(n) )); - MetaAccumulator metaAccumulator = this.holder.accumulateMeta(null, Contexts.global().setContexts(contexts)); + MetaAccumulator metaAccumulator = this.holder.accumulateMeta(null, QueryOptions.defaultContextualOptions().toBuilder().context(contexts).build()); metaAccumulator.complete(); int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0); priority += 10; - node = NodeFactory.buildChatMetaNode(type, priority, value).withExtraContext(contexts).build(); + node = NodeFactory.buildChatMetaNode(type, priority, value).withContext(contexts).build(); } else { // standard remove streamNodes() - .filter(n -> n.isMeta() && n.getMeta().getKey().equals(key)) - .filter(n -> n.getFullContexts().equals(contexts)) + .filter(n -> n instanceof MetaNode && ((MetaNode) n).getMetaKey().equals(key)) + .filter(n -> n.getContexts().equals(contexts)) .forEach(n -> this.type.run( () -> this.holder.unsetPermission(n), () -> this.holder.unsetTransientPermission(n) )); - node = NodeFactory.buildMetaNode(key, value).withExtraContext(contexts).build(); + node = NodeFactory.buildMetaNode(key, value).withContext(contexts).build(); } this.type.run( @@ -415,14 +420,14 @@ public class PermissionHolderSubjectData implements LPSubjectData { streamNodes() .filter(n -> { if (key.equalsIgnoreCase(NodeTypes.PREFIX_KEY)) { - return n.isPrefix(); + return n instanceof PrefixNode; } else if (key.equalsIgnoreCase(NodeTypes.SUFFIX_KEY)) { - return n.isSuffix(); + return n instanceof SuffixNode; } else { - return n.isMeta() && n.getMeta().getKey().equals(key); + return n instanceof MetaNode && ((MetaNode) n).getMetaKey().equals(key); } }) - .filter(n -> n.getFullContexts().equals(contexts)) + .filter(n -> n.getContexts().equals(contexts)) .forEach(node -> this.type.run( () -> this.holder.unsetPermission(node), () -> this.holder.unsetTransientPermission(node) @@ -436,8 +441,8 @@ public class PermissionHolderSubjectData implements LPSubjectData { Objects.requireNonNull(contexts, "contexts"); List toRemove = streamNodes() - .filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix()) - .filter(n -> n.getFullContexts().equals(contexts)) + .filter(NodeType.META_OR_CHAT_META::matches) + .filter(n -> n.getContexts().equals(contexts)) .collect(Collectors.toList()); toRemove.forEach(node -> this.type.run( @@ -455,7 +460,7 @@ public class PermissionHolderSubjectData implements LPSubjectData { @Override public CompletableFuture clearOptions() { List toRemove = streamNodes() - .filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix()) + .filter(NodeType.META_OR_CHAT_META::matches) .collect(Collectors.toList()); toRemove.forEach(node -> this.type.run( diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/persisted/PersistedCollection.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/persisted/PersistedCollection.java index d375d97f1..26bb19240 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/persisted/PersistedCollection.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/persisted/PersistedCollection.java @@ -30,8 +30,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.cache.LoadingMap; import me.lucko.luckperms.common.util.ImmutableCollectors; import me.lucko.luckperms.common.util.Predicates; diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/persisted/SubjectDataContainer.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/persisted/SubjectDataContainer.java index de067f6dd..5b031cbf8 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/persisted/SubjectDataContainer.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/model/persisted/SubjectDataContainer.java @@ -121,7 +121,7 @@ public class SubjectDataContainer { JsonObject context = section.get("context").getAsJsonObject(); JsonObject data = section.get("data").getAsJsonObject(); - ImmutableContextSet contextSet = ContextSetJsonSerializer.deserializeContextSet(context).makeImmutable(); + ImmutableContextSet contextSet = ContextSetJsonSerializer.deserializeContextSet(context).immutableCopy(); ImmutableMap.Builder perms = ImmutableMap.builder(); for (Map.Entry perm : data.entrySet()) { perms.put(perm.getKey(), perm.getValue().getAsBoolean()); @@ -144,7 +144,7 @@ public class SubjectDataContainer { JsonObject context = section.get("context").getAsJsonObject(); JsonObject data = section.get("data").getAsJsonObject(); - ImmutableContextSet contextSet = ContextSetJsonSerializer.deserializeContextSet(context).makeImmutable(); + ImmutableContextSet contextSet = ContextSetJsonSerializer.deserializeContextSet(context).immutableCopy(); ImmutableMap.Builder opts = ImmutableMap.builder(); for (Map.Entry opt : data.entrySet()) { opts.put(opt.getKey(), opt.getValue().getAsString()); @@ -167,7 +167,7 @@ public class SubjectDataContainer { JsonObject context = section.get("context").getAsJsonObject(); JsonArray data = section.get("data").getAsJsonArray(); - ImmutableContextSet contextSet = ContextSetJsonSerializer.deserializeContextSet(context).makeImmutable(); + ImmutableContextSet contextSet = ContextSetJsonSerializer.deserializeContextSet(context).immutableCopy(); ImmutableList.Builder pars = ImmutableList.builder(); for (JsonElement p : data) { if (!p.isJsonObject()) { diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/LPVelocityBootstrap.java b/velocity/src/main/java/me/lucko/luckperms/velocity/LPVelocityBootstrap.java index 121355b94..10293da5d 100644 --- a/velocity/src/main/java/me/lucko/luckperms/velocity/LPVelocityBootstrap.java +++ b/velocity/src/main/java/me/lucko/luckperms/velocity/LPVelocityBootstrap.java @@ -35,7 +35,7 @@ import com.velocitypowered.api.plugin.annotation.DataDirectory; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; -import me.lucko.luckperms.api.platform.PlatformType; +import me.lucko.luckperms.api.platform.Platform; import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader; import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap; import me.lucko.luckperms.common.plugin.logging.PluginLogger; @@ -179,8 +179,8 @@ public class LPVelocityBootstrap implements LuckPermsBootstrap { // provide information about the platform @Override - public PlatformType getType() { - return PlatformType.VELOCITY; + public Platform.Type getType() { + return Platform.Type.VELOCITY; } @Override diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/LPVelocityPlugin.java b/velocity/src/main/java/me/lucko/luckperms/velocity/LPVelocityPlugin.java index 1018a2cf1..6f4e9d0d4 100644 --- a/velocity/src/main/java/me/lucko/luckperms/velocity/LPVelocityPlugin.java +++ b/velocity/src/main/java/me/lucko/luckperms/velocity/LPVelocityPlugin.java @@ -27,8 +27,8 @@ package me.lucko.luckperms.velocity; import com.velocitypowered.api.proxy.Player; -import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.LuckPerms; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.api.LuckPermsApiProvider; import me.lucko.luckperms.common.calculator.CalculatorFactory; import me.lucko.luckperms.common.command.CommandManager; @@ -158,7 +158,7 @@ public class LPVelocityPlugin extends AbstractLuckPermsPlugin { } @Override - protected void registerApiOnPlatform(LuckPermsApi api) { + protected void registerApiOnPlatform(LuckPerms api) { // Velocity doesn't have a services manager } @@ -190,8 +190,8 @@ public class LPVelocityPlugin extends AbstractLuckPermsPlugin { } @Override - public Optional getContextForUser(User user) { - return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getApplicableContexts(player)); + public Optional getQueryOptionsForUser(User user) { + return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getQueryOptions(player)); } @Override diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/VelocitySenderFactory.java b/velocity/src/main/java/me/lucko/luckperms/velocity/VelocitySenderFactory.java index a1713f06e..deda9add8 100644 --- a/velocity/src/main/java/me/lucko/luckperms/velocity/VelocitySenderFactory.java +++ b/velocity/src/main/java/me/lucko/luckperms/velocity/VelocitySenderFactory.java @@ -28,7 +28,7 @@ package me.lucko.luckperms.velocity; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.proxy.Player; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.sender.Sender; import me.lucko.luckperms.common.sender.SenderFactory; diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/calculator/VelocityCalculatorFactory.java b/velocity/src/main/java/me/lucko/luckperms/velocity/calculator/VelocityCalculatorFactory.java index c84b8dca5..232570dbb 100644 --- a/velocity/src/main/java/me/lucko/luckperms/velocity/calculator/VelocityCalculatorFactory.java +++ b/velocity/src/main/java/me/lucko/luckperms/velocity/calculator/VelocityCalculatorFactory.java @@ -27,7 +27,7 @@ package me.lucko.luckperms.velocity.calculator; import com.google.common.collect.ImmutableList; -import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.cacheddata.CacheMetadata; import me.lucko.luckperms.common.calculator.CalculatorFactory; import me.lucko.luckperms.common.calculator.PermissionCalculator; @@ -46,7 +46,7 @@ public class VelocityCalculatorFactory implements CalculatorFactory { } @Override - public PermissionCalculator build(Contexts contexts, CacheMetadata metadata) { + public PermissionCalculator build(QueryOptions queryOptions, CacheMetadata metadata) { ImmutableList.Builder processors = ImmutableList.builder(); processors.add(new MapProcessor()); diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/context/BackendServerCalculator.java b/velocity/src/main/java/me/lucko/luckperms/velocity/context/BackendServerCalculator.java index 4cd52cebf..6e1efd9b5 100644 --- a/velocity/src/main/java/me/lucko/luckperms/velocity/context/BackendServerCalculator.java +++ b/velocity/src/main/java/me/lucko/luckperms/velocity/context/BackendServerCalculator.java @@ -27,14 +27,17 @@ package me.lucko.luckperms.velocity.context; import com.velocitypowered.api.proxy.Player; -import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ContextCalculator; -import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.api.context.ContextConsumer; +import me.lucko.luckperms.api.context.DefaultContextKeys; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import org.checkerframework.checker.nullness.qual.NonNull; +import java.util.HashSet; +import java.util.Set; + public class BackendServerCalculator implements ContextCalculator { private static String getServer(Player player) { @@ -48,13 +51,12 @@ public class BackendServerCalculator implements ContextCalculator { } @Override - public @NonNull MutableContextSet giveApplicableContext(@NonNull Player subject, @NonNull MutableContextSet accumulator) { + public void giveApplicableContext(@NonNull Player subject, @NonNull ContextConsumer consumer) { + Set seen = new HashSet<>(); String server = getServer(subject); - while (server != null && !accumulator.has(Contexts.WORLD_KEY, server)) { - accumulator.add(Contexts.WORLD_KEY, server); + while (server != null && seen.add(server)) { + consumer.accept(DefaultContextKeys.WORLD_KEY, server); server = this.plugin.getConfiguration().get(ConfigKeys.WORLD_REWRITES).getOrDefault(server, server).toLowerCase(); } - - return accumulator; } } 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 4cddf8cab..1eccdbc28 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 @@ -28,11 +28,11 @@ package me.lucko.luckperms.velocity.context; import com.github.benmanes.caffeine.cache.LoadingCache; import com.velocitypowered.api.proxy.Player; -import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.context.ContextManager; -import me.lucko.luckperms.common.context.ContextsCache; -import me.lucko.luckperms.common.context.ContextsSupplier; +import me.lucko.luckperms.common.context.QueryOptionsCache; +import me.lucko.luckperms.common.context.QueryOptionsSupplier; import me.lucko.luckperms.common.util.CaffeineFactory; import me.lucko.luckperms.velocity.LPVelocityPlugin; @@ -40,16 +40,16 @@ import java.util.concurrent.TimeUnit; public class VelocityContextManager extends ContextManager { - private final LoadingCache> subjectCaches = CaffeineFactory.newBuilder() + private final LoadingCache> subjectCaches = CaffeineFactory.newBuilder() .expireAfterAccess(1, TimeUnit.MINUTES) - .build(key -> new ContextsCache<>(key, this)); + .build(key -> new QueryOptionsCache<>(key, this)); public VelocityContextManager(LPVelocityPlugin plugin) { super(plugin, Player.class); } @Override - public ContextsSupplier getCacheFor(Player subject) { + public QueryOptionsSupplier getCacheFor(Player subject) { if (subject == null) { throw new NullPointerException("subject"); } @@ -63,14 +63,14 @@ public class VelocityContextManager extends ContextManager { throw new NullPointerException("subject"); } - ContextsCache cache = this.subjectCaches.getIfPresent(subject); + QueryOptionsCache cache = this.subjectCaches.getIfPresent(subject); if (cache != null) { cache.invalidate(); } } @Override - public Contexts formContexts(Player subject, ImmutableContextSet contextSet) { - return formContexts(contextSet); + public QueryOptions formQueryOptions(Player subject, ImmutableContextSet contextSet) { + return formQueryOptions(contextSet); } } diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/MonitoringPermissionCheckListener.java b/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/MonitoringPermissionCheckListener.java index c03b3c29f..078071f34 100644 --- a/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/MonitoringPermissionCheckListener.java +++ b/velocity/src/main/java/me/lucko/luckperms/velocity/listeners/MonitoringPermissionCheckListener.java @@ -33,8 +33,8 @@ import com.velocitypowered.api.permission.PermissionProvider; import com.velocitypowered.api.permission.PermissionSubject; import com.velocitypowered.api.proxy.Player; -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.node.Tristate; +import me.lucko.luckperms.api.query.QueryOptions; import me.lucko.luckperms.common.calculator.result.TristateResult; import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent; import me.lucko.luckperms.velocity.LPVelocityPlugin; @@ -89,7 +89,7 @@ public class MonitoringPermissionCheckListener { // report result Tristate result = CompatibilityUtil.convertTristate(setting); - MonitoringPermissionCheckListener.this.plugin.getVerboseHandler().offerPermissionCheckEvent(PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK, this.name, ContextSet.empty(), permission, TristateResult.of(result)); + MonitoringPermissionCheckListener.this.plugin.getVerboseHandler().offerPermissionCheckEvent(PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK, this.name, QueryOptions.defaultContextualOptions(), permission, TristateResult.of(result)); MonitoringPermissionCheckListener.this.plugin.getPermissionRegistry().offer(permission); return setting; diff --git a/velocity/src/main/java/me/lucko/luckperms/velocity/service/CompatibilityUtil.java b/velocity/src/main/java/me/lucko/luckperms/velocity/service/CompatibilityUtil.java index 3dfe7d762..3aaf76962 100644 --- a/velocity/src/main/java/me/lucko/luckperms/velocity/service/CompatibilityUtil.java +++ b/velocity/src/main/java/me/lucko/luckperms/velocity/service/CompatibilityUtil.java @@ -25,7 +25,7 @@ package me.lucko.luckperms.velocity.service; -import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.node.Tristate; import java.util.Objects; 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 6e9077880..a3ca824cd 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 @@ -32,7 +32,7 @@ import com.velocitypowered.api.permission.PermissionSubject; import com.velocitypowered.api.permission.Tristate; import com.velocitypowered.api.proxy.Player; -import me.lucko.luckperms.common.context.ContextsSupplier; +import me.lucko.luckperms.common.context.QueryOptionsSupplier; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent; @@ -41,12 +41,12 @@ import org.checkerframework.checker.nullness.qual.NonNull; public class PlayerPermissionProvider implements PermissionProvider, PermissionFunction { private final Player player; private final User user; - private final ContextsSupplier contextsSupplier; + private final QueryOptionsSupplier queryOptionsSupplier; - public PlayerPermissionProvider(Player player, User user, ContextsSupplier contextsSupplier) { + public PlayerPermissionProvider(Player player, User user, QueryOptionsSupplier queryOptionsSupplier) { this.player = player; this.user = user; - this.contextsSupplier = contextsSupplier; + this.queryOptionsSupplier = queryOptionsSupplier; } @Override @@ -57,6 +57,6 @@ public class PlayerPermissionProvider implements PermissionProvider, PermissionF @Override public @NonNull Tristate getPermissionValue(@NonNull String permission) { - return CompatibilityUtil.convertTristate(this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission, PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result()); + return CompatibilityUtil.convertTristate(this.user.getCachedData().getPermissionData(this.queryOptionsSupplier.getQueryOptions()).checkPermission(permission, PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result()); } }