1
0
mirror of https://github.com/lucko/LuckPerms.git synced 2025-08-20 13:21:25 +02:00

Provide API access to cached data result info (#3243)

This commit is contained in:
Luck
2022-01-01 14:38:46 +00:00
parent acdc259771
commit 6781c1fb51
14 changed files with 239 additions and 97 deletions

View File

@@ -31,6 +31,10 @@ import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Holds cached lookup data for a given set of query options.
*
* <p>All calls will account for inheritance, as well as any default data
* provided by the platform. These calls are heavily cached and are therefore
* fast.</p>
*/
public interface CachedData {

View File

@@ -39,7 +39,7 @@ import java.util.concurrent.CompletableFuture;
* Holds cached permission and meta lookup data for a {@link PermissionHolder}.
*
* <p>All calls will account for inheritance, as well as any default data
* provided by the platform. This calls are heavily cached and are therefore
* provided by the platform. These calls are heavily cached and are therefore
* fast.</p>
*/
public interface CachedDataManager {
@@ -81,11 +81,10 @@ public interface CachedDataManager {
* <p>For {@link User}s, the most appropriate query options will be their
* {@link ContextManager#getQueryOptions(User) current active query options} if the
* corresponding player is online, and otherwise, will fallback to
* {@link ContextManager#getStaticQueryOptions() the current static query options}
* if they are offline.</p>
* {@link ContextManager#getStaticQueryOptions() the current static query options}.</p>
*
* <p>For {@link Group}s, the most appropriate query options will always be
* {@link ContextManager#getStaticQueryOptions()} the current static query options.</p>
* {@link ContextManager#getStaticQueryOptions() the current static query options}.</p>
*
* @return a permission data instance
* @since 5.1
@@ -99,11 +98,10 @@ public interface CachedDataManager {
* <p>For {@link User}s, the most appropriate query options will be their
* {@link ContextManager#getQueryOptions(User) current active query options} if the
* corresponding player is online, and otherwise, will fallback to
* {@link ContextManager#getStaticQueryOptions() the current static query options}
* if they are offline.</p>
* {@link ContextManager#getStaticQueryOptions() the current static query options}.</p>
*
* <p>For {@link Group}s, the most appropriate query options will always be
* {@link ContextManager#getStaticQueryOptions()} the current static query options.</p>
* {@link ContextManager#getStaticQueryOptions() the current static query options}.</p>
*
* @return a meta data instance
* @since 5.1
@@ -118,7 +116,7 @@ public interface CachedDataManager {
void invalidate();
/**
* Invalidates all of the underlying Permission calculators.
* Invalidates all underlying permission calculators.
*
* <p>Can be called to allow for an update in defaults.</p>
*/

View File

@@ -26,6 +26,9 @@
package net.luckperms.api.cacheddata;
import net.luckperms.api.metastacking.MetaStackDefinition;
import net.luckperms.api.node.types.MetaNode;
import net.luckperms.api.node.types.PrefixNode;
import net.luckperms.api.node.types.SuffixNode;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -39,16 +42,40 @@ import java.util.function.Function;
/**
* Holds cached meta lookup data for a specific set of contexts.
*
* <p>Meta data refers to {@link PrefixNode prefixes}, {@link SuffixNode suffixes} and
* {@link MetaNode meta (options)} held by a permission holder.</p>
*
* <p>All calls will account for inheritance, as well as any default data
* provided by the platform. These calls are heavily cached and are therefore
* fast.</p>
*/
public interface CachedMetaData extends CachedData {
/**
* Query a meta value for the given {@code key}.
*
* <p>This method will always return a {@link Result}, but the
* {@link Result#result() inner result} {@link String} will be null if a value
* for the given key was not found.</p>
*
* @param key the key
* @return a result containing the value
* @since 5.4
*/
@NonNull Result<String, MetaNode> queryMetaValue(@NonNull String key);
/**
* Gets a value for the given meta key.
*
* <p>If no such meta value exists for the given key, {@code null} is returned.</p>
*
* @param key the key
* @return the value
*/
@Nullable String getMetaValue(@NonNull String key);
default @Nullable String getMetaValue(@NonNull String key) {
return queryMetaValue(key).result();
}
/**
* Gets a value for the given meta key, and runs it through the given {@code transformer}.
@@ -81,37 +108,97 @@ public interface CachedMetaData extends CachedData {
}
/**
* Gets the holder's highest priority prefix, or null if the holder has no prefixes
* Query for a prefix.
*
* <p>This method uses the rules defined by the {@link #getPrefixStackDefinition() prefix stack}
* to produce a {@link String} output.</p>
*
* <p>Assuming the default configuration is used, this will usually be the value of the
* holder's highest priority prefix node.</p>
*
* <p>This method will always return a {@link Result}, but the
* {@link Result#result() inner result} {@link String} will be null if
* a the resultant prefix stack contained no elements.</p>
*
* @return a result containing the prefix
* @since 5.4
*/
@NonNull Result<String, PrefixNode> queryPrefix();
/**
* Gets the prefix.
*
* <p>This method uses the rules defined by the {@link #getPrefixStackDefinition() prefix stack}
* to produce a {@link String} output.</p>
*
* <p>Assuming the default configuration is used, this will usually be the value of the
* holder's highest priority prefix node.</p>
*
* <p>If the resultant prefix stack contained no elements, {@code null} is returned.</p>
*
* @return a prefix string, or null
*/
@Nullable String getPrefix();
default @Nullable String getPrefix() {
return queryPrefix().result();
}
/**
* Gets the holder's highest priority suffix, or null if the holder has no suffixes
* Query for a suffix.
*
* <p>This method uses the rules defined by the {@link #getSuffixStackDefinition() suffix stack}
* to produce a {@link String} output.</p>
*
* <p>Assuming the default configuration is used, this will usually be the value of the
* holder's highest priority suffix node.</p>
*
* <p>This method will always return a {@link Result}, but the
* {@link Result#result() inner result} {@link String} will be null if
* a the resultant suffix stack contained no elements.</p>
*
* @return a result containing the suffix
* @since 5.4
*/
@NonNull Result<String, SuffixNode> querySuffix();
/**
* Gets the suffix.
*
* <p>This method uses the rules defined by the {@link #getSuffixStackDefinition() suffix stack}
* to produce a {@link String} output.</p>
*
* <p>Assuming the default configuration is used, this will usually be the value of the
* holder's highest priority suffix node.</p>
*
* <p>If the resultant suffix stack contained no elements, {@code null} is returned.</p>
*
* @return a suffix string, or null
*/
@Nullable String getSuffix();
default @Nullable String getSuffix() {
return querySuffix().result();
}
/**
* Gets an immutable copy of the meta this holder has.
* Gets a map of all accumulated {@link MetaNode meta}.
*
* @return an immutable map of meta
* <p>Prefer using the {@link #getMetaValue(String)} method for querying values.</p>
*
* @return a map of meta
*/
@NonNull @Unmodifiable Map<String, List<String>> getMeta();
/**
* Gets an immutable sorted map of all of the prefixes the holder has, whereby the first
* value is the highest priority prefix.
* Gets a sorted map of all accumulated {@link PrefixNode prefixes}.
*
* <p>Prefer using the {@link #getPrefix()} method for querying.</p>
*
* @return a sorted map of prefixes
*/
@NonNull @Unmodifiable SortedMap<Integer, String> getPrefixes();
/**
* Gets an immutable sorted map of all of the suffixes the holder has, whereby the first
* value is the highest priority suffix.
* Gets a sorted map of all accumulated {@link SuffixNode suffixes}.
*
* <p>Prefer using the {@link #getSuffix()} method for querying.</p>
*
* @return a sorted map of suffixes
*/
@@ -128,14 +215,14 @@ public interface CachedMetaData extends CachedData {
@Nullable String getPrimaryGroup();
/**
* Gets the definition used for the prefix stack
* Gets the definition used for the prefix stack.
*
* @return the definition used for the prefix stack
*/
@NonNull MetaStackDefinition getPrefixStackDefinition();
/**
* Gets the definition used for the suffix stack
* Gets the definition used for the suffix stack.
*
* @return the definition used for the suffix stack
*/

View File

@@ -25,6 +25,7 @@
package net.luckperms.api.cacheddata;
import net.luckperms.api.node.Node;
import net.luckperms.api.util.Tristate;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -34,17 +35,39 @@ import java.util.Map;
/**
* Holds cached permission lookup data for a specific set of contexts.
*
* <p>All calls will account for inheritance, as well as any default data
* provided by the platform. These calls are heavily cached and are therefore
* fast.</p>
*/
public interface CachedPermissionData extends CachedData {
/**
* Gets a permission check result for the given permission node.
* Performs a permission check for the given {@code permission} node.
*
* <p>This check is equivalent to the "hasPermission" method call on most platforms.
* You can use {@link Tristate#asBoolean()} if you need a truthy result.</p>
*
* @param permission the permission node
* @return a result containing the tristate
* @throws NullPointerException if permission is null
* @since 5.4
*/
@NonNull Result<Tristate, Node> queryPermission(@NonNull String permission);
/**
* Performs a permission check for the given {@code permission} node.
*
* <p>This check is equivalent to the "hasPermission" method call on most platforms.
* You can use {@link Tristate#asBoolean()} if you need a truthy result.</p>
*
* @param permission the permission node
* @return a tristate result
* @throws NullPointerException if permission is null
*/
@NonNull Tristate checkPermission(@NonNull String permission);
default @NonNull Tristate checkPermission(@NonNull String permission) {
return queryPermission(permission).result();
}
/**
* Invalidates the underlying permission calculator cache.

View File

@@ -30,9 +30,37 @@ import net.luckperms.api.node.Node;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents the result of a cached data lookup
* Represents the result of a cached data lookup.
*
* <p>You can find "the holder that has the node that caused this result"
* using the following code:</p>
* <p></p>
* <blockquote>
* <pre>
* public static {@link net.luckperms.api.model.PermissionHolder.Identifier} holderThatHasTheNodeThatCausedTheResult(Result&lt;?, ?&gt; result) {
* {@link Node} node = result.node();
* if (node == null) {
* return null;
* }
* {@link net.luckperms.api.node.metadata.types.InheritanceOriginMetadata} origin = node.getMetadata(InheritanceOriginMetadata.KEY).orElse(null);
* if (origin == null) {
* return null;
* }
* return origin.getOrigin();
* }
* </pre>
*
* <p>Combined with the node itself, this is all the information needed to determine
* the root cause of the result.</p>
* </blockquote>
*
* <p>The nullability of {@link #result()} is purposely undefined to allow the
* flexibility for methods using {@link Result} to declare it. In general, if the {@code T} type
* has a nullable/undefined value, then the return of {@link #result()} will be non-null,
* and if not, it will be nullable.</p>
*
* @param <T> the result type
* @param <N> the node type
* @since 5.4
*/
public interface Result<T, N extends Node> {
@@ -51,11 +79,4 @@ public interface Result<T, N extends Node> {
*/
@Nullable N node();
/**
* Gets the result that this result overrides, if applicable.
*
* @return the overridden result
*/
@Nullable Result<T, N> overriddenResult();
}

View File

@@ -24,7 +24,7 @@
*/
/**
* CachedData lookup API for {@link net.luckperms.api.model.user.User}s and
* Caches permission checks and meta lookups for {@link net.luckperms.api.model.user.User}s and
* {@link net.luckperms.api.model.group.Group}s.
*/
package net.luckperms.api.cacheddata;