diff --git a/api/src/main/java/net/luckperms/api/cacheddata/CachedMetaData.java b/api/src/main/java/net/luckperms/api/cacheddata/CachedMetaData.java index 10414a586..cc2e42561 100644 --- a/api/src/main/java/net/luckperms/api/cacheddata/CachedMetaData.java +++ b/api/src/main/java/net/luckperms/api/cacheddata/CachedMetaData.java @@ -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> 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 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 getSuffixes(); + /** + * Gets the name of the holders primary group. + * + *

Will return {@code null} for Group holder types.

+ * + * @return the name of the primary group + * @since 5.1 + */ + @Nullable String getPrimaryGroup(); + /** * Gets the definition used for the prefix stack * 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 23a71e8e7..9d8ca0531 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 @@ -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) 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 3dc9186e0..8f7bb8301 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 @@ -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; } 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 77a0c00ee..0ea0c6662 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 @@ -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 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 53e999182..73fa79156 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 @@ -78,6 +78,7 @@ public class MetaAccumulator { private final SortedMap prefixes; private final SortedMap 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 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 + ")"; } 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 4b66c03b1..0e51cfc59 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 @@ -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> meta = ImmutableMap.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(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 builder = ImmutableMap.builder(); - for (Map.Entry> 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> getMeta(MetaCheckEvent.Origin origin) { - return new MonitoredMetaMap(origin); + return new MonitoredMetaMap(super.getMeta(origin), origin); } - @Override - public @NonNull Map> getMeta() { - return getMeta(MetaCheckEvent.Origin.LUCKPERMS_API); - } - - @Override - public @NonNull SortedMap getPrefixes() { - return this.prefixes; - } - - @Override - public @NonNull SortedMap 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> { + private final Map> delegate; private final MetaCheckEvent.Origin origin; - MonitoredMetaMap(MetaCheckEvent.Origin origin) { + private MonitoredMetaMap(Map> delegate, MetaCheckEvent.Origin origin) { + this.delegate = delegate; this.origin = origin; } @Override protected Map> delegate() { - return MetaCache.this.meta; + return this.delegate; } @Override diff --git a/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/SimpleMetaCache.java b/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/SimpleMetaCache.java new file mode 100644 index 000000000..2f7745495 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/cacheddata/type/SimpleMetaCache.java @@ -0,0 +1,163 @@ +/* + * 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.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> meta = ImmutableMap.of(); + protected Map flattenedMeta = ImmutableMap.of(); + protected SortedMap prefixes = ImmutableSortedMap.of(); + protected SortedMap 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 builder = ImmutableMap.builder(); + for (Map.Entry> 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> getMeta(MetaCheckEvent.Origin origin) { + return this.meta; + } + + @Override + public final @NonNull Map> getMeta() { + return getMeta(MetaCheckEvent.Origin.LUCKPERMS_API); + } + + @Override + public @NonNull SortedMap getPrefixes() { + return this.prefixes; + } + + @Override + public @NonNull SortedMap 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; + } + +} 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 cef57b66a..afbcbe18d 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 @@ -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) { 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 ab6efda39..fc88c1fb3 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 @@ -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) { 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 34a7b3880..065299c59 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 @@ -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 { @@ -64,14 +65,19 @@ public class UserInfo extends ChildCommand { return CommandResult.NO_PERMISSION; } + Optional 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 parents = user.normalData().inheritanceAsSortedSet().stream() @@ -103,16 +109,16 @@ public class UserInfo extends ChildCommand { 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\""; 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 ec731b86c..04d9c6a0d 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 @@ -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 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; } diff --git a/common/src/main/java/me/lucko/luckperms/common/model/PrimaryGroupHolder.java b/common/src/main/java/me/lucko/luckperms/common/model/PrimaryGroupHolder.java index c66413660..b9b0f26ab 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/PrimaryGroupHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/PrimaryGroupHolder.java @@ -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> cache = LoadingMap.of(this::calculateValue); - AbstractContextual(User user) { - super(user); - } - - protected abstract @NonNull Optional 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 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 calculateValue(QueryOptions queryOptions) { + public String calculateValue(QueryOptions queryOptions) { Set 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(); } } } 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 d9dc9db93..ee752a259 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 @@ -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; } 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 e3515d6bb..757341461 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 @@ -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 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)) { 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 e79ae1fb0..40159a3bc 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 @@ -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;