mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 11:38:40 +01:00
Refactor MetaAccumulator to be a little more sane
This commit is contained in:
parent
274286032a
commit
f0c0328919
@ -262,8 +262,8 @@ public class VaultChatHook extends AbstractVaultChat {
|
|||||||
|
|
||||||
// find the max inherited priority & add 10
|
// find the max inherited priority & add 10
|
||||||
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, createContextForWorldSet(world));
|
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, createContextForWorldSet(world));
|
||||||
int priority = (type == ChatMetaType.PREFIX ? metaAccumulator.getPrefixes() : metaAccumulator.getSuffixes()).keySet().stream()
|
metaAccumulator.complete();
|
||||||
.mapToInt(e -> e).max().orElse(0) + 10;
|
int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 10;
|
||||||
|
|
||||||
Node.Builder chatMetaNode = NodeFactory.buildChatMetaNode(type, priority, value);
|
Node.Builder chatMetaNode = NodeFactory.buildChatMetaNode(type, priority, value);
|
||||||
chatMetaNode.setServer(this.permissionHook.getVaultServer());
|
chatMetaNode.setServer(this.permissionHook.getVaultServer());
|
||||||
|
@ -44,12 +44,14 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.SortedMap;
|
import java.util.SortedMap;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds temporary mutable meta whilst this object is passed up the
|
* Holds temporary mutable meta whilst this object is passed up the
|
||||||
* inheritance tree to accumulate meta from parents
|
* inheritance tree to accumulate meta from parents
|
||||||
*/
|
*/
|
||||||
public class MetaAccumulator {
|
public class MetaAccumulator {
|
||||||
|
|
||||||
public static MetaAccumulator makeFromConfig(LuckPermsPlugin plugin) {
|
public static MetaAccumulator makeFromConfig(LuckPermsPlugin plugin) {
|
||||||
return new MetaAccumulator(
|
return new MetaAccumulator(
|
||||||
new SimpleMetaStack(plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS), ChatMetaType.PREFIX),
|
new SimpleMetaStack(plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS), ChatMetaType.PREFIX),
|
||||||
@ -57,6 +59,18 @@ public class MetaAccumulator {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the current state of a {@link MetaAccumulator}.
|
||||||
|
*/
|
||||||
|
private enum State {
|
||||||
|
/** Marks that the accumulator is still gaining (accumulating) new data. */
|
||||||
|
ACCUMULATING,
|
||||||
|
/** Marks that the process of gaining (accumulating) new data is complete. */
|
||||||
|
COMPLETE
|
||||||
|
}
|
||||||
|
|
||||||
|
private final AtomicReference<State> state = new AtomicReference<>(State.ACCUMULATING);
|
||||||
|
|
||||||
private final ListMultimap<String, String> meta;
|
private final ListMultimap<String, String> meta;
|
||||||
private final SortedMap<Integer, String> prefixes;
|
private final SortedMap<Integer, String> prefixes;
|
||||||
private final SortedMap<Integer, String> suffixes;
|
private final SortedMap<Integer, String> suffixes;
|
||||||
@ -75,7 +89,34 @@ public class MetaAccumulator {
|
|||||||
this.suffixStack = suffixStack;
|
this.suffixStack = suffixStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ensureState(State state) {
|
||||||
|
if (this.state.get() != state) {
|
||||||
|
throw new IllegalStateException("State must be " + state + ", but is actually " + this.state.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Completes" the accumulator, preventing any further changes.
|
||||||
|
*
|
||||||
|
* Also performs some final processing on the accumulators state, before
|
||||||
|
* data is read.
|
||||||
|
*/
|
||||||
|
public void complete() {
|
||||||
|
if (!this.state.compareAndSet(State.ACCUMULATING, State.COMPLETE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform final changes
|
||||||
|
if (!this.meta.containsKey(NodeTypes.WEIGHT_KEY) && this.weight != 0) {
|
||||||
|
this.meta.put(NodeTypes.WEIGHT_KEY, String.valueOf(this.weight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// accumulate methods
|
||||||
|
|
||||||
public void accumulateNode(LocalizedNode n) {
|
public void accumulateNode(LocalizedNode n) {
|
||||||
|
ensureState(State.ACCUMULATING);
|
||||||
|
|
||||||
n.getTypeData(MetaType.KEY).ifPresent(metaType ->
|
n.getTypeData(MetaType.KEY).ifPresent(metaType ->
|
||||||
this.meta.put(metaType.getKey(), metaType.getValue())
|
this.meta.put(metaType.getKey(), metaType.getValue())
|
||||||
);
|
);
|
||||||
@ -92,60 +133,60 @@ public class MetaAccumulator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void accumulateMeta(String key, String value) {
|
public void accumulateMeta(String key, String value) {
|
||||||
|
ensureState(State.ACCUMULATING);
|
||||||
this.meta.put(key, value);
|
this.meta.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void accumulateWeight(int weight) {
|
public void accumulateWeight(int weight) {
|
||||||
|
ensureState(State.ACCUMULATING);
|
||||||
this.weight = Math.max(this.weight, weight);
|
this.weight = Math.max(this.weight, weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can assume that if this method is being called, this holder is effectively finalized.
|
// read methods
|
||||||
// (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(NodeTypes.WEIGHT_KEY) && this.weight != 0) {
|
|
||||||
this.meta.put(NodeTypes.WEIGHT_KEY, String.valueOf(this.weight));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public ListMultimap<String, String> getMeta() {
|
||||||
|
ensureState(State.COMPLETE);
|
||||||
return this.meta;
|
return this.meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Integer, String> getChatMeta(ChatMetaType type) {
|
public Map<Integer, String> getChatMeta(ChatMetaType type) {
|
||||||
|
ensureState(State.COMPLETE);
|
||||||
return type == ChatMetaType.PREFIX ? this.prefixes : this.suffixes;
|
return type == ChatMetaType.PREFIX ? this.prefixes : this.suffixes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetaStack getStack(ChatMetaType type) {
|
|
||||||
return type == ChatMetaType.PREFIX ? this.prefixStack : this.suffixStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SortedMap<Integer, String> getPrefixes() {
|
public SortedMap<Integer, String> getPrefixes() {
|
||||||
|
ensureState(State.COMPLETE);
|
||||||
return this.prefixes;
|
return this.prefixes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SortedMap<Integer, String> getSuffixes() {
|
public SortedMap<Integer, String> getSuffixes() {
|
||||||
|
ensureState(State.COMPLETE);
|
||||||
return this.suffixes;
|
return this.suffixes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWeight() {
|
public int getWeight() {
|
||||||
|
ensureState(State.COMPLETE);
|
||||||
return this.weight;
|
return this.weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetaStack getPrefixStack() {
|
public MetaStack getPrefixStack() {
|
||||||
|
ensureState(State.COMPLETE);
|
||||||
return this.prefixStack;
|
return this.prefixStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetaStack getSuffixStack() {
|
public MetaStack getSuffixStack() {
|
||||||
|
ensureState(State.COMPLETE);
|
||||||
return this.suffixStack;
|
return this.suffixStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "MetaAccumulator(" +
|
return "MetaAccumulator(" +
|
||||||
"meta=" + this.getMeta() + ", " +
|
"meta=" + this.meta + ", " +
|
||||||
"prefixes=" + this.getPrefixes() + ", " +
|
"prefixes=" + this.prefixes + ", " +
|
||||||
"suffixes=" + this.getSuffixes() + ", " +
|
"suffixes=" + this.suffixes + ", " +
|
||||||
"weight=" + this.getWeight() + ", " +
|
"weight=" + this.weight + ", " +
|
||||||
"prefixStack=" + this.getPrefixStack() + ", " +
|
"prefixStack=" + this.prefixStack + ", " +
|
||||||
"suffixStack=" + this.getSuffixStack() + ")";
|
"suffixStack=" + this.suffixStack + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,6 @@ import me.lucko.luckperms.common.metastacking.MetaStack;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.SortedMap;
|
import java.util.SortedMap;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
@ -48,7 +46,6 @@ import javax.annotation.Nonnull;
|
|||||||
* Holds cached meta for a given context
|
* Holds cached meta for a given context
|
||||||
*/
|
*/
|
||||||
public class MetaCache implements MetaData {
|
public class MetaCache implements MetaData {
|
||||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The contexts this container is holding data for
|
* The contexts this container is holding data for
|
||||||
@ -67,51 +64,40 @@ public class MetaCache implements MetaData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadMeta(MetaAccumulator meta) {
|
public void loadMeta(MetaAccumulator meta) {
|
||||||
this.lock.writeLock().lock();
|
meta.complete();
|
||||||
try {
|
|
||||||
this.metaMultimap = ImmutableListMultimap.copyOf(meta.getMeta());
|
|
||||||
|
|
||||||
//noinspection unchecked
|
this.metaMultimap = ImmutableListMultimap.copyOf(meta.getMeta());
|
||||||
Map<String, List<String>> metaMap = (Map) this.metaMultimap.asMap();
|
|
||||||
ImmutableMap.Builder<String, String> metaMapBuilder = ImmutableMap.builder();
|
|
||||||
|
|
||||||
for (Map.Entry<String, List<String>> e : metaMap.entrySet()) {
|
//noinspection unchecked
|
||||||
if (e.getValue().isEmpty()) {
|
Map<String, List<String>> metaMap = (Map) this.metaMultimap.asMap();
|
||||||
continue;
|
ImmutableMap.Builder<String, String> metaMapBuilder = ImmutableMap.builder();
|
||||||
}
|
|
||||||
|
|
||||||
// take the value which was accumulated first
|
for (Map.Entry<String, List<String>> e : metaMap.entrySet()) {
|
||||||
metaMapBuilder.put(e.getKey(), e.getValue().get(0));
|
if (e.getValue().isEmpty()) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
this.meta = metaMapBuilder.build();
|
|
||||||
|
|
||||||
this.prefixes = ImmutableSortedMap.copyOfSorted(meta.getPrefixes());
|
// take the value which was accumulated first
|
||||||
this.suffixes = ImmutableSortedMap.copyOfSorted(meta.getSuffixes());
|
metaMapBuilder.put(e.getKey(), e.getValue().get(0));
|
||||||
this.prefixStack = meta.getPrefixStack();
|
|
||||||
this.suffixStack = meta.getSuffixStack();
|
|
||||||
} finally {
|
|
||||||
this.lock.writeLock().unlock();
|
|
||||||
}
|
}
|
||||||
|
this.meta = metaMapBuilder.build();
|
||||||
|
|
||||||
|
this.prefixes = ImmutableSortedMap.copyOfSorted(meta.getPrefixes());
|
||||||
|
this.suffixes = ImmutableSortedMap.copyOfSorted(meta.getSuffixes());
|
||||||
|
this.prefixStack = meta.getPrefixStack();
|
||||||
|
this.suffixStack = meta.getSuffixStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPrefix() {
|
public String getPrefix() {
|
||||||
this.lock.readLock().lock();
|
MetaStack prefixStack = this.prefixStack;
|
||||||
try {
|
return prefixStack == null ? null : prefixStack.toFormattedString();
|
||||||
return this.prefixStack == null ? null : this.prefixStack.toFormattedString();
|
|
||||||
} finally {
|
|
||||||
this.lock.readLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSuffix() {
|
public String getSuffix() {
|
||||||
this.lock.readLock().lock();
|
MetaStack suffixStack = this.suffixStack;
|
||||||
try {
|
return suffixStack == null ? null : suffixStack.toFormattedString();
|
||||||
return this.suffixStack == null ? null : this.suffixStack.toFormattedString();
|
|
||||||
} finally {
|
|
||||||
this.lock.readLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -107,6 +107,7 @@ public class MetaSetChatMeta extends SharedSubCommand {
|
|||||||
// determine the priority to set at
|
// determine the priority to set at
|
||||||
if (priority == Integer.MIN_VALUE) {
|
if (priority == Integer.MIN_VALUE) {
|
||||||
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, Contexts.of(context, Contexts.global().getSettings()));
|
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, Contexts.of(context, Contexts.global().getSettings()));
|
||||||
|
metaAccumulator.complete();
|
||||||
priority = metaAccumulator.getChatMeta(this.type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 1;
|
priority = metaAccumulator.getChatMeta(this.type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 1;
|
||||||
|
|
||||||
if (holder instanceof Group) {
|
if (holder instanceof Group) {
|
||||||
|
@ -118,6 +118,7 @@ public class MetaSetTempChatMeta extends SharedSubCommand {
|
|||||||
// determine the priority to set at
|
// determine the priority to set at
|
||||||
if (priority == Integer.MIN_VALUE) {
|
if (priority == Integer.MIN_VALUE) {
|
||||||
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, Contexts.of(context, Contexts.global().getSettings()));
|
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, Contexts.of(context, Contexts.global().getSettings()));
|
||||||
|
metaAccumulator.complete();
|
||||||
priority = metaAccumulator.getChatMeta(this.type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 1;
|
priority = metaAccumulator.getChatMeta(this.type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 1;
|
||||||
|
|
||||||
if (holder instanceof Group) {
|
if (holder instanceof Group) {
|
||||||
|
@ -362,6 +362,7 @@ public class HolderSubjectData implements LPSubjectData {
|
|||||||
));
|
));
|
||||||
|
|
||||||
MetaAccumulator metaAccumulator = this.holder.accumulateMeta(null, Contexts.of(contexts, Contexts.global().getSettings()));
|
MetaAccumulator metaAccumulator = this.holder.accumulateMeta(null, Contexts.of(contexts, Contexts.global().getSettings()));
|
||||||
|
metaAccumulator.complete();
|
||||||
int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0);
|
int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0);
|
||||||
priority += 10;
|
priority += 10;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user