Store result of primary group calculation in CachedMetaData

This commit is contained in:
Luck 2020-03-30 14:13:17 +01:00
parent c40ad63291
commit 42e9f43443
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
15 changed files with 265 additions and 178 deletions

View File

@ -48,42 +48,52 @@ public interface CachedMetaData extends CachedData {
@Nullable String getMetaValue(String key);
/**
* Gets the user's highest priority prefix, or null if the user has no prefixes
* Gets the holder's highest priority prefix, or null if the holder 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
* Gets the holder's highest priority suffix, or null if the holder has no suffixes
*
* @return a suffix string, or null
*/
@Nullable String getSuffix();
/**
* Gets an immutable copy of the meta this user has.
* Gets an immutable copy of the meta this holder has.
*
* @return an immutable map of meta
*/
@NonNull Map<String, List<String>> getMeta();
/**
* Gets an immutable sorted map of all of the prefixes the user has, whereby the first value is the highest priority
* prefix.
* Gets an immutable sorted map of all of the prefixes the holder has, whereby the first
* value is the highest priority prefix.
*
* @return a sorted map of prefixes
*/
@NonNull SortedMap<Integer, String> getPrefixes();
/**
* Gets an immutable sorted map of all of the suffixes the user has, whereby the first value is the highest priority
* suffix.
* Gets an immutable sorted map of all of the suffixes the holder has, whereby the first
* value is the highest priority suffix.
*
* @return a sorted map of suffixes
*/
@NonNull SortedMap<Integer, String> getSuffixes();
/**
* Gets the name of the holders primary group.
*
* <p>Will return {@code null} for Group holder types.</p>
*
* @return the name of the primary group
* @since 5.1
*/
@Nullable String getPrimaryGroup();
/**
* Gets the definition used for the prefix stack
*

View File

@ -238,8 +238,7 @@ public class LuckPermsVaultChat extends AbstractVaultChat {
}
// find the max inherited priority & add 10
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, createQueryOptionsForWorldSet(world));
metaAccumulator.complete();
MetaAccumulator metaAccumulator = holder.accumulateMeta(createQueryOptionsForWorldSet(world));
int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 10;
Node node = type.builder(value, priority)

View File

@ -29,6 +29,7 @@ import com.google.common.base.Preconditions;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.bukkit.context.BukkitContextManager;
import me.lucko.luckperms.common.cacheddata.type.MetaCache;
import me.lucko.luckperms.common.cacheddata.type.PermissionCache;
import me.lucko.luckperms.common.calculator.processor.MapProcessor;
import me.lucko.luckperms.common.calculator.result.TristateResult;
@ -273,13 +274,16 @@ public class LuckPermsVaultPermission extends AbstractVaultPermission {
if (user instanceof Group) { // npc
return this.plugin.getConfiguration().get(ConfigKeys.VAULT_NPC_GROUP);
}
String value = ((User) user).getPrimaryGroup().getValue();
QueryOptions queryOptions = getQueryOptions(uuid, world);
MetaCache metaData = user.getCachedData().getMetaData(queryOptions);
String value = metaData.getPrimaryGroup(MetaCheckEvent.Origin.THIRD_PARTY_API);
Group group = getGroup(value);
if (group != null) {
value = group.getPlainDisplayName();
return group.getPlainDisplayName();
}
this.plugin.getVerboseHandler().offerMetaCheckEvent(MetaCheckEvent.Origin.THIRD_PARTY_API, user.getPlainDisplayName(), QueryOptionsImpl.DEFAULT_CONTEXTUAL, "primarygroup", value);
return value;
}

View File

@ -30,10 +30,12 @@ import com.google.common.base.Preconditions;
import me.lucko.luckperms.common.cacheddata.UserCachedDataManager;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.types.Inheritance;
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
import net.luckperms.api.model.data.DataMutateResult;
import net.luckperms.api.model.data.DataType;
import net.luckperms.api.node.NodeEqualityPredicate;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
@ -70,7 +72,12 @@ public class ApiUser extends ApiPermissionHolder implements net.luckperms.api.mo
@Override
public @NonNull String getPrimaryGroup() {
return this.handle.getPrimaryGroup().getValue();
QueryOptions queryOptions = this.handle.getPlugin().getQueryOptionsForUser(this.handle)
.orElseGet(() -> this.handle.getPlugin().getContextManager().getStaticQueryOptions());
String value = this.handle.getCachedData().getMetaData(queryOptions).getPrimaryGroup(MetaCheckEvent.Origin.LUCKPERMS_API);
Objects.requireNonNull(value, "value"); // assert nonnull
return value;
}
@Override

View File

@ -78,6 +78,7 @@ public class MetaAccumulator {
private final SortedMap<Integer, String> prefixes;
private final SortedMap<Integer, String> suffixes;
private int weight = 0;
private String primaryGroup;
private final MetaStack prefixStack;
private final MetaStack suffixStack;
@ -113,6 +114,9 @@ public class MetaAccumulator {
if (!this.meta.containsKey(Weight.NODE_KEY) && this.weight != 0) {
this.meta.put(Weight.NODE_KEY, String.valueOf(this.weight));
}
if (this.primaryGroup != null && !this.meta.containsKey("primarygroup")) {
this.meta.put("primarygroup", this.primaryGroup);
}
this.state.set(State.COMPLETE);
}
@ -150,6 +154,11 @@ public class MetaAccumulator {
this.weight = Math.max(this.weight, weight);
}
public void setPrimaryGroup(String primaryGroup) {
ensureState(State.ACCUMULATING);
this.primaryGroup = primaryGroup;
}
// read methods
public ListMultimap<String, String> getMeta() {
@ -177,6 +186,11 @@ public class MetaAccumulator {
return this.weight;
}
public String getPrimaryGroup() {
ensureState(State.COMPLETE);
return this.primaryGroup;
}
public MetaStack getPrefixStack() {
ensureState(State.COMPLETE);
return this.prefixStack;
@ -194,6 +208,7 @@ public class MetaAccumulator {
"prefixes=" + this.prefixes + ", " +
"suffixes=" + this.suffixes + ", " +
"weight=" + this.weight + ", " +
"primaryGroup=" + this.primaryGroup + ", " +
"prefixStack=" + this.prefixStack + ", " +
"suffixStack=" + this.suffixStack + ")";
}

View File

@ -26,13 +26,8 @@
package me.lucko.luckperms.common.cacheddata.type;
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.Multimaps;
import me.lucko.luckperms.common.cacheddata.CacheMetadata;
import me.lucko.luckperms.common.metastacking.MetaStack;
import me.lucko.luckperms.common.model.HolderType;
import me.lucko.luckperms.common.node.types.Prefix;
import me.lucko.luckperms.common.node.types.Suffix;
@ -40,44 +35,30 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
import net.luckperms.api.cacheddata.CachedMetaData;
import net.luckperms.api.metastacking.MetaStackDefinition;
import net.luckperms.api.query.QueryOptions;
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;
import java.util.SortedMap;
/**
* Holds cached meta for a given context
*/
public class MetaCache implements CachedMetaData {
public class MetaCache extends SimpleMetaCache implements CachedMetaData {
/** The plugin instance */
private final LuckPermsPlugin plugin;
/** The query options this container is holding data for */
private final QueryOptions queryOptions;
/** The metadata for this cache */
private final CacheMetadata metadata;
/** The object name passed to the verbose handler when checks are made */
private final String verboseCheckTarget;
/* The data */
private Map<String, List<String>> meta = ImmutableMap.of();
private Map<String, String> flattenedMeta = ImmutableMap.of();
private SortedMap<Integer, String> prefixes = ImmutableSortedMap.of();
private SortedMap<Integer, String> suffixes = ImmutableSortedMap.of();
private MetaStack prefixStack = null;
private MetaStack suffixStack = null;
public MetaCache(LuckPermsPlugin plugin, QueryOptions queryOptions, CacheMetadata metadata) {
super(queryOptions);
this.plugin = plugin;
this.queryOptions = queryOptions;
this.metadata = metadata;
if (this.metadata.getHolderType() == HolderType.GROUP) {
@ -87,108 +68,46 @@ public class MetaCache implements CachedMetaData {
}
}
public void loadMeta(MetaAccumulator meta) {
meta.complete();
this.meta = Multimaps.asMap(ImmutableListMultimap.copyOf(meta.getMeta()));
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
for (Map.Entry<String, List<String>> e : this.meta.entrySet()) {
if (e.getValue().isEmpty()) {
continue;
}
// take the value which was accumulated first
builder.put(e.getKey(), e.getValue().get(0));
}
this.flattenedMeta = builder.build();
this.prefixes = ImmutableSortedMap.copyOfSorted(meta.getPrefixes());
this.suffixes = ImmutableSortedMap.copyOfSorted(meta.getSuffixes());
this.prefixStack = meta.getPrefixStack();
this.suffixStack = meta.getSuffixStack();
}
public String getMetaValue(String key, MetaCheckEvent.Origin origin) {
Objects.requireNonNull(key, "key");
String value = this.flattenedMeta.get(key);
String value = super.getMetaValue(key, origin);
this.plugin.getVerboseHandler().offerMetaCheckEvent(origin, this.verboseCheckTarget, this.metadata.getQueryOptions(), key, String.valueOf(value));
return value;
}
@Override
public String getMetaValue(String key) {
return getMetaValue(key, MetaCheckEvent.Origin.LUCKPERMS_API);
}
public String getPrefix(MetaCheckEvent.Origin origin) {
MetaStack prefixStack = this.prefixStack;
String value = prefixStack == null ? null : prefixStack.toFormattedString();
String value = super.getPrefix(origin);
this.plugin.getVerboseHandler().offerMetaCheckEvent(origin, this.verboseCheckTarget, this.metadata.getQueryOptions(), Prefix.NODE_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();
String value = super.getSuffix(origin);
this.plugin.getVerboseHandler().offerMetaCheckEvent(origin, this.verboseCheckTarget, this.metadata.getQueryOptions(), Suffix.NODE_KEY, String.valueOf(value));
return value;
}
@Override
public String getSuffix() {
return getSuffix(MetaCheckEvent.Origin.LUCKPERMS_API);
}
public Map<String, List<String>> getMeta(MetaCheckEvent.Origin origin) {
return new MonitoredMetaMap(origin);
return new MonitoredMetaMap(super.getMeta(origin), origin);
}
@Override
public @NonNull Map<String, List<String>> getMeta() {
return getMeta(MetaCheckEvent.Origin.LUCKPERMS_API);
}
@Override
public @NonNull SortedMap<Integer, String> getPrefixes() {
return this.prefixes;
}
@Override
public @NonNull SortedMap<Integer, String> getSuffixes() {
return this.suffixes;
}
@Override
public @NonNull MetaStackDefinition getPrefixStackDefinition() {
return this.prefixStack.getDefinition();
}
@Override
public @NonNull MetaStackDefinition getSuffixStackDefinition() {
return this.suffixStack.getDefinition();
}
@Override
public @NonNull QueryOptions getQueryOptions() {
return this.queryOptions;
public @Nullable String getPrimaryGroup(MetaCheckEvent.Origin origin) {
String value = super.getPrimaryGroup(origin);
this.plugin.getVerboseHandler().offerMetaCheckEvent(origin, this.verboseCheckTarget, this.metadata.getQueryOptions(), "primarygroup", String.valueOf(value));
return value;
}
private final class MonitoredMetaMap extends ForwardingMap<String, List<String>> {
private final Map<String, List<String>> delegate;
private final MetaCheckEvent.Origin origin;
MonitoredMetaMap(MetaCheckEvent.Origin origin) {
private MonitoredMetaMap(Map<String, List<String>> delegate, MetaCheckEvent.Origin origin) {
this.delegate = delegate;
this.origin = origin;
}
@Override
protected Map<String, List<String>> delegate() {
return MetaCache.this.meta;
return this.delegate;
}
@Override

View File

@ -0,0 +1,163 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.cacheddata.type;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Multimaps;
import me.lucko.luckperms.common.metastacking.MetaStack;
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
import net.luckperms.api.cacheddata.CachedMetaData;
import net.luckperms.api.metastacking.MetaStackDefinition;
import net.luckperms.api.query.QueryOptions;
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;
import java.util.SortedMap;
/**
* Holds cached meta for a given context
*/
public class SimpleMetaCache implements CachedMetaData {
/** The query options this container is holding data for */
private final QueryOptions queryOptions;
/* The data */
protected Map<String, List<String>> meta = ImmutableMap.of();
protected Map<String, String> flattenedMeta = ImmutableMap.of();
protected SortedMap<Integer, String> prefixes = ImmutableSortedMap.of();
protected SortedMap<Integer, String> suffixes = ImmutableSortedMap.of();
protected String primaryGroup = null;
protected MetaStack prefixStack = null;
protected MetaStack suffixStack = null;
public SimpleMetaCache(QueryOptions queryOptions) {
this.queryOptions = queryOptions;
}
public void loadMeta(MetaAccumulator meta) {
this.meta = Multimaps.asMap(ImmutableListMultimap.copyOf(meta.getMeta()));
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
for (Map.Entry<String, List<String>> e : this.meta.entrySet()) {
if (e.getValue().isEmpty()) {
continue;
}
// take the value which was accumulated first
builder.put(e.getKey(), e.getValue().get(0));
}
this.flattenedMeta = builder.build();
this.prefixes = ImmutableSortedMap.copyOfSorted(meta.getPrefixes());
this.suffixes = ImmutableSortedMap.copyOfSorted(meta.getSuffixes());
this.primaryGroup = meta.getPrimaryGroup();
this.prefixStack = meta.getPrefixStack();
this.suffixStack = meta.getSuffixStack();
}
public String getMetaValue(String key, MetaCheckEvent.Origin origin) {
Objects.requireNonNull(key, "key");
return this.flattenedMeta.get(key);
}
@Override
public final String getMetaValue(String key) {
return getMetaValue(key, MetaCheckEvent.Origin.LUCKPERMS_API);
}
public String getPrefix(MetaCheckEvent.Origin origin) {
MetaStack prefixStack = this.prefixStack;
return prefixStack == null ? null : prefixStack.toFormattedString();
}
@Override
public final String getPrefix() {
return getPrefix(MetaCheckEvent.Origin.LUCKPERMS_API);
}
public String getSuffix(MetaCheckEvent.Origin origin) {
MetaStack suffixStack = this.suffixStack;
return suffixStack == null ? null : suffixStack.toFormattedString();
}
@Override
public final String getSuffix() {
return getSuffix(MetaCheckEvent.Origin.LUCKPERMS_API);
}
public Map<String, List<String>> getMeta(MetaCheckEvent.Origin origin) {
return this.meta;
}
@Override
public final @NonNull Map<String, List<String>> getMeta() {
return getMeta(MetaCheckEvent.Origin.LUCKPERMS_API);
}
@Override
public @NonNull SortedMap<Integer, String> getPrefixes() {
return this.prefixes;
}
@Override
public @NonNull SortedMap<Integer, String> getSuffixes() {
return this.suffixes;
}
public @Nullable String getPrimaryGroup(MetaCheckEvent.Origin origin) {
return this.primaryGroup;
}
@Override
public final @Nullable String getPrimaryGroup() {
return this.primaryGroup;
}
@Override
public @NonNull MetaStackDefinition getPrefixStackDefinition() {
return this.prefixStack.getDefinition();
}
@Override
public @NonNull MetaStackDefinition getSuffixStackDefinition() {
return this.suffixStack.getDefinition();
}
@Override
public @NonNull QueryOptions getQueryOptions() {
return this.queryOptions;
}
}

View File

@ -109,8 +109,7 @@ public class MetaSetChatMeta extends GenericChildCommand {
// determine the priority to set at
if (priority == Integer.MIN_VALUE) {
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, QueryOptionsImpl.DEFAULT_CONTEXTUAL.toBuilder().context(context).build());
metaAccumulator.complete();
MetaAccumulator metaAccumulator = holder.accumulateMeta(QueryOptionsImpl.DEFAULT_CONTEXTUAL.toBuilder().context(context).build());
priority = metaAccumulator.getChatMeta(this.type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 1;
if (holder instanceof Group) {

View File

@ -119,8 +119,7 @@ public class MetaSetTempChatMeta extends GenericChildCommand {
// determine the priority to set at
if (priority == Integer.MIN_VALUE) {
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, QueryOptionsImpl.DEFAULT_CONTEXTUAL.toBuilder().context(context).build());
metaAccumulator.complete();
MetaAccumulator metaAccumulator = holder.accumulateMeta(QueryOptionsImpl.DEFAULT_CONTEXTUAL.toBuilder().context(context).build());
priority = metaAccumulator.getChatMeta(this.type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 1;
if (holder instanceof Group) {

View File

@ -50,6 +50,7 @@ import net.luckperms.api.query.QueryOptions;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
public class UserInfo extends ChildCommand<User> {
@ -64,14 +65,19 @@ public class UserInfo extends ChildCommand<User> {
return CommandResult.NO_PERMISSION;
}
Optional<QueryOptions> queryOptions = plugin.getQueryOptionsForUser(user);
Message status = plugin.getBootstrap().isPlayerOnline(user.getUniqueId()) ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
String primaryGroup = user.getCachedData().getMetaData(queryOptions.orElseGet(() -> plugin.getContextManager().getStaticQueryOptions()))
.getPrimaryGroup(MetaCheckEvent.Origin.INTERNAL);
Message.USER_INFO_GENERAL.send(sender,
user.getUsername().orElse("Unknown"),
user.getUniqueId(),
user.getUniqueId().version() == 4 ? "&2mojang" : "&8offline",
status.asString(plugin.getLocaleManager()),
user.getPrimaryGroup().getValue()
primaryGroup
);
List<InheritanceNode> parents = user.normalData().inheritanceAsSortedSet().stream()
@ -103,16 +109,16 @@ public class UserInfo extends ChildCommand<User> {
String prefix = "&bNone";
String suffix = "&bNone";
String meta = "&bNone";
QueryOptions queryOptions = plugin.getQueryOptionsForUser(user).orElse(null);
if (queryOptions != null) {
ContextSet contextSet = queryOptions.context();
if (contextSet != null && !contextSet.isEmpty()) {
if (queryOptions.isPresent()) {
ContextSet contextSet = queryOptions.get().context();
if (!contextSet.isEmpty()) {
context = contextSet.toSet().stream()
.map(e -> MessageUtils.contextToString(plugin.getLocaleManager(), e.getKey(), e.getValue()))
.collect(Collectors.joining(" "));
}
MetaCache data = user.getCachedData().getMetaData(queryOptions);
MetaCache data = user.getCachedData().getMetaData(queryOptions.get());
String prefixValue = data.getPrefix(MetaCheckEvent.Origin.INTERNAL);
if (prefixValue != null) {
prefix = "&f\"" + prefixValue + "&f\"";

View File

@ -347,11 +347,11 @@ public abstract class PermissionHolder {
return ImmutableMap.copyOf(map);
}
public MetaAccumulator accumulateMeta(MetaAccumulator accumulator, QueryOptions queryOptions) {
if (accumulator == null) {
accumulator = MetaAccumulator.makeFromConfig(this.plugin);
}
public MetaAccumulator accumulateMeta(QueryOptions queryOptions) {
return accumulateMeta(MetaAccumulator.makeFromConfig(this.plugin), queryOptions);
}
public MetaAccumulator accumulateMeta(MetaAccumulator accumulator, QueryOptions queryOptions) {
InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(queryOptions);
Iterable<PermissionHolder> traversal = graph.traverse(this);
for (PermissionHolder holder : traversal) {
@ -369,6 +369,12 @@ public abstract class PermissionHolder {
}
}
if (this instanceof User) {
String primaryGroup = ((User) this).getPrimaryGroup().calculateValue(queryOptions);
accumulator.setPrimaryGroup(primaryGroup);
}
accumulator.complete();
return accumulator;
}

View File

@ -25,18 +25,13 @@
package me.lucko.luckperms.common.model;
import me.lucko.luckperms.common.cache.LoadingMap;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.inheritance.InheritanceGraph;
import me.lucko.luckperms.common.model.manager.group.GroupManager;
import net.luckperms.api.node.types.InheritanceNode;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@ -49,9 +44,10 @@ public interface PrimaryGroupHolder {
/**
* Gets the name of the primary group, or null.
*
* @param queryOptions the query options to lookup with
* @return the name of the primary group, or null.
*/
String getValue();
String calculateValue(QueryOptions queryOptions);
/**
* Gets the primary group which is stored against the user's data.
@ -80,7 +76,7 @@ public interface PrimaryGroupHolder {
}
@Override
public String getValue() {
public String calculateValue(QueryOptions queryOptions) {
return this.value;
}
@ -99,42 +95,14 @@ public interface PrimaryGroupHolder {
}
}
/**
* Abstract implementation of {@link PrimaryGroupHolder} which caches all lookups by context.
*/
abstract class AbstractContextual extends Stored {
private final Map<QueryOptions, Optional<String>> cache = LoadingMap.of(this::calculateValue);
AbstractContextual(User user) {
super(user);
}
protected abstract @NonNull Optional<String> calculateValue(QueryOptions queryOptions);
public void invalidateCache() {
this.cache.clear();
}
@Override
public final String getValue() {
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(queryOptions))
.orElseGet(() -> getStoredValue().orElse(GroupManager.DEFAULT_GROUP_NAME));
}
}
class AllParentsByWeight extends AbstractContextual {
class AllParentsByWeight extends Stored {
public AllParentsByWeight(User user) {
super(user);
}
@Override
protected @NonNull Optional<String> calculateValue(QueryOptions queryOptions) {
public String 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.
@ -143,20 +111,22 @@ public interface PrimaryGroupHolder {
// return the name of the first found group
for (PermissionHolder holder : traversal) {
if (holder instanceof Group) {
return Optional.of(((Group) holder).getName());
return ((Group) holder).getName();
}
}
return Optional.empty();
// fallback to stored
return super.calculateValue(queryOptions);
}
}
class ParentsByWeight extends AbstractContextual {
class ParentsByWeight extends Stored {
public ParentsByWeight(User user) {
super(user);
}
@Override
protected @NonNull Optional<String> calculateValue(QueryOptions queryOptions) {
public String calculateValue(QueryOptions queryOptions) {
Set<Group> groups = new LinkedHashSet<>();
for (InheritanceNode node : this.user.getOwnInheritanceNodes(queryOptions)) {
Group group = this.user.getPlugin().getGroupManager().getIfLoaded(node.getGroupName());
@ -176,7 +146,7 @@ public interface PrimaryGroupHolder {
}
}
return bestGroup == null ? Optional.empty() : Optional.of(bestGroup.getName());
return bestGroup == null ? super.calculateValue(queryOptions) : bestGroup.getName();
}
}
}

View File

@ -66,16 +66,6 @@ public class User extends PermissionHolder {
getPlugin().getEventDispatcher().dispatchUserCacheLoad(this, this.cachedData);
}
@Override
protected void invalidateCache() {
super.invalidateCache();
// invalidate our caches
if (this.primaryGroup instanceof PrimaryGroupHolder.AbstractContextual) {
((PrimaryGroupHolder.AbstractContextual) this.primaryGroup).invalidateCache();
}
}
public UUID getUniqueId() {
return this.uniqueId;
}

View File

@ -35,6 +35,7 @@ import me.lucko.luckperms.common.model.manager.group.GroupManager;
import me.lucko.luckperms.common.node.types.Inheritance;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
import net.luckperms.api.model.data.DataType;
import net.luckperms.api.node.Node;
@ -85,7 +86,7 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
// check that they are actually a member of their primary group, otherwise remove it
if (this.plugin.getConfiguration().get(ConfigKeys.PRIMARY_GROUP_CALCULATION_METHOD).equals("stored")) {
String primaryGroup = user.getPrimaryGroup().getValue();
String primaryGroup = user.getCachedData().getMetaData(this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_QUERY_OPTIONS)).getPrimaryGroup(MetaCheckEvent.Origin.INTERNAL);
boolean memberOfPrimaryGroup = false;
for (InheritanceNode node : user.normalData().immutableInheritance().get(ImmutableContextSetImpl.EMPTY)) {

View File

@ -302,8 +302,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
// remove all prefixes/suffixes from the user
this.holder.removeIf(this.type, contexts, type.nodeType()::matches, false);
MetaAccumulator metaAccumulator = this.holder.accumulateMeta(null, QueryOptionsImpl.DEFAULT_CONTEXTUAL.toBuilder().context(contexts).build());
metaAccumulator.complete();
MetaAccumulator metaAccumulator = this.holder.accumulateMeta(QueryOptionsImpl.DEFAULT_CONTEXTUAL.toBuilder().context(contexts).build());
int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0);
priority += 10;