From 4c21957b04b1fcacce3ed0ce7d0dc5da3f5246ff Mon Sep 17 00:00:00 2001 From: Luck Date: Tue, 27 Sep 2016 20:18:06 +0100 Subject: [PATCH] Cache Vault lookups & properly sort listnodes output --- .../me/lucko/luckperms/BukkitListener.java | 6 +- .../me/lucko/luckperms/LPBukkitPlugin.java | 9 +- .../luckperms/api/vault/VaultChatHook.java | 55 +++++------ .../lucko/luckperms/api/vault/VaultHook.java | 27 ++++-- .../api/vault/VaultPermissionHook.java | 52 ++++++++--- .../api/vault/cache/ContextData.java | 75 +++++++++++++++ .../api/vault/cache/VaultUserCache.java | 91 +++++++++++++++++++ .../api/vault/cache/VaultUserManager.java | 66 ++++++++++++++ .../lucko/luckperms/inject/LPPermissible.java | 2 +- .../me/lucko/luckperms/users/BukkitUser.java | 4 + .../luckperms/core/PriorityComparator.java | 6 +- .../luckperms/api/sponge/ContextData.java | 2 +- 12 files changed, 339 insertions(+), 56 deletions(-) create mode 100644 bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/ContextData.java create mode 100644 bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/VaultUserCache.java create mode 100644 bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/VaultUserManager.java diff --git a/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java b/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java index e9ba8569..18b7957e 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java +++ b/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java @@ -90,8 +90,12 @@ class BukkitListener extends AbstractListener implements Listener { @EventHandler(priority = EventPriority.LOWEST) public void onPlayerQuit(PlayerQuitEvent e) { - plugin.getWorldCalculator().getWorldCache().remove(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId())); + final UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()); + plugin.getWorldCalculator().getWorldCache().remove(internal); onLeave(e.getPlayer().getUniqueId()); + if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) { + plugin.getVaultHook().getPermissionHook().getVaultUserManager().clearUser(internal); + } } @EventHandler diff --git a/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java index 4041c5a5..6c9bc388 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java +++ b/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java @@ -62,6 +62,8 @@ import java.util.stream.Collectors; @Getter public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { + private VaultHook vaultHook = null; + private final Set ignoringLogs = ConcurrentHashMap.newKeySet(); private LPConfiguration configuration; private BukkitUserManager userManager; @@ -142,7 +144,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { getLog().info("Attempting to hook into Vault..."); try { if (getServer().getPluginManager().isPluginEnabled("Vault")) { - VaultHook.hook(this); + vaultHook = new VaultHook(); + vaultHook.hook(this); getLog().info("Registered Vault permission & chat hook."); } else { getLog().info("Vault not found."); @@ -181,6 +184,10 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { getLog().info("Unregistering API..."); LuckPerms.unregisterProvider(); getServer().getServicesManager().unregisterAll(this); + + if (vaultHook != null) { + vaultHook.unhook(this); + } } @Override diff --git a/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultChatHook.java b/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultChatHook.java index a4941b40..be349c43 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultChatHook.java +++ b/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultChatHook.java @@ -23,8 +23,6 @@ package me.lucko.luckperms.api.vault; import lombok.NonNull; -import lombok.Setter; -import me.lucko.luckperms.LPBukkitPlugin; import me.lucko.luckperms.api.Node; import me.lucko.luckperms.contexts.Contexts; import me.lucko.luckperms.core.PermissionHolder; @@ -55,12 +53,9 @@ import static me.lucko.luckperms.utils.ArgumentChecker.unescapeCharacters; * Node that special characters used within LuckPerms are escaped: * See {@link me.lucko.luckperms.utils.ArgumentChecker#escapeCharacters(String)} * - * Registered on normal priority so other plugins can override. + * Registered on normal priority so other perms.getPlugin()s can override. */ public class VaultChatHook extends Chat { - - @Setter - private LPBukkitPlugin plugin; private final VaultPermissionHook perms; VaultChatHook(VaultPermissionHook perms) { @@ -191,47 +186,47 @@ public class VaultChatHook extends Chat { } public String getPlayerPrefix(String world, @NonNull String player) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); return getChatMeta(true, user, world); } public void setPlayerPrefix(String world, @NonNull String player, @NonNull String prefix) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); setChatMeta(true, user, prefix, world); } public String getPlayerSuffix(String world, @NonNull String player) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); return getChatMeta(false, user, world); } public void setPlayerSuffix(String world, @NonNull String player, @NonNull String suffix) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); setChatMeta(false, user, suffix, world); } public String getGroupPrefix(String world, @NonNull String group) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); return getChatMeta(false, g, world); } public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); setChatMeta(true, g, prefix, world); } public String getGroupSuffix(String world, @NonNull String group) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); return getChatMeta(false, g, world); } public void setGroupSuffix(String world, @NonNull String group, @NonNull String suffix) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); setChatMeta(false, g, suffix, world); } public int getPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int defaultValue) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); try { return Integer.parseInt(getMeta(user, world, node, String.valueOf(defaultValue))); } catch (NumberFormatException e) { @@ -240,12 +235,12 @@ public class VaultChatHook extends Chat { } public void setPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int value) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); saveMeta(user, world, node, String.valueOf(value)); } public int getGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int defaultValue) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); try { return Integer.parseInt(getMeta(g, world, node, String.valueOf(defaultValue))); } catch (NumberFormatException e) { @@ -254,12 +249,12 @@ public class VaultChatHook extends Chat { } public void setGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int value) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); saveMeta(g, world, node, String.valueOf(value)); } public double getPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double defaultValue) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); try { return Double.parseDouble(getMeta(user, world, node, String.valueOf(defaultValue))); } catch (NumberFormatException e) { @@ -268,12 +263,12 @@ public class VaultChatHook extends Chat { } public void setPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double value) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); saveMeta(user, world, node, String.valueOf(value)); } public double getGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double defaultValue) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); try { return Double.parseDouble(getMeta(g, world, node, String.valueOf(defaultValue))); } catch (NumberFormatException e) { @@ -282,12 +277,12 @@ public class VaultChatHook extends Chat { } public void setGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double value) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); saveMeta(g, world, node, String.valueOf(value)); } public boolean getPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean defaultValue) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); String s = getMeta(user, world, node, String.valueOf(defaultValue)); if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) { return defaultValue; @@ -296,12 +291,12 @@ public class VaultChatHook extends Chat { } public void setPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean value) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); saveMeta(user, world, node, String.valueOf(value)); } public boolean getGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean defaultValue) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); String s = getMeta(g, world, node, String.valueOf(defaultValue)); if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) { return defaultValue; @@ -310,27 +305,27 @@ public class VaultChatHook extends Chat { } public void setGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean value) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); saveMeta(g, world, node, String.valueOf(value)); } public String getPlayerInfoString(String world, @NonNull String player, @NonNull String node, String defaultValue) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); return getMeta(user, world, node, defaultValue); } public void setPlayerInfoString(String world, @NonNull String player, @NonNull String node, String value) { - final User user = plugin.getUserManager().get(player); + final User user = perms.getPlugin().getUserManager().get(player); saveMeta(user, world, node, value); } public String getGroupInfoString(String world, @NonNull String group, @NonNull String node, String defaultValue) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); return getMeta(g, world, node, defaultValue); } public void setGroupInfoString(String world, @NonNull String group, @NonNull String node, String value) { - final Group g = plugin.getGroupManager().get(group); + final Group g = perms.getPlugin().getGroupManager().get(group); saveMeta(g, world, node, value); } diff --git a/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultHook.java b/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultHook.java index ee5e88c0..b975928a 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultHook.java +++ b/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultHook.java @@ -22,18 +22,19 @@ package me.lucko.luckperms.api.vault; +import lombok.Getter; import me.lucko.luckperms.LPBukkitPlugin; import net.milkbowl.vault.chat.Chat; import net.milkbowl.vault.permission.Permission; import org.bukkit.plugin.ServicePriority; import org.bukkit.plugin.ServicesManager; +@Getter public class VaultHook { + private VaultChatHook chatHook = null; + private VaultPermissionHook permissionHook = null; - private static VaultChatHook chatHook = null; - private static VaultPermissionHook permissionHook = null; - - public static void hook(LPBukkitPlugin plugin) { + public void hook(LPBukkitPlugin plugin) { try { if (permissionHook == null) { permissionHook = new VaultPermissionHook(); @@ -41,21 +42,33 @@ public class VaultHook { permissionHook.setPlugin(plugin); permissionHook.setServer(plugin.getConfiguration().getVaultServer()); permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIncludingGlobal()); + permissionHook.setup(); if (chatHook == null) { chatHook = new VaultChatHook(permissionHook); } - chatHook.setPlugin(plugin); final ServicesManager sm = plugin.getServer().getServicesManager(); - sm.unregisterAll(plugin); sm.register(Permission.class, permissionHook, plugin, ServicePriority.High); - sm.register(Chat.class, chatHook, plugin, ServicePriority.Low); + sm.register(Chat.class, chatHook, plugin, ServicePriority.High); } catch (Exception e) { e.printStackTrace(); } + } + public void unhook(LPBukkitPlugin plugin) { + final ServicesManager sm = plugin.getServer().getServicesManager(); + if (permissionHook != null) { + sm.unregister(Permission.class, permissionHook); + } + if (chatHook != null) { + sm.unregister(Chat.class, chatHook); + } + } + + public boolean isHooked() { + return permissionHook != null && chatHook != null; } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultPermissionHook.java b/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultPermissionHook.java index 93f2c4ba..abeebddb 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultPermissionHook.java +++ b/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultPermissionHook.java @@ -27,6 +27,9 @@ import lombok.NonNull; import lombok.Setter; import me.lucko.luckperms.LPBukkitPlugin; import me.lucko.luckperms.api.data.Callback; +import me.lucko.luckperms.api.vault.cache.ContextData; +import me.lucko.luckperms.api.vault.cache.VaultUserCache; +import me.lucko.luckperms.api.vault.cache.VaultUserManager; import me.lucko.luckperms.contexts.Contexts; import me.lucko.luckperms.core.PermissionHolder; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; @@ -41,9 +44,13 @@ import java.util.Map; public class VaultPermissionHook extends Permission { + @Getter @Setter private LPBukkitPlugin plugin; + @Getter + private VaultUserManager vaultUserManager; + @Getter @Setter private String server = "global"; @@ -67,8 +74,12 @@ public class VaultPermissionHook extends Permission { return true; } - private boolean objectHas(String world, PermissionHolder object, String permission) { - if (object == null) return false; + public void setup() { + vaultUserManager = new VaultUserManager(plugin, this); + } + + private boolean objectHas(String world, Group group, String permission) { + if (group == null) return false; Map context = new HashMap<>(); if (world != null && !world.equals("")) { @@ -76,7 +87,7 @@ public class VaultPermissionHook extends Permission { } context.put("server", server); - Map toApply = object.exportNodes( + Map toApply = group.exportNodes( new Contexts(context, includeGlobal, includeGlobal, true, true, true), Collections.emptyList(), true ); @@ -126,7 +137,21 @@ public class VaultPermissionHook extends Permission { @Override public boolean playerHas(String world, @NonNull String player, @NonNull String permission) { - return objectHas(world, plugin.getUserManager().get(player), permission); + User user = plugin.getUserManager().get(player); + if (user == null) return false; + + if (!vaultUserManager.containsUser(user.getUuid())) { + return false; + } + + VaultUserCache vaultUser = vaultUserManager.getUser(user.getUuid()); + Map context = new HashMap<>(); + context.put("server", server); + if (world != null) { + context.put("world", world); + } + + return vaultUser.hasPermission(context, permission); } @Override @@ -204,23 +229,22 @@ public class VaultPermissionHook extends Permission { @Override public String[] getPlayerGroups(String world, @NonNull String player) { - final User user = plugin.getUserManager().get(player); - if (user == null) { + User user = plugin.getUserManager().get(player); + if (user == null) return new String[0]; + + if (!vaultUserManager.containsUser(user.getUuid())) { return new String[0]; } + VaultUserCache vaultUser = vaultUserManager.getUser(user.getUuid()); Map context = new HashMap<>(); - if (world != null && !world.equals("")) { + context.put("server", server); + if (world != null) { context.put("world", world); } - context.put("server", server); - Map toApply = user.exportNodes( - new Contexts(context, includeGlobal, includeGlobal, true, true, true), - Collections.emptyList(), true - ); - - return toApply.entrySet().stream() + ContextData cd = vaultUser.getContextData().computeIfAbsent(context, map -> vaultUser.calculatePermissions(map, false)); + return cd.getPermissionCache().entrySet().stream() .filter(Map.Entry::getValue) .filter(e -> e.getKey().startsWith("group.")) .map(e -> e.getKey().substring("group.".length())) diff --git a/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/ContextData.java b/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/ContextData.java new file mode 100644 index 00000000..3a1e6f29 --- /dev/null +++ b/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/ContextData.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * 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.api.vault.cache; + +import lombok.Getter; +import lombok.NonNull; +import me.lucko.luckperms.LuckPermsPlugin; +import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.calculators.PermissionCalculator; +import me.lucko.luckperms.calculators.PermissionProcessor; +import me.lucko.luckperms.inject.DefaultsProvider; +import me.lucko.luckperms.inject.LPPermissible; +import me.lucko.luckperms.users.BukkitUser; +import me.lucko.luckperms.users.User; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ContextData { + + @Getter + private final Map context; + + @Getter + private final Map permissionCache = new ConcurrentHashMap<>(); + + private final PermissionCalculator calculator; + + public ContextData(User user, Map context, LuckPermsPlugin plugin, DefaultsProvider defaultsProvider) { + this.context = context; + + List processors = new ArrayList<>(5); + processors.add(new PermissionCalculator.MapProcessor(permissionCache)); + if (plugin.getConfiguration().isApplyingWildcards()) { + processors.add(new PermissionCalculator.WildcardProcessor(permissionCache)); + } + if (plugin.getConfiguration().isApplyingRegex()) { + processors.add(new PermissionCalculator.RegexProcessor(permissionCache)); + } + + processors.add(new LPPermissible.BukkitDefaultsProcessor(() -> ((BukkitUser) user).getLpPermissible().isOp(), defaultsProvider)); + calculator = new PermissionCalculator(plugin, user.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors); + } + + public void invalidateCache() { + calculator.invalidateCache(); + } + + public Tristate getPermissionValue(@NonNull String permission) { + return calculator.getPermissionValue(permission); + } + +} diff --git a/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/VaultUserCache.java b/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/VaultUserCache.java new file mode 100644 index 00000000..7dc4e6e2 --- /dev/null +++ b/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/VaultUserCache.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * 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.api.vault.cache; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import me.lucko.luckperms.LPBukkitPlugin; +import me.lucko.luckperms.api.vault.VaultPermissionHook; +import me.lucko.luckperms.contexts.Contexts; +import me.lucko.luckperms.users.User; + +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@RequiredArgsConstructor +public class VaultUserCache { + private final LPBukkitPlugin plugin; + private final VaultPermissionHook vault; + + @Getter + private final User user; + + @Getter + private final Map, ContextData> contextData = new ConcurrentHashMap<>(); + + public boolean hasPermission(Map context, String permission) { + ContextData cd = contextData.computeIfAbsent(context, map -> calculatePermissions(map, false)); + return cd.getPermissionValue(permission).asBoolean(); + } + + public ContextData calculatePermissions(Map context, boolean apply) { + Map toApply = user.exportNodes( + new Contexts(context, vault.isIncludeGlobal(), true, true, true, true), + Collections.emptyList(), + true + ); + + ContextData existing = contextData.get(context); + if (existing == null) { + existing = new ContextData(user, context, plugin, plugin.getDefaultsProvider()); + if (apply) { + contextData.put(context, existing); + } + } + + boolean different = false; + if (toApply.size() != existing.getPermissionCache().size()) { + different = true; + } else { + for (Map.Entry e : existing.getPermissionCache().entrySet()) { + if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) { + continue; + } + different = true; + break; + } + } + + if (!different) return existing; + + existing.getPermissionCache().clear(); + existing.invalidateCache(); + existing.getPermissionCache().putAll(toApply); + return existing; + } + + + + +} diff --git a/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/VaultUserManager.java b/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/VaultUserManager.java new file mode 100644 index 00000000..1a4b0b93 --- /dev/null +++ b/bukkit/src/main/java/me/lucko/luckperms/api/vault/cache/VaultUserManager.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * 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.api.vault.cache; + +import lombok.RequiredArgsConstructor; +import me.lucko.luckperms.LPBukkitPlugin; +import me.lucko.luckperms.api.vault.VaultPermissionHook; +import me.lucko.luckperms.users.User; +import org.bukkit.World; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@RequiredArgsConstructor +public class VaultUserManager { + private final LPBukkitPlugin plugin; + private final VaultPermissionHook vault; + private final Map userCache = new ConcurrentHashMap<>(); + + public void setupUser(User user) { + VaultUserCache vaultUser = userCache.computeIfAbsent(user.getUuid(), uuid -> new VaultUserCache(plugin, vault, user)); + vaultUser.calculatePermissions(Collections.singletonMap("server", vault.getServer()), true); + for (World world : plugin.getServer().getWorlds()) { + Map context = new HashMap<>(); + context.put("server", vault.getServer()); + context.put("world", world.getName()); + vaultUser.calculatePermissions(context, true); + } + } + + public void clearUser(UUID uuid) { + userCache.remove(uuid); + } + + public boolean containsUser(UUID uuid) { + return userCache.containsKey(uuid); + } + + public VaultUserCache getUser(UUID uuid) { + return userCache.get(uuid); + } + +} diff --git a/bukkit/src/main/java/me/lucko/luckperms/inject/LPPermissible.java b/bukkit/src/main/java/me/lucko/luckperms/inject/LPPermissible.java index ac13a886..e7236be9 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/inject/LPPermissible.java +++ b/bukkit/src/main/java/me/lucko/luckperms/inject/LPPermissible.java @@ -279,7 +279,7 @@ public class LPPermissible extends PermissibleBase { } @AllArgsConstructor - private static class BukkitDefaultsProcessor implements PermissionProcessor { + public static class BukkitDefaultsProcessor implements PermissionProcessor { private final Supplier isOp; private final DefaultsProvider defaultsProvider; diff --git a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java index 4fe5b505..1b1b0d66 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java +++ b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java @@ -119,5 +119,9 @@ public class BukkitUser extends User { } catch (Exception e) { e.printStackTrace(); } + + if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) { + plugin.getVaultHook().getPermissionHook().getVaultUserManager().setupUser(this); + } } } diff --git a/common/src/main/java/me/lucko/luckperms/core/PriorityComparator.java b/common/src/main/java/me/lucko/luckperms/core/PriorityComparator.java index 2db1b4fb..77662d0f 100644 --- a/common/src/main/java/me/lucko/luckperms/core/PriorityComparator.java +++ b/common/src/main/java/me/lucko/luckperms/core/PriorityComparator.java @@ -26,7 +26,9 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import me.lucko.luckperms.api.Node; +import java.text.Collator; import java.util.Comparator; +import java.util.Locale; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class PriorityComparator implements Comparator { @@ -40,6 +42,8 @@ public class PriorityComparator implements Comparator { return INSTANCE.reversed(); } + private final Collator collator = Collator.getInstance(Locale.ENGLISH); + @Override public int compare(Node o1, Node o2) { if (o1.equals(o2)) { @@ -74,6 +78,6 @@ public class PriorityComparator implements Comparator { return o1.getWildcardLevel() > o2.getWildcardLevel() ? 1 : -1; } - return o1.getPermission().compareToIgnoreCase(o2.getPermission()) == 1 ? -1 : 1; + return collator.compare(o1.getPermission(), o2.getPermission()) == 1 ? -1 : 1; } } diff --git a/sponge/src/main/java/me/lucko/luckperms/api/sponge/ContextData.java b/sponge/src/main/java/me/lucko/luckperms/api/sponge/ContextData.java index 5eb8385c..4ba47865 100644 --- a/sponge/src/main/java/me/lucko/luckperms/api/sponge/ContextData.java +++ b/sponge/src/main/java/me/lucko/luckperms/api/sponge/ContextData.java @@ -67,7 +67,7 @@ public class ContextData { } public Tristate getPermissionValue(@NonNull String permission) { - me.lucko.luckperms.api.Tristate t = calculator.getPermissionValue(permission); + me.lucko.luckperms.api.Tristate t = calculator.getPermissionValue(permission); if (t != me.lucko.luckperms.api.Tristate.UNDEFINED) { return Tristate.fromBoolean(t.asBoolean()); } else {