diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java index 7fb03b631..4a58f1370 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationBPermissions.java @@ -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 { } 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; } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationGroupManager.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationGroupManager.java index 321cd4239..37e48bcdc 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationGroupManager.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationGroupManager.java @@ -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 { } 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 { } 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()); } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationZPermissions.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationZPermissions.java index 4462e3bd9..d3302d968 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationZPermissions.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationZPermissions.java @@ -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 { 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()); } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/VaultChatHook.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/VaultChatHook.java index 4949dc753..027dd52c2 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/VaultChatHook.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/vault/VaultChatHook.java @@ -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 value = prefix ? n.getPrefix() : n.getSuffix(); + Map.Entry 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 diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/MetaAccumulator.java b/common/src/main/java/me/lucko/luckperms/common/caching/MetaAccumulator.java index db3974c7d..3b8afc7db 100644 --- a/common/src/main/java/me/lucko/luckperms/common/caching/MetaAccumulator.java +++ b/common/src/main/java/me/lucko/luckperms/common/caching/MetaAccumulator.java @@ -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 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 getChatMeta(MetaType type) { + return type == MetaType.PREFIX ? prefixes : suffixes; + } + + public MetaStack getStack(MetaType type) { + return type == MetaType.PREFIX ? prefixStack : suffixStack; + } + } diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/MetaCache.java b/common/src/main/java/me/lucko/luckperms/common/caching/MetaCache.java index 2942089ef..44d2ad512 100644 --- a/common/src/main/java/me/lucko/luckperms/common/caching/MetaCache.java +++ b/common/src/main/java/me/lucko/luckperms/common/caching/MetaCache.java @@ -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 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(); } diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/MetaContexts.java b/common/src/main/java/me/lucko/luckperms/common/caching/MetaContexts.java new file mode 100644 index 000000000..f9a554e55 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/caching/MetaContexts.java @@ -0,0 +1,67 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.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) + ); + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/UserCache.java b/common/src/main/java/me/lucko/luckperms/common/caching/UserCache.java index 50f0b42e5..1aca2335c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/caching/UserCache.java +++ b/common/src/main/java/me/lucko/luckperms/common/caching/UserCache.java @@ -69,17 +69,17 @@ public class UserCache implements UserData { } }); - private final LoadingCache meta = Caffeine.newBuilder() + private final LoadingCache meta = Caffeine.newBuilder() .expireAfterAccess(10, TimeUnit.MINUTES) - .build(new CacheLoader() { + .build(new CacheLoader() { @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 keys = ImmutableSet.copyOf(meta.asMap().keySet()); + Set 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() { diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/MetaStackElement.java b/common/src/main/java/me/lucko/luckperms/common/caching/stacking/MetaStackElement.java deleted file mode 100644 index 1d800af32..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/MetaStackElement.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This file is part of LuckPerms, licensed under the MIT License. - * - * Copyright (c) lucko (Luck) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.lucko.luckperms.common.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> 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()); - } - -} diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/StackElementFactory.java b/common/src/main/java/me/lucko/luckperms/common/caching/stacking/StackElementFactory.java deleted file mode 100644 index 539a1bc8d..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/StackElementFactory.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of LuckPerms, licensed under the MIT License. - * - * Copyright (c) lucko (Luck) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.lucko.luckperms.common.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 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 fromList(LuckPermsPlugin plugin, List strings, boolean prefix) { - return strings.stream().map(s -> fromString(plugin, s, prefix)).filter(Optional::isPresent).map(Optional::get).collect(ImmutableCollectors.toImmutableList()); - } - -} diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityElement.java b/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityElement.java deleted file mode 100644 index f1105f9fa..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityElement.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of LuckPerms, licensed under the MIT License. - * - * Copyright (c) lucko (Luck) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.lucko.luckperms.common.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 current, Map.Entry newEntry) { - return current != null && current.getKey() >= newEntry.getKey(); - } - - private final boolean prefix; - private Map.Entry entry = null; - - @Override - public Optional> getEntry() { - return Optional.ofNullable(entry); - } - - @Override - public boolean accumulateNode(LocalizedNode node) { - if (MetaStackElement.checkMetaType(prefix, node)) { - return false; - } - - Map.Entry 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); - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityNotOnTrackElement.java b/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityNotOnTrackElement.java deleted file mode 100644 index 9a518e66c..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityNotOnTrackElement.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of LuckPerms, licensed under the MIT License. - * - * Copyright (c) lucko (Luck) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.lucko.luckperms.common.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 entry = null; - - @Override - public Optional> getEntry() { - return Optional.ofNullable(entry); - } - - @Override - public boolean accumulateNode(LocalizedNode node) { - if (MetaStackElement.checkMetaType(prefix, node)) { - return false; - } - - Map.Entry 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); - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityTrackElement.java b/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityTrackElement.java deleted file mode 100644 index 76c896092..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityTrackElement.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of LuckPerms, licensed under the MIT License. - * - * Copyright (c) lucko (Luck) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.lucko.luckperms.common.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 entry = null; - - @Override - public Optional> getEntry() { - return Optional.ofNullable(entry); - } - - @Override - public boolean accumulateNode(LocalizedNode node) { - if (MetaStackElement.checkMetaType(prefix, node)) { - return false; - } - - Map.Entry 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); - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityElement.java b/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityElement.java deleted file mode 100644 index 0114eaa82..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityElement.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of LuckPerms, licensed under the MIT License. - * - * Copyright (c) lucko (Luck) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.lucko.luckperms.common.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 current, Map.Entry newEntry) { - return current != null && current.getKey() <= newEntry.getKey(); - } - - private final boolean prefix; - private Map.Entry entry = null; - - @Override - public Optional> getEntry() { - return Optional.ofNullable(entry); - } - - @Override - public boolean accumulateNode(LocalizedNode node) { - if (MetaStackElement.checkMetaType(prefix, node)) { - return false; - } - - Map.Entry 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); - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityNotOnTrackElement.java b/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityNotOnTrackElement.java deleted file mode 100644 index a5062d2d8..000000000 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityNotOnTrackElement.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of LuckPerms, licensed under the MIT License. - * - * Copyright (c) lucko (Luck) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.lucko.luckperms.common.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 entry = null; - - @Override - public Optional> getEntry() { - return Optional.ofNullable(entry); - } - - @Override - public boolean accumulateNode(LocalizedNode node) { - if (MetaStackElement.checkMetaType(prefix, node)) { - return false; - } - - Map.Entry 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); - } -} diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/CommandMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/CommandMeta.java index 47331335c..742666a1b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/CommandMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/CommandMeta.java @@ -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 extends SharedMainCommand { public CommandMeta(boolean user) { @@ -39,14 +40,14 @@ public class CommandMeta extends SharedMainCommand 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; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaAddTempChatMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaAddTempChatMeta.java index 8b515c2db..fa4cb4b6e 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaAddTempChatMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaAddTempChatMeta.java @@ -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 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 ret = holder.setPermission(NodeFactory.makeChatMetaNode(isPrefix, priority, meta).setExpiry(duration).withExtraContext(context).build(), modifier); + Map.Entry 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; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaRemoveChatMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaRemoveChatMeta.java index b20699bfb..760ad0bf9 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaRemoveChatMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaRemoveChatMeta.java @@ -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 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; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaRemoveTempChatMeta.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaRemoveTempChatMeta.java index 2d26150d0..c4500b726 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaRemoveTempChatMeta.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/meta/MetaRemoveTempChatMeta.java @@ -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 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; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java index ffe6d58ed..a5519ac5d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java +++ b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java @@ -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 PREFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> { + public static final ConfigKey PREFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> { List 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 SUFFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> { + public static final ConfigKey SUFFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> { List 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); }); /** diff --git a/common/src/main/java/me/lucko/luckperms/common/core/NodeFactory.java b/common/src/main/java/me/lucko/luckperms/common/core/NodeFactory.java index 7ebb014d7..a84debe4d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/core/NodeFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/core/NodeFactory.java @@ -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) { diff --git a/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java b/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java index 316b456d6..dfc1315a3 100644 --- a/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java @@ -663,10 +663,7 @@ public abstract class PermissionHolder { public MetaAccumulator accumulateMeta(MetaAccumulator accumulator, Set 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) { diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/GenericMetaStack.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/GenericMetaStack.java similarity index 63% rename from common/src/main/java/me/lucko/luckperms/common/caching/stacking/GenericMetaStack.java rename to common/src/main/java/me/lucko/luckperms/common/metastacking/GenericMetaStack.java index bc2446dc1..dcc3b658a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/GenericMetaStack.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/GenericMetaStack.java @@ -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 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 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 ret = new ArrayList<>(elements); + List 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)); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/MetaStack.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStack.java similarity index 83% rename from common/src/main/java/me/lucko/luckperms/common/caching/stacking/MetaStack.java rename to common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStack.java index b8b98fc6d..74af568c4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/MetaStack.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStack.java @@ -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 getElements(); - String toFormattedString(); - MetaStack copy(); + MetaStackDefinition getDefinition(); - default void accumulateToAll(LocalizedNode node) { - getElements().forEach(m -> m.accumulateNode(node)); - } + MetaType getTargetType(); + + String toFormattedString(); + + void accumulateToAll(LocalizedNode node); } diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/NoopMetaStack.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStackEntry.java similarity index 72% rename from common/src/main/java/me/lucko/luckperms/common/caching/stacking/NoopMetaStack.java rename to common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStackEntry.java index f9c73689a..99fb0fc1c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/NoopMetaStack.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaStackEntry.java @@ -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; - @Override - public List getElements() { - return Collections.emptyList(); - } +public interface MetaStackEntry { - @Override - public String toFormattedString() { - return null; - } + MetaStack getParentStack(); + + MetaStackElement getElement(); + + Optional> getEntry(); + + boolean accumulateNode(LocalizedNode node); - @Override - public MetaStack copy() { - return this; - } } diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityTrackElement.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaType.java similarity index 50% rename from common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityTrackElement.java rename to common/src/main/java/me/lucko/luckperms/common/metastacking/MetaType.java index 9d3694108..e53d68161 100644 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityTrackElement.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/MetaType.java @@ -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; +public enum MetaType { - private Map.Entry entry = null; - - @Override - public Optional> getEntry() { - return Optional.ofNullable(entry); - } - - @Override - public boolean accumulateNode(LocalizedNode node) { - if (MetaStackElement.checkMetaType(prefix, node)) { - return false; + PREFIX { + @Override + public boolean matches(Node node) { + return node.isPrefix(); } - Map.Entry entry = prefix ? node.getPrefix() : node.getSuffix(); - if (LowestPriorityElement.compareEntries(this.entry, entry)) { - return false; + @Override + public boolean shouldIgnore(Node node) { + return !node.isPrefix(); } - if (MetaStackElement.checkTrackElement(plugin, node, trackName)) { - return false; + @Override + public Map.Entry getEntry(Node node) { + return node.getPrefix(); + } + }, + + SUFFIX { + @Override + public boolean matches(Node node) { + return node.isSuffix(); } - this.entry = entry; - return true; - } + @Override + public boolean shouldIgnore(Node node) { + return !node.isSuffix(); + } + + @Override + public Map.Entry getEntry(Node node) { + return node.getSuffix(); + } + }; + + public abstract boolean matches(Node node); + + public abstract boolean shouldIgnore(Node node); + + public abstract Map.Entry getEntry(Node node); - @Override - public MetaStackElement copy() { - return new LowestPriorityTrackElement(prefix, plugin, trackName); - } } diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityOwnElement.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStackEntry.java similarity index 64% rename from common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityOwnElement.java rename to common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStackEntry.java index b8ae58598..0e22d5d60 100644 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/LowestPriorityOwnElement.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/SimpleMetaStackEntry.java @@ -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 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 current = null; @Override public Optional> getEntry() { - return Optional.ofNullable(entry); + return Optional.ofNullable(current); } @Override public boolean accumulateNode(LocalizedNode node) { - if (MetaStackElement.checkMetaType(prefix, node)) { - return false; + if (element.shouldAccumulate(node, type, current)) { + this.current = type.getEntry(node); + return true; } - - if (MetaStackElement.checkOwnElement(node)) { - return false; - } - - Map.Entry entry = prefix ? node.getPrefix() : node.getSuffix(); - if (LowestPriorityElement.compareEntries(this.entry, entry)) { - return false; - } - - this.entry = entry; - return true; - } - - @Override - public MetaStackElement copy() { - return new LowestPriorityOwnElement(prefix); + return false; } } diff --git a/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/MetaStackDefinition.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/MetaStackDefinition.java new file mode 100644 index 000000000..320b389e5 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/MetaStackDefinition.java @@ -0,0 +1,52 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.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 elements, String startSpacer, String middleSpacer, String endSpacer) { + return new SimpleMetaStackDefinition(elements, startSpacer, middleSpacer, endSpacer); + } + + List getElements(); + + String getStartSpacer(); + + String getMiddleSpacer(); + + String getEndSpacer(); + + default MetaStack newStack(MetaType type) { + return new GenericMetaStack(this, type); + } + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityOwnElement.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/MetaStackElement.java similarity index 53% rename from common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityOwnElement.java rename to common/src/main/java/me/lucko/luckperms/common/metastacking/definition/MetaStackElement.java index 3f1178282..a2fa7c3bf 100644 --- a/common/src/main/java/me/lucko/luckperms/common/caching/stacking/elements/HighestPriorityOwnElement.java +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/MetaStackElement.java @@ -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 entry = null; +public interface MetaStackElement { - @Override - public Optional> 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 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 current); } diff --git a/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/SimpleMetaStackDefinition.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/SimpleMetaStackDefinition.java new file mode 100644 index 000000000..df55919d8 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/SimpleMetaStackDefinition.java @@ -0,0 +1,53 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.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 elements; + private final String startSpacer; + private final String middleSpacer; + private final String endSpacer; + + public SimpleMetaStackDefinition(@NonNull List elements, @NonNull String startSpacer, @NonNull String middleSpacer, @NonNull String endSpacer) { + this.elements = ImmutableList.copyOf(elements); + this.startSpacer = startSpacer; + this.middleSpacer = middleSpacer; + this.endSpacer = endSpacer; + } +} diff --git a/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/StandardStackElements.java b/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/StandardStackElements.java new file mode 100644 index 000000000..1690626c5 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/metastacking/definition/StandardStackElements.java @@ -0,0 +1,298 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.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 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 parseList(LuckPermsPlugin plugin, List 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 current, Map.Entry 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 current, Map.Entry 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 current) { + if (type.shouldIgnore(node)) { + return false; + } + + Map.Entry 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 current) { + if (type.shouldIgnore(node)) { + return false; + } + + if (checkOwnElement(node)) { + return false; + } + + Map.Entry 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 current) { + if (type.shouldIgnore(node)) { + return false; + } + + Map.Entry 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 current) { + if (type.shouldIgnore(node)) { + return false; + } + + Map.Entry 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 current) { + if (type.shouldIgnore(node)) { + return false; + } + + Map.Entry 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 current) { + if (type.shouldIgnore(node)) { + return false; + } + + if (checkOwnElement(node)) { + return false; + } + + Map.Entry 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 current) { + if (type.shouldIgnore(node)) { + return false; + } + + Map.Entry 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 current) { + if (type.shouldIgnore(node)) { + return false; + } + + Map.Entry newEntry = type.getEntry(node); + return !compareEntriesLowest(current, newEntry) && !checkNotTrackElement(plugin, node, trackName); + } + } +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeSenderFactory.java b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeSenderFactory.java index c86b05fe8..2aa0b2f79 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeSenderFactory.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeSenderFactory.java @@ -58,9 +58,9 @@ public class SpongeSenderFactory extends SenderFactory { return Constants.CONSOLE_UUID; } - @SuppressWarnings("deprecation") @Override protected void sendMessage(CommandSource source, String s) { + //noinspection deprecation source.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(s)); } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeCalculatorLink.java b/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeCalculatorLink.java index c19acdacd..789c08486 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeCalculatorLink.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeCalculatorLink.java @@ -43,7 +43,18 @@ public class SpongeCalculatorLink implements ContextCalculator { @Override public MutableContextSet giveApplicableContext(Subject subject, MutableContextSet accumulator) { - Set contexts = new HashSet<>(); + Set contexts = new HashSet() { + + // 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); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java index 4b322c2f2..390d71161 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java @@ -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 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 getChatMeta(ImmutableContextSet contexts, boolean prefix) { + private Optional 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 getMeta(ImmutableContextSet contexts, String key) { diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java index 5c833d542..bf6291e40 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java @@ -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 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 {