mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-28 05:35:26 +01:00
Refactor meta stacking to be mapped in MetaCache - towards lucko/LuckPermsPlaceholders#1
This commit is contained in:
parent
99c6fe20c2
commit
dc801464ef
@ -41,6 +41,7 @@ import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.core.NodeFactory;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.ProgressLogger;
|
||||
@ -224,7 +225,8 @@ public class MigrationBPermissions extends SubCommand<Object> {
|
||||
}
|
||||
|
||||
if (meta.getKey().equalsIgnoreCase("prefix") || meta.getKey().equalsIgnoreCase("suffix")) {
|
||||
holder.setPermission(NodeFactory.makeChatMetaNode(meta.getKey().equalsIgnoreCase("prefix"), c.getPriority(), meta.getValue()).setWorld(world.getName()).build());
|
||||
MetaType type = MetaType.valueOf(meta.getKey().toUpperCase());
|
||||
holder.setPermission(NodeFactory.makeChatMetaNode(type, c.getPriority(), meta.getValue()).setWorld(world.getName()).build());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.core.NodeFactory;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.ProgressLogger;
|
||||
@ -172,7 +173,8 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
}
|
||||
|
||||
if (key.equals("prefix") || key.equals("suffix")) {
|
||||
groups.get(groupName).add(NodeFactory.makeChatMetaNode(key.equals("prefix"), 50, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
MetaType type = MetaType.valueOf(key.toUpperCase());
|
||||
groups.get(groupName).add(NodeFactory.makeChatMetaNode(type, 50, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
} else {
|
||||
groups.get(groupName).add(NodeFactory.makeMetaNode(key, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
}
|
||||
@ -228,7 +230,8 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
}
|
||||
|
||||
if (key.equals("prefix") || key.equals("suffix")) {
|
||||
users.get(uuid).add(NodeFactory.makeChatMetaNode(key.equals("prefix"), 100, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
MetaType type = MetaType.valueOf(key.toUpperCase());
|
||||
users.get(uuid).add(NodeFactory.makeChatMetaNode(type, 100, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
} else {
|
||||
users.get(uuid).add(NodeFactory.makeMetaNode(key, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.core.model.Track;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.common.utils.ProgressLogger;
|
||||
@ -213,7 +214,8 @@ public class MigrationZPermissions extends SubCommand<Object> {
|
||||
String key = metadata.getName().toLowerCase();
|
||||
|
||||
if (key.equals("prefix") || key.equals("suffix")) {
|
||||
holder.setPermission(NodeFactory.makeChatMetaNode(key.equals("prefix"), weight, metadata.getStringValue()).build());
|
||||
MetaType type = MetaType.valueOf(key.toUpperCase());
|
||||
holder.setPermission(NodeFactory.makeChatMetaNode(type, weight, metadata.getStringValue()).build());
|
||||
} else {
|
||||
holder.setPermission(NodeFactory.makeMetaNode(key, metadata.getStringValue()).build());
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import me.lucko.luckperms.common.core.NodeFactory;
|
||||
import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.utils.ExtractedContexts;
|
||||
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
@ -83,23 +84,23 @@ public class VaultChatHook extends Chat {
|
||||
});
|
||||
}
|
||||
|
||||
private void setChatMeta(boolean prefix, PermissionHolder holder, String value, String world) {
|
||||
private void setChatMeta(MetaType type, PermissionHolder holder, String value, String world) {
|
||||
String finalWorld = perms.isIgnoreWorld() ? null : world;
|
||||
if (holder == null) return;
|
||||
if (value.equals("")) return;
|
||||
|
||||
perms.log("Setting " + (prefix ? "prefix" : "suffix") + " for " + holder.getObjectName() + " on world " + world + ", server " + perms.getServer());
|
||||
perms.log("Setting " + type.name().toLowerCase() + " for " + holder.getObjectName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
perms.getScheduler().execute(() -> {
|
||||
// remove all prefixes/suffixes directly set on the user/group
|
||||
holder.removeIf(n -> prefix ? n.isPrefix() : n.isSuffix());
|
||||
holder.removeIf(type::matches);
|
||||
|
||||
// find the max inherited priority & add 10
|
||||
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, null, ExtractedContexts.generate(perms.createContextForWorldSet(finalWorld)));
|
||||
int priority = (prefix ? metaAccumulator.getPrefixes() : metaAccumulator.getSuffixes()).keySet().stream()
|
||||
int priority = (type == MetaType.PREFIX ? metaAccumulator.getPrefixes() : metaAccumulator.getSuffixes()).keySet().stream()
|
||||
.mapToInt(e -> e).max().orElse(0) + 10;
|
||||
|
||||
Node.Builder chatMetaNode = NodeFactory.makeChatMetaNode(prefix, priority, value);
|
||||
Node.Builder chatMetaNode = NodeFactory.makeChatMetaNode(type, priority, value);
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
chatMetaNode.setServer(perms.getServer());
|
||||
}
|
||||
@ -122,14 +123,14 @@ public class VaultChatHook extends Chat {
|
||||
return ret != null ? ret : defaultValue;
|
||||
}
|
||||
|
||||
private String getUserChatMeta(boolean prefix, User user, String world) {
|
||||
private String getUserChatMeta(MetaType type, User user, String world) {
|
||||
if (user == null) return "";
|
||||
world = perms.isIgnoreWorld() ? null : world;
|
||||
|
||||
perms.log("Getting " + (prefix ? "prefix" : "suffix") + " for user " + user.getFriendlyName() + " on world " + world + ", server " + perms.getServer());
|
||||
perms.log("Getting " + type.name().toLowerCase() + " for user " + user.getFriendlyName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
MetaData data = user.getUserData().getMetaData(perms.createContextForWorldLookup(perms.getPlugin().getPlayer(user), world));
|
||||
String ret = prefix ? data.getPrefix() : data.getSuffix();
|
||||
String ret = type == MetaType.PREFIX ? data.getPrefix() : data.getSuffix();
|
||||
return ret != null ? ret : "";
|
||||
}
|
||||
|
||||
@ -153,11 +154,11 @@ public class VaultChatHook extends Chat {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private String getGroupChatMeta(boolean prefix, Group group, String world) {
|
||||
private String getGroupChatMeta(MetaType type, Group group, String world) {
|
||||
world = perms.isIgnoreWorld() ? null : world;
|
||||
if (group == null) return "";
|
||||
|
||||
perms.log("Getting " + (prefix ? "prefix" : "suffix") + " for group " + group + " on world " + world + ", server " + perms.getServer());
|
||||
perms.log("Getting " + type.name().toLowerCase() + " for group " + group + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
int priority = Integer.MIN_VALUE;
|
||||
String meta = null;
|
||||
@ -165,10 +166,10 @@ public class VaultChatHook extends Chat {
|
||||
ExtractedContexts ec = ExtractedContexts.generate(Contexts.of(perms.createContextForWorldLookup(world).getContexts(), perms.isIncludeGlobal(), true, true, true, true, false));
|
||||
for (Node n : group.getAllNodes(ec)) {
|
||||
if (!n.getValue()) continue;
|
||||
if (prefix ? !n.isPrefix() : !n.isSuffix()) continue;
|
||||
if (type.shouldIgnore(n)) continue;
|
||||
if (!n.shouldApplyWithContext(perms.createContextForWorldLookup(world).getContexts())) continue;
|
||||
|
||||
Map.Entry<Integer, String> value = prefix ? n.getPrefix() : n.getSuffix();
|
||||
Map.Entry<Integer, String> value = type.getEntry(n);
|
||||
if (value.getKey() > priority) {
|
||||
meta = value.getValue();
|
||||
priority = value.getKey();
|
||||
@ -181,49 +182,49 @@ public class VaultChatHook extends Chat {
|
||||
@Override
|
||||
public String getPlayerPrefix(String world, @NonNull String player) {
|
||||
final User user = perms.getPlugin().getUserManager().getByUsername(player);
|
||||
return getUserChatMeta(true, user, world);
|
||||
return getUserChatMeta(MetaType.PREFIX, user, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerPrefix(String world, @NonNull String player, @NonNull String prefix) {
|
||||
final User user = perms.getPlugin().getUserManager().getByUsername(player);
|
||||
setChatMeta(true, user, prefix, world);
|
||||
setChatMeta(MetaType.PREFIX, user, prefix, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerSuffix(String world, @NonNull String player) {
|
||||
final User user = perms.getPlugin().getUserManager().getByUsername(player);
|
||||
return getUserChatMeta(false, user, world);
|
||||
return getUserChatMeta(MetaType.SUFFIX, user, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerSuffix(String world, @NonNull String player, @NonNull String suffix) {
|
||||
final User user = perms.getPlugin().getUserManager().getByUsername(player);
|
||||
setChatMeta(false, user, suffix, world);
|
||||
setChatMeta(MetaType.SUFFIX, user, suffix, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupPrefix(String world, @NonNull String group) {
|
||||
final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group);
|
||||
return getGroupChatMeta(true, g, world);
|
||||
return getGroupChatMeta(MetaType.PREFIX, g, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) {
|
||||
final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group);
|
||||
setChatMeta(true, g, prefix, world);
|
||||
setChatMeta(MetaType.PREFIX, g, prefix, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupSuffix(String world, @NonNull String group) {
|
||||
final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group);
|
||||
return getGroupChatMeta(false, g, world);
|
||||
return getGroupChatMeta(MetaType.SUFFIX, g, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupSuffix(String world, @NonNull String group, @NonNull String suffix) {
|
||||
final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group);
|
||||
setChatMeta(false, g, suffix, world);
|
||||
setChatMeta(MetaType.SUFFIX, g, suffix, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -27,10 +27,14 @@ package me.lucko.luckperms.common.caching;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.caching.stacking.MetaStack;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.metastacking.MetaStack;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
@ -44,6 +48,12 @@ import java.util.TreeMap;
|
||||
@Getter
|
||||
@ToString
|
||||
public class MetaAccumulator {
|
||||
public static MetaAccumulator makeFromConfig(LuckPermsPlugin plugin) {
|
||||
return new MetaAccumulator(
|
||||
plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS).newStack(MetaType.PREFIX),
|
||||
plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS).newStack(MetaType.SUFFIX)
|
||||
);
|
||||
}
|
||||
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final Map<String, String> meta;
|
||||
@ -54,7 +64,7 @@ public class MetaAccumulator {
|
||||
private final MetaStack prefixStack;
|
||||
private final MetaStack suffixStack;
|
||||
|
||||
public MetaAccumulator(MetaStack prefixStack, MetaStack suffixStack) {
|
||||
public MetaAccumulator(@NonNull MetaStack prefixStack, @NonNull MetaStack suffixStack) {
|
||||
this.meta = new HashMap<>();
|
||||
this.prefixes = new TreeMap<>(Comparator.reverseOrder());
|
||||
this.suffixes = new TreeMap<>(Comparator.reverseOrder());
|
||||
@ -103,4 +113,12 @@ public class MetaAccumulator {
|
||||
return this.meta;
|
||||
}
|
||||
|
||||
public Map<Integer, String> getChatMeta(MetaType type) {
|
||||
return type == MetaType.PREFIX ? prefixes : suffixes;
|
||||
}
|
||||
|
||||
public MetaStack getStack(MetaType type) {
|
||||
return type == MetaType.PREFIX ? prefixStack : suffixStack;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,8 +32,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
|
||||
import me.lucko.luckperms.api.caching.MetaData;
|
||||
import me.lucko.luckperms.common.caching.stacking.MetaStack;
|
||||
import me.lucko.luckperms.common.caching.stacking.NoopMetaStack;
|
||||
import me.lucko.luckperms.common.metastacking.MetaStack;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
@ -57,10 +56,10 @@ public class MetaCache implements MetaData {
|
||||
private SortedMap<Integer, String> suffixes = ImmutableSortedMap.of();
|
||||
|
||||
@Getter
|
||||
private MetaStack prefixStack = NoopMetaStack.INSTANCE;
|
||||
private MetaStack prefixStack = null;
|
||||
|
||||
@Getter
|
||||
private MetaStack suffixStack = NoopMetaStack.INSTANCE;
|
||||
private MetaStack suffixStack = null;
|
||||
|
||||
public void loadMeta(MetaAccumulator meta) {
|
||||
lock.writeLock().lock();
|
||||
@ -79,7 +78,7 @@ public class MetaCache implements MetaData {
|
||||
public String getPrefix() {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return prefixStack.toFormattedString();
|
||||
return prefixStack == null ? null : prefixStack.toFormattedString();
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
@ -89,7 +88,7 @@ public class MetaCache implements MetaData {
|
||||
public String getSuffix() {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return suffixStack.toFormattedString();
|
||||
return suffixStack == null ? null : suffixStack.toFormattedString();
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.metastacking.definition.MetaStackDefinition;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
public final class MetaContexts {
|
||||
public static MetaContexts makeFromConfig(Contexts contexts, LuckPermsPlugin plugin) {
|
||||
return new MetaContexts(
|
||||
contexts,
|
||||
plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS),
|
||||
plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS)
|
||||
);
|
||||
}
|
||||
|
||||
private final Contexts contexts;
|
||||
private final MetaStackDefinition prefixStackDefinition;
|
||||
private final MetaStackDefinition suffixStackDefinition;
|
||||
|
||||
public MetaContexts(@NonNull Contexts contexts, @NonNull MetaStackDefinition prefixStackDefinition, @NonNull MetaStackDefinition suffixStackDefinition) {
|
||||
this.contexts = contexts;
|
||||
this.prefixStackDefinition = prefixStackDefinition;
|
||||
this.suffixStackDefinition = suffixStackDefinition;
|
||||
}
|
||||
|
||||
public MetaAccumulator newAccumulator() {
|
||||
return new MetaAccumulator(
|
||||
prefixStackDefinition.newStack(MetaType.PREFIX),
|
||||
suffixStackDefinition.newStack(MetaType.SUFFIX)
|
||||
);
|
||||
}
|
||||
}
|
@ -69,17 +69,17 @@ public class UserCache implements UserData {
|
||||
}
|
||||
});
|
||||
|
||||
private final LoadingCache<Contexts, MetaCache> meta = Caffeine.newBuilder()
|
||||
private final LoadingCache<MetaContexts, MetaCache> meta = Caffeine.newBuilder()
|
||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||
.build(new CacheLoader<Contexts, MetaCache>() {
|
||||
.build(new CacheLoader<MetaContexts, MetaCache>() {
|
||||
@Override
|
||||
public MetaCache load(Contexts contexts) {
|
||||
public MetaCache load(MetaContexts contexts) {
|
||||
return calculateMeta(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaCache reload(Contexts contexts, MetaCache oldData) {
|
||||
oldData.loadMeta(user.accumulateMeta(null, null, ExtractedContexts.generate(contexts)));
|
||||
public MetaCache reload(MetaContexts contexts, MetaCache oldData) {
|
||||
oldData.loadMeta(user.accumulateMeta(contexts.newAccumulator(), null, ExtractedContexts.generate(contexts.getContexts())));
|
||||
return oldData;
|
||||
}
|
||||
});
|
||||
@ -91,6 +91,11 @@ public class UserCache implements UserData {
|
||||
|
||||
@Override
|
||||
public MetaData getMetaData(@NonNull Contexts contexts) {
|
||||
// just create a MetaContexts instance using the values in the config
|
||||
return getMetaData(MetaContexts.makeFromConfig(contexts, user.getPlugin()));
|
||||
}
|
||||
|
||||
public MetaData getMetaData(@NonNull MetaContexts contexts) {
|
||||
return meta.get(contexts);
|
||||
}
|
||||
|
||||
@ -103,8 +108,13 @@ public class UserCache implements UserData {
|
||||
|
||||
@Override
|
||||
public MetaCache calculateMeta(@NonNull Contexts contexts) {
|
||||
// just create a MetaContexts instance using the values in the config
|
||||
return calculateMeta(MetaContexts.makeFromConfig(contexts, user.getPlugin()));
|
||||
}
|
||||
|
||||
public MetaCache calculateMeta(@NonNull MetaContexts contexts) {
|
||||
MetaCache data = new MetaCache();
|
||||
data.loadMeta(user.accumulateMeta(null, null, ExtractedContexts.generate(contexts)));
|
||||
data.loadMeta(user.accumulateMeta(contexts.newAccumulator(), null, ExtractedContexts.generate(contexts.getContexts())));
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -115,6 +125,10 @@ public class UserCache implements UserData {
|
||||
|
||||
@Override
|
||||
public void recalculateMeta(@NonNull Contexts contexts) {
|
||||
recalculateMeta(MetaContexts.makeFromConfig(contexts, user.getPlugin()));
|
||||
}
|
||||
|
||||
public void recalculateMeta(@NonNull MetaContexts contexts) {
|
||||
meta.refresh(contexts);
|
||||
}
|
||||
|
||||
@ -126,7 +140,7 @@ public class UserCache implements UserData {
|
||||
|
||||
@Override
|
||||
public void recalculateMeta() {
|
||||
Set<Contexts> keys = ImmutableSet.copyOf(meta.asMap().keySet());
|
||||
Set<MetaContexts> keys = ImmutableSet.copyOf(meta.asMap().keySet());
|
||||
keys.forEach(meta::refresh);
|
||||
}
|
||||
|
||||
@ -138,7 +152,7 @@ public class UserCache implements UserData {
|
||||
@Override
|
||||
public void preCalculate(@NonNull Contexts contexts) {
|
||||
permission.get(contexts);
|
||||
meta.get(contexts);
|
||||
meta.get(MetaContexts.makeFromConfig(contexts, user.getPlugin()));
|
||||
}
|
||||
|
||||
public void invalidateCache() {
|
||||
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.common.core.model.Track;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface MetaStackElement {
|
||||
|
||||
Optional<Map.Entry<Integer, String>> getEntry();
|
||||
|
||||
boolean accumulateNode(LocalizedNode node);
|
||||
|
||||
MetaStackElement copy();
|
||||
|
||||
/**
|
||||
* Returns true if the types do not match
|
||||
* @param expectingPrefix if the method is expecting a prefix
|
||||
* @param node the node to check
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
static boolean checkMetaType(boolean expectingPrefix, Node node) {
|
||||
if (expectingPrefix) {
|
||||
if (!node.isPrefix()) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (!node.isSuffix()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the node is not held by a user
|
||||
* @param node the node to check
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
static boolean checkOwnElement(LocalizedNode node) {
|
||||
if (node.getLocation() == null || node.getLocation().equals("")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
UUID.fromString(node.getLocation());
|
||||
return false;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the node is not held by a group on the track
|
||||
* @param node the node to check
|
||||
* @param track the track
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
static boolean checkTrackElement(LuckPermsPlugin plugin, LocalizedNode node, String track) {
|
||||
if (node.getLocation() == null || node.getLocation().equals("")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Track t = plugin.getTrackManager().getIfLoaded(track);
|
||||
return t == null || !t.containsGroup(node.getLocation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the node is held by a group on the track
|
||||
* @param node the node to check
|
||||
* @param track the track
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
static boolean checkNotTrackElement(LuckPermsPlugin plugin, LocalizedNode node, String track) {
|
||||
// it's not come from a group on this track (from the user directly)
|
||||
if (node.getLocation() == null || node.getLocation().equals("")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Track t = plugin.getTrackManager().getIfLoaded(track);
|
||||
return t == null || t.containsGroup(node.getLocation());
|
||||
}
|
||||
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import me.lucko.luckperms.common.caching.stacking.elements.HighestPriorityElement;
|
||||
import me.lucko.luckperms.common.caching.stacking.elements.HighestPriorityNotOnTrackElement;
|
||||
import me.lucko.luckperms.common.caching.stacking.elements.HighestPriorityOwnElement;
|
||||
import me.lucko.luckperms.common.caching.stacking.elements.HighestPriorityTrackElement;
|
||||
import me.lucko.luckperms.common.caching.stacking.elements.LowestPriorityElement;
|
||||
import me.lucko.luckperms.common.caching.stacking.elements.LowestPriorityNotOnTrackElement;
|
||||
import me.lucko.luckperms.common.caching.stacking.elements.LowestPriorityOwnElement;
|
||||
import me.lucko.luckperms.common.caching.stacking.elements.LowestPriorityTrackElement;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@UtilityClass
|
||||
public class StackElementFactory {
|
||||
|
||||
public static Optional<MetaStackElement> fromString(LuckPermsPlugin plugin, String s, boolean prefix) {
|
||||
s = s.toLowerCase();
|
||||
|
||||
if (s.equals("highest")) {
|
||||
return Optional.of(new HighestPriorityElement(prefix));
|
||||
}
|
||||
|
||||
if (s.equals("lowest")) {
|
||||
return Optional.of(new LowestPriorityElement(prefix));
|
||||
}
|
||||
|
||||
if (s.equals("highest_own")) {
|
||||
return Optional.of(new HighestPriorityOwnElement(prefix));
|
||||
}
|
||||
|
||||
if (s.equals("lowest_own")) {
|
||||
return Optional.of(new LowestPriorityOwnElement(prefix));
|
||||
}
|
||||
|
||||
if (s.startsWith("highest_on_track_") && s.length() > "highest_on_track_".length()) {
|
||||
String track = s.substring("highest_on_track_".length());
|
||||
return Optional.of(new HighestPriorityTrackElement(prefix, plugin, track));
|
||||
}
|
||||
|
||||
if (s.startsWith("lowest_on_track_") && s.length() > "lowest_on_track_".length()) {
|
||||
String track = s.substring("lowest_on_track_".length());
|
||||
return Optional.of(new LowestPriorityTrackElement(prefix, plugin, track));
|
||||
}
|
||||
|
||||
if (s.startsWith("highest_not_on_track_") && s.length() > "highest_not_on_track_".length()) {
|
||||
String track = s.substring("highest_not_on_track_".length());
|
||||
return Optional.of(new HighestPriorityNotOnTrackElement(prefix, plugin, track));
|
||||
}
|
||||
|
||||
if (s.startsWith("lowest_not_on_track_") && s.length() > "lowest_not_on_track_".length()) {
|
||||
String track = s.substring("lowest_not_on_track_".length());
|
||||
return Optional.of(new LowestPriorityNotOnTrackElement(prefix, plugin, track));
|
||||
}
|
||||
|
||||
new IllegalArgumentException("Cannot parse MetaStackElement: " + s).printStackTrace();
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static List<MetaStackElement> fromList(LuckPermsPlugin plugin, List<String> strings, boolean prefix) {
|
||||
return strings.stream().map(s -> fromString(plugin, s, prefix)).filter(Optional::isPresent).map(Optional::get).collect(ImmutableCollectors.toImmutableList());
|
||||
}
|
||||
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking.elements;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.caching.stacking.MetaStackElement;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class HighestPriorityElement implements MetaStackElement {
|
||||
|
||||
/**
|
||||
* Returns true if the current node has the greater priority
|
||||
* @param current the current entry
|
||||
* @param newEntry the new entry
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
public static boolean compareEntries(Map.Entry<Integer, String> current, Map.Entry<Integer, String> newEntry) {
|
||||
return current != null && current.getKey() >= newEntry.getKey();
|
||||
}
|
||||
|
||||
private final boolean prefix;
|
||||
private Map.Entry<Integer, String> entry = null;
|
||||
|
||||
@Override
|
||||
public Optional<Map.Entry<Integer, String>> getEntry() {
|
||||
return Optional.ofNullable(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accumulateNode(LocalizedNode node) {
|
||||
if (MetaStackElement.checkMetaType(prefix, node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> entry = prefix ? node.getPrefix() : node.getSuffix();
|
||||
if (compareEntries(this.entry, entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.entry = entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaStackElement copy() {
|
||||
return new HighestPriorityElement(prefix);
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking.elements;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.caching.stacking.MetaStackElement;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class HighestPriorityNotOnTrackElement implements MetaStackElement {
|
||||
private final boolean prefix;
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final String trackName;
|
||||
|
||||
private Map.Entry<Integer, String> entry = null;
|
||||
|
||||
@Override
|
||||
public Optional<Map.Entry<Integer, String>> getEntry() {
|
||||
return Optional.ofNullable(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accumulateNode(LocalizedNode node) {
|
||||
if (MetaStackElement.checkMetaType(prefix, node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> entry = prefix ? node.getPrefix() : node.getSuffix();
|
||||
if (HighestPriorityElement.compareEntries(this.entry, entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MetaStackElement.checkNotTrackElement(plugin, node, trackName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.entry = entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaStackElement copy() {
|
||||
return new HighestPriorityNotOnTrackElement(prefix, plugin, trackName);
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking.elements;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.caching.stacking.MetaStackElement;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class HighestPriorityTrackElement implements MetaStackElement {
|
||||
private final boolean prefix;
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final String trackName;
|
||||
|
||||
private Map.Entry<Integer, String> entry = null;
|
||||
|
||||
@Override
|
||||
public Optional<Map.Entry<Integer, String>> getEntry() {
|
||||
return Optional.ofNullable(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accumulateNode(LocalizedNode node) {
|
||||
if (MetaStackElement.checkMetaType(prefix, node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> entry = prefix ? node.getPrefix() : node.getSuffix();
|
||||
if (HighestPriorityElement.compareEntries(this.entry, entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MetaStackElement.checkTrackElement(plugin, node, trackName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.entry = entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaStackElement copy() {
|
||||
return new HighestPriorityTrackElement(prefix, plugin, trackName);
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking.elements;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.caching.stacking.MetaStackElement;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class LowestPriorityElement implements MetaStackElement {
|
||||
|
||||
/**
|
||||
* Returns true if the current node has the lesser priority
|
||||
* @param current the current entry
|
||||
* @param newEntry the new entry
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
public static boolean compareEntries(Map.Entry<Integer, String> current, Map.Entry<Integer, String> newEntry) {
|
||||
return current != null && current.getKey() <= newEntry.getKey();
|
||||
}
|
||||
|
||||
private final boolean prefix;
|
||||
private Map.Entry<Integer, String> entry = null;
|
||||
|
||||
@Override
|
||||
public Optional<Map.Entry<Integer, String>> getEntry() {
|
||||
return Optional.ofNullable(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accumulateNode(LocalizedNode node) {
|
||||
if (MetaStackElement.checkMetaType(prefix, node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> entry = prefix ? node.getPrefix() : node.getSuffix();
|
||||
if (compareEntries(this.entry, entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.entry = entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaStackElement copy() {
|
||||
return new LowestPriorityElement(prefix);
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking.elements;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.caching.stacking.MetaStackElement;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class LowestPriorityNotOnTrackElement implements MetaStackElement {
|
||||
private final boolean prefix;
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final String trackName;
|
||||
|
||||
private Map.Entry<Integer, String> entry = null;
|
||||
|
||||
@Override
|
||||
public Optional<Map.Entry<Integer, String>> getEntry() {
|
||||
return Optional.ofNullable(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accumulateNode(LocalizedNode node) {
|
||||
if (MetaStackElement.checkMetaType(prefix, node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> entry = prefix ? node.getPrefix() : node.getSuffix();
|
||||
if (LowestPriorityElement.compareEntries(this.entry, entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MetaStackElement.checkNotTrackElement(plugin, node, trackName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.entry = entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaStackElement copy() {
|
||||
return new LowestPriorityNotOnTrackElement(prefix, plugin, trackName);
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.common.commands.abstraction.SharedMainCommand;
|
||||
import me.lucko.luckperms.common.commands.abstraction.SharedSubCommand;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
|
||||
public class CommandMeta<T extends PermissionHolder> extends SharedMainCommand<T> {
|
||||
public CommandMeta(boolean user) {
|
||||
@ -39,14 +40,14 @@ public class CommandMeta<T extends PermissionHolder> extends SharedMainCommand<T
|
||||
.add(new MetaUnset())
|
||||
.add(new MetaSetTemp())
|
||||
.add(new MetaUnsetTemp())
|
||||
.add(new MetaAddChatMeta(true))
|
||||
.add(new MetaAddChatMeta(false))
|
||||
.add(new MetaRemoveChatMeta(true))
|
||||
.add(new MetaRemoveChatMeta(false))
|
||||
.add(new MetaAddTempChatMeta(true))
|
||||
.add(new MetaAddTempChatMeta(false))
|
||||
.add(new MetaRemoveTempChatMeta(true))
|
||||
.add(new MetaRemoveTempChatMeta(false))
|
||||
.add(new MetaAddChatMeta(MetaType.PREFIX))
|
||||
.add(new MetaAddChatMeta(MetaType.SUFFIX))
|
||||
.add(new MetaRemoveChatMeta(MetaType.PREFIX))
|
||||
.add(new MetaRemoveChatMeta(MetaType.SUFFIX))
|
||||
.add(new MetaAddTempChatMeta(MetaType.PREFIX))
|
||||
.add(new MetaAddTempChatMeta(MetaType.SUFFIX))
|
||||
.add(new MetaRemoveTempChatMeta(MetaType.PREFIX))
|
||||
.add(new MetaRemoveTempChatMeta(MetaType.SUFFIX))
|
||||
.add(new MetaClear())
|
||||
.build());
|
||||
}
|
||||
|
@ -39,30 +39,29 @@ import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.core.NodeFactory;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.data.LogEntry;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MetaAddChatMeta extends SharedSubCommand {
|
||||
private static final Function<Boolean, String> DESCRIPTOR = b -> b ? "prefix" : "suffix";
|
||||
private final boolean isPrefix;
|
||||
private final MetaType type;
|
||||
|
||||
public MetaAddChatMeta(boolean isPrefix) {
|
||||
super("add" + DESCRIPTOR.apply(isPrefix),
|
||||
"Adds a " + DESCRIPTOR.apply(isPrefix),
|
||||
isPrefix ? Permission.USER_META_ADDPREFIX : Permission.USER_META_ADDSUFFIX,
|
||||
isPrefix ? Permission.GROUP_META_ADDPREFIX : Permission.GROUP_META_ADDSUFFIX,
|
||||
public MetaAddChatMeta(MetaType type) {
|
||||
super("add" + type.name().toLowerCase(),
|
||||
"Adds a " + type.name().toLowerCase(),
|
||||
type == MetaType.PREFIX ? Permission.USER_META_ADDPREFIX : Permission.USER_META_ADDSUFFIX,
|
||||
type == MetaType.PREFIX ? Permission.GROUP_META_ADDPREFIX : Permission.GROUP_META_ADDSUFFIX,
|
||||
Predicates.inRange(0, 1),
|
||||
Arg.list(
|
||||
Arg.create("priority", true, "the priority to add the " + DESCRIPTOR.apply(isPrefix) + " at"),
|
||||
Arg.create(DESCRIPTOR.apply(isPrefix), true, "the " + DESCRIPTOR.apply(isPrefix) + " string"),
|
||||
Arg.create("context...", false, "the contexts to add the " + DESCRIPTOR.apply(isPrefix) + " in")
|
||||
Arg.create("priority", true, "the priority to add the " + type.name().toLowerCase() + " at"),
|
||||
Arg.create(type.name().toLowerCase(), true, "the " + type.name().toLowerCase() + " string"),
|
||||
Arg.create("context...", false, "the contexts to add the " + type.name().toLowerCase() + " in")
|
||||
)
|
||||
);
|
||||
this.isPrefix = isPrefix;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -71,18 +70,18 @@ public class MetaAddChatMeta extends SharedSubCommand {
|
||||
String meta = ArgumentUtils.handleString(1, args);
|
||||
MutableContextSet context = ArgumentUtils.handleContext(2, args, plugin);
|
||||
|
||||
DataMutateResult result = holder.setPermission(NodeFactory.makeChatMetaNode(isPrefix, priority, meta).withExtraContext(context).build());
|
||||
DataMutateResult result = holder.setPermission(NodeFactory.makeChatMetaNode(type, priority, meta).withExtraContext(context).build());
|
||||
if (result.asBoolean()) {
|
||||
Message.ADD_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), DESCRIPTOR.apply(isPrefix), meta, priority, Util.contextSetToString(context));
|
||||
Message.ADD_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), type.name().toLowerCase(), meta, priority, Util.contextSetToString(context));
|
||||
|
||||
LogEntry.build().actor(sender).acted(holder)
|
||||
.action("meta add" + DESCRIPTOR.apply(isPrefix) + " " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
|
||||
.action("meta add" + type.name().toLowerCase() + " " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
|
||||
.build().submit(plugin, sender);
|
||||
|
||||
save(holder, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} else {
|
||||
Message.ALREADY_HAS_CHAT_META.send(sender, holder.getFriendlyName(), DESCRIPTOR.apply(isPrefix));
|
||||
Message.ALREADY_HAS_CHAT_META.send(sender, holder.getFriendlyName(), type.name().toLowerCase());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -42,33 +42,32 @@ import me.lucko.luckperms.common.core.NodeFactory;
|
||||
import me.lucko.luckperms.common.core.TemporaryModifier;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.data.LogEntry;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MetaAddTempChatMeta extends SharedSubCommand {
|
||||
private static final Function<Boolean, String> DESCRIPTOR = b -> b ? "prefix" : "suffix";
|
||||
private final boolean isPrefix;
|
||||
private final MetaType type;
|
||||
|
||||
public MetaAddTempChatMeta(boolean isPrefix) {
|
||||
super("addtemp" + DESCRIPTOR.apply(isPrefix),
|
||||
"Adds a " + DESCRIPTOR.apply(isPrefix) + " temporarily",
|
||||
isPrefix ? Permission.USER_META_ADDTEMP_PREFIX : Permission.USER_META_ADDTEMP_SUFFIX,
|
||||
isPrefix ? Permission.GROUP_META_ADDTEMP_PREFIX : Permission.GROUP_META_ADDTEMP_SUFFIX,
|
||||
public MetaAddTempChatMeta(MetaType type) {
|
||||
super("addtemp" + type.name().toLowerCase(),
|
||||
"Adds a " + type.name().toLowerCase() + " temporarily",
|
||||
type == MetaType.PREFIX ? Permission.USER_META_ADDTEMP_PREFIX : Permission.USER_META_ADDTEMP_SUFFIX,
|
||||
type == MetaType.PREFIX ? Permission.GROUP_META_ADDTEMP_PREFIX : Permission.GROUP_META_ADDTEMP_SUFFIX,
|
||||
Predicates.inRange(0, 2),
|
||||
Arg.list(
|
||||
Arg.create("priority", true, "the priority to add the " + DESCRIPTOR.apply(isPrefix) + " at"),
|
||||
Arg.create(DESCRIPTOR.apply(isPrefix), true, "the " + DESCRIPTOR.apply(isPrefix) + " string"),
|
||||
Arg.create("duration", true, "the duration until the " + DESCRIPTOR.apply(isPrefix) + " expires"),
|
||||
Arg.create("context...", false, "the contexts to add the " + DESCRIPTOR.apply(isPrefix) + " in")
|
||||
Arg.create("priority", true, "the priority to add the " + type.name().toLowerCase() + " at"),
|
||||
Arg.create(type.name().toLowerCase(), true, "the " + type.name().toLowerCase() + " string"),
|
||||
Arg.create("duration", true, "the duration until the " + type.name().toLowerCase() + " expires"),
|
||||
Arg.create("context...", false, "the contexts to add the " + type.name().toLowerCase() + " in")
|
||||
)
|
||||
);
|
||||
this.isPrefix = isPrefix;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -79,21 +78,21 @@ public class MetaAddTempChatMeta extends SharedSubCommand {
|
||||
MutableContextSet context = ArgumentUtils.handleContext(3, args, plugin);
|
||||
TemporaryModifier modifier = plugin.getConfiguration().get(ConfigKeys.TEMPORARY_ADD_BEHAVIOUR);
|
||||
|
||||
Map.Entry<DataMutateResult, Node> ret = holder.setPermission(NodeFactory.makeChatMetaNode(isPrefix, priority, meta).setExpiry(duration).withExtraContext(context).build(), modifier);
|
||||
Map.Entry<DataMutateResult, Node> ret = holder.setPermission(NodeFactory.makeChatMetaNode(type, priority, meta).setExpiry(duration).withExtraContext(context).build(), modifier);
|
||||
|
||||
if (ret.getKey().asBoolean()) {
|
||||
duration = ret.getValue().getExpiryUnixTime();
|
||||
|
||||
Message.ADD_TEMP_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), DESCRIPTOR.apply(isPrefix), meta, priority, DateUtil.formatDateDiff(duration), Util.contextSetToString(context));
|
||||
Message.ADD_TEMP_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), type.name().toLowerCase(), meta, priority, DateUtil.formatDateDiff(duration), Util.contextSetToString(context));
|
||||
|
||||
LogEntry.build().actor(sender).acted(holder)
|
||||
.action("meta addtemp" + DESCRIPTOR.apply(isPrefix) + " " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
|
||||
.action("meta addtemp" + type.name().toLowerCase() + " " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
|
||||
.build().submit(plugin, sender);
|
||||
|
||||
save(holder, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} else {
|
||||
Message.ALREADY_HAS_CHAT_META.send(sender, holder.getFriendlyName(), DESCRIPTOR.apply(isPrefix));
|
||||
Message.ALREADY_HAS_CHAT_META.send(sender, holder.getFriendlyName(), type.name().toLowerCase());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -39,30 +39,29 @@ import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.core.NodeFactory;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.data.LogEntry;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MetaRemoveChatMeta extends SharedSubCommand {
|
||||
private static final Function<Boolean, String> DESCRIPTOR = b -> b ? "prefix" : "suffix";
|
||||
private final boolean isPrefix;
|
||||
private final MetaType type;
|
||||
|
||||
public MetaRemoveChatMeta(boolean isPrefix) {
|
||||
super("remove" + DESCRIPTOR.apply(isPrefix),
|
||||
"Removes a " + DESCRIPTOR.apply(isPrefix),
|
||||
isPrefix ? Permission.USER_META_REMOVEPREFIX : Permission.USER_META_REMOVESUFFIX,
|
||||
isPrefix ? Permission.GROUP_META_REMOVEPREFIX : Permission.GROUP_META_REMOVESUFFIX,
|
||||
public MetaRemoveChatMeta(MetaType type) {
|
||||
super("remove" + type.name().toLowerCase(),
|
||||
"Removes a " + type.name().toLowerCase(),
|
||||
type == MetaType.PREFIX ? Permission.USER_META_REMOVEPREFIX : Permission.USER_META_REMOVESUFFIX,
|
||||
type == MetaType.PREFIX ? Permission.GROUP_META_REMOVEPREFIX : Permission.GROUP_META_REMOVESUFFIX,
|
||||
Predicates.is(0),
|
||||
Arg.list(
|
||||
Arg.create("priority", true, "the priority to remove the " + DESCRIPTOR.apply(isPrefix) + " at"),
|
||||
Arg.create(DESCRIPTOR.apply(isPrefix), false, "the " + DESCRIPTOR.apply(isPrefix) + " string"),
|
||||
Arg.create("context...", false, "the contexts to remove the " + DESCRIPTOR.apply(isPrefix) + " in")
|
||||
Arg.create("priority", true, "the priority to remove the " + type.name().toLowerCase() + " at"),
|
||||
Arg.create(type.name().toLowerCase(), false, "the " + type.name().toLowerCase() + " string"),
|
||||
Arg.create("context...", false, "the contexts to remove the " + type.name().toLowerCase() + " in")
|
||||
)
|
||||
);
|
||||
this.isPrefix = isPrefix;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -74,29 +73,29 @@ public class MetaRemoveChatMeta extends SharedSubCommand {
|
||||
// Handle bulk removal
|
||||
if (meta.equalsIgnoreCase("null") || meta.equals("*")) {
|
||||
holder.removeIf(n ->
|
||||
(isPrefix ? n.isPrefix() : n.isSuffix()) &&
|
||||
(isPrefix ? n.getPrefix() : n.getSuffix()).getKey() == priority &&
|
||||
type.matches(n) &&
|
||||
type.getEntry(n).getKey() == priority &&
|
||||
!n.isTemporary() &&
|
||||
n.getFullContexts().makeImmutable().equals(context.makeImmutable())
|
||||
);
|
||||
Message.BULK_REMOVE_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), DESCRIPTOR.apply(isPrefix), priority, Util.contextSetToString(context));
|
||||
Message.BULK_REMOVE_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), type.name().toLowerCase(), priority, Util.contextSetToString(context));
|
||||
save(holder, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
DataMutateResult result = holder.unsetPermission(NodeFactory.makeChatMetaNode(isPrefix, priority, meta).withExtraContext(context).build());
|
||||
DataMutateResult result = holder.unsetPermission(NodeFactory.makeChatMetaNode(type, priority, meta).withExtraContext(context).build());
|
||||
|
||||
if (result.asBoolean()) {
|
||||
Message.REMOVE_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), DESCRIPTOR.apply(isPrefix), meta, priority, Util.contextSetToString(context));
|
||||
Message.REMOVE_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), type.name().toLowerCase(), meta, priority, Util.contextSetToString(context));
|
||||
|
||||
LogEntry.build().actor(sender).acted(holder)
|
||||
.action("meta remove" + DESCRIPTOR.apply(isPrefix) + " " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
|
||||
.action("meta remove" + type.name().toLowerCase() + " " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
|
||||
.build().submit(plugin, sender);
|
||||
|
||||
save(holder, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} else {
|
||||
Message.DOES_NOT_HAVE_CHAT_META.send(sender, holder.getFriendlyName(), DESCRIPTOR.apply(isPrefix));
|
||||
Message.DOES_NOT_HAVE_CHAT_META.send(sender, holder.getFriendlyName(), type.name().toLowerCase());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -39,30 +39,29 @@ import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.core.NodeFactory;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.data.LogEntry;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MetaRemoveTempChatMeta extends SharedSubCommand {
|
||||
private static final Function<Boolean, String> DESCRIPTOR = b -> b ? "prefix" : "suffix";
|
||||
private final boolean isPrefix;
|
||||
private final MetaType type;
|
||||
|
||||
public MetaRemoveTempChatMeta(boolean isPrefix) {
|
||||
super("removetemp" + DESCRIPTOR.apply(isPrefix),
|
||||
"Removes a temporary " + DESCRIPTOR.apply(isPrefix),
|
||||
isPrefix ? Permission.USER_META_REMOVETEMP_PREFIX : Permission.USER_META_REMOVETEMP_SUFFIX,
|
||||
isPrefix ? Permission.GROUP_META_REMOVETEMP_PREFIX : Permission.GROUP_META_REMOVETEMP_SUFFIX,
|
||||
public MetaRemoveTempChatMeta(MetaType type) {
|
||||
super("removetemp" +type.name().toLowerCase(),
|
||||
"Removes a temporary " + type.name().toLowerCase(),
|
||||
type == MetaType.PREFIX ? Permission.USER_META_REMOVETEMP_PREFIX : Permission.USER_META_REMOVETEMP_SUFFIX,
|
||||
type == MetaType.PREFIX ? Permission.GROUP_META_REMOVETEMP_PREFIX : Permission.GROUP_META_REMOVETEMP_SUFFIX,
|
||||
Predicates.is(0),
|
||||
Arg.list(
|
||||
Arg.create("priority", true, "the priority to remove the " + DESCRIPTOR.apply(isPrefix) + " at"),
|
||||
Arg.create(DESCRIPTOR.apply(isPrefix), false, "the " + DESCRIPTOR.apply(isPrefix) + " string"),
|
||||
Arg.create("context...", false, "the contexts to remove the " + DESCRIPTOR.apply(isPrefix) + " in")
|
||||
Arg.create("priority", true, "the priority to remove the " + type.name().toLowerCase() + " at"),
|
||||
Arg.create(type.name().toLowerCase(), false, "the " +type.name().toLowerCase() + " string"),
|
||||
Arg.create("context...", false, "the contexts to remove the " + type.name().toLowerCase() + " in")
|
||||
)
|
||||
);
|
||||
this.isPrefix = isPrefix;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -74,29 +73,29 @@ public class MetaRemoveTempChatMeta extends SharedSubCommand {
|
||||
// Handle bulk removal
|
||||
if (meta.equalsIgnoreCase("null") || meta.equals("*")) {
|
||||
holder.removeIf(n ->
|
||||
(isPrefix ? n.isPrefix() : n.isSuffix()) &&
|
||||
(isPrefix ? n.getPrefix() : n.getSuffix()).getKey() == priority &&
|
||||
type.matches(n) &&
|
||||
type.getEntry(n).getKey() == priority &&
|
||||
!n.isPermanent() &&
|
||||
n.getFullContexts().makeImmutable().equals(context.makeImmutable())
|
||||
);
|
||||
Message.BULK_REMOVE_TEMP_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), DESCRIPTOR.apply(isPrefix), priority, Util.contextSetToString(context));
|
||||
Message.BULK_REMOVE_TEMP_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), type.name().toLowerCase(), priority, Util.contextSetToString(context));
|
||||
save(holder, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
DataMutateResult result = holder.unsetPermission(NodeFactory.makeChatMetaNode(isPrefix, priority, meta).setExpiry(10L).withExtraContext(context).build());
|
||||
DataMutateResult result = holder.unsetPermission(NodeFactory.makeChatMetaNode(type, priority, meta).setExpiry(10L).withExtraContext(context).build());
|
||||
|
||||
if (result.asBoolean()) {
|
||||
Message.REMOVE_TEMP_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), DESCRIPTOR.apply(isPrefix), meta, priority, Util.contextSetToString(context));
|
||||
Message.REMOVE_TEMP_CHATMETA_SUCCESS.send(sender, holder.getFriendlyName(), type.name().toLowerCase(), meta, priority, Util.contextSetToString(context));
|
||||
|
||||
LogEntry.build().actor(sender).acted(holder)
|
||||
.action("meta removetemp" + DESCRIPTOR.apply(isPrefix) + " " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
|
||||
.action("meta removetemp" + type.name().toLowerCase() + " " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
|
||||
.build().submit(plugin, sender);
|
||||
|
||||
save(holder, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} else {
|
||||
Message.DOES_NOT_HAVE_CHAT_META.send(sender, holder.getFriendlyName(), DESCRIPTOR.apply(isPrefix));
|
||||
Message.DOES_NOT_HAVE_CHAT_META.send(sender, holder.getFriendlyName(), type.name().toLowerCase());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -30,8 +30,6 @@ import lombok.experimental.UtilityClass;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import me.lucko.luckperms.common.caching.stacking.GenericMetaStack;
|
||||
import me.lucko.luckperms.common.caching.stacking.StackElementFactory;
|
||||
import me.lucko.luckperms.common.config.keys.AbstractKey;
|
||||
import me.lucko.luckperms.common.config.keys.BooleanKey;
|
||||
import me.lucko.luckperms.common.config.keys.EnduringKey;
|
||||
@ -43,6 +41,8 @@ import me.lucko.luckperms.common.config.keys.StringKey;
|
||||
import me.lucko.luckperms.common.core.TemporaryModifier;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.common.defaults.Rule;
|
||||
import me.lucko.luckperms.common.metastacking.definition.MetaStackDefinition;
|
||||
import me.lucko.luckperms.common.metastacking.definition.StandardStackElements;
|
||||
import me.lucko.luckperms.common.primarygroup.AllParentsByWeightHolder;
|
||||
import me.lucko.luckperms.common.primarygroup.ParentsByWeightHolder;
|
||||
import me.lucko.luckperms.common.primarygroup.PrimaryGroupHolder;
|
||||
@ -216,9 +216,9 @@ public class ConfigKeys {
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a new prefix MetaStack element based upon the configured values. Be aware that this instance should be copied for each unique user.
|
||||
* Creates a new prefix MetaStack element based upon the configured values.
|
||||
*/
|
||||
public static final ConfigKey<GenericMetaStack> PREFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> {
|
||||
public static final ConfigKey<MetaStackDefinition> PREFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> {
|
||||
List<String> format = l.getList("meta-formatting.prefix.format", new ArrayList<>());
|
||||
if (format.isEmpty()) {
|
||||
format.add("highest");
|
||||
@ -227,13 +227,13 @@ public class ConfigKeys {
|
||||
String middleSpacer = l.getString("meta-formatting.prefix.middle-spacer", " ");
|
||||
String endSpacer = l.getString("meta-formatting.prefix.end-spacer", "");
|
||||
|
||||
return new GenericMetaStack(StackElementFactory.fromList(l.getPlugin(), format, true), startSpacer, middleSpacer, endSpacer);
|
||||
return MetaStackDefinition.create(StandardStackElements.parseList(l.getPlugin(), format), startSpacer, middleSpacer, endSpacer);
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a new suffix MetaStack element based upon the configured values. Be aware that this instance should be copied for each unique user.
|
||||
* Creates a new suffix MetaStack element based upon the configured values.
|
||||
*/
|
||||
public static final ConfigKey<GenericMetaStack> SUFFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> {
|
||||
public static final ConfigKey<MetaStackDefinition> SUFFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> {
|
||||
List<String> format = l.getList("meta-formatting.suffix.format", new ArrayList<>());
|
||||
if (format.isEmpty()) {
|
||||
format.add("highest");
|
||||
@ -242,7 +242,7 @@ public class ConfigKeys {
|
||||
String middleSpacer = l.getString("meta-formatting.suffix.middle-spacer", " ");
|
||||
String endSpacer = l.getString("meta-formatting.suffix.end-spacer", "");
|
||||
|
||||
return new GenericMetaStack(StackElementFactory.fromList(l.getPlugin(), format, false), startSpacer, middleSpacer, endSpacer);
|
||||
return MetaStackDefinition.create(StandardStackElements.parseList(l.getPlugin(), format), startSpacer, middleSpacer, endSpacer);
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -35,6 +35,7 @@ import me.lucko.luckperms.api.MetaUtils;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.utils.PatternCache;
|
||||
|
||||
import java.util.List;
|
||||
@ -122,8 +123,8 @@ public class NodeFactory {
|
||||
return new NodeBuilder("meta." + MetaUtils.escapeCharacters(key) + "." + MetaUtils.escapeCharacters(value));
|
||||
}
|
||||
|
||||
public static Node.Builder makeChatMetaNode(boolean prefix, int priority, String s) {
|
||||
return prefix ? makePrefixNode(priority, s) : makeSuffixNode(priority, s);
|
||||
public static Node.Builder makeChatMetaNode(MetaType type, int priority, String s) {
|
||||
return type == MetaType.PREFIX ? makePrefixNode(priority, s) : makeSuffixNode(priority, s);
|
||||
}
|
||||
|
||||
public static Node.Builder makePrefixNode(int priority, String prefix) {
|
||||
|
@ -663,10 +663,7 @@ public abstract class PermissionHolder {
|
||||
|
||||
public MetaAccumulator accumulateMeta(MetaAccumulator accumulator, Set<String> excludedGroups, ExtractedContexts context) {
|
||||
if (accumulator == null) {
|
||||
accumulator = new MetaAccumulator(
|
||||
plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS).copy(),
|
||||
plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS).copy()
|
||||
);
|
||||
accumulator = MetaAccumulator.makeFromConfig(plugin);
|
||||
}
|
||||
|
||||
if (excludedGroups == null) {
|
||||
|
@ -23,28 +23,38 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking;
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.metastacking.definition.MetaStackDefinition;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class GenericMetaStack implements MetaStack {
|
||||
|
||||
private final List<MetaStackElement> elements;
|
||||
private final String startSpacer;
|
||||
private final String middleSpacer;
|
||||
private final String endSpacer;
|
||||
private final MetaStackDefinition definition;
|
||||
private final MetaType targetType;
|
||||
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final List<MetaStackEntry> entries;
|
||||
|
||||
public GenericMetaStack(MetaStackDefinition definition, MetaType targetType) {
|
||||
this.definition = definition;
|
||||
this.targetType = targetType;
|
||||
this.entries = definition.getElements().stream()
|
||||
.map(element -> new SimpleMetaStackEntry(this, element, targetType))
|
||||
.collect(ImmutableCollectors.toImmutableList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toFormattedString() {
|
||||
List<MetaStackElement> ret = new ArrayList<>(elements);
|
||||
List<MetaStackEntry> ret = new ArrayList<>(entries);
|
||||
ret.removeIf(m -> !m.getEntry().isPresent());
|
||||
|
||||
if (ret.isEmpty()) {
|
||||
@ -52,27 +62,22 @@ public class GenericMetaStack implements MetaStack {
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(startSpacer);
|
||||
sb.append(definition.getStartSpacer());
|
||||
for (int i = 0; i < ret.size(); i++) {
|
||||
if (i != 0) {
|
||||
sb.append(middleSpacer);
|
||||
sb.append(definition.getMiddleSpacer());
|
||||
}
|
||||
|
||||
MetaStackElement e = ret.get(i);
|
||||
MetaStackEntry e = ret.get(i);
|
||||
sb.append(e.getEntry().get().getValue());
|
||||
}
|
||||
sb.append(endSpacer);
|
||||
sb.append(definition.getEndSpacer());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaStack copy() {
|
||||
return new GenericMetaStack(
|
||||
elements.stream().map(MetaStackElement::copy).collect(ImmutableCollectors.toImmutableList()),
|
||||
startSpacer,
|
||||
middleSpacer,
|
||||
endSpacer
|
||||
);
|
||||
public void accumulateToAll(LocalizedNode node) {
|
||||
entries.forEach(e -> e.accumulateNode(node));
|
||||
}
|
||||
}
|
@ -23,20 +23,19 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking;
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
|
||||
import java.util.List;
|
||||
import me.lucko.luckperms.common.metastacking.definition.MetaStackDefinition;
|
||||
|
||||
public interface MetaStack {
|
||||
|
||||
List<MetaStackElement> getElements();
|
||||
MetaStackDefinition getDefinition();
|
||||
|
||||
MetaType getTargetType();
|
||||
|
||||
String toFormattedString();
|
||||
MetaStack copy();
|
||||
|
||||
default void accumulateToAll(LocalizedNode node) {
|
||||
getElements().forEach(m -> m.accumulateNode(node));
|
||||
}
|
||||
void accumulateToAll(LocalizedNode node);
|
||||
|
||||
}
|
@ -23,26 +23,22 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking;
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.metastacking.definition.MetaStackElement;
|
||||
|
||||
public class NoopMetaStack implements MetaStack {
|
||||
public static final NoopMetaStack INSTANCE = new NoopMetaStack();
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface MetaStackEntry {
|
||||
|
||||
MetaStack getParentStack();
|
||||
|
||||
MetaStackElement getElement();
|
||||
|
||||
Optional<Map.Entry<Integer, String>> getEntry();
|
||||
|
||||
boolean accumulateNode(LocalizedNode node);
|
||||
|
||||
@Override
|
||||
public List<MetaStackElement> getElements() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toFormattedString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaStack copy() {
|
||||
return this;
|
||||
}
|
||||
}
|
@ -23,51 +23,52 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking.elements;
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.caching.stacking.MetaStackElement;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class LowestPriorityTrackElement implements MetaStackElement {
|
||||
private final boolean prefix;
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final String trackName;
|
||||
|
||||
private Map.Entry<Integer, String> entry = null;
|
||||
public enum MetaType {
|
||||
|
||||
PREFIX {
|
||||
@Override
|
||||
public Optional<Map.Entry<Integer, String>> getEntry() {
|
||||
return Optional.ofNullable(entry);
|
||||
public boolean matches(Node node) {
|
||||
return node.isPrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accumulateNode(LocalizedNode node) {
|
||||
if (MetaStackElement.checkMetaType(prefix, node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> entry = prefix ? node.getPrefix() : node.getSuffix();
|
||||
if (LowestPriorityElement.compareEntries(this.entry, entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MetaStackElement.checkTrackElement(plugin, node, trackName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.entry = entry;
|
||||
return true;
|
||||
public boolean shouldIgnore(Node node) {
|
||||
return !node.isPrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaStackElement copy() {
|
||||
return new LowestPriorityTrackElement(prefix, plugin, trackName);
|
||||
public Map.Entry<Integer, String> getEntry(Node node) {
|
||||
return node.getPrefix();
|
||||
}
|
||||
},
|
||||
|
||||
SUFFIX {
|
||||
@Override
|
||||
public boolean matches(Node node) {
|
||||
return node.isSuffix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIgnore(Node node) {
|
||||
return !node.isSuffix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map.Entry<Integer, String> getEntry(Node node) {
|
||||
return node.getSuffix();
|
||||
}
|
||||
};
|
||||
|
||||
public abstract boolean matches(Node node);
|
||||
|
||||
public abstract boolean shouldIgnore(Node node);
|
||||
|
||||
public abstract Map.Entry<Integer, String> getEntry(Node node);
|
||||
|
||||
}
|
@ -23,47 +23,40 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking.elements;
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.caching.stacking.MetaStackElement;
|
||||
import me.lucko.luckperms.common.metastacking.definition.MetaStackElement;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class LowestPriorityOwnElement implements MetaStackElement {
|
||||
private final boolean prefix;
|
||||
private Map.Entry<Integer, String> entry = null;
|
||||
public class SimpleMetaStackEntry implements MetaStackEntry {
|
||||
|
||||
private final MetaStack parentStack;
|
||||
private final MetaStackElement element;
|
||||
private final MetaType type;
|
||||
|
||||
@Getter(AccessLevel.NONE)
|
||||
private Map.Entry<Integer, String> current = null;
|
||||
|
||||
@Override
|
||||
public Optional<Map.Entry<Integer, String>> getEntry() {
|
||||
return Optional.ofNullable(entry);
|
||||
return Optional.ofNullable(current);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accumulateNode(LocalizedNode node) {
|
||||
if (MetaStackElement.checkMetaType(prefix, node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MetaStackElement.checkOwnElement(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> entry = prefix ? node.getPrefix() : node.getSuffix();
|
||||
if (LowestPriorityElement.compareEntries(this.entry, entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.entry = entry;
|
||||
if (element.shouldAccumulate(node, type, current)) {
|
||||
this.current = type.getEntry(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaStackElement copy() {
|
||||
return new LowestPriorityOwnElement(prefix);
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking.definition;
|
||||
|
||||
import me.lucko.luckperms.common.metastacking.GenericMetaStack;
|
||||
import me.lucko.luckperms.common.metastacking.MetaStack;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MetaStackDefinition {
|
||||
|
||||
static MetaStackDefinition create(List<MetaStackElement> elements, String startSpacer, String middleSpacer, String endSpacer) {
|
||||
return new SimpleMetaStackDefinition(elements, startSpacer, middleSpacer, endSpacer);
|
||||
}
|
||||
|
||||
List<MetaStackElement> getElements();
|
||||
|
||||
String getStartSpacer();
|
||||
|
||||
String getMiddleSpacer();
|
||||
|
||||
String getEndSpacer();
|
||||
|
||||
default MetaStack newStack(MetaType type) {
|
||||
return new GenericMetaStack(this, type);
|
||||
}
|
||||
|
||||
}
|
@ -23,48 +23,15 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.caching.stacking.elements;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
package me.lucko.luckperms.common.metastacking.definition;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.caching.stacking.MetaStackElement;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class HighestPriorityOwnElement implements MetaStackElement {
|
||||
private final boolean prefix;
|
||||
private Map.Entry<Integer, String> entry = null;
|
||||
public interface MetaStackElement {
|
||||
|
||||
@Override
|
||||
public Optional<Map.Entry<Integer, String>> getEntry() {
|
||||
return Optional.ofNullable(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accumulateNode(LocalizedNode node) {
|
||||
if (MetaStackElement.checkMetaType(prefix, node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MetaStackElement.checkOwnElement(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> entry = prefix ? node.getPrefix() : node.getSuffix();
|
||||
if (HighestPriorityElement.compareEntries(this.entry, entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.entry = entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaStackElement copy() {
|
||||
return new HighestPriorityOwnElement(prefix);
|
||||
}
|
||||
boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current);
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking.definition;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@ToString
|
||||
final class SimpleMetaStackDefinition implements MetaStackDefinition {
|
||||
|
||||
private final List<MetaStackElement> elements;
|
||||
private final String startSpacer;
|
||||
private final String middleSpacer;
|
||||
private final String endSpacer;
|
||||
|
||||
public SimpleMetaStackDefinition(@NonNull List<MetaStackElement> elements, @NonNull String startSpacer, @NonNull String middleSpacer, @NonNull String endSpacer) {
|
||||
this.elements = ImmutableList.copyOf(elements);
|
||||
this.startSpacer = startSpacer;
|
||||
this.middleSpacer = middleSpacer;
|
||||
this.endSpacer = endSpacer;
|
||||
}
|
||||
}
|
@ -0,0 +1,298 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking.definition;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.common.core.model.Track;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@UtilityClass
|
||||
public class StandardStackElements {
|
||||
|
||||
public static Optional<MetaStackElement> parseFromString(LuckPermsPlugin plugin, String s) {
|
||||
s = s.toLowerCase();
|
||||
|
||||
if (s.equals("highest")) {
|
||||
return Optional.of(new HighestPriority());
|
||||
}
|
||||
|
||||
if (s.equals("lowest")) {
|
||||
return Optional.of(new LowestPriority());
|
||||
}
|
||||
|
||||
if (s.equals("highest_own")) {
|
||||
return Optional.of(new HighestPriorityOwn());
|
||||
}
|
||||
|
||||
if (s.equals("lowest_own")) {
|
||||
return Optional.of(new LowestPriorityOwn());
|
||||
}
|
||||
|
||||
if (s.startsWith("highest_on_track_") && s.length() > "highest_on_track_".length()) {
|
||||
String track = s.substring("highest_on_track_".length());
|
||||
return Optional.of(new HighestPriorityTrack(plugin, track));
|
||||
}
|
||||
|
||||
if (s.startsWith("lowest_on_track_") && s.length() > "lowest_on_track_".length()) {
|
||||
String track = s.substring("lowest_on_track_".length());
|
||||
return Optional.of(new LowestPriorityTrack(plugin, track));
|
||||
}
|
||||
|
||||
if (s.startsWith("highest_not_on_track_") && s.length() > "highest_not_on_track_".length()) {
|
||||
String track = s.substring("highest_not_on_track_".length());
|
||||
return Optional.of(new HighestPriorityNotOnTrack(plugin, track));
|
||||
}
|
||||
|
||||
if (s.startsWith("lowest_not_on_track_") && s.length() > "lowest_not_on_track_".length()) {
|
||||
String track = s.substring("lowest_not_on_track_".length());
|
||||
return Optional.of(new LowestPriorityNotOnTrack(plugin, track));
|
||||
}
|
||||
|
||||
new IllegalArgumentException("Cannot parse MetaStackElement: " + s).printStackTrace();
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static List<MetaStackElement> parseList(LuckPermsPlugin plugin, List<String> strings) {
|
||||
return strings.stream()
|
||||
.map(s -> parseFromString(plugin, s))
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.collect(ImmutableCollectors.toImmutableList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current node has the greater priority
|
||||
* @param current the current entry
|
||||
* @param newEntry the new entry
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
private static boolean compareEntriesHighest(Map.Entry<Integer, String> current, Map.Entry<Integer, String> newEntry) {
|
||||
return current != null && current.getKey() >= newEntry.getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current node has the lesser priority
|
||||
* @param current the current entry
|
||||
* @param newEntry the new entry
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
private static boolean compareEntriesLowest(Map.Entry<Integer, String> current, Map.Entry<Integer, String> newEntry) {
|
||||
return current != null && current.getKey() <= newEntry.getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the node is not held by a user
|
||||
* @param node the node to check
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
private static boolean checkOwnElement(LocalizedNode node) {
|
||||
if (node.getLocation() == null || node.getLocation().equals("")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
UUID.fromString(node.getLocation());
|
||||
return false;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the node is not held by a group on the track
|
||||
* @param node the node to check
|
||||
* @param track the track
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
private static boolean checkTrackElement(LuckPermsPlugin plugin, LocalizedNode node, String track) {
|
||||
if (node.getLocation() == null || node.getLocation().equals("")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Track t = plugin.getTrackManager().getIfLoaded(track);
|
||||
return t == null || !t.containsGroup(node.getLocation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the node is held by a group on the track
|
||||
* @param node the node to check
|
||||
* @param track the track
|
||||
* @return true if the accumulation should return
|
||||
*/
|
||||
private static boolean checkNotTrackElement(LuckPermsPlugin plugin, LocalizedNode node, String track) {
|
||||
// it's not come from a group on this track (from the user directly)
|
||||
if (node.getLocation() == null || node.getLocation().equals("")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Track t = plugin.getTrackManager().getIfLoaded(track);
|
||||
return t == null || t.containsGroup(node.getLocation());
|
||||
}
|
||||
|
||||
@ToString
|
||||
private static final class HighestPriority implements MetaStackElement {
|
||||
@Override
|
||||
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) {
|
||||
if (type.shouldIgnore(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> newEntry = type.getEntry(node);
|
||||
return !compareEntriesHighest(current, newEntry);
|
||||
}
|
||||
}
|
||||
|
||||
@ToString
|
||||
private static final class HighestPriorityOwn implements MetaStackElement {
|
||||
@Override
|
||||
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) {
|
||||
if (type.shouldIgnore(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkOwnElement(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> newEntry = type.getEntry(node);
|
||||
return !compareEntriesHighest(current, newEntry);
|
||||
}
|
||||
}
|
||||
|
||||
@ToString
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode(of = "trackName")
|
||||
private static final class HighestPriorityTrack implements MetaStackElement {
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final String trackName;
|
||||
|
||||
@Override
|
||||
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) {
|
||||
if (type.shouldIgnore(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> newEntry = type.getEntry(node);
|
||||
return !compareEntriesHighest(current, newEntry) && !checkTrackElement(plugin, node, trackName);
|
||||
}
|
||||
}
|
||||
|
||||
@ToString
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode(of = "trackName")
|
||||
private static final class HighestPriorityNotOnTrack implements MetaStackElement {
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final String trackName;
|
||||
|
||||
@Override
|
||||
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) {
|
||||
if (type.shouldIgnore(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> newEntry = type.getEntry(node);
|
||||
return !compareEntriesHighest(current, newEntry) && !checkNotTrackElement(plugin, node, trackName);
|
||||
}
|
||||
}
|
||||
|
||||
@ToString
|
||||
private static final class LowestPriority implements MetaStackElement {
|
||||
@Override
|
||||
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) {
|
||||
if (type.shouldIgnore(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> newEntry = type.getEntry(node);
|
||||
return !compareEntriesLowest(current, newEntry);
|
||||
}
|
||||
}
|
||||
|
||||
@ToString
|
||||
private static final class LowestPriorityOwn implements MetaStackElement {
|
||||
@Override
|
||||
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) {
|
||||
if (type.shouldIgnore(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkOwnElement(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> newEntry = type.getEntry(node);
|
||||
return !compareEntriesLowest(current, newEntry);
|
||||
}
|
||||
}
|
||||
|
||||
@ToString
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode(of = "trackName")
|
||||
private static final class LowestPriorityTrack implements MetaStackElement {
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final String trackName;
|
||||
|
||||
@Override
|
||||
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) {
|
||||
if (type.shouldIgnore(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> entry = type.getEntry(node);
|
||||
return !compareEntriesLowest(current, entry) && !checkTrackElement(plugin, node, trackName);
|
||||
}
|
||||
}
|
||||
|
||||
@ToString
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode(of = "trackName")
|
||||
private static final class LowestPriorityNotOnTrack implements MetaStackElement {
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final String trackName;
|
||||
|
||||
@Override
|
||||
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) {
|
||||
if (type.shouldIgnore(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> newEntry = type.getEntry(node);
|
||||
return !compareEntriesLowest(current, newEntry) && !checkNotTrackElement(plugin, node, trackName);
|
||||
}
|
||||
}
|
||||
}
|
@ -58,9 +58,9 @@ public class SpongeSenderFactory extends SenderFactory<CommandSource> {
|
||||
return Constants.CONSOLE_UUID;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void sendMessage(CommandSource source, String s) {
|
||||
//noinspection deprecation
|
||||
source.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(s));
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,18 @@ public class SpongeCalculatorLink implements ContextCalculator<Subject> {
|
||||
|
||||
@Override
|
||||
public MutableContextSet giveApplicableContext(Subject subject, MutableContextSet accumulator) {
|
||||
Set<Context> contexts = new HashSet<>();
|
||||
Set<Context> contexts = new HashSet<Context>() {
|
||||
|
||||
// don't allow null elements
|
||||
@Override
|
||||
public boolean add(Context context) {
|
||||
if (context == null) {
|
||||
throw new NullPointerException("context");
|
||||
}
|
||||
|
||||
return super.add(context);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
delegate.accumulateContexts(subject, contexts);
|
||||
|
@ -37,6 +37,7 @@ import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.caching.MetaAccumulator;
|
||||
import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.utils.ExtractedContexts;
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
@ -197,10 +198,10 @@ public class SpongeGroup extends Group {
|
||||
try (Timing ignored = plugin.getService().getPlugin().getTimings().time(LPTiming.GROUP_GET_OPTION)) {
|
||||
Optional<String> option;
|
||||
if (s.equalsIgnoreCase("prefix")) {
|
||||
option = getChatMeta(contexts, true);
|
||||
option = getChatMeta(contexts, MetaType.PREFIX);
|
||||
|
||||
} else if (s.equalsIgnoreCase("suffix")) {
|
||||
option = getChatMeta(contexts, false);
|
||||
option = getChatMeta(contexts, MetaType.SUFFIX);
|
||||
|
||||
} else {
|
||||
option = getMeta(contexts, s);
|
||||
@ -226,13 +227,9 @@ public class SpongeGroup extends Group {
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<String> getChatMeta(ImmutableContextSet contexts, boolean prefix) {
|
||||
private Optional<String> getChatMeta(ImmutableContextSet contexts, MetaType type) {
|
||||
MetaAccumulator metaAccumulator = parent.accumulateMeta(null, null, ExtractedContexts.generate(plugin.getService().calculateContexts(contexts)));
|
||||
if (prefix) {
|
||||
return Optional.ofNullable(metaAccumulator.getPrefixStack().toFormattedString());
|
||||
} else {
|
||||
return Optional.ofNullable(metaAccumulator.getSuffixStack().toFormattedString());
|
||||
}
|
||||
return Optional.ofNullable(metaAccumulator.getStack(type).toFormattedString());
|
||||
}
|
||||
|
||||
private Optional<String> getMeta(ImmutableContextSet contexts, String key) {
|
||||
|
@ -41,6 +41,7 @@ import me.lucko.luckperms.common.core.NodeFactory;
|
||||
import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.common.metastacking.MetaType;
|
||||
import me.lucko.luckperms.common.utils.ExtractedContexts;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
@ -369,26 +370,24 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_OPTION)) {
|
||||
if (key.equalsIgnoreCase("prefix") || key.equalsIgnoreCase("suffix")) {
|
||||
// special handling.
|
||||
String type = key.toLowerCase();
|
||||
boolean prefix = type.equals("prefix");
|
||||
MetaType type = MetaType.valueOf(key.toUpperCase());
|
||||
|
||||
// remove all prefixes/suffixes from the user
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(n -> prefix ? n.isPrefix() : n.isSuffix())
|
||||
.filter(type::matches)
|
||||
.filter(n -> n.getFullContexts().equals(context))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, null, ExtractedContexts.generate(service.calculateContexts(context)));
|
||||
int priority = (type.equals("prefix") ? metaAccumulator.getPrefixes() : metaAccumulator.getSuffixes()).keySet().stream()
|
||||
.mapToInt(e -> e).max().orElse(0);
|
||||
int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0);
|
||||
priority += 10;
|
||||
|
||||
if (enduring) {
|
||||
holder.setPermission(NodeFactory.makeChatMetaNode(type.equals("prefix"), priority, value).withExtraContext(context).build());
|
||||
holder.setPermission(NodeFactory.makeChatMetaNode(type, priority, value).withExtraContext(context).build());
|
||||
} else {
|
||||
holder.setTransientPermission(NodeFactory.makeChatMetaNode(type.equals("prefix"), priority, value).withExtraContext(context).build());
|
||||
holder.setTransientPermission(NodeFactory.makeChatMetaNode(type, priority, value).withExtraContext(context).build());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user