mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-12-28 20:17:55 +01:00
Refactor metastacks & primary group calculation
This commit is contained in:
parent
41b0e10709
commit
f45c0caa45
@ -33,8 +33,8 @@ import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
|
||||
import me.lucko.luckperms.api.metastacking.MetaStackElement;
|
||||
import me.lucko.luckperms.api.metastacking.MetaStackFactory;
|
||||
import me.lucko.luckperms.common.metastacking.definition.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.metastacking.definition.StandardStackElements;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.metastacking.StandardStackElements;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -36,8 +36,8 @@ import com.google.common.collect.ListMultimap;
|
||||
import me.lucko.luckperms.api.ChatMetaType;
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.metastacking.GenericMetaStack;
|
||||
import me.lucko.luckperms.common.metastacking.MetaStack;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStack;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.Comparator;
|
||||
@ -46,15 +46,16 @@ import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Holds temporary mutable meta whilst this object is passed up the inheritance tree to accumulate meta from parents
|
||||
* Holds temporary mutable meta whilst this object is passed up the
|
||||
* inheritance tree to accumulate meta from parents
|
||||
*/
|
||||
@Getter
|
||||
@ToString
|
||||
public class MetaAccumulator {
|
||||
public static MetaAccumulator makeFromConfig(LuckPermsPlugin plugin) {
|
||||
return new MetaAccumulator(
|
||||
new GenericMetaStack(plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS), ChatMetaType.PREFIX),
|
||||
new GenericMetaStack(plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS), ChatMetaType.SUFFIX)
|
||||
new SimpleMetaStack(plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS), ChatMetaType.PREFIX),
|
||||
new SimpleMetaStack(plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS), ChatMetaType.SUFFIX)
|
||||
);
|
||||
}
|
||||
|
||||
@ -104,7 +105,8 @@ public class MetaAccumulator {
|
||||
this.weight = Math.max(this.weight, weight);
|
||||
}
|
||||
|
||||
// We can assume that if this method is being called, this holder is effectively finalized. (it's not going to accumulate more nodes)
|
||||
// We can assume that if this method is being called, this holder is effectively finalized.
|
||||
// (it's not going to accumulate more nodes)
|
||||
// Therefore, it should be ok to set the weight meta key, if not already present.
|
||||
public ListMultimap<String, String> getMeta() {
|
||||
if (!this.meta.containsKey("weight") && this.weight != 0) {
|
||||
|
@ -41,7 +41,7 @@ import me.lucko.luckperms.api.caching.PermissionData;
|
||||
import me.lucko.luckperms.api.caching.UserData;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.contexts.ExtractedContexts;
|
||||
import me.lucko.luckperms.common.metastacking.GenericMetaStack;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStack;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
@ -219,8 +219,8 @@ public class UserCache implements UserData {
|
||||
|
||||
private static MetaAccumulator newAccumulator(MetaContexts contexts) {
|
||||
return new MetaAccumulator(
|
||||
new GenericMetaStack(contexts.getPrefixStackDefinition(), ChatMetaType.PREFIX),
|
||||
new GenericMetaStack(contexts.getSuffixStackDefinition(), ChatMetaType.SUFFIX)
|
||||
new SimpleMetaStack(contexts.getPrefixStackDefinition(), ChatMetaType.PREFIX),
|
||||
new SimpleMetaStack(contexts.getSuffixStackDefinition(), ChatMetaType.SUFFIX)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,8 @@ import me.lucko.luckperms.common.config.keys.MapKey;
|
||||
import me.lucko.luckperms.common.config.keys.StaticKey;
|
||||
import me.lucko.luckperms.common.config.keys.StringKey;
|
||||
import me.lucko.luckperms.common.defaults.Rule;
|
||||
import me.lucko.luckperms.common.metastacking.definition.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.metastacking.definition.StandardStackElements;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.metastacking.StandardStackElements;
|
||||
import me.lucko.luckperms.common.model.TemporaryModifier;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.primarygroup.AllParentsByWeightHolder;
|
||||
|
@ -29,14 +29,42 @@ import me.lucko.luckperms.api.ChatMetaType;
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
|
||||
|
||||
/**
|
||||
* A live stack of {@link MetaStackEntry} instances, formed from a
|
||||
* {@link MetaStackDefinition}.
|
||||
*
|
||||
* This class is used to construct a formatted string, by accumulating
|
||||
* nodes to each element.
|
||||
*/
|
||||
public interface MetaStack {
|
||||
|
||||
/**
|
||||
* Gets the definition this stack is based upon
|
||||
*
|
||||
* @return the definition of the stack
|
||||
*/
|
||||
MetaStackDefinition getDefinition();
|
||||
|
||||
/**
|
||||
* Gets the target of this stack
|
||||
*
|
||||
* @return the stack target
|
||||
*/
|
||||
ChatMetaType getTargetType();
|
||||
|
||||
/**
|
||||
* Returns a formatted string, as defined by the {@link MetaStackDefinition},
|
||||
* using the accumulated elements in the stack.
|
||||
*
|
||||
* @return the string output
|
||||
*/
|
||||
String toFormattedString();
|
||||
|
||||
/**
|
||||
* Tries to accumulate the given node to all elements in the stack.
|
||||
*
|
||||
* @param node the node to accumulate
|
||||
*/
|
||||
void accumulateToAll(LocalizedNode node);
|
||||
|
||||
}
|
||||
|
@ -31,14 +31,39 @@ import me.lucko.luckperms.api.metastacking.MetaStackElement;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Represents a specific entry in a {@link MetaStack}.
|
||||
* An entry is basically a live/mutable version of a {@link MetaStackElement}.
|
||||
*/
|
||||
public interface MetaStackEntry {
|
||||
|
||||
/**
|
||||
* Gets the stack this entry belongs to.
|
||||
*
|
||||
* @return the parent stack
|
||||
*/
|
||||
MetaStack getParentStack();
|
||||
|
||||
/**
|
||||
* Gets the element this entry was formed form
|
||||
*
|
||||
* @return the forming element
|
||||
*/
|
||||
MetaStackElement getElement();
|
||||
|
||||
Optional<Map.Entry<Integer, String>> getEntry();
|
||||
/**
|
||||
* Gets the value currently held by this entry.
|
||||
*
|
||||
* @return the entry
|
||||
*/
|
||||
Optional<Map.Entry<Integer, String>> getCurrentValue();
|
||||
|
||||
/**
|
||||
* Accumulates a node to this entry
|
||||
*
|
||||
* @param node the node to accumulate
|
||||
* @return if the node was accepted
|
||||
*/
|
||||
boolean accumulateNode(LocalizedNode node);
|
||||
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
public class GenericMetaStack implements MetaStack {
|
||||
public final class SimpleMetaStack implements MetaStack {
|
||||
|
||||
private final MetaStackDefinition definition;
|
||||
private final ChatMetaType targetType;
|
||||
@ -45,7 +45,7 @@ public class GenericMetaStack implements MetaStack {
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final List<MetaStackEntry> entries;
|
||||
|
||||
public GenericMetaStack(MetaStackDefinition definition, ChatMetaType targetType) {
|
||||
public SimpleMetaStack(MetaStackDefinition definition, ChatMetaType targetType) {
|
||||
this.definition = definition;
|
||||
this.targetType = targetType;
|
||||
this.entries = definition.getElements().stream()
|
||||
@ -56,7 +56,7 @@ public class GenericMetaStack implements MetaStack {
|
||||
@Override
|
||||
public String toFormattedString() {
|
||||
List<MetaStackEntry> ret = new ArrayList<>(entries);
|
||||
ret.removeIf(m -> !m.getEntry().isPresent());
|
||||
ret.removeIf(m -> !m.getCurrentValue().isPresent());
|
||||
|
||||
if (ret.isEmpty()) {
|
||||
return null;
|
||||
@ -70,7 +70,7 @@ public class GenericMetaStack implements MetaStack {
|
||||
}
|
||||
|
||||
MetaStackEntry e = ret.get(i);
|
||||
sb.append(e.getEntry().get().getValue());
|
||||
sb.append(e.getCurrentValue().get().getValue());
|
||||
}
|
||||
sb.append(definition.getEndSpacer());
|
||||
|
@ -23,7 +23,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking.definition;
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
@ -26,8 +26,10 @@
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.api.ChatMetaType;
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
@ -37,8 +39,10 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@EqualsAndHashCode(of = {"element", "type", "current"})
|
||||
@RequiredArgsConstructor
|
||||
class SimpleMetaStackEntry implements MetaStackEntry {
|
||||
final class SimpleMetaStackEntry implements MetaStackEntry {
|
||||
|
||||
private final MetaStack parentStack;
|
||||
private final MetaStackElement element;
|
||||
@ -48,7 +52,7 @@ class SimpleMetaStackEntry implements MetaStackEntry {
|
||||
private Map.Entry<Integer, String> current = null;
|
||||
|
||||
@Override
|
||||
public Optional<Map.Entry<Integer, String>> getEntry() {
|
||||
public Optional<Map.Entry<Integer, String>> getCurrentValue() {
|
||||
return Optional.ofNullable(current);
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking.definition;
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -42,6 +42,9 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Contains the standard {@link MetaStackElement}s provided by LuckPerms.
|
||||
*/
|
||||
@UtilityClass
|
||||
public class StandardStackElements {
|
||||
|
@ -515,7 +515,7 @@ public abstract class PermissionHolder {
|
||||
* @param context context to decide if groups should be applied
|
||||
* @return a set of nodes
|
||||
*/
|
||||
protected List<LocalizedNode> resolveInheritances(List<LocalizedNode> accumulator, Set<String> excludedGroups, ExtractedContexts context) {
|
||||
public List<LocalizedNode> resolveInheritances(List<LocalizedNode> accumulator, Set<String> excludedGroups, ExtractedContexts context) {
|
||||
if (accumulator == null) {
|
||||
accumulator = new ArrayList<>();
|
||||
}
|
||||
@ -595,7 +595,7 @@ public abstract class PermissionHolder {
|
||||
* @param excludedGroups a list of groups to exclude
|
||||
* @return a set of nodes
|
||||
*/
|
||||
protected List<LocalizedNode> resolveInheritances(List<LocalizedNode> accumulator, Set<String> excludedGroups) {
|
||||
public List<LocalizedNode> resolveInheritances(List<LocalizedNode> accumulator, Set<String> excludedGroups) {
|
||||
if (accumulator == null) {
|
||||
accumulator = new ArrayList<>();
|
||||
}
|
||||
|
@ -28,15 +28,16 @@ package me.lucko.luckperms.common.primarygroup;
|
||||
import lombok.NonNull;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.contexts.ExtractedContexts;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class AllParentsByWeightHolder extends StoredHolder {
|
||||
|
||||
@ -67,18 +68,51 @@ public class AllParentsByWeightHolder extends StoredHolder {
|
||||
);
|
||||
}
|
||||
|
||||
cachedValue = user.resolveInheritancesAlmostEqual(ExtractedContexts.generate(contexts)).stream()
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(Node::getValue)
|
||||
.map(n -> Optional.ofNullable(user.getPlugin().getGroupManager().getIfLoaded(n.getGroupName())))
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.sorted(Collections.reverseOrder(Comparator.comparingInt(o -> o.getWeight().orElse(0))))
|
||||
.findFirst()
|
||||
.map(Group::getName)
|
||||
.orElse(null);
|
||||
// hack to get a list of groups the holder is inheriting from
|
||||
Set<String> groupNames = new HashSet<>();
|
||||
user.resolveInheritances(new NoopList<>(), groupNames, ExtractedContexts.generate(contexts));
|
||||
|
||||
List<Group> groups = new ArrayList<>();
|
||||
for (String groupName : groupNames) {
|
||||
Group group = user.getPlugin().getGroupManager().getIfLoaded(groupName);
|
||||
if (group != null) {
|
||||
groups.add(group);
|
||||
}
|
||||
}
|
||||
|
||||
Group bestGroup = null;
|
||||
|
||||
if (!groups.isEmpty()) {
|
||||
int best = 0;
|
||||
for (Group g : groups) {
|
||||
int weight = g.getWeight().orElse(0);
|
||||
if (bestGroup == null || g.getWeight().orElse(0) > best) {
|
||||
bestGroup = g;
|
||||
best = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cachedValue = bestGroup == null ? null : bestGroup.getName();
|
||||
useCached = true;
|
||||
return cachedValue;
|
||||
}
|
||||
|
||||
private static final class NoopList<E> extends AbstractList<E> implements List<E> {
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,9 +33,8 @@ import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ParentsByWeightHolder extends StoredHolder {
|
||||
|
||||
@ -55,17 +54,33 @@ public class ParentsByWeightHolder extends StoredHolder {
|
||||
|
||||
Contexts contexts = user.getPlugin().getContextForUser(user);
|
||||
ContextSet contextSet = contexts != null ? contexts.getContexts() : user.getPlugin().getContextManager().getStaticContexts();
|
||||
cachedValue = user.filterNodes(contextSet).stream()
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(Node::getValue)
|
||||
.map(n -> Optional.ofNullable(user.getPlugin().getGroupManager().getIfLoaded(n.getGroupName())))
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.sorted(Collections.reverseOrder(Comparator.comparingInt(o -> o.getWeight().orElse(0))))
|
||||
.findFirst()
|
||||
.map(Group::getName)
|
||||
.orElse(null);
|
||||
|
||||
List<Group> groups = new ArrayList<>();
|
||||
for (Node node : user.filterNodes(contextSet)) {
|
||||
if (!node.getValue() || !node.isGroupNode()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Group group = user.getPlugin().getGroupManager().getIfLoaded(node.getGroupName());
|
||||
if (group != null) {
|
||||
groups.add(group);
|
||||
}
|
||||
}
|
||||
|
||||
Group bestGroup = null;
|
||||
|
||||
if (!groups.isEmpty()) {
|
||||
int best = 0;
|
||||
for (Group g : groups) {
|
||||
int weight = g.getWeight().orElse(0);
|
||||
if (bestGroup == null || g.getWeight().orElse(0) > best) {
|
||||
bestGroup = g;
|
||||
best = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cachedValue = bestGroup == null ? null : bestGroup.getName();
|
||||
useCached = true;
|
||||
return cachedValue;
|
||||
}
|
||||
|
@ -25,12 +25,30 @@
|
||||
|
||||
package me.lucko.luckperms.common.primarygroup;
|
||||
|
||||
/**
|
||||
* Calculates and caches a User's "primary group"
|
||||
*/
|
||||
public interface PrimaryGroupHolder {
|
||||
|
||||
/**
|
||||
* Gets the name of the primary group, or null.
|
||||
*
|
||||
* @return the name of the primary group, or null.
|
||||
*/
|
||||
String getValue();
|
||||
|
||||
/**
|
||||
* Gets the primary group which is stored against the user's data.
|
||||
*
|
||||
* @return the stored value
|
||||
*/
|
||||
String getStoredValue();
|
||||
|
||||
/**
|
||||
* Sets the primary group which is stored against the user's data.
|
||||
*
|
||||
* @param storedValue the new stored value
|
||||
*/
|
||||
void setStoredValue(String storedValue);
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user