mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2025-01-29 19:51:40 +01:00
Remove NodeMap immutable cache
This commit is contained in:
parent
b460e282b1
commit
cc08390abe
@ -174,7 +174,7 @@ public class ApiPermissionHolder implements net.luckperms.api.model.PermissionHo
|
||||
|
||||
@Override
|
||||
public @NonNull Map<ImmutableContextSet, Collection<Node>> toMap() {
|
||||
return ApiPermissionHolder.this.handle.getData(this.dataType).immutable().asMap();
|
||||
return ApiPermissionHolder.this.handle.getData(this.dataType).asMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -167,7 +167,7 @@ public class CommandManager {
|
||||
}
|
||||
|
||||
Collection<? extends Group> groups = this.plugin.getGroupManager().getAll().values();
|
||||
if (groups.size() <= 1 && groups.stream().allMatch(g -> g.normalData().immutable().isEmpty())) {
|
||||
if (groups.size() <= 1 && groups.stream().allMatch(g -> g.normalData().isEmpty())) {
|
||||
Message.FIRST_TIME_SETUP.send(sender, label, sender.getName());
|
||||
} else {
|
||||
Message.NO_PERMISSION_FOR_SUBCOMMANDS.send(sender);
|
||||
|
@ -90,7 +90,7 @@ public class MetaClear extends GenericChildCommand {
|
||||
type = NodeType.META_OR_CHAT_META;
|
||||
}
|
||||
|
||||
int before = target.normalData().immutable().size();
|
||||
int before = target.normalData().size();
|
||||
|
||||
MutableContextSet context = args.getContextOrDefault(0, plugin);
|
||||
|
||||
@ -106,7 +106,7 @@ public class MetaClear extends GenericChildCommand {
|
||||
target.removeIf(DataType.NORMAL, context, type::matches, false);
|
||||
}
|
||||
|
||||
int changed = before - target.normalData().immutable().size();
|
||||
int changed = before - target.normalData().size();
|
||||
if (changed == 1) {
|
||||
Message.META_CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), type.name().toLowerCase(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed);
|
||||
} else {
|
||||
|
@ -62,7 +62,7 @@ public class HolderClear<T extends PermissionHolder> extends ChildCommand<T> {
|
||||
return CommandResult.NO_PERMISSION;
|
||||
}
|
||||
|
||||
int before = target.normalData().immutable().size();
|
||||
int before = target.normalData().size();
|
||||
|
||||
MutableContextSet context = args.getContextOrDefault(0, plugin);
|
||||
|
||||
@ -78,7 +78,7 @@ public class HolderClear<T extends PermissionHolder> extends ChildCommand<T> {
|
||||
target.clearNodes(DataType.NORMAL, context, true);
|
||||
}
|
||||
|
||||
int changed = before - target.normalData().immutable().size();
|
||||
int changed = before - target.normalData().size();
|
||||
if (changed == 1) {
|
||||
Message.CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed);
|
||||
} else {
|
||||
|
@ -84,7 +84,7 @@ public class HolderEditor<T extends PermissionHolder> extends ChildCommand<T> {
|
||||
Map<UUID, User> users = new LinkedHashMap<>(plugin.getUserManager().getAll());
|
||||
|
||||
// only include online players who are in the group
|
||||
users.values().removeIf(user -> user.normalData().immutable().values().stream().noneMatch(matcher));
|
||||
users.values().removeIf(user -> user.normalData().asList().stream().noneMatch(matcher));
|
||||
|
||||
// fill up with other matching users
|
||||
if (users.size() < EditorCommand.MAX_USERS) {
|
||||
|
@ -77,7 +77,7 @@ public class HolderShowTracks<T extends PermissionHolder> extends ChildCommand<T
|
||||
|
||||
if (target.getType() == HolderType.USER) {
|
||||
// if the holder is a user, we want to query parent groups for tracks
|
||||
Set<InheritanceNode> nodes = target.normalData().immutableInheritance().values().stream()
|
||||
Set<InheritanceNode> nodes = target.normalData().inheritanceAsList().stream()
|
||||
.filter(Node::getValue)
|
||||
.filter(n -> !n.hasExpiry())
|
||||
.collect(Collectors.toSet());
|
||||
|
@ -62,7 +62,7 @@ public class ParentClear extends GenericChildCommand {
|
||||
return CommandResult.NO_PERMISSION;
|
||||
}
|
||||
|
||||
int before = target.normalData().immutable().size();
|
||||
int before = target.normalData().size();
|
||||
|
||||
MutableContextSet context = args.getContextOrDefault(0, plugin);
|
||||
|
||||
@ -77,7 +77,7 @@ public class ParentClear extends GenericChildCommand {
|
||||
target.removeIf(DataType.NORMAL, context, NodeType.INHERITANCE::matches, true);
|
||||
}
|
||||
|
||||
int changed = before - target.normalData().immutable().size();
|
||||
int changed = before - target.normalData().size();
|
||||
if (changed == 1) {
|
||||
Message.PARENT_CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed);
|
||||
} else {
|
||||
|
@ -82,7 +82,7 @@ public class ParentClearTrack extends GenericChildCommand {
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
int before = target.normalData().immutable().size();
|
||||
int before = target.normalData().size();
|
||||
|
||||
ImmutableContextSet context = args.getContextOrDefault(1, plugin).immutableCopy();
|
||||
|
||||
@ -99,7 +99,7 @@ public class ParentClearTrack extends GenericChildCommand {
|
||||
plugin.getUserManager().giveDefaultIfNeeded(((User) target), false);
|
||||
}
|
||||
|
||||
int changed = before - target.normalData().immutable().size();
|
||||
int changed = before - target.normalData().size();
|
||||
|
||||
if (changed == 1) {
|
||||
Message.PARENT_CLEAR_TRACK_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), track.getName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed);
|
||||
|
@ -62,7 +62,7 @@ public class PermissionClear extends GenericChildCommand {
|
||||
return CommandResult.NO_PERMISSION;
|
||||
}
|
||||
|
||||
int before = target.normalData().immutable().size();
|
||||
int before = target.normalData().size();
|
||||
|
||||
MutableContextSet context = args.getContextOrDefault(0, plugin);
|
||||
|
||||
@ -74,7 +74,7 @@ public class PermissionClear extends GenericChildCommand {
|
||||
|
||||
target.removeIf(DataType.NORMAL, context.isEmpty() ? null : context, NodeType.PERMISSION::matches, false);
|
||||
|
||||
int changed = before - target.normalData().immutable().size();
|
||||
int changed = before - target.normalData().size();
|
||||
if (changed == 1) {
|
||||
Message.PERMISSION_CLEAR_SUCCESS_SINGULAR.send(sender, target.getFormattedDisplayName(), MessageUtils.contextSetToString(plugin.getLocaleManager(), context), changed);
|
||||
} else {
|
||||
|
@ -73,7 +73,7 @@ public class GroupClone extends ChildCommand<Group> {
|
||||
return CommandResult.NO_PERMISSION;
|
||||
}
|
||||
|
||||
newGroup.setNodes(DataType.NORMAL, target.normalData().immutable());
|
||||
newGroup.setNodes(DataType.NORMAL, target.normalData().asList());
|
||||
|
||||
Message.CLONE_SUCCESS.send(sender, target.getName(), newGroup.getName());
|
||||
|
||||
|
@ -79,7 +79,7 @@ public class GroupRename extends ChildCommand<Group> {
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
newGroup.setNodes(DataType.NORMAL, target.normalData().immutable());
|
||||
newGroup.setNodes(DataType.NORMAL, target.normalData().asList());
|
||||
|
||||
Message.RENAME_SUCCESS.send(sender, target.getName(), newGroup.getName());
|
||||
|
||||
|
@ -67,7 +67,7 @@ public class GroupSetDisplayName extends ChildCommand<Group> {
|
||||
String name = args.get(0);
|
||||
ImmutableContextSet context = args.getContextOrDefault(1, plugin).immutableCopy();
|
||||
|
||||
String previousName = target.normalData().immutable().get(context).stream()
|
||||
String previousName = target.normalData().nodesSetInContext(context).stream()
|
||||
.filter(NodeType.DISPLAY_NAME::matches)
|
||||
.map(NodeType.DISPLAY_NAME::cast)
|
||||
.findFirst()
|
||||
|
@ -59,7 +59,7 @@ public class LogNotify extends ChildCommand<Log> {
|
||||
return false;
|
||||
}
|
||||
|
||||
Optional<? extends Node> node = user.normalData().immutable().get(ImmutableContextSetImpl.EMPTY).stream()
|
||||
Optional<? extends Node> node = user.normalData().nodesSetInContext(ImmutableContextSetImpl.EMPTY).stream()
|
||||
.filter(n -> n.getKey().equalsIgnoreCase(IGNORE_NODE))
|
||||
.findFirst();
|
||||
|
||||
|
@ -176,7 +176,7 @@ public class ApplyEditsCommand extends SingleCommand {
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<Node> before = new HashSet<>(holder.normalData().immutable().values());
|
||||
Set<Node> before = holder.normalData().asSet();
|
||||
Set<Node> after = new HashSet<>(NodeJsonSerializer.deserializeNodes(data.getAsJsonArray("nodes")));
|
||||
|
||||
Set<Node> diffAdded = getAdded(before, after);
|
||||
|
@ -110,7 +110,7 @@ public class EditorCommand extends SingleCommand {
|
||||
ConstraintNodeMatcher<Node> matcher = StandardNodeMatchers.keyStartsWith(filter);
|
||||
|
||||
// only include online players matching the permission
|
||||
users.values().removeIf(user -> user.normalData().immutable().values().stream().noneMatch(matcher));
|
||||
users.values().removeIf(user -> user.normalData().asList().stream().noneMatch(matcher));
|
||||
|
||||
// fill up with other matching users
|
||||
if (type.includingOffline && users.size() < MAX_USERS) {
|
||||
|
@ -72,7 +72,7 @@ public class UserClone extends ChildCommand<User> {
|
||||
return CommandResult.NO_PERMISSION;
|
||||
}
|
||||
|
||||
otherUser.setNodes(DataType.NORMAL, target.normalData().immutable());
|
||||
otherUser.setNodes(DataType.NORMAL, target.normalData().asList());
|
||||
|
||||
Message.CLONE_SUCCESS.send(sender, target.getFormattedDisplayName(), otherUser.getFormattedDisplayName());
|
||||
|
||||
|
@ -160,7 +160,7 @@ public final class EventDispatcher {
|
||||
}
|
||||
|
||||
public void dispatchGroupDelete(Group group, DeletionCause cause) {
|
||||
post(GroupDeleteEvent.class, () -> generate(GroupDeleteEvent.class, group.getName(), ImmutableSet.copyOf(group.normalData().immutable().values()), cause));
|
||||
post(GroupDeleteEvent.class, () -> generate(GroupDeleteEvent.class, group.getName(), ImmutableSet.copyOf(group.normalData().asSet()), cause));
|
||||
}
|
||||
|
||||
public void dispatchGroupLoadAll() {
|
||||
|
@ -25,16 +25,12 @@
|
||||
|
||||
package me.lucko.luckperms.common.model;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
|
||||
import me.lucko.luckperms.common.cache.Cache;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
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.query.QueryOptionsImpl;
|
||||
|
||||
import net.luckperms.api.context.ContextSatisfyMode;
|
||||
import net.luckperms.api.context.ContextSet;
|
||||
@ -48,15 +44,14 @@ import net.luckperms.api.node.types.InheritanceNode;
|
||||
import net.luckperms.api.query.Flag;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
|
||||
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.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -104,40 +99,78 @@ public final class NodeMap {
|
||||
*/
|
||||
private final SortedMap<ImmutableContextSet, SortedSet<InheritanceNode>> inheritanceMap = new ConcurrentSkipListMap<>(ContextSetComparator.reverse());
|
||||
|
||||
/**
|
||||
* A cache which holds an immutable copy of the backing map
|
||||
*/
|
||||
private final ImmutableSetMultimapCache<ImmutableContextSet, Node> mapCache = new ImmutableSetMultimapCache<>(this.map);
|
||||
private final ImmutableSetMultimapCache<ImmutableContextSet, InheritanceNode> inheritanceMapCache = new ImmutableSetMultimapCache<>(this.inheritanceMap);
|
||||
|
||||
NodeMap(PermissionHolder holder) {
|
||||
this.holder = holder;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.map.isEmpty();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.map.size();
|
||||
}
|
||||
|
||||
public List<Node> asList() {
|
||||
List<Node> list = new ArrayList<>();
|
||||
copyTo(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public LinkedHashSet<Node> asSet() {
|
||||
LinkedHashSet<Node> set = new LinkedHashSet<>();
|
||||
copyTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL);
|
||||
copyTo(set);
|
||||
return set;
|
||||
}
|
||||
|
||||
public SortedSet<Node> asSortedSet() {
|
||||
SortedSet<Node> set = new TreeSet<>(NodeWithContextComparator.reverse());
|
||||
copyTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL);
|
||||
copyTo(set);
|
||||
return set;
|
||||
}
|
||||
|
||||
public ImmutableSet<Node> asImmutableSet() {
|
||||
ImmutableSet.Builder<Node> builder = ImmutableSet.builder();
|
||||
for (SortedSet<Node> values : this.map.values()) {
|
||||
builder.addAll(values);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public Map<ImmutableContextSet, Collection<Node>> asMap() {
|
||||
Map<ImmutableContextSet, Collection<Node>> map = new HashMap<>();
|
||||
for (Map.Entry<ImmutableContextSet, SortedSet<Node>> e : this.map.entrySet()) {
|
||||
map.put(e.getKey(), new ArrayList<>(e.getValue()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public List<InheritanceNode> inheritanceAsList() {
|
||||
List<InheritanceNode> set = new ArrayList<>();
|
||||
copyInheritanceNodesTo(set);
|
||||
return set;
|
||||
}
|
||||
|
||||
public LinkedHashSet<InheritanceNode> inheritanceAsSet() {
|
||||
LinkedHashSet<InheritanceNode> set = new LinkedHashSet<>();
|
||||
copyInheritanceNodesTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL);
|
||||
copyInheritanceNodesTo(set);
|
||||
return set;
|
||||
}
|
||||
|
||||
public SortedSet<InheritanceNode> inheritanceAsSortedSet() {
|
||||
SortedSet<InheritanceNode> set = new TreeSet<>(NodeWithContextComparator.reverse());
|
||||
copyInheritanceNodesTo(set, QueryOptionsImpl.DEFAULT_NON_CONTEXTUAL);
|
||||
copyInheritanceNodesTo(set);
|
||||
return set;
|
||||
}
|
||||
|
||||
public Map<ImmutableContextSet, Collection<InheritanceNode>> inheritanceAsMap() {
|
||||
Map<ImmutableContextSet, Collection<InheritanceNode>> map = new HashMap<>();
|
||||
for (Map.Entry<ImmutableContextSet, SortedSet<InheritanceNode>> e : this.inheritanceMap.entrySet()) {
|
||||
map.put(e.getKey(), new ArrayList<>(e.getValue()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static boolean flagExcludeTest(Flag flag, String contextKey, QueryOptions filter, ImmutableContextSet contextSet) {
|
||||
// return true (negative result) if the explicit *include* flag is not set, and if the context set doesn't contain the required context key.
|
||||
return !filter.flag(flag) && !contextSet.containsKey(contextKey);
|
||||
@ -159,6 +192,12 @@ public final class NodeMap {
|
||||
return this.holder.getPlugin().getConfiguration().get(ConfigKeys.CONTEXT_SATISFY_MODE);
|
||||
}
|
||||
|
||||
public void forEach(Consumer<? super Node> consumer) {
|
||||
for (SortedSet<Node> values : this.map.values()) {
|
||||
values.forEach(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
public void forEach(QueryOptions filter, Consumer<? super Node> consumer) {
|
||||
for (Map.Entry<ImmutableContextSet, SortedSet<Node>> e : this.map.entrySet()) {
|
||||
if (!filter.satisfies(e.getKey(), defaultSatisfyMode())) {
|
||||
@ -179,6 +218,12 @@ public final class NodeMap {
|
||||
}
|
||||
}
|
||||
|
||||
public void copyTo(Collection<? super Node> collection) {
|
||||
for (SortedSet<Node> values : this.map.values()) {
|
||||
collection.addAll(values);
|
||||
}
|
||||
}
|
||||
|
||||
public void copyTo(Collection<? super Node> collection, QueryOptions filter) {
|
||||
for (Map.Entry<ImmutableContextSet, SortedSet<Node>> e : this.map.entrySet()) {
|
||||
if (!filter.satisfies(e.getKey(), defaultSatisfyMode())) {
|
||||
@ -227,6 +272,12 @@ public final class NodeMap {
|
||||
}
|
||||
}
|
||||
|
||||
public void copyInheritanceNodesTo(Collection<? super InheritanceNode> collection) {
|
||||
for (SortedSet<InheritanceNode> values : this.inheritanceMap.values()) {
|
||||
collection.addAll(values);
|
||||
}
|
||||
}
|
||||
|
||||
public void copyInheritanceNodesTo(Collection<? super InheritanceNode> collection, QueryOptions filter) {
|
||||
for (Map.Entry<ImmutableContextSet, SortedSet<InheritanceNode>> e : this.inheritanceMap.entrySet()) {
|
||||
if (!filter.satisfies(e.getKey(), defaultSatisfyMode())) {
|
||||
@ -239,25 +290,20 @@ public final class NodeMap {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable representation of the maps current state.
|
||||
*
|
||||
* @return an immutable copy
|
||||
*/
|
||||
public ImmutableSetMultimap<ImmutableContextSet, Node> immutable() {
|
||||
return this.mapCache.get();
|
||||
public Collection<Node> nodesSetInContext(ContextSet context) {
|
||||
final SortedSet<Node> values = this.map.get(context.immutableCopy());
|
||||
if (values == null) {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
return new ArrayList<>(values);
|
||||
}
|
||||
|
||||
public ImmutableSetMultimap<ImmutableContextSet, InheritanceNode> immutableInheritance() {
|
||||
return this.inheritanceMapCache.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the cache
|
||||
*/
|
||||
void invalidate() {
|
||||
this.mapCache.invalidate();
|
||||
this.inheritanceMapCache.invalidate();
|
||||
public Collection<InheritanceNode> inheritanceNodesSetInContext(ContextSet context) {
|
||||
final SortedSet<InheritanceNode> values = this.inheritanceMap.get(context.immutableCopy());
|
||||
if (values == null) {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
return new ArrayList<>(values);
|
||||
}
|
||||
|
||||
private Node localise(Node node) {
|
||||
@ -414,45 +460,4 @@ public final class NodeMap {
|
||||
return work;
|
||||
}
|
||||
|
||||
private static final class ImmutableSetMultimapCache<K, V> extends Cache<ImmutableSetMultimap<K, V>> {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final Constructor<ImmutableSetMultimap> IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR;
|
||||
static {
|
||||
try {
|
||||
IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR = ImmutableSetMultimap.class.getDeclaredConstructor(ImmutableMap.class, int.class, Comparator.class);
|
||||
IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<K, ? extends Collection<V>> handle;
|
||||
|
||||
private ImmutableSetMultimapCache(Map<K, ? extends Collection<V>> handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull ImmutableSetMultimap<K, V> supply() {
|
||||
ImmutableMap.Builder<K, ImmutableSet<V>> builder = ImmutableMap.builder();
|
||||
int size = 0;
|
||||
|
||||
for (Map.Entry<K, ? extends Collection<V>> entry : this.handle.entrySet()) {
|
||||
K key = entry.getKey();
|
||||
ImmutableSet<V> values = ImmutableSet.copyOf(entry.getValue());
|
||||
if (!values.isEmpty()) {
|
||||
builder.put(key, values);
|
||||
size += values.size();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
//noinspection unchecked
|
||||
return IMMUTABLE_SET_MULTIMAP_CONSTRUCTOR.newInstance(builder.build(), size, null);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,10 +25,9 @@
|
||||
|
||||
package me.lucko.luckperms.common.model;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import me.lucko.luckperms.common.cacheddata.HolderCachedDataManager;
|
||||
import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator;
|
||||
@ -39,7 +38,6 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.query.DataSelector;
|
||||
|
||||
import net.luckperms.api.context.ContextSet;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import net.luckperms.api.model.data.DataMutateResult;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.model.data.TemporaryNodeMergeStrategy;
|
||||
@ -234,9 +232,6 @@ public abstract class PermissionHolder {
|
||||
public abstract HolderType getType();
|
||||
|
||||
protected void invalidateCache() {
|
||||
this.normalNodes.invalidate();
|
||||
this.transientNodes.invalidate();
|
||||
|
||||
getCachedData().invalidate();
|
||||
getPlugin().getEventDispatcher().dispatchDataRecalculate(this);
|
||||
}
|
||||
@ -251,11 +246,6 @@ public abstract class PermissionHolder {
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
public void setNodes(DataType type, Multimap<ImmutableContextSet, ? extends Node> multimap) {
|
||||
getData(type).setContent(multimap.values());
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
public void mergeNodes(DataType type, Iterable<? extends Node> set) {
|
||||
getData(type).mergeContent(set);
|
||||
invalidateCache();
|
||||
@ -446,19 +436,19 @@ public abstract class PermissionHolder {
|
||||
}
|
||||
|
||||
private boolean auditTemporaryNodes(DataType dataType) {
|
||||
ImmutableCollection<? extends Node> before = getData(dataType).immutable().values();
|
||||
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
|
||||
Set<Node> removed = new HashSet<>();
|
||||
|
||||
boolean work = getData(dataType).auditTemporaryNodes(removed);
|
||||
if (work) {
|
||||
// invalidate
|
||||
invalidateCache();
|
||||
|
||||
// call event
|
||||
ImmutableCollection<? extends Node> after = getData(dataType).immutable().values();
|
||||
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
|
||||
for (Node r : removed) {
|
||||
this.plugin.getEventDispatcher().dispatchNodeRemove(r, this, dataType, before, after);
|
||||
}
|
||||
|
||||
// invalidate
|
||||
invalidateCache();
|
||||
}
|
||||
return work;
|
||||
}
|
||||
@ -468,7 +458,7 @@ public abstract class PermissionHolder {
|
||||
return Tristate.TRUE;
|
||||
}
|
||||
|
||||
return getData(type).immutable().values().stream()
|
||||
return getData(type).asList().stream()
|
||||
.filter(equalityPredicate.equalTo(node))
|
||||
.findFirst()
|
||||
.map(n -> Tristate.of(n.getValue())).orElse(Tristate.UNDEFINED);
|
||||
@ -481,22 +471,23 @@ public abstract class PermissionHolder {
|
||||
|
||||
NodeMap data = getData(dataType);
|
||||
|
||||
ImmutableCollection<? extends Node> before = data.immutable().values();
|
||||
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
|
||||
|
||||
data.add(node);
|
||||
invalidateCache();
|
||||
|
||||
ImmutableCollection<? extends Node> after = data.immutable().values();
|
||||
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
|
||||
if (callEvent) {
|
||||
this.plugin.getEventDispatcher().dispatchNodeAdd(node, this, dataType, before, after);
|
||||
}
|
||||
|
||||
invalidateCache();
|
||||
|
||||
return DataMutateResult.SUCCESS;
|
||||
}
|
||||
|
||||
public DataMutateResult.WithMergedNode setNode(DataType dataType, Node node, TemporaryNodeMergeStrategy mergeStrategy) {
|
||||
if (node.getExpiry() != null && mergeStrategy != TemporaryNodeMergeStrategy.NONE) {
|
||||
Node otherMatch = getData(dataType).immutable().values().stream()
|
||||
Node otherMatch = getData(dataType).asList().stream()
|
||||
.filter(NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE.equalTo(node))
|
||||
.findFirst().orElse(null);
|
||||
|
||||
@ -522,14 +513,15 @@ public abstract class PermissionHolder {
|
||||
|
||||
if (newNode != null) {
|
||||
// Remove the old Node & add the new one.
|
||||
ImmutableCollection<? extends Node> before = data.immutable().values();
|
||||
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
|
||||
|
||||
data.replace(newNode, otherMatch);
|
||||
invalidateCache();
|
||||
|
||||
ImmutableCollection<? extends Node> after = data.immutable().values();
|
||||
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
|
||||
this.plugin.getEventDispatcher().dispatchNodeAdd(newNode, this, dataType, before, after);
|
||||
|
||||
invalidateCache();
|
||||
|
||||
return new MergedNodeResult(DataMutateResult.SUCCESS, newNode);
|
||||
}
|
||||
}
|
||||
@ -544,20 +536,21 @@ public abstract class PermissionHolder {
|
||||
return DataMutateResult.FAIL_LACKS;
|
||||
}
|
||||
|
||||
ImmutableCollection<? extends Node> before = getData(dataType).immutable().values();
|
||||
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
|
||||
|
||||
getData(dataType).remove(node);
|
||||
invalidateCache();
|
||||
|
||||
ImmutableCollection<? extends Node> after = getData(dataType).immutable().values();
|
||||
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
|
||||
this.plugin.getEventDispatcher().dispatchNodeRemove(node, this, dataType, before, after);
|
||||
|
||||
invalidateCache();
|
||||
|
||||
return DataMutateResult.SUCCESS;
|
||||
}
|
||||
|
||||
public DataMutateResult.WithMergedNode unsetNode(DataType dataType, Node node, @Nullable Duration duration) {
|
||||
if (node.getExpiry() != null && duration != null) {
|
||||
Node otherMatch = getData(dataType).immutable().values().stream()
|
||||
Node otherMatch = getData(dataType).asList().stream()
|
||||
.filter(NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE.equalTo(node))
|
||||
.findFirst().orElse(null);
|
||||
|
||||
@ -570,15 +563,16 @@ public abstract class PermissionHolder {
|
||||
Node newNode = node.toBuilder().expiry(newExpiry).build();
|
||||
|
||||
// Remove the old Node & add the new one.
|
||||
ImmutableCollection<? extends Node> before = data.immutable().values();
|
||||
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
|
||||
|
||||
data.replace(newNode, otherMatch);
|
||||
invalidateCache();
|
||||
|
||||
ImmutableCollection<? extends Node> after = data.immutable().values();
|
||||
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
|
||||
this.plugin.getEventDispatcher().dispatchNodeRemove(otherMatch, this, dataType, before, after);
|
||||
this.plugin.getEventDispatcher().dispatchNodeAdd(newNode, this, dataType, before, after);
|
||||
|
||||
invalidateCache();
|
||||
|
||||
return new MergedNodeResult(DataMutateResult.SUCCESS, newNode);
|
||||
}
|
||||
}
|
||||
@ -590,7 +584,7 @@ public abstract class PermissionHolder {
|
||||
|
||||
public boolean removeIf(DataType dataType, @Nullable ContextSet contextSet, Predicate<? super Node> predicate, boolean giveDefault) {
|
||||
NodeMap data = getData(dataType);
|
||||
ImmutableCollection<? extends Node> before = data.immutable().values();
|
||||
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
|
||||
|
||||
if (contextSet == null) {
|
||||
if (!data.removeIf(predicate)) {
|
||||
@ -606,17 +600,17 @@ public abstract class PermissionHolder {
|
||||
getPlugin().getUserManager().giveDefaultIfNeeded((User) this, false);
|
||||
}
|
||||
|
||||
invalidateCache();
|
||||
|
||||
ImmutableCollection<? extends Node> after = data.immutable().values();
|
||||
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
|
||||
this.plugin.getEventDispatcher().dispatchNodeClear(this, dataType, before, after);
|
||||
|
||||
invalidateCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean clearNodes(DataType dataType, ContextSet contextSet, boolean giveDefault) {
|
||||
NodeMap data = getData(dataType);
|
||||
ImmutableCollection<? extends Node> before = data.immutable().values();
|
||||
ImmutableSet<Node> before = getData(dataType).asImmutableSet();
|
||||
|
||||
if (contextSet == null) {
|
||||
data.clear();
|
||||
@ -628,15 +622,11 @@ public abstract class PermissionHolder {
|
||||
getPlugin().getUserManager().giveDefaultIfNeeded((User) this, false);
|
||||
}
|
||||
|
||||
ImmutableSet<Node> after = getData(dataType).asImmutableSet();
|
||||
this.plugin.getEventDispatcher().dispatchNodeClear(this, dataType, before, after);
|
||||
|
||||
invalidateCache();
|
||||
|
||||
ImmutableCollection<? extends Node> after = data.immutable().values();
|
||||
|
||||
if (before.size() == after.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.plugin.getEventDispatcher().dispatchNodeClear(this, dataType, before, after);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@ public final class Track {
|
||||
}
|
||||
|
||||
// find all groups that are inherited by the user in the exact contexts given and applicable to this track
|
||||
List<InheritanceNode> nodes = user.normalData().immutableInheritance().get(context.immutableCopy()).stream()
|
||||
List<InheritanceNode> nodes = user.normalData().inheritanceNodesSetInContext(context).stream()
|
||||
.filter(Node::getValue)
|
||||
.filter(node -> containsGroup(node.getGroupName()))
|
||||
.distinct()
|
||||
@ -340,7 +340,7 @@ public final class Track {
|
||||
}
|
||||
|
||||
// find all groups that are inherited by the user in the exact contexts given and applicable to this track
|
||||
List<InheritanceNode> nodes = user.normalData().immutableInheritance().get(context.immutableCopy()).stream()
|
||||
List<InheritanceNode> nodes = user.normalData().inheritanceNodesSetInContext(context).stream()
|
||||
.filter(Node::getValue)
|
||||
.filter(node -> containsGroup(node.getGroupName()))
|
||||
.distinct()
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.model.manager.user;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.context.contextset.ImmutableContextSetImpl;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
@ -40,7 +38,9 @@ import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.types.InheritanceNode;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
@ -82,12 +82,14 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
|
||||
public boolean giveDefaultIfNeeded(User user, boolean save) {
|
||||
boolean work = false;
|
||||
|
||||
Collection<InheritanceNode> globalGroups = user.normalData().inheritanceNodesSetInContext(ImmutableContextSetImpl.EMPTY);
|
||||
|
||||
// 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.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)) {
|
||||
for (InheritanceNode node : globalGroups) {
|
||||
if (node.getGroupName().equalsIgnoreCase(primaryGroup)) {
|
||||
memberOfPrimaryGroup = true;
|
||||
break;
|
||||
@ -96,7 +98,7 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
|
||||
|
||||
// need to find a new primary group for the user.
|
||||
if (!memberOfPrimaryGroup) {
|
||||
String group = user.normalData().immutableInheritance().get(ImmutableContextSetImpl.EMPTY).stream()
|
||||
String group = globalGroups.stream()
|
||||
.findFirst()
|
||||
.map(InheritanceNode::getGroupName)
|
||||
.orElse(null);
|
||||
@ -112,7 +114,7 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
|
||||
// check that all users are member of at least one group
|
||||
boolean hasGroup = false;
|
||||
if (user.getPrimaryGroup().getStoredValue().isPresent()) {
|
||||
hasGroup = !user.normalData().immutableInheritance().get(ImmutableContextSetImpl.EMPTY).isEmpty();
|
||||
hasGroup = !globalGroups.isEmpty();
|
||||
}
|
||||
|
||||
if (!hasGroup) {
|
||||
@ -163,7 +165,11 @@ public abstract class AbstractUserManager<T extends User> extends AbstractManage
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldSave(User user) {
|
||||
ImmutableCollection<Node> nodes = user.normalData().immutable().values();
|
||||
if (user.normalData().size() != 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<Node> nodes = user.normalData().asList();
|
||||
if (nodes.size() != 1) {
|
||||
return true;
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
|
||||
data.getNode("name").setValue(user.getUsername().orElse("null"));
|
||||
data.getNode(this.loader instanceof JsonLoader ? "primaryGroup" : "primary-group").setValue(user.getPrimaryGroup().getStoredValue().orElse(GroupManager.DEFAULT_GROUP_NAME));
|
||||
|
||||
writeNodes(data, user.normalData().immutable().values());
|
||||
writeNodes(data, user.normalData().asList());
|
||||
saveFile(StorageLocation.USER, user.getUniqueId().toString(), data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -270,7 +270,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
|
||||
data.getNode("name").setValue(group.getName());
|
||||
}
|
||||
|
||||
writeNodes(data, group.normalData().immutable().values());
|
||||
writeNodes(data, group.normalData().asList());
|
||||
saveFile(StorageLocation.GROUP, name, data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -321,7 +321,7 @@ public abstract class AbstractConfigurateStorage implements StorageImplementatio
|
||||
data.getNode("name").setValue(group.getName());
|
||||
}
|
||||
|
||||
writeNodes(data, group.normalData().immutable().values());
|
||||
writeNodes(data, group.normalData().asList());
|
||||
saveFile(StorageLocation.GROUP, group.getName(), data);
|
||||
} catch (Exception e) {
|
||||
throw reportException(group.getName(), e);
|
||||
|
@ -650,7 +650,7 @@ public class MongoStorage implements StorageImplementation {
|
||||
}
|
||||
|
||||
private static Document userToDoc(User user) {
|
||||
List<Document> nodes = user.normalData().immutable().values().stream()
|
||||
List<Document> nodes = user.normalData().asList().stream()
|
||||
.map(MongoStorage::nodeToDoc)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
@ -673,7 +673,7 @@ public class MongoStorage implements StorageImplementation {
|
||||
}
|
||||
|
||||
private static Document groupToDoc(Group group) {
|
||||
List<Document> nodes = group.normalData().immutable().values().stream()
|
||||
List<Document> nodes = group.normalData().asList().stream()
|
||||
.map(MongoStorage::nodeToDoc)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
@ -331,7 +331,7 @@ public class SqlStorage implements StorageImplementation {
|
||||
remote = selectUserPermissions(new HashSet<>(), c, user.getUniqueId());
|
||||
}
|
||||
|
||||
Set<SqlNode> local = user.normalData().immutable().values().stream().map(SqlNode::fromNode).collect(Collectors.toSet());
|
||||
Set<SqlNode> local = user.normalData().asList().stream().map(SqlNode::fromNode).collect(Collectors.toSet());
|
||||
Set<SqlNode> missingFromRemote = getMissingFromRemote(local, remote);
|
||||
Set<SqlNode> missingFromLocal = getMissingFromLocal(local, remote);
|
||||
|
||||
@ -463,7 +463,7 @@ public class SqlStorage implements StorageImplementation {
|
||||
public void saveGroup(Group group) throws SQLException {
|
||||
group.getIoLock().lock();
|
||||
try {
|
||||
if (group.normalData().immutable().isEmpty()) {
|
||||
if (group.normalData().isEmpty()) {
|
||||
try (Connection c = this.connectionFactory.getConnection()) {
|
||||
deleteGroupPermissions(c, group.getName());
|
||||
}
|
||||
@ -475,7 +475,7 @@ public class SqlStorage implements StorageImplementation {
|
||||
remote = selectGroupPermissions(new HashSet<>(), c, group.getName());
|
||||
}
|
||||
|
||||
Set<SqlNode> local = group.normalData().immutable().values().stream().map(SqlNode::fromNode).collect(Collectors.toSet());
|
||||
Set<SqlNode> local = group.normalData().asList().stream().map(SqlNode::fromNode).collect(Collectors.toSet());
|
||||
Set<SqlNode> missingFromRemote = getMissingFromRemote(local, remote);
|
||||
Set<SqlNode> missingFromLocal = getMissingFromLocal(local, remote);
|
||||
|
||||
|
@ -73,7 +73,7 @@ public final class WebEditor {
|
||||
.add("type", holder.getType().toString())
|
||||
.add("id", holder.getObjectName())
|
||||
.add("displayName", holder.getPlainDisplayName())
|
||||
.add("nodes", NodeJsonSerializer.serializeNodes(holder.normalData().immutable().values()));
|
||||
.add("nodes", NodeJsonSerializer.serializeNodes(holder.normalData().asList()));
|
||||
}
|
||||
|
||||
private static JObject writeData(Track track) {
|
||||
|
@ -98,7 +98,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
|
||||
@Override
|
||||
public ImmutableMap<ImmutableContextSet, ImmutableMap<String, Boolean>> getAllPermissions() {
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableMap<String, Boolean>> permissions = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, ? extends Collection<? extends Node>> entry : this.holder.getData(this.type).immutable().asMap().entrySet()) {
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> entry : this.holder.getData(this.type).asMap().entrySet()) {
|
||||
ImmutableMap.Builder<String, Boolean> builder = ImmutableMap.builder();
|
||||
for (Node n : entry.getValue()) {
|
||||
builder.put(n.getKey(), n.getValue());
|
||||
@ -111,7 +111,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
|
||||
@Override
|
||||
public ImmutableMap<String, Boolean> getPermissions(ImmutableContextSet contexts) {
|
||||
ImmutableMap.Builder<String, Boolean> builder = ImmutableMap.builder();
|
||||
for (Node n : this.holder.getData(this.type).immutable().get(contexts)) {
|
||||
for (Node n : this.holder.getData(this.type).nodesSetInContext(contexts)) {
|
||||
builder.put(n.getKey(), n.getValue());
|
||||
}
|
||||
return builder.build();
|
||||
@ -159,7 +159,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
|
||||
@Override
|
||||
public ImmutableMap<ImmutableContextSet, ImmutableList<LPSubjectReference>> getAllParents() {
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableList<LPSubjectReference>> parents = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, ? extends Collection<? extends InheritanceNode>> entry : this.holder.getData(this.type).immutableInheritance().asMap().entrySet()) {
|
||||
for (Map.Entry<ImmutableContextSet, Collection<InheritanceNode>> entry : this.holder.getData(this.type).inheritanceAsMap().entrySet()) {
|
||||
ImmutableList.Builder<LPSubjectReference> builder = ImmutableList.builder();
|
||||
for (InheritanceNode n : entry.getValue()) {
|
||||
builder.add(this.service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference());
|
||||
@ -172,7 +172,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
|
||||
@Override
|
||||
public ImmutableList<LPSubjectReference> getParents(ImmutableContextSet contexts) {
|
||||
ImmutableList.Builder<LPSubjectReference> builder = ImmutableList.builder();
|
||||
for (InheritanceNode n : this.holder.getData(this.type).immutableInheritance().get(contexts)) {
|
||||
for (InheritanceNode n : this.holder.getData(this.type).inheritanceNodesSetInContext(contexts)) {
|
||||
builder.add(this.service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference());
|
||||
}
|
||||
return builder.build();
|
||||
@ -241,7 +241,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
|
||||
@Override
|
||||
public ImmutableMap<ImmutableContextSet, ImmutableMap<String, String>> getAllOptions() {
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableMap<String, String>> options = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, ? extends Collection<? extends Node>> entry : this.holder.getData(this.type).immutable().asMap().entrySet()) {
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> entry : this.holder.getData(this.type).asMap().entrySet()) {
|
||||
options.put(entry.getKey(), nodesToOptions(entry.getValue()));
|
||||
}
|
||||
return options.build();
|
||||
@ -249,7 +249,7 @@ public class PermissionHolderSubjectData implements LPSubjectData {
|
||||
|
||||
@Override
|
||||
public ImmutableMap<String, String> getOptions(ImmutableContextSet contexts) {
|
||||
return nodesToOptions(this.holder.getData(this.type).immutable().get(contexts));
|
||||
return nodesToOptions(this.holder.getData(this.type).nodesSetInContext(contexts));
|
||||
}
|
||||
|
||||
private static ImmutableMap<String, String> nodesToOptions(Iterable<? extends Node> nodes) {
|
||||
|
Loading…
Reference in New Issue
Block a user