diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/BukkitMigrationUtils.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/BukkitMigrationUtils.java index 0fed3435..8cf8c9bc 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/BukkitMigrationUtils.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/BukkitMigrationUtils.java @@ -45,7 +45,7 @@ public final class BukkitMigrationUtils { } } if (uuid == null) { - log.logErr("Unable to get a UUID for user identifier: " + s); + log.logError("Unable to get a UUID for user identifier: " + s); } return uuid; } 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 45ed1ef1..69a70af4 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 @@ -85,7 +85,7 @@ public class MigrationBPermissions extends SubCommand { WorldManager worldManager = WorldManager.getInstance(); if (worldManager == null) { - log.logErr("Plugin not loaded."); + log.logError("Plugin not loaded."); return CommandResult.STATE_ERROR; } @@ -111,7 +111,7 @@ public class MigrationBPermissions extends SubCommand { Set users = configSection.getKeys(false); if (users == null) { - log.logErr("Couldn't get a list of users."); + log.logError("Couldn't get a list of users."); return CommandResult.FAILURE; } AtomicInteger userLoadCount = new AtomicInteger(0); 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 023c32ee..c0003a50 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 @@ -74,14 +74,14 @@ public class MigrationGroupManager extends SubCommand { log.log("Starting."); if (!args.get(0).equalsIgnoreCase("true") && !args.get(0).equalsIgnoreCase("false")) { - log.logErr("Was expecting true/false, but got " + args.get(0) + " instead."); + log.logError("Was expecting true/false, but got " + args.get(0) + " instead."); return CommandResult.STATE_ERROR; } final boolean migrateAsGlobal = Boolean.parseBoolean(args.get(0)); final Function worldMappingFunc = s -> migrateAsGlobal ? null : s; if (!Bukkit.getPluginManager().isPluginEnabled("GroupManager")) { - log.logErr("Plugin not loaded."); + log.logError("Plugin not loaded."); return CommandResult.STATE_ERROR; } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsBukkit.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsBukkit.java index ee25dfc9..8cb2b7ed 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsBukkit.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsBukkit.java @@ -66,7 +66,7 @@ public class MigrationPermissionsBukkit extends SubCommand { log.log("Starting."); if (!Bukkit.getPluginManager().isPluginEnabled("PermissionsBukkit")) { - log.logErr("Plugin not loaded."); + log.logError("Plugin not loaded."); return CommandResult.STATE_ERROR; } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsEx.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsEx.java index f43d6683..8355b1a1 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsEx.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPermissionsEx.java @@ -99,7 +99,7 @@ public class MigrationPermissionsEx extends SubCommand { log.log("Starting."); if (!Bukkit.getPluginManager().isPluginEnabled("PermissionsEx")) { - log.logErr("Plugin not loaded."); + log.logError("Plugin not loaded."); return CommandResult.STATE_ERROR; } diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPowerfulPerms.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPowerfulPerms.java index 2fdc38d1..3ec9df80 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPowerfulPerms.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/migration/MigrationPowerfulPerms.java @@ -85,7 +85,7 @@ public class MigrationPowerfulPerms extends SubCommand { log.log("Starting."); if (!Bukkit.getPluginManager().isPluginEnabled("PowerfulPerms")) { - log.logErr("Plugin not loaded."); + log.logError("Plugin not loaded."); return CommandResult.STATE_ERROR; } @@ -143,7 +143,7 @@ public class MigrationPowerfulPerms extends SubCommand { } if (uuids.isEmpty()) { - log.logErr("Unable to find any UUIDs to migrate."); + log.logError("Unable to find any UUIDs to migrate."); return CommandResult.FAILURE; } 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 d0eeaf7f..38a2948e 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 @@ -76,12 +76,12 @@ public class MigrationZPermissions extends SubCommand { log.log("Starting."); if (!Bukkit.getPluginManager().isPluginEnabled("zPermissions")) { - log.logErr("Plugin not loaded."); + log.logError("Plugin not loaded."); return CommandResult.STATE_ERROR; } if (!Bukkit.getServicesManager().isProvidedFor(ZPermissionsService.class)) { - log.logErr("Plugin not loaded."); + log.logError("Plugin not loaded."); return CommandResult.STATE_ERROR; } diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/migration/MigrationBungeePerms.java b/bungee/src/main/java/me/lucko/luckperms/bungee/migration/MigrationBungeePerms.java index 12bac34c..53bdb350 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/migration/MigrationBungeePerms.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/migration/MigrationBungeePerms.java @@ -66,7 +66,7 @@ public class MigrationBungeePerms extends SubCommand { // Get BungeePerms instance BungeePerms bp = BungeePerms.getInstance(); if (bp == null) { - log.logErr("Plugin not loaded."); + log.logError("Plugin not loaded."); return CommandResult.STATE_ERROR; } @@ -106,7 +106,7 @@ public class MigrationBungeePerms extends SubCommand { SafeIteration.iterate(bp.getPermissionsManager().getBackEnd().loadUsers(), u -> { if (u.getUUID() == null) { - log.logErr("Could not parse UUID for user: " + u.getName()); + log.logError("Could not parse UUID for user: " + u.getName()); return; } diff --git a/common/src/main/java/me/lucko/luckperms/common/logging/ProgressLogger.java b/common/src/main/java/me/lucko/luckperms/common/logging/ProgressLogger.java index d8c6c880..55123e2d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/logging/ProgressLogger.java +++ b/common/src/main/java/me/lucko/luckperms/common/logging/ProgressLogger.java @@ -62,7 +62,7 @@ public class ProgressLogger { } } - public void logErr(String msg) { + public void logError(String msg) { if (this.pluginName == null) { this.listeners.forEach(s -> this.logMessage.send(s, "Error -> " + msg)); } else { @@ -80,7 +80,6 @@ public class ProgressLogger { public void logProgress(String msg, int amount) { if (amount % NOTIFY_FREQUENCY == 0) { - // migrated {} groups so far. logAllProgress(msg, amount); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/model/NodeMapType.java b/common/src/main/java/me/lucko/luckperms/common/model/NodeMapType.java index 9abdb773..cfe9ea38 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/NodeMapType.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/NodeMapType.java @@ -25,8 +25,30 @@ package me.lucko.luckperms.common.model; +import java.util.function.Supplier; + public enum NodeMapType { - ENDURING, TRANSIENT + ENDURING, + TRANSIENT; + + // useful methods for fluent/conditional execution + + public void run(Runnable ifEnduring, Runnable ifTransient) { + if (this == ENDURING) { + ifEnduring.run(); + } else { + ifTransient.run(); + } + } + + public T supply(Supplier ifEnduring, Supplier ifTransient) { + if (this == ENDURING) { + return ifEnduring.get(); + } else { + return ifTransient.get(); + } + } + } diff --git a/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java b/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java index 3eb7c9bf..970af414 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java @@ -262,6 +262,10 @@ public abstract class PermissionHolder { return this.transientNodes; } + public ImmutableSetMultimap getNodes(NodeMapType type) { + return getData(type).immutable(); + } + public ImmutableSetMultimap getEnduringNodes() { return this.enduringNodes.immutable(); } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/calculators/SpongeCalculatorFactory.java b/sponge/src/main/java/me/lucko/luckperms/sponge/calculators/SpongeCalculatorFactory.java index 039b77bc..c5136941 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/calculators/SpongeCalculatorFactory.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/calculators/SpongeCalculatorFactory.java @@ -36,7 +36,6 @@ import me.lucko.luckperms.common.processors.MapProcessor; import me.lucko.luckperms.common.processors.PermissionProcessor; import me.lucko.luckperms.common.processors.RegexProcessor; import me.lucko.luckperms.common.processors.WildcardProcessor; -import me.lucko.luckperms.common.references.HolderType; import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.processors.GroupDefaultsProcessor; import me.lucko.luckperms.sponge.processors.SpongeWildcardProcessor; @@ -68,9 +67,9 @@ public class SpongeCalculatorFactory extends AbstractCalculatorFactory { } if (this.plugin.getConfiguration().get(ConfigKeys.APPLY_SPONGE_DEFAULT_SUBJECTS)) { - if (metadata.getHolderType() == HolderType.USER) { + if (metadata.getHolderType().isUser()) { processors.add(new UserDefaultsProcessor(this.plugin.getService(), contexts.getContexts().makeImmutable())); - } else if (metadata.getHolderType() == HolderType.GROUP) { + } else if (metadata.getHolderType().isGroup()) { processors.add(new GroupDefaultsProcessor(this.plugin.getService(), contexts.getContexts().makeImmutable())); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/listeners/SpongeConnectionListener.java b/sponge/src/main/java/me/lucko/luckperms/sponge/listeners/SpongeConnectionListener.java index f95d82cc..411e7073 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/listeners/SpongeConnectionListener.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/listeners/SpongeConnectionListener.java @@ -62,14 +62,14 @@ public class SpongeConnectionListener extends AbstractLoginListener { /* Called when the player first attempts a connection with the server. Listening on AFTER_PRE priority to allow plugins to modify username / UUID data here. (auth plugins) */ - final GameProfile p = e.getProfile(); - final String username = p.getName().orElseThrow(() -> new RuntimeException("No username present for user " + p.getUniqueId())); + final GameProfile profile = e.getProfile(); + final String username = profile.getName().orElseThrow(() -> new RuntimeException("No username present for user " + profile.getUniqueId())); if (this.plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) { - this.plugin.getLog().info("Processing auth event for " + p.getUniqueId() + " - " + p.getName()); + this.plugin.getLog().info("Processing auth event for " + profile.getUniqueId() + " - " + profile.getName()); } - this.plugin.getUniqueConnections().add(p.getUniqueId()); + this.plugin.getUniqueConnections().add(profile.getUniqueId()); /* Actually process the login for the connection. We do this here to delay the login until the data is ready. @@ -81,13 +81,13 @@ public class SpongeConnectionListener extends AbstractLoginListener { - creating a user instance in the UserManager for this connection. - setting up cached data. */ try { - User user = loadUser(p.getUniqueId(), username); - this.plugin.getEventFactory().handleUserLoginProcess(p.getUniqueId(), username, user); + User user = loadUser(profile.getUniqueId(), username); + this.plugin.getEventFactory().handleUserLoginProcess(profile.getUniqueId(), username, user); } catch (Exception ex) { - this.plugin.getLog().severe("Exception occurred whilst loading data for " + p.getUniqueId() + " - " + p.getName()); + this.plugin.getLog().severe("Exception occurred whilst loading data for " + profile.getUniqueId() + " - " + profile.getName()); ex.printStackTrace(); - this.deniedAsyncLogin.add(p.getUniqueId()); + this.deniedAsyncLogin.add(profile.getUniqueId()); e.setCancelled(true); e.setMessageCancelled(false); @@ -120,19 +120,19 @@ public class SpongeConnectionListener extends AbstractLoginListener { At this point, the users data should be present and loaded. Listening on LOW priority to allow plugins to further modify data here. (auth plugins, etc.) */ - final GameProfile player = e.getProfile(); + final GameProfile profile = e.getProfile(); if (this.plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) { - this.plugin.getLog().info("Processing login event for " + player.getUniqueId() + " - " + player.getName()); + this.plugin.getLog().info("Processing login event for " + profile.getUniqueId() + " - " + profile.getName()); } - final User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId()); + final User user = this.plugin.getUserManager().getIfLoaded(profile.getUniqueId()); /* User instance is null for whatever reason. Could be that it was unloaded between asyncpre and now. */ if (user == null) { - this.deniedLogin.add(player.getUniqueId()); + this.deniedLogin.add(profile.getUniqueId()); - this.plugin.getLog().warn("User " + player.getUniqueId() + " - " + player.getName() + " doesn't have data pre-loaded. - denying login."); + this.plugin.getLog().warn("User " + profile.getUniqueId() + " - " + profile.getName() + " doesn't have data pre-loaded. - denying login."); e.setCancelled(true); e.setMessageCancelled(false); //noinspection deprecation diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionManager.java b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionManager.java index c6dd8a73..c2c32357 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionManager.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionManager.java @@ -73,7 +73,7 @@ public class MigrationPermissionManager extends SubCommand { Optional pm = Sponge.getPluginManager().getPlugin("permissionmanager"); if (!pm.isPresent()) { - log.logErr("Plugin not loaded."); + log.logError("Plugin not loaded."); return CommandResult.STATE_ERROR; } @@ -120,7 +120,7 @@ public class MigrationPermissionManager extends SubCommand { SafeIteration.iterate(pmService.getUserSubjects().getAllSubjects(), pmUser -> { UUID uuid = Uuids.parseNullable(pmUser.getIdentifier()); if (uuid == null) { - log.logErr("Could not parse UUID for user: " + pmUser.getIdentifier()); + log.logError("Could not parse UUID for user: " + pmUser.getIdentifier()); return; } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java index b1cf471e..c039e99e 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java @@ -79,7 +79,7 @@ public class MigrationPermissionsEx extends SubCommand { Optional pex = Sponge.getPluginManager().getPlugin("permissionsex"); if (!pex.isPresent()) { - log.logErr("Plugin not loaded."); + log.logError("Plugin not loaded."); return CommandResult.STATE_ERROR; } @@ -172,7 +172,7 @@ public class MigrationPermissionsEx extends SubCommand { SafeIteration.iterate(pexService.getUserSubjects().getAllSubjects(), pexUser -> { UUID uuid = Uuids.parseNullable(pexUser.getIdentifier()); if (uuid == null) { - log.logErr("Could not parse UUID for user: " + pexUser.getIdentifier()); + log.logError("Could not parse UUID for user: " + pexUser.getIdentifier()); return; } 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 035bc812..0659030d 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 @@ -25,32 +25,11 @@ package me.lucko.luckperms.sponge.model; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.caching.MetaData; -import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.common.model.Group; -import me.lucko.luckperms.common.node.NodeFactory; -import me.lucko.luckperms.common.verbose.CheckOrigin; import me.lucko.luckperms.sponge.LPSpongePlugin; -import me.lucko.luckperms.sponge.service.LuckPermsService; -import me.lucko.luckperms.sponge.service.LuckPermsSubjectData; -import me.lucko.luckperms.sponge.service.ProxyFactory; -import me.lucko.luckperms.sponge.service.model.LPSubject; -import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; -import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; - -import org.spongepowered.api.command.CommandSource; -import org.spongepowered.api.service.permission.PermissionService; -import org.spongepowered.api.service.permission.Subject; - -import java.util.Map; -import java.util.Optional; - -public class SpongeGroup extends Group { +import me.lucko.luckperms.sponge.service.internal.GroupSubject; +public class SpongeGroup extends Group implements SpongePermissionHolder { private final GroupSubject spongeData; public SpongeGroup(String name, LPSpongePlugin plugin) { @@ -58,133 +37,9 @@ public class SpongeGroup extends Group { this.spongeData = new GroupSubject(plugin, this); } + @Override public GroupSubject sponge() { return this.spongeData; } - public static class GroupSubject implements LPSubject { - private final SpongeGroup parent; - private final LPSpongePlugin plugin; - - private final LuckPermsSubjectData subjectData; - - private final LuckPermsSubjectData transientSubjectData; - - private GroupSubject(LPSpongePlugin plugin, SpongeGroup parent) { - this.parent = parent; - this.plugin = plugin; - this.subjectData = new LuckPermsSubjectData(true, plugin.getService(), parent, this); - this.transientSubjectData = new LuckPermsSubjectData(false, plugin.getService(), parent, this); - } - - @Override - public String getIdentifier() { - return this.parent.getObjectName(); - } - - @Override - public Optional getFriendlyIdentifier() { - return this.parent.getDisplayName(); - } - - @Override - public Optional getCommandSource() { - return Optional.empty(); - } - - @Override - public LPSubjectCollection getParentCollection() { - return this.plugin.getService().getGroupSubjects(); - } - - @Override - public Subject sponge() { - return ProxyFactory.toSponge(this); - } - - @Override - public LuckPermsService getService() { - return this.plugin.getService(); - } - - @Override - public LuckPermsSubjectData getSubjectData() { - return this.subjectData; - } - - @Override - public LuckPermsSubjectData getTransientSubjectData() { - return this.transientSubjectData; - } - - @Override - public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) { - return this.parent.getCachedData().getPermissionData(this.plugin.getContextManager().formContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK); - } - - @Override - public boolean isChildOf(ImmutableContextSet contexts, LPSubjectReference parent) { - return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, NodeFactory.groupNode(parent.getSubjectIdentifier())).asBoolean(); - } - - @Override - public ImmutableList getParents(ImmutableContextSet contexts) { - ImmutableSet.Builder subjects = ImmutableSet.builder(); - - for (Map.Entry entry : this.parent.getCachedData().getPermissionData(this.plugin.getContextManager().formContexts(contexts)).getImmutableBacking().entrySet()) { - if (!entry.getValue()) { - continue; - } - - String groupName = NodeFactory.parseGroupNode(entry.getKey()); - if (groupName == null) { - continue; - } - - if (this.plugin.getGroupManager().isLoaded(groupName)) { - subjects.add(this.plugin.getService().getGroupSubjects().loadSubject(groupName).join().toReference()); - } - } - - subjects.addAll(this.plugin.getService().getGroupSubjects().getDefaults().getParents(contexts)); - subjects.addAll(this.plugin.getService().getDefaults().getParents(contexts)); - - return getService().sortSubjects(subjects.build()); - } - - @Override - public Optional getOption(ImmutableContextSet contexts, String s) { - MetaData data = this.parent.getCachedData().getMetaData(this.plugin.getContextManager().formContexts(contexts)); - if (s.equalsIgnoreCase(NodeFactory.PREFIX_KEY)) { - if (data.getPrefix() != null) { - return Optional.of(data.getPrefix()); - } - } - - if (s.equalsIgnoreCase(NodeFactory.SUFFIX_KEY)) { - if (data.getSuffix() != null) { - return Optional.of(data.getSuffix()); - } - } - - String val = data.getMeta().get(s); - if (val != null) { - return Optional.of(val); - } - - Optional v = this.plugin.getService().getGroupSubjects().getDefaults().getOption(contexts, s); - if (v.isPresent()) { - return v; - } - - return this.plugin.getService().getDefaults().getOption(contexts, s); - } - - @Override - public void invalidateCaches(CacheLevel cacheLevel) { - // invalidate for all changes - this.parent.getCachedData().invalidateCaches(); - } - } - } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongePermissionHolder.java b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongePermissionHolder.java new file mode 100644 index 00000000..02eea2da --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongePermissionHolder.java @@ -0,0 +1,43 @@ +/* + * 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.sponge.model; + +import me.lucko.luckperms.common.model.PermissionHolder; +import me.lucko.luckperms.sponge.service.model.LPSubject; + +/** + * A sponge specific extension of {@link PermissionHolder}. + */ +public interface SpongePermissionHolder { + + /** + * Gets a {@link LPSubject} representation of this holder. + * + * @return a subject + */ + LPSubject sponge(); + +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeUser.java b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeUser.java index ad7f28c3..d0c58a9b 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeUser.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeUser.java @@ -25,35 +25,17 @@ package me.lucko.luckperms.sponge.model; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -import me.lucko.luckperms.api.Tristate; -import me.lucko.luckperms.api.caching.MetaData; -import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.common.model.User; -import me.lucko.luckperms.common.node.NodeFactory; -import me.lucko.luckperms.common.verbose.CheckOrigin; import me.lucko.luckperms.sponge.LPSpongePlugin; -import me.lucko.luckperms.sponge.service.LuckPermsService; -import me.lucko.luckperms.sponge.service.LuckPermsSubjectData; -import me.lucko.luckperms.sponge.service.ProxyFactory; +import me.lucko.luckperms.sponge.service.internal.UserSubject; import me.lucko.luckperms.sponge.service.model.LPSubject; -import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; -import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.command.CommandSource; -import org.spongepowered.api.service.permission.PermissionService; -import org.spongepowered.api.service.permission.Subject; - -import java.util.Map; -import java.util.Optional; import java.util.UUID; -import java.util.function.Function; - -public class SpongeUser extends User { +/** + * Extension of {@link User} to hold an implementation for {@link LPSubject}. + */ +public class SpongeUser extends User implements SpongePermissionHolder { private final UserSubject spongeData; public SpongeUser(UUID uuid, LPSpongePlugin plugin) { @@ -66,134 +48,9 @@ public class SpongeUser extends User { this.spongeData = new UserSubject(plugin, this); } + @Override public UserSubject sponge() { return this.spongeData; } - public static final class UserSubject implements LPSubject { - private final SpongeUser parent; - private final LPSpongePlugin plugin; - - private final LuckPermsSubjectData subjectData; - - private final LuckPermsSubjectData transientSubjectData; - - private UserSubject(LPSpongePlugin plugin, SpongeUser parent) { - this.parent = parent; - this.plugin = plugin; - this.subjectData = new LuckPermsSubjectData(true, plugin.getService(), parent, this); - this.transientSubjectData = new LuckPermsSubjectData(false, plugin.getService(), parent, this); - } - - @Override - public String getIdentifier() { - return this.parent.getUuid().toString(); - } - - @Override - public Optional getFriendlyIdentifier() { - return this.parent.getName(); - } - - @Override - public Optional getCommandSource() { - final UUID uuid = this.parent.getUuid(); - return Sponge.getServer().getPlayer(uuid).map(Function.identity()); - } - - @Override - public LPSubjectCollection getParentCollection() { - return this.plugin.getService().getUserSubjects(); - } - - @Override - public Subject sponge() { - return ProxyFactory.toSponge(this); - } - - @Override - public LuckPermsService getService() { - return this.plugin.getService(); - } - - @Override - public LuckPermsSubjectData getSubjectData() { - return this.subjectData; - } - - @Override - public LuckPermsSubjectData getTransientSubjectData() { - return this.transientSubjectData; - } - - @Override - public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) { - return this.parent.getCachedData().getPermissionData(this.plugin.getContextManager().formContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK); - } - - @Override - public boolean isChildOf(ImmutableContextSet contexts, LPSubjectReference parent) { - return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, NodeFactory.groupNode(parent.getSubjectIdentifier())).asBoolean(); - } - - @Override - public ImmutableList getParents(ImmutableContextSet contexts) { - ImmutableSet.Builder subjects = ImmutableSet.builder(); - - for (Map.Entry entry : this.parent.getCachedData().getPermissionData(this.plugin.getContextManager().formContexts(contexts)).getImmutableBacking().entrySet()) { - if (!entry.getValue()) { - continue; - } - - String groupName = NodeFactory.parseGroupNode(entry.getKey()); - if (groupName == null) { - continue; - } - - if (this.plugin.getGroupManager().isLoaded(groupName)) { - subjects.add(this.plugin.getService().getGroupSubjects().loadSubject(groupName).join().toReference()); - } - } - - subjects.addAll(this.plugin.getService().getUserSubjects().getDefaults().getParents(contexts)); - subjects.addAll(this.plugin.getService().getDefaults().getParents(contexts)); - - return getService().sortSubjects(subjects.build()); - } - - @Override - public Optional getOption(ImmutableContextSet contexts, String s) { - MetaData data = this.parent.getCachedData().getMetaData(this.plugin.getContextManager().formContexts(contexts)); - if (s.equalsIgnoreCase(NodeFactory.PREFIX_KEY)) { - if (data.getPrefix() != null) { - return Optional.of(data.getPrefix()); - } - } - - if (s.equalsIgnoreCase(NodeFactory.SUFFIX_KEY)) { - if (data.getSuffix() != null) { - return Optional.of(data.getSuffix()); - } - } - - String val = data.getMeta().get(s); - if (val != null) { - return Optional.of(val); - } - - Optional v = this.plugin.getService().getUserSubjects().getDefaults().getOption(contexts, s); - if (v.isPresent()) { - return v; - } - - return this.plugin.getService().getDefaults().getOption(contexts, s); - } - - @Override - public void invalidateCaches(CacheLevel cacheLevel) { - // invalidate for all changes - this.parent.getCachedData().invalidateCaches(); - } - } - } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsPermissionDescription.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsPermissionDescription.java index 078b93ee..fe410007 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsPermissionDescription.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsPermissionDescription.java @@ -43,7 +43,6 @@ import java.util.concurrent.CompletableFuture; import javax.annotation.Nullable; public final class LuckPermsPermissionDescription implements LPPermissionDescription { - private final LPPermissionService service; private final String id; diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsService.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsService.java index 453c417e..018739a6 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsService.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsService.java @@ -37,7 +37,6 @@ import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.contexts.SpongeProxiedContextCalculator; import me.lucko.luckperms.sponge.managers.SpongeGroupManager; import me.lucko.luckperms.sponge.managers.SpongeUserManager; -import me.lucko.luckperms.sponge.service.legacy.LegacyDataMigrator; import me.lucko.luckperms.sponge.service.model.LPPermissionDescription; import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubject; @@ -90,7 +89,6 @@ public class LuckPermsService implements LPPermissionService { this.spongeProxy = ProxyFactory.toSponge(this); this.storage = new SubjectStorage(this, new File(plugin.getDataDirectory(), "sponge-data")); - new LegacyDataMigrator(plugin, new File(plugin.getDataDirectory(), "local"), this.storage).run(); this.userSubjects = plugin.getUserManager(); this.groupSubjects = plugin.getGroupManager(); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java index 6b4e048e..b27e47a7 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java @@ -29,7 +29,6 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSortedMap; import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; @@ -38,7 +37,6 @@ import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata; import me.lucko.luckperms.common.contexts.ContextSetComparator; import me.lucko.luckperms.common.processors.MapProcessor; import me.lucko.luckperms.common.processors.PermissionProcessor; -import me.lucko.luckperms.common.references.HolderType; import me.lucko.luckperms.common.verbose.CheckOrigin; import me.lucko.luckperms.sponge.processors.SpongeWildcardProcessor; import me.lucko.luckperms.sponge.service.model.LPPermissionService; @@ -52,6 +50,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.SortedMap; +import java.util.TreeMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -60,33 +59,28 @@ import java.util.concurrent.TimeUnit; * In-memory implementation of {@link LPSubjectData}. */ public class CalculatedSubjectData implements LPSubjectData { - private final LPSubject parentSubject; - private final LPPermissionService service; - private final String calculatorDisplayName; private final Map> permissions = new ConcurrentHashMap<>(); private final Map> parents = new ConcurrentHashMap<>(); private final Map> options = new ConcurrentHashMap<>(); - private final LoadingCache permissionCache = Caffeine.newBuilder() - .expireAfterAccess(10, TimeUnit.MINUTES) - .build(contexts -> { - ImmutableList.Builder processors = ImmutableList.builder(); - processors.add(new MapProcessor()); - processors.add(new SpongeWildcardProcessor()); - - CalculatorHolder holder = new CalculatorHolder(new PermissionCalculator(CalculatedSubjectData.this.service.getPlugin(), PermissionCalculatorMetadata.of(HolderType.GROUP, CalculatedSubjectData.this.calculatorDisplayName, contexts), processors.build())); - holder.setPermissions(flattenMap(getRelevantEntries(contexts, CalculatedSubjectData.this.permissions))); - - return holder; - }); + private final LoadingCache permissionCache; public CalculatedSubjectData(LPSubject parentSubject, LPPermissionService service, String calculatorDisplayName) { this.parentSubject = parentSubject; this.service = service; - this.calculatorDisplayName = calculatorDisplayName; + this.permissionCache = Caffeine.newBuilder() + .expireAfterAccess(10, TimeUnit.MINUTES) + .build(contexts -> { + ImmutableList processors = ImmutableList.of(new MapProcessor(), new SpongeWildcardProcessor()); + PermissionCalculatorMetadata calcMetadata = PermissionCalculatorMetadata.of(null, calculatorDisplayName, contexts); + + CalculatorHolder holder = new CalculatorHolder(new PermissionCalculator(this.service.getPlugin(), calcMetadata, processors)); + holder.setPermissions(processPermissionsMap(contexts, this.permissions)); + return holder; + }); } @Override @@ -103,7 +97,8 @@ public class CalculatedSubjectData implements LPSubjectData { } public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) { - return this.permissionCache.get(contexts).getCalculator().getPermissionValue(permission, CheckOrigin.INTERNAL); + CalculatorHolder calculatorHolder = Objects.requireNonNull(this.permissionCache.get(contexts)); + return calculatorHolder.getCalculator().getPermissionValue(permission, CheckOrigin.INTERNAL); } public void replacePermissions(Map> map) { @@ -291,30 +286,25 @@ public class CalculatedSubjectData implements LPSubjectData { return CompletableFuture.completedFuture(!map.isEmpty()); } - private static Map flattenMap(SortedMap> data) { - Map map = new HashMap<>(); - - for (Map m : data.values()) { - for (Map.Entry e : m.entrySet()) { - map.putIfAbsent(e.getKey(), e.getValue()); - } - } - - return ImmutableMap.copyOf(map); - } - - private static SortedMap> getRelevantEntries(ImmutableContextSet set, Map> map) { - ImmutableSortedMap.Builder> perms = ImmutableSortedMap.orderedBy(ContextSetComparator.reverse()); - - for (Map.Entry> e : map.entrySet()) { - if (!e.getKey().isSatisfiedBy(set)) { + private static Map processPermissionsMap(ImmutableContextSet filter, Map> input) { + // get relevant entries + SortedMap> sorted = new TreeMap<>(ContextSetComparator.reverse()); + for (Map.Entry> entry : input.entrySet()) { + if (!entry.getKey().isSatisfiedBy(filter)) { continue; } - perms.put(e.getKey(), ImmutableMap.copyOf(e.getValue())); + sorted.put(entry.getKey(), entry.getValue()); } - return perms.build(); + // flatten + Map result = new HashMap<>(); + for (Map map : sorted.values()) { + for (Map.Entry e : map.entrySet()) { + result.putIfAbsent(e.getKey(), e.getValue()); + } + } + return ImmutableMap.copyOf(result); } private static boolean stringEquals(String a, String b) { @@ -322,9 +312,7 @@ public class CalculatedSubjectData implements LPSubjectData { } private static class CalculatorHolder { - private final PermissionCalculator calculator; - private final Map permissions; public CalculatorHolder(PermissionCalculator calculator) { diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/OptionLookupKey.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/GroupSubject.java similarity index 50% rename from sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/OptionLookupKey.java rename to sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/GroupSubject.java index 1ea45ecc..44e46290 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/OptionLookupKey.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/GroupSubject.java @@ -23,52 +23,42 @@ * SOFTWARE. */ -package me.lucko.luckperms.sponge.service.persisted; +package me.lucko.luckperms.sponge.service.internal; -import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.sponge.LPSpongePlugin; +import me.lucko.luckperms.sponge.model.SpongeGroup; +import me.lucko.luckperms.sponge.service.model.LPSubject; +import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; -public final class OptionLookupKey { +import org.spongepowered.api.command.CommandSource; - public static OptionLookupKey of(String key, ImmutableContextSet contexts) { - return new OptionLookupKey(key, contexts); - } +import java.util.Optional; - private final String key; - private final ImmutableContextSet contexts; - - private OptionLookupKey(String key, ImmutableContextSet contexts) { - this.key = key; - this.contexts = contexts; - } - - public String getKey() { - return this.key; - } - - public ImmutableContextSet getContexts() { - return this.contexts; +/** + * Implements {@link LPSubject} for a {@link SpongeGroup}. + */ +public class GroupSubject extends HolderSubject implements LPSubject { + public GroupSubject(LPSpongePlugin plugin, SpongeGroup parent) { + super(plugin, parent); } @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof OptionLookupKey)) return false; - final OptionLookupKey other = (OptionLookupKey) o; - - return this.getKey().equals(other.getKey()) && this.getContexts().equals(other.getContexts()); + public String getIdentifier() { + return this.parent.getObjectName(); } @Override - public int hashCode() { - final int PRIME = 59; - int result = 1; - result = result * PRIME + this.getKey().hashCode(); - result = result * PRIME + this.getContexts().hashCode(); - return result; + public Optional getFriendlyIdentifier() { + return this.parent.getDisplayName(); } @Override - public String toString() { - return "OptionLookupKey(key=" + this.getKey() + ", contexts=" + this.getContexts() + ")"; + public Optional getCommandSource() { + return Optional.empty(); } -} \ No newline at end of file + + @Override + public LPSubjectCollection getParentCollection() { + return this.plugin.getService().getGroupSubjects(); + } +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/HolderSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/HolderSubject.java new file mode 100644 index 00000000..b33d2374 --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/HolderSubject.java @@ -0,0 +1,156 @@ +/* + * 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.sponge.service.internal; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.caching.MetaData; +import me.lucko.luckperms.api.context.ImmutableContextSet; +import me.lucko.luckperms.common.model.NodeMapType; +import me.lucko.luckperms.common.model.PermissionHolder; +import me.lucko.luckperms.common.node.NodeFactory; +import me.lucko.luckperms.common.verbose.CheckOrigin; +import me.lucko.luckperms.sponge.LPSpongePlugin; +import me.lucko.luckperms.sponge.service.LuckPermsService; +import me.lucko.luckperms.sponge.service.ProxyFactory; +import me.lucko.luckperms.sponge.service.model.LPSubject; +import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; + +import org.spongepowered.api.service.permission.PermissionService; +import org.spongepowered.api.service.permission.Subject; + +import java.util.Map; +import java.util.Optional; + +/** + * Implements {@link LPSubject} for a {@link PermissionHolder}. + */ +public abstract class HolderSubject implements LPSubject { + protected final T parent; + protected final LPSpongePlugin plugin; + + private final HolderSubjectData subjectData; + private final HolderSubjectData transientSubjectData; + + HolderSubject(LPSpongePlugin plugin, T parent) { + this.parent = parent; + this.plugin = plugin; + this.subjectData = new HolderSubjectData(plugin.getService(), NodeMapType.ENDURING, parent, this); + this.transientSubjectData = new HolderSubjectData(plugin.getService(), NodeMapType.TRANSIENT, parent, this); + } + + @Override + public Subject sponge() { + return ProxyFactory.toSponge(this); + } + + @Override + public LuckPermsService getService() { + return this.plugin.getService(); + } + + @Override + public HolderSubjectData getSubjectData() { + return this.subjectData; + } + + @Override + public HolderSubjectData getTransientSubjectData() { + return this.transientSubjectData; + } + + @Override + public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) { + return this.parent.getCachedData().getPermissionData(this.plugin.getContextManager().formContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK); + } + + @Override + public boolean isChildOf(ImmutableContextSet contexts, LPSubjectReference parent) { + return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, NodeFactory.groupNode(parent.getSubjectIdentifier())).asBoolean(); + } + + @Override + public ImmutableList getParents(ImmutableContextSet contexts) { + ImmutableSet.Builder subjects = ImmutableSet.builder(); + + for (Map.Entry entry : this.parent.getCachedData().getPermissionData(this.plugin.getContextManager().formContexts(contexts)).getImmutableBacking().entrySet()) { + if (!entry.getValue()) { + continue; + } + + String groupName = NodeFactory.parseGroupNode(entry.getKey()); + if (groupName == null) { + continue; + } + + if (this.plugin.getGroupManager().isLoaded(groupName)) { + subjects.add(this.plugin.getService().getGroupSubjects().loadSubject(groupName).join().toReference()); + } + } + + subjects.addAll(getParentCollection().getDefaults().getParents(contexts)); + subjects.addAll(this.plugin.getService().getDefaults().getParents(contexts)); + + return getService().sortSubjects(subjects.build()); + } + + @Override + public Optional getOption(ImmutableContextSet contexts, String s) { + MetaData data = this.parent.getCachedData().getMetaData(this.plugin.getContextManager().formContexts(contexts)); + if (s.equalsIgnoreCase(NodeFactory.PREFIX_KEY)) { + if (data.getPrefix() != null) { + return Optional.of(data.getPrefix()); + } + } + + if (s.equalsIgnoreCase(NodeFactory.SUFFIX_KEY)) { + if (data.getSuffix() != null) { + return Optional.of(data.getSuffix()); + } + } + + String val = data.getMeta().get(s); + if (val != null) { + return Optional.of(val); + } + + Optional v = getParentCollection().getDefaults().getOption(contexts, s); + if (v.isPresent()) { + return v; + } + + return this.plugin.getService().getDefaults().getOption(contexts, s); + } + + @Override + public void invalidateCaches(CacheLevel cacheLevel) { + // invalidate for all changes + this.parent.getCachedData().invalidateCaches(); + } + +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/HolderSubjectData.java similarity index 56% rename from sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java rename to sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/HolderSubjectData.java index eb78b311..b4bbf2ca 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/HolderSubjectData.java @@ -23,7 +23,7 @@ * SOFTWARE. */ -package me.lucko.luckperms.sponge.service; +package me.lucko.luckperms.sponge.service.internal; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -35,9 +35,11 @@ import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.common.caching.type.MetaAccumulator; import me.lucko.luckperms.common.model.Group; +import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.NodeFactory; +import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; @@ -50,25 +52,27 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; -public class LuckPermsSubjectData implements LPSubjectData { - private final boolean enduring; +public class HolderSubjectData implements LPSubjectData { private final LuckPermsService service; + private final NodeMapType type; private final PermissionHolder holder; - private final LPSubject parentSubject; - public LuckPermsSubjectData(boolean enduring, LuckPermsService service, PermissionHolder holder, LPSubject parentSubject) { - this.enduring = enduring; + public HolderSubjectData(LuckPermsService service, NodeMapType type, PermissionHolder holder, LPSubject parentSubject) { + this.type = type; this.service = service; this.holder = holder; this.parentSubject = parentSubject; } + private Stream streamNodes() { + return this.holder.getNodes(this.type).values().stream(); + } + @Override public LPSubject getParentSubject() { return this.parentSubject; @@ -76,21 +80,15 @@ public class LuckPermsSubjectData implements LPSubjectData { @Override public ImmutableMap> getAllPermissions() { - Map> perms = new HashMap<>(); - - for (Map.Entry> e : (this.enduring ? this.holder.getEnduringNodes() : this.holder.getTransientNodes()).asMap().entrySet()) { - ImmutableMap.Builder results = ImmutableMap.builder(); - for (Node n : e.getValue()) { - results.put(n.getPermission(), n.getValuePrimitive()); + ImmutableMap.Builder> ret = ImmutableMap.builder(); + for (Map.Entry> entry : this.holder.getNodes(this.type).asMap().entrySet()) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Node n : entry.getValue()) { + builder.put(n.getPermission(), n.getValuePrimitive()); } - perms.put(e.getKey(), results); + ret.put(entry.getKey(), builder.build()); } - - ImmutableMap.Builder> map = ImmutableMap.builder(); - for (Map.Entry> e : perms.entrySet()) { - map.put(e.getKey(), e.getValue().build()); - } - return map.build(); + return ret.build(); } @Override @@ -102,42 +100,35 @@ public class LuckPermsSubjectData implements LPSubjectData { if (tristate == Tristate.UNDEFINED) { // Unset Node node = NodeFactory.builder(permission).withExtraContext(contexts).build(); - - if (this.enduring) { - this.holder.unsetPermission(node); - } else { - this.holder.unsetTransientPermission(node); - } - + this.type.run( + () -> this.holder.unsetPermission(node), + () -> this.holder.unsetTransientPermission(node) + ); return objectSave(this.holder).thenApply(v -> true); } Node node = NodeFactory.builder(permission).setValue(tristate.asBoolean()).withExtraContext(contexts).build(); - - // Workaround: unset the inverse, to allow false -> true, true -> false overrides. - if (this.enduring) { - this.holder.unsetPermission(node); - } else { - this.holder.unsetTransientPermission(node); - } - - if (this.enduring) { - this.holder.setPermission(node); - } else { - this.holder.setTransientPermission(node); - } - + this.type.run( + () -> { + // unset the inverse, to allow false -> true, true -> false overrides. + this.holder.unsetPermission(node); + this.holder.setPermission(node); + }, + () -> { + // unset the inverse, to allow false -> true, true -> false overrides. + this.holder.unsetTransientPermission(node); + this.holder.setTransientPermission(node); + } + ); return objectSave(this.holder).thenApply(v -> true); } @Override public CompletableFuture clearPermissions() { - boolean ret; - if (this.enduring) { - ret = this.holder.clearNodes(); - } else { - ret = this.holder.clearTransientNodes(); - } + boolean ret = this.type.supply( + this.holder::clearNodes, + this.holder::clearTransientNodes + ); if (!ret) { return CompletableFuture.completedFuture(false); @@ -153,18 +144,17 @@ public class LuckPermsSubjectData implements LPSubjectData { @Override public CompletableFuture clearPermissions(ImmutableContextSet contexts) { Objects.requireNonNull(contexts, "contexts"); + boolean ret = this.type.supply( + () -> this.holder.clearNodes(contexts), + () -> { + List toRemove = streamNodes() + .filter(n -> n.getFullContexts().equals(contexts)) + .collect(Collectors.toList()); - boolean ret; - if (this.enduring) { - ret = this.holder.clearNodes(contexts); - } else { - List toRemove = streamNodes(false) - .filter(n -> n.getFullContexts().equals(contexts)) - .collect(Collectors.toList()); - - toRemove.forEach(makeUnsetConsumer(false)); - ret = !toRemove.isEmpty(); - } + toRemove.forEach(this.holder::unsetTransientPermission); + return !toRemove.isEmpty(); + } + ); if (!ret) { return CompletableFuture.completedFuture(false); @@ -179,23 +169,17 @@ public class LuckPermsSubjectData implements LPSubjectData { @Override public ImmutableMap> getAllParents() { - Map> parents = new HashMap<>(); - - for (Map.Entry> e : (this.enduring ? this.holder.getEnduringNodes() : this.holder.getTransientNodes()).asMap().entrySet()) { - ImmutableList.Builder results = ImmutableList.builder(); - for (Node n : e.getValue()) { + ImmutableMap.Builder> ret = ImmutableMap.builder(); + for (Map.Entry> entry : this.holder.getNodes(this.type).asMap().entrySet()) { + ImmutableList.Builder builder = ImmutableList.builder(); + for (Node n : entry.getValue()) { if (n.isGroupNode()) { - results.add(this.service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference()); + builder.add(this.service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference()); } } - parents.put(e.getKey(), results); + ret.put(entry.getKey(), builder.build()); } - - ImmutableMap.Builder> map = ImmutableMap.builder(); - for (Map.Entry> e : parents.entrySet()) { - map.put(e.getKey(), e.getValue().build()); - } - return map.build(); + return ret.build(); } @Override @@ -203,28 +187,24 @@ public class LuckPermsSubjectData implements LPSubjectData { Objects.requireNonNull(contexts, "contexts"); Objects.requireNonNull(subject, "subject"); - if (subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) { - return subject.resolveLp().thenCompose(sub -> { - DataMutateResult result; - - if (this.enduring) { - result = this.holder.setPermission(NodeFactory.buildGroupNode(sub.getIdentifier()) - .withExtraContext(contexts) - .build()); - } else { - result = this.holder.setTransientPermission(NodeFactory.buildGroupNode(sub.getIdentifier()) - .withExtraContext(contexts) - .build()); - } - - if (!result.asBoolean()) { - return CompletableFuture.completedFuture(false); - } - - return objectSave(this.holder).thenApply(v -> true); - }); + if (!subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) { + return CompletableFuture.completedFuture(false); } - return CompletableFuture.completedFuture(false); + + Node node = NodeFactory.buildGroupNode(subject.getSubjectIdentifier()) + .withExtraContext(contexts) + .build(); + + DataMutateResult result = this.type.supply( + () -> this.holder.setPermission(node), + () -> this.holder.setTransientPermission(node) + ); + + if (!result.asBoolean()) { + return CompletableFuture.completedFuture(false); + } + + return objectSave(this.holder).thenApply(v -> true); } @Override @@ -232,47 +212,39 @@ public class LuckPermsSubjectData implements LPSubjectData { Objects.requireNonNull(contexts, "contexts"); Objects.requireNonNull(subject, "subject"); - if (subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) { - subject.resolveLp().thenCompose(sub -> { - DataMutateResult result; - - if (this.enduring) { - result = this.holder.unsetPermission(NodeFactory.buildGroupNode(sub.getIdentifier()) - .withExtraContext(contexts) - .build()); - } else { - result = this.holder.unsetTransientPermission(NodeFactory.buildGroupNode(sub.getIdentifier()) - .withExtraContext(contexts) - .build()); - } - - if (!result.asBoolean()) { - return CompletableFuture.completedFuture(false); - } - - return objectSave(this.holder).thenApply(v -> true); - }); + if (!subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) { + return CompletableFuture.completedFuture(false); } - return CompletableFuture.completedFuture(false); + + Node node = NodeFactory.buildGroupNode(subject.getSubjectIdentifier()) + .withExtraContext(contexts) + .build(); + + DataMutateResult result = this.type.supply( + () -> this.holder.unsetPermission(node), + () -> this.holder.unsetTransientPermission(node) + ); + + if (!result.asBoolean()) { + return CompletableFuture.completedFuture(false); + } + + return objectSave(this.holder).thenApply(v -> true); } @Override public CompletableFuture clearParents() { - boolean ret; - if (this.enduring) { - ret = this.holder.clearParents(true); - } else { - List toRemove = streamNodes(false) - .filter(Node::isGroupNode) - .collect(Collectors.toList()); + boolean ret = this.type.supply( + () -> this.holder.clearParents(true), + () -> { + List toRemove = streamNodes() + .filter(Node::isGroupNode) + .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(false)); - ret = !toRemove.isEmpty(); - - if (ret && this.holder.getType().isUser()) { - this.service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) this.holder), false); - } - } + toRemove.forEach(this.holder::unsetTransientPermission); + return !toRemove.isEmpty(); + } + ); if (!ret) { return CompletableFuture.completedFuture(false); @@ -284,23 +256,18 @@ public class LuckPermsSubjectData implements LPSubjectData { @Override public CompletableFuture clearParents(ImmutableContextSet contexts) { Objects.requireNonNull(contexts, "contexts"); + boolean ret = this.type.supply( + () -> this.holder.clearParents(contexts, true), + () -> { + List toRemove = streamNodes() + .filter(Node::isGroupNode) + .filter(n -> n.getFullContexts().equals(contexts)) + .collect(Collectors.toList()); - boolean ret; - if (this.enduring) { - ret = this.holder.clearParents(contexts, true); - } else { - List toRemove = streamNodes(false) - .filter(Node::isGroupNode) - .filter(n -> n.getFullContexts().equals(contexts)) - .collect(Collectors.toList()); - - toRemove.forEach(makeUnsetConsumer(false)); - ret = !toRemove.isEmpty(); - - if (ret && this.holder.getType().isUser()) { - this.service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) this.holder), false); - } - } + toRemove.forEach(this.holder::unsetTransientPermission); + return !toRemove.isEmpty(); + } + ); if (!ret) { return CompletableFuture.completedFuture(false); @@ -315,7 +282,7 @@ public class LuckPermsSubjectData implements LPSubjectData { Map minPrefixPriority = new HashMap<>(); Map minSuffixPriority = new HashMap<>(); - for (Node n : this.enduring ? this.holder.getEnduringNodes().values() : this.holder.getTransientNodes().values()) { + for (Node n : this.holder.getNodes(this.type).values()) { if (!n.getValuePrimitive()) continue; if (!n.isMeta() && !n.isPrefix() && !n.isSuffix()) continue; @@ -364,44 +331,46 @@ public class LuckPermsSubjectData implements LPSubjectData { Objects.requireNonNull(key, "key"); Objects.requireNonNull(value, "value"); + Node node; if (key.equalsIgnoreCase(NodeFactory.PREFIX_KEY) || key.equalsIgnoreCase(NodeFactory.SUFFIX_KEY)) { // special handling. ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase()); // remove all prefixes/suffixes from the user - List toRemove = streamNodes(this.enduring) + List toRemove = streamNodes() .filter(type::matches) .filter(n -> n.getFullContexts().equals(contexts)) .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(this.enduring)); + toRemove.forEach(n -> this.type.run( + () -> this.holder.unsetPermission(n), + () -> this.holder.unsetTransientPermission(n) + )); MetaAccumulator metaAccumulator = this.holder.accumulateMeta(null, this.service.getPlugin().getContextManager().formContexts(contexts)); int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0); priority += 10; - if (this.enduring) { - this.holder.setPermission(NodeFactory.buildChatMetaNode(type, priority, value).withExtraContext(contexts).build()); - } else { - this.holder.setTransientPermission(NodeFactory.buildChatMetaNode(type, priority, value).withExtraContext(contexts).build()); - } - + node = NodeFactory.buildChatMetaNode(type, priority, value).withExtraContext(contexts).build(); } else { // standard remove - List toRemove = streamNodes(this.enduring) + List toRemove = streamNodes() .filter(n -> n.isMeta() && n.getMeta().getKey().equals(key)) .filter(n -> n.getFullContexts().equals(contexts)) .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(this.enduring)); + toRemove.forEach(n -> this.type.run( + () -> this.holder.unsetPermission(n), + () -> this.holder.unsetTransientPermission(n) + )); - if (this.enduring) { - this.holder.setPermission(NodeFactory.buildMetaNode(key, value).withExtraContext(contexts).build()); - } else { - this.holder.setTransientPermission(NodeFactory.buildMetaNode(key, value).withExtraContext(contexts).build()); - } + node = NodeFactory.buildMetaNode(key, value).withExtraContext(contexts).build(); } + this.type.run( + () -> this.holder.setPermission(node), + () -> this.holder.setTransientPermission(node) + ); return objectSave(this.holder).thenApply(v -> true); } @@ -410,7 +379,7 @@ public class LuckPermsSubjectData implements LPSubjectData { Objects.requireNonNull(contexts, "contexts"); Objects.requireNonNull(key, "key"); - List toRemove = streamNodes(this.enduring) + List toRemove = streamNodes() .filter(n -> { if (key.equalsIgnoreCase(NodeFactory.PREFIX_KEY)) { return n.isPrefix(); @@ -423,7 +392,10 @@ public class LuckPermsSubjectData implements LPSubjectData { .filter(n -> n.getFullContexts().equals(contexts)) .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(this.enduring)); + toRemove.forEach(node -> this.type.run( + () -> this.holder.unsetPermission(node), + () -> this.holder.unsetTransientPermission(node) + )); return objectSave(this.holder).thenApply(v -> true); } @@ -432,43 +404,36 @@ public class LuckPermsSubjectData implements LPSubjectData { public CompletableFuture clearOptions(ImmutableContextSet contexts) { Objects.requireNonNull(contexts, "contexts"); - List toRemove = streamNodes(this.enduring) + List toRemove = streamNodes() .filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix()) .filter(n -> n.getFullContexts().equals(contexts)) .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(this.enduring)); + toRemove.forEach(node -> this.type.run( + () -> this.holder.unsetPermission(node), + () -> this.holder.unsetTransientPermission(node) + )); return objectSave(this.holder).thenApply(v -> !toRemove.isEmpty()); } @Override public CompletableFuture clearOptions() { - List toRemove = streamNodes(this.enduring) + List toRemove = streamNodes() .filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix()) .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(this.enduring)); + toRemove.forEach(node -> this.type.run( + () -> this.holder.unsetPermission(node), + () -> this.holder.unsetTransientPermission(node) + )); return objectSave(this.holder).thenApply(v -> !toRemove.isEmpty()); } - private Stream streamNodes(boolean enduring) { - return (enduring ? this.holder.getEnduringNodes() : this.holder.getTransientNodes()).values().stream(); - } - - private Consumer makeUnsetConsumer(boolean enduring) { - return n -> { - if (enduring) { - this.holder.unsetPermission(n); - } else { - this.holder.unsetTransientPermission(n); - } - }; - } - private CompletableFuture objectSave(PermissionHolder t) { - if (!this.enduring) { + // handle transient first + if (this.type == NodeMapType.TRANSIENT) { // don't bother saving to primary storage. just refresh if (t.getType().isUser()) { User user = ((User) t); @@ -476,30 +441,31 @@ public class LuckPermsSubjectData implements LPSubjectData { } else { return this.service.getPlugin().getUpdateTaskBuffer().request(); } + } + + // handle enduring + if (t.getType().isUser()) { + User user = ((User) t); + CompletableFuture fut = new CompletableFuture<>(); + this.service.getPlugin().getStorage().saveUser(user).whenCompleteAsync((v, ex) -> { + if (ex != null) { + fut.complete(null); + } + + user.getRefreshBuffer().request().thenAccept(fut::complete); + }, this.service.getPlugin().getScheduler().async()); + return fut; } else { - if (t.getType().isUser()) { - User user = ((User) t); - CompletableFuture fut = new CompletableFuture<>(); - this.service.getPlugin().getStorage().saveUser(user).whenCompleteAsync((v, ex) -> { - if (ex != null) { - fut.complete(null); - } + Group group = ((Group) t); + CompletableFuture fut = new CompletableFuture<>(); + this.service.getPlugin().getStorage().saveGroup(group).whenCompleteAsync((v, ex) -> { + if (ex != null) { + fut.complete(null); + } - user.getRefreshBuffer().request().thenAccept(fut::complete); - }, this.service.getPlugin().getScheduler().async()); - return fut; - } else { - Group group = ((Group) t); - CompletableFuture fut = new CompletableFuture<>(); - this.service.getPlugin().getStorage().saveGroup(group).whenCompleteAsync((v, ex) -> { - if (ex != null) { - fut.complete(null); - } - - this.service.getPlugin().getUpdateTaskBuffer().request().thenAccept(fut::complete); - }, this.service.getPlugin().getScheduler().async()); - return fut; - } + this.service.getPlugin().getUpdateTaskBuffer().request().thenAccept(fut::complete); + }, this.service.getPlugin().getScheduler().async()); + return fut; } } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/UserSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/UserSubject.java new file mode 100644 index 00000000..b9076929 --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/internal/UserSubject.java @@ -0,0 +1,68 @@ +/* + * 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.sponge.service.internal; + +import me.lucko.luckperms.sponge.LPSpongePlugin; +import me.lucko.luckperms.sponge.model.SpongeUser; +import me.lucko.luckperms.sponge.service.model.LPSubject; +import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; + +import org.spongepowered.api.Sponge; +import org.spongepowered.api.command.CommandSource; + +import java.util.Optional; +import java.util.UUID; +import java.util.function.Function; + +/** + * Implements {@link LPSubject} for a {@link SpongeUser}. + */ +public final class UserSubject extends HolderSubject implements LPSubject { + public UserSubject(LPSpongePlugin plugin, SpongeUser parent) { + super(plugin, parent); + } + + @Override + public String getIdentifier() { + return this.parent.getUuid().toString(); + } + + @Override + public Optional getFriendlyIdentifier() { + return this.parent.getName(); + } + + @Override + public Optional getCommandSource() { + final UUID uuid = this.parent.getUuid(); + return Sponge.getServer().getPlayer(uuid).map(Function.identity()); + } + + @Override + public LPSubjectCollection getParentCollection() { + return this.plugin.getService().getUserSubjects(); + } +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/legacy/LegacyDataMigrator.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/legacy/LegacyDataMigrator.java deleted file mode 100644 index e65495eb..00000000 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/legacy/LegacyDataMigrator.java +++ /dev/null @@ -1,88 +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.sponge.service.legacy; - -import me.lucko.luckperms.sponge.LPSpongePlugin; -import me.lucko.luckperms.sponge.service.storage.SubjectStorage; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -@SuppressWarnings("deprecation") -public class LegacyDataMigrator implements Runnable { - private final LPSpongePlugin plugin; - - private final File oldDirectory; - private final SubjectStorage storage; - - public LegacyDataMigrator(LPSpongePlugin plugin, File oldDirectory, SubjectStorage storage) { - this.plugin = plugin; - this.oldDirectory = oldDirectory; - this.storage = storage; - } - - @Override - public void run() { - if (!this.oldDirectory.exists() || !this.oldDirectory.isDirectory()) { - return; - } - - this.plugin.getLog().warn("Migrating old sponge data... Please wait."); - - File[] collections = this.oldDirectory.listFiles(File::isDirectory); - if (collections == null) { - return; - } - - for (File collectionDir : collections) { - - File[] subjects = collectionDir.listFiles((dir, name) -> name.endsWith(".json")); - if (subjects == null) { - continue; - } - - for (File subjectFile : subjects) { - String subjectName = subjectFile.getName().substring(0, subjectFile.getName().length() - ".json".length()); - - try (BufferedReader reader = Files.newBufferedReader(subjectFile.toPath(), StandardCharsets.UTF_8)) { - SubjectDataHolder holder = this.storage.getGson().fromJson(reader, SubjectDataHolder.class); - this.storage.saveToFile(holder.asSubjectModel(this.plugin.getService()), this.storage.resolveFile(collectionDir.getName(), subjectName)); - } catch (IOException e) { - e.printStackTrace(); - } - - subjectFile.delete(); - } - - collectionDir.delete(); - } - - this.oldDirectory.delete(); - } -} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/legacy/SubjectDataHolder.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/legacy/SubjectDataHolder.java deleted file mode 100644 index 54c3468b..00000000 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/legacy/SubjectDataHolder.java +++ /dev/null @@ -1,71 +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.sponge.service.legacy; - -import me.lucko.luckperms.api.context.ImmutableContextSet; -import me.lucko.luckperms.sponge.service.model.LPPermissionService; -import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory; -import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @deprecated Because this format is no longer being used to store data. - * @see SubjectStorageModel - */ -@SuppressWarnings("DeprecatedIsStillUsed") -@Deprecated -public class SubjectDataHolder { - private Map, Map> permissions; - private Map, Map> options; - private Map, List> parents; - - public SubjectDataHolder() { - // For gson - } - - public SubjectStorageModel asSubjectModel(LPPermissionService service) { - return new SubjectStorageModel(service, - this.permissions.entrySet().stream() - .collect(Collectors.toMap( - k -> ImmutableContextSet.fromMap(k.getKey()), - Map.Entry::getValue - )), - this.options.entrySet().stream() - .collect(Collectors.toMap( - k -> ImmutableContextSet.fromMap(k.getKey()), - Map.Entry::getValue - )), - this.parents.entrySet().stream() - .collect(Collectors.toMap( - k -> ImmutableContextSet.fromMap(k.getKey()), - v -> v.getValue().stream().map(s -> SubjectReferenceFactory.deserialize(service, s)).collect(Collectors.toList()) - )) - ); - } -} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PermissionLookupKey.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PermissionLookupKey.java deleted file mode 100644 index bdbcb9ba..00000000 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PermissionLookupKey.java +++ /dev/null @@ -1,74 +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.sponge.service.persisted; - -import me.lucko.luckperms.api.context.ImmutableContextSet; - -public final class PermissionLookupKey { - - public static PermissionLookupKey of(String node, ImmutableContextSet contexts) { - return new PermissionLookupKey(node, contexts); - } - - private final String node; - private final ImmutableContextSet contexts; - - private PermissionLookupKey(String node, ImmutableContextSet contexts) { - this.node = node; - this.contexts = contexts; - } - - public String getNode() { - return this.node; - } - - public ImmutableContextSet getContexts() { - return this.contexts; - } - - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof PermissionLookupKey)) return false; - final PermissionLookupKey other = (PermissionLookupKey) o; - - return this.getNode().equals(other.getNode()) && this.getContexts().equals(other.getContexts()); - } - - @Override - public int hashCode() { - final int PRIME = 59; - int result = 1; - result = result * PRIME + this.getNode().hashCode(); - result = result * PRIME + this.getContexts().hashCode(); - return result; - } - - @Override - public String toString() { - return "PermissionLookupKey(node=" + this.getNode() + ", contexts=" + this.getContexts() + ")"; - } -} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java index a6d06cee..510d422d 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java @@ -62,7 +62,7 @@ public class PersistedCollection implements LPSubjectCollection { private final SubjectCollection spongeProxy; private final LoadingCache subjects = Caffeine.newBuilder() - .build(s -> new PersistedSubject(s, getService(), PersistedCollection.this)); + .build(s -> new PersistedSubject(s, getService(), this)); public PersistedCollection(LuckPermsService service, String identifier) { this.service = service; diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubject.java index 5b4989b6..972b1956 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubject.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubject.java @@ -64,7 +64,7 @@ public class PersistedSubject implements LPSubject { private final LoadingCache permissionLookupCache = Caffeine.newBuilder() .expireAfterAccess(20, TimeUnit.MINUTES) - .build(lookup -> lookupPermissionValue(lookup.getContexts(), lookup.getNode())); + .build(lookup -> lookupPermissionValue(lookup.contexts, lookup.node)); private final LoadingCache> parentLookupCache = Caffeine.newBuilder() .expireAfterAccess(20, TimeUnit.MINUTES) @@ -72,7 +72,7 @@ public class PersistedSubject implements LPSubject { private final LoadingCache> optionLookupCache = Caffeine.newBuilder() .expireAfterAccess(20, TimeUnit.MINUTES) - .build(lookup -> lookupOptionValue(lookup.getContexts(), lookup.getKey())); + .build(lookup -> lookupOptionValue(lookup.contexts, lookup.key)); private final BufferedRequest saveBuffer = new BufferedRequest(1000L, 500L, r -> PersistedSubject.this.service.getPlugin().getScheduler().doAsync(r)) { @Override @@ -91,8 +91,9 @@ public class PersistedSubject implements LPSubject { this.service = service; this.parentCollection = parentCollection; - this.subjectData = new PersistedSubjectData(service, parentCollection.getIdentifier() + "/" + identifier + "/p", this); - this.transientSubjectData = new CalculatedSubjectData(this, service, parentCollection.getIdentifier() + "/" + identifier + "/t"); + String displayName = parentCollection.getIdentifier() + "/" + identifier; + this.subjectData = new PersistedSubjectData(service, displayName + "/p", this); + this.transientSubjectData = new CalculatedSubjectData(this, service, displayName + "/t"); } @Override @@ -277,7 +278,7 @@ public class PersistedSubject implements LPSubject { Objects.requireNonNull(contexts, "contexts"); Objects.requireNonNull(node, "node"); - Tristate t = this.permissionLookupCache.get(PermissionLookupKey.of(node, contexts)); + Tristate t = this.permissionLookupCache.get(new PermissionLookupKey(node, contexts)); this.service.getPlugin().getVerboseHandler().offerCheckData(CheckOrigin.INTERNAL, getParentCollection().getIdentifier() + "/" + this.identifier, contexts, node, t); return t; } @@ -306,6 +307,54 @@ public class PersistedSubject implements LPSubject { @Override public Optional getOption(ImmutableContextSet contexts, String key) { - return this.optionLookupCache.get(OptionLookupKey.of(key, contexts)); + return this.optionLookupCache.get(new OptionLookupKey(key, contexts)); + } + + private static final class PermissionLookupKey { + private final String node; + private final ImmutableContextSet contexts; + + public PermissionLookupKey(String node, ImmutableContextSet contexts) { + this.node = node; + this.contexts = contexts; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof PermissionLookupKey)) return false; + final PermissionLookupKey other = (PermissionLookupKey) o; + + return this.node.equals(other.node) && this.contexts.equals(other.contexts); + } + + @Override + public int hashCode() { + return Objects.hash(this.node, this.contexts); + } + } + + public static final class OptionLookupKey { + private final String key; + private final ImmutableContextSet contexts; + + public OptionLookupKey(String key, ImmutableContextSet contexts) { + this.key = key; + this.contexts = contexts; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof OptionLookupKey)) return false; + final OptionLookupKey other = (OptionLookupKey) o; + + return this.key.equals(other.key) && this.contexts.equals(other.contexts); + } + + @Override + public int hashCode() { + return Objects.hash(this.key, this.contexts); + } } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubjectData.java index 96b3d4ce..2d0a0784 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubjectData.java @@ -37,11 +37,16 @@ import java.util.function.Function; /** * Extension of MemorySubjectData which persists data when modified */ -public class PersistedSubjectData extends CalculatedSubjectData implements Function { +public class PersistedSubjectData extends CalculatedSubjectData { private final PersistedSubject subject; private boolean save = true; + private final Function saveFunction = b -> { + save(); + return b; + }; + public PersistedSubjectData(LuckPermsService service, String calculatorDisplayName, PersistedSubject subject) { super(subject, service, calculatorDisplayName); this.subject = subject; @@ -57,72 +62,62 @@ public class PersistedSubjectData extends CalculatedSubjectData implements Funct } } - @Override - public Boolean apply(Boolean b) { - save(); - return b; + public void setSave(boolean save) { + this.save = save; } @Override public CompletableFuture setPermission(ImmutableContextSet contexts, String permission, Tristate value) { - return super.setPermission(contexts, permission, value).thenApply(this); + return super.setPermission(contexts, permission, value).thenApply(this.saveFunction); } @Override public CompletableFuture clearPermissions() { - return super.clearPermissions().thenApply(this); + return super.clearPermissions().thenApply(this.saveFunction); } @Override public CompletableFuture clearPermissions(ImmutableContextSet contexts) { - return super.clearPermissions(contexts).thenApply(this); + return super.clearPermissions(contexts).thenApply(this.saveFunction); } @Override public CompletableFuture addParent(ImmutableContextSet contexts, LPSubjectReference parent) { - return super.addParent(contexts, parent).thenApply(this); + return super.addParent(contexts, parent).thenApply(this.saveFunction); } @Override public CompletableFuture removeParent(ImmutableContextSet contexts, LPSubjectReference parent) { - return super.removeParent(contexts, parent).thenApply(this); + return super.removeParent(contexts, parent).thenApply(this.saveFunction); } @Override public CompletableFuture clearParents() { - return super.clearParents().thenApply(this); + return super.clearParents().thenApply(this.saveFunction); } @Override public CompletableFuture clearParents(ImmutableContextSet contexts) { - return super.clearParents(contexts).thenApply(this); + return super.clearParents(contexts).thenApply(this.saveFunction); } @Override public CompletableFuture setOption(ImmutableContextSet contexts, String key, String value) { - return super.setOption(contexts, key, value).thenApply(this); + return super.setOption(contexts, key, value).thenApply(this.saveFunction); } @Override public CompletableFuture unsetOption(ImmutableContextSet contexts, String key) { - return super.unsetOption(contexts, key).thenApply(this); + return super.unsetOption(contexts, key).thenApply(this.saveFunction); } @Override public CompletableFuture clearOptions() { - return super.clearOptions().thenApply(this); + return super.clearOptions().thenApply(this.saveFunction); } @Override public CompletableFuture clearOptions(ImmutableContextSet contexts) { - return super.clearOptions(contexts).thenApply(this); - } - - public boolean isSave() { - return this.save; - } - - public void setSave(boolean save) { - this.save = save; + return super.clearOptions(contexts).thenApply(this.saveFunction); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/storage/SubjectStorage.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/storage/SubjectStorage.java index 1ad180e6..6ab72f42 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/storage/SubjectStorage.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/storage/SubjectStorage.java @@ -50,11 +50,8 @@ import java.util.stream.Collectors; * Handles persisted Subject I/O and (de)serialization */ public class SubjectStorage { - private final LPPermissionService service; - private final Gson gson; - private final File container; public SubjectStorage(LPPermissionService service, File container) { @@ -158,8 +155,4 @@ public class SubjectStorage { return Maps.immutableEntry(subjectName, model); } } - - public Gson getGson() { - return this.gson; - } }