From 777c972bdcfb2d130f37efe7887b331124f37dee Mon Sep 17 00:00:00 2001 From: Luck Date: Thu, 21 Sep 2017 21:59:27 +0100 Subject: [PATCH] Cache SubjectReference instances, general cleanup --- .../luckperms/bukkit/LPBukkitPlugin.java | 3 + .../lucko/luckperms/bungee/BungeeCommand.java | 2 +- .../luckperms/bungee/LPBungeePlugin.java | 3 + .../common/api/delegates/GroupDelegate.java | 2 +- .../common/api/delegates/TrackDelegate.java | 2 +- .../common/api/delegates/UserDelegate.java | 2 +- .../luckperms/common/node/ImmutableNode.java | 4 +- .../backing/mongodb/MongoDBBacking.java | 94 ++-- .../luckperms/common/tasks/UpdateTask.java | 9 +- .../common/treeview/PermissionVault.java | 1 + .../common/utils/HikariSupplier.java | 3 + .../luckperms/common/utils/PasteUtils.java | 16 +- .../luckperms/common/utils/Predicates.java | 4 +- .../luckperms/common/utils/Scripting.java | 3 + .../common/verbose/VerboseListener.java | 2 + .../service/proxy/api7/SubjectDataProxy.java | 5 +- .../service/proxy/api7/SubjectProxy.java | 5 +- .../service/model/CompatibilityUtil.java | 3 + .../sponge/service/model/LPSubjectData.java | 4 +- .../service/model/SubjectReference.java | 140 +++-- .../model/SubjectReferenceFactory.java | 110 ++++ .../luckperms/sponge/LPSpongePlugin.java | 15 +- .../lucko/luckperms/sponge/SpongeCommand.java | 62 +-- .../luckperms/sponge/SpongeListener.java | 78 ++- .../sponge/contexts/SpongeCalculatorLink.java | 2 +- .../migration/SpongeMigrationUtils.java | 22 +- .../luckperms/sponge/model/SpongeGroup.java | 77 ++- .../luckperms/sponge/model/SpongeUser.java | 88 ++- .../sponge/service/LuckPermsService.java | 29 +- .../sponge/service/LuckPermsSubjectData.java | 521 ++++++++---------- .../calculated/CalculatedSubjectData.java | 21 +- .../service/legacy/SubjectDataHolder.java | 4 +- .../service/persisted/PersistedSubject.java | 41 +- .../service/storage/SubjectStorageModel.java | 3 +- .../luckperms/sponge/timings/LPTiming.java | 76 --- .../luckperms/sponge/timings/LPTimings.java | 56 -- 36 files changed, 732 insertions(+), 780 deletions(-) create mode 100644 sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/SubjectReferenceFactory.java delete mode 100644 sponge/src/main/java/me/lucko/luckperms/sponge/timings/LPTiming.java delete mode 100644 sponge/src/main/java/me/lucko/luckperms/sponge/timings/LPTimings.java diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java index 9eccae3a..0a6e4881 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/LPBukkitPlugin.java @@ -106,6 +106,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.stream.Collectors; +/** + * LuckPerms implementation for the Bukkit API. + */ @Getter public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeCommand.java b/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeCommand.java index 4f5d9aaf..35368637 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeCommand.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/BungeeCommand.java @@ -37,7 +37,7 @@ import net.md_5.bungee.api.plugin.TabExecutor; import java.util.Arrays; -class BungeeCommand extends Command implements TabExecutor { +public class BungeeCommand extends Command implements TabExecutor { private final LPBungeePlugin plugin; private final CommandManager manager; diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java index 47eb0a4a..781a1874 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/LPBungeePlugin.java @@ -91,6 +91,9 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +/** + * LuckPerms implementation for the BungeeCord API. + */ @Getter public class LPBungeePlugin extends Plugin implements LuckPermsPlugin { diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/GroupDelegate.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/GroupDelegate.java index 17d8514a..d342d3b8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/GroupDelegate.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/GroupDelegate.java @@ -188,7 +188,7 @@ public final class GroupDelegate extends PermissionHolderDelegate implements Gro if (!(o instanceof GroupDelegate)) return false; GroupDelegate other = (GroupDelegate) o; - return this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()); + return this.getName().equals(other.getName()); } public int hashCode() { diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/TrackDelegate.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/TrackDelegate.java index d640b7f7..7c3b52fc 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/TrackDelegate.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/TrackDelegate.java @@ -117,7 +117,7 @@ public final class TrackDelegate implements Track { if (!(o instanceof TrackDelegate)) return false; TrackDelegate other = (TrackDelegate) o; - return this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()); + return this.getName().equals(other.getName()); } public int hashCode() { diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/UserDelegate.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/UserDelegate.java index 3c736e39..a0450b74 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/UserDelegate.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/UserDelegate.java @@ -228,7 +228,7 @@ public final class UserDelegate extends PermissionHolderDelegate implements User if (!(o instanceof UserDelegate)) return false; UserDelegate other = (UserDelegate) o; - return this.getUuid() == null ? other.getUuid() == null : this.getUuid().equals(other.getUuid()); + return this.getUuid().equals(other.getUuid()); } public int hashCode() { diff --git a/common/src/main/java/me/lucko/luckperms/common/node/ImmutableNode.java b/common/src/main/java/me/lucko/luckperms/common/node/ImmutableNode.java index 8c0242c7..e8643bbc 100644 --- a/common/src/main/java/me/lucko/luckperms/common/node/ImmutableNode.java +++ b/common/src/main/java/me/lucko/luckperms/common/node/ImmutableNode.java @@ -66,8 +66,8 @@ public final class ImmutableNode implements Node { /* * NODE STATE * - * This are the actual node parameters, and are - * basically what this class wraps. + * This are the actual node attributes, and are + * really just what this class wraps. */ @Getter diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/backing/mongodb/MongoDBBacking.java b/common/src/main/java/me/lucko/luckperms/common/storage/backing/mongodb/MongoDBBacking.java index a9ace918..b5220903 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/backing/mongodb/MongoDBBacking.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/backing/mongodb/MongoDBBacking.java @@ -83,53 +83,6 @@ public class MongoDBBacking extends AbstractBacking { } } - /* MongoDB does not allow '.' or '$' in key names. - See: https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names - The following two methods convert the node maps so they can be stored. */ - - private static final Function CONVERT_STRING = s -> s.replace(".", "[**DOT**]").replace("$", "[**DOLLAR**]"); - private static final Function REVERT_STRING = s -> s.replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$"); - - private static Map convert(Map map) { - return map.entrySet().stream() - .collect(Collectors.toMap(e -> CONVERT_STRING.apply(e.getKey()), Map.Entry::getValue)); - } - - private static Map revert(Map map) { - return map.entrySet().stream() - .collect(Collectors.toMap(e -> REVERT_STRING.apply(e.getKey()), Map.Entry::getValue)); - } - - private static Document fromUser(User user) { - Document main = new Document("_id", user.getUuid()) - .append("name", user.getName().orElse("null")) - .append("primaryGroup", user.getPrimaryGroup().getStoredValue()); - - Document perms = new Document(); - for (Map.Entry e : convert(exportToLegacy(user.getEnduringNodes().values())).entrySet()) { - perms.append(e.getKey(), e.getValue()); - } - - main.append("perms", perms); - return main; - } - - private static Document fromGroup(Group group) { - Document main = new Document("_id", group.getName()); - - Document perms = new Document(); - for (Map.Entry e : convert(exportToLegacy(group.getEnduringNodes().values())).entrySet()) { - perms.append(e.getKey(), e.getValue()); - } - - main.append("perms", perms); - return main; - } - - private static Document fromTrack(Track track) { - return new Document("_id", track.getName()).append("groups", track.getGroups()); - } - private final DatastoreConfiguration configuration; private MongoClient mongoClient; private MongoDatabase database; @@ -752,6 +705,53 @@ public class MongoDBBacking extends AbstractBacking { }, null); } + /* MongoDB does not allow '.' or '$' in key names. + See: https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names + The following two methods convert the node maps so they can be stored. */ + + private static final Function CONVERT_STRING = s -> s.replace(".", "[**DOT**]").replace("$", "[**DOLLAR**]"); + private static final Function REVERT_STRING = s -> s.replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$"); + + private static Map convert(Map map) { + return map.entrySet().stream() + .collect(Collectors.toMap(e -> CONVERT_STRING.apply(e.getKey()), Map.Entry::getValue)); + } + + private static Map revert(Map map) { + return map.entrySet().stream() + .collect(Collectors.toMap(e -> REVERT_STRING.apply(e.getKey()), Map.Entry::getValue)); + } + + private static Document fromUser(User user) { + Document main = new Document("_id", user.getUuid()) + .append("name", user.getName().orElse("null")) + .append("primaryGroup", user.getPrimaryGroup().getStoredValue()); + + Document perms = new Document(); + for (Map.Entry e : convert(exportToLegacy(user.getEnduringNodes().values())).entrySet()) { + perms.append(e.getKey(), e.getValue()); + } + + main.append("perms", perms); + return main; + } + + private static Document fromGroup(Group group) { + Document main = new Document("_id", group.getName()); + + Document perms = new Document(); + for (Map.Entry e : convert(exportToLegacy(group.getEnduringNodes().values())).entrySet()) { + perms.append(e.getKey(), e.getValue()); + } + + main.append("perms", perms); + return main; + } + + private static Document fromTrack(Track track) { + return new Document("_id", track.getName()).append("groups", track.getGroups()); + } + public static Map exportToLegacy(Iterable nodes) { Map m = new HashMap<>(); for (Node node : nodes) { diff --git a/common/src/main/java/me/lucko/luckperms/common/tasks/UpdateTask.java b/common/src/main/java/me/lucko/luckperms/common/tasks/UpdateTask.java index 1d6c2b61..0e065df2 100644 --- a/common/src/main/java/me/lucko/luckperms/common/tasks/UpdateTask.java +++ b/common/src/main/java/me/lucko/luckperms/common/tasks/UpdateTask.java @@ -33,6 +33,11 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import java.util.concurrent.CompletableFuture; +/** + * System wide update task for LuckPerms. + * + *

Ensures that all local data is consistent with the storage.

+ */ @AllArgsConstructor public class UpdateTask implements Runnable { private final LuckPermsPlugin plugin; @@ -43,7 +48,9 @@ public class UpdateTask implements Runnable { private final boolean initialUpdate; /** - * Called ASYNC + * Runs the update task + * + *

Called async.

*/ @Override public void run() { diff --git a/common/src/main/java/me/lucko/luckperms/common/treeview/PermissionVault.java b/common/src/main/java/me/lucko/luckperms/common/treeview/PermissionVault.java index abd1c665..44f3a9e8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/treeview/PermissionVault.java +++ b/common/src/main/java/me/lucko/luckperms/common/treeview/PermissionVault.java @@ -72,6 +72,7 @@ public class PermissionVault implements Runnable { for (String e; (e = queue.poll()) != null; ) { try { String s = e.toLowerCase(); + // only attempt an insert if we're not seen this permission before if (knownPermissions.add(s)) { insert(s); } diff --git a/common/src/main/java/me/lucko/luckperms/common/utils/HikariSupplier.java b/common/src/main/java/me/lucko/luckperms/common/utils/HikariSupplier.java index 62d1f438..ef5e9579 100644 --- a/common/src/main/java/me/lucko/luckperms/common/utils/HikariSupplier.java +++ b/common/src/main/java/me/lucko/luckperms/common/utils/HikariSupplier.java @@ -32,6 +32,9 @@ import com.zaxxer.hikari.HikariDataSource; import java.sql.Connection; import java.sql.SQLException; +/** + * A simple hikari wrapper + */ @RequiredArgsConstructor public class HikariSupplier implements AutoCloseable { diff --git a/common/src/main/java/me/lucko/luckperms/common/utils/PasteUtils.java b/common/src/main/java/me/lucko/luckperms/common/utils/PasteUtils.java index 4b9319a6..6d42a2b4 100644 --- a/common/src/main/java/me/lucko/luckperms/common/utils/PasteUtils.java +++ b/common/src/main/java/me/lucko/luckperms/common/utils/PasteUtils.java @@ -39,12 +39,24 @@ import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; +/** + * Uploads content to GitHub's GIST service. + */ public class PasteUtils { + private static final String GIST_API = "https://api.github.com/gists"; + private static final String SHORTEN_API = "https://git.io"; + /** + * Uploads content to GIST, and returns a shortened URL. + * + * @param desc the description of the gist + * @param files the files to include in the gist (file name --> content) + * @return the url, or null + */ public static String paste(String desc, List> files) { HttpURLConnection connection = null; try { - connection = (HttpURLConnection) new URL("https://api.github.com/gists").openConnection(); + connection = (HttpURLConnection) new URL(GIST_API).openConnection(); connection.setRequestMethod("POST"); connection.setDoInput(true); connection.setDoOutput(true); @@ -82,7 +94,7 @@ public class PasteUtils { connection.disconnect(); try { - connection = (HttpURLConnection) new URL("https://git.io").openConnection(); + connection = (HttpURLConnection) new URL(SHORTEN_API).openConnection(); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); connection.setDoOutput(true); try (OutputStream os = connection.getOutputStream()) { diff --git a/common/src/main/java/me/lucko/luckperms/common/utils/Predicates.java b/common/src/main/java/me/lucko/luckperms/common/utils/Predicates.java index fdd1c0e8..017fc786 100644 --- a/common/src/main/java/me/lucko/luckperms/common/utils/Predicates.java +++ b/common/src/main/java/me/lucko/luckperms/common/utils/Predicates.java @@ -66,7 +66,7 @@ public class Predicates { public static Predicate isOneOf(Set ta) { return t -> { for (T i : ta) { - if (i == t) { + if (i.equals(t)) { return true; } } @@ -79,7 +79,7 @@ public class Predicates { } public static Predicate is(T t) { - return t2 -> t == t2; + return t::equals; } public static Predicate inverse(Predicate t) { diff --git a/common/src/main/java/me/lucko/luckperms/common/utils/Scripting.java b/common/src/main/java/me/lucko/luckperms/common/utils/Scripting.java index 3ef5b7cd..a7bdd965 100644 --- a/common/src/main/java/me/lucko/luckperms/common/utils/Scripting.java +++ b/common/src/main/java/me/lucko/luckperms/common/utils/Scripting.java @@ -30,6 +30,9 @@ import lombok.experimental.UtilityClass; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; +/** + * Nashorn provider utility + */ @UtilityClass public class Scripting { private static ScriptEngine SCRIPT_ENGINE = null; diff --git a/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseListener.java b/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseListener.java index 41288697..cf707250 100644 --- a/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseListener.java +++ b/common/src/main/java/me/lucko/luckperms/common/verbose/VerboseListener.java @@ -171,6 +171,8 @@ public class VerboseListener { /** * Uploads the captured data in this listener to a paste and returns the url * + * @param showTraces if stack traces should be included in the output + * @param attachRaw if the rawdata should be attached to the gist * @return the url * @see PasteUtils#paste(String, List) */ diff --git a/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectDataProxy.java b/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectDataProxy.java index 39c06e20..46e5f769 100644 --- a/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectDataProxy.java +++ b/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectDataProxy.java @@ -33,6 +33,7 @@ import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.model.SubjectReference; +import me.lucko.luckperms.sponge.service.model.SubjectReferenceFactory; import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.permission.SubjectData; @@ -111,12 +112,12 @@ public class SubjectDataProxy implements SubjectData { @Override public CompletableFuture addParent(Set contexts, org.spongepowered.api.service.permission.SubjectReference ref) { - return getHandle().thenCompose(handle -> handle.addParent(CompatibilityUtil.convertContexts(contexts), SubjectReference.cast(service, ref))); + return getHandle().thenCompose(handle -> handle.addParent(CompatibilityUtil.convertContexts(contexts), SubjectReferenceFactory.obtain(service, ref))); } @Override public CompletableFuture removeParent(Set contexts, org.spongepowered.api.service.permission.SubjectReference ref) { - return getHandle().thenCompose(handle -> handle.removeParent(CompatibilityUtil.convertContexts(contexts), SubjectReference.cast(service, ref))); + return getHandle().thenCompose(handle -> handle.removeParent(CompatibilityUtil.convertContexts(contexts), SubjectReferenceFactory.obtain(service, ref))); } @Override diff --git a/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectProxy.java b/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectProxy.java index 5a3b4f9f..e1fa62bc 100644 --- a/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectProxy.java +++ b/sponge/sponge-service-api7/src/main/java/me/lucko/luckperms/sponge/service/proxy/api7/SubjectProxy.java @@ -32,6 +32,7 @@ import me.lucko.luckperms.sponge.service.model.CompatibilityUtil; import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.SubjectReference; +import me.lucko.luckperms.sponge.service.model.SubjectReferenceFactory; import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.service.context.Context; @@ -109,14 +110,14 @@ public class SubjectProxy implements Subject { @Override public boolean isChildOf(org.spongepowered.api.service.permission.SubjectReference parent) { return getHandle().thenApply(handle -> { - return handle.isChildOf(ImmutableContextSet.empty(), SubjectReference.cast(service, parent)); + return handle.isChildOf(ImmutableContextSet.empty(), SubjectReferenceFactory.obtain(service, parent)); }).join(); } @Override public boolean isChildOf(Set contexts, org.spongepowered.api.service.permission.SubjectReference parent) { return getHandle().thenApply(handle -> { - return handle.isChildOf(CompatibilityUtil.convertContexts(contexts), SubjectReference.cast(service, parent)); + return handle.isChildOf(CompatibilityUtil.convertContexts(contexts), SubjectReferenceFactory.obtain(service, parent)); }).join(); } diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/CompatibilityUtil.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/CompatibilityUtil.java index d5ed7a74..b5bdafad 100644 --- a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/CompatibilityUtil.java +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/CompatibilityUtil.java @@ -40,6 +40,7 @@ import org.spongepowered.api.service.context.Context; import org.spongepowered.api.util.Tristate; import java.util.Set; +import java.util.concurrent.TimeUnit; /** * Utility class for converting between Sponge and LuckPerms context and tristate classes @@ -47,9 +48,11 @@ import java.util.Set; @UtilityClass public class CompatibilityUtil { private static final LoadingCache, ImmutableContextSet> SPONGE_TO_LP_CACHE = Caffeine.newBuilder() + .expireAfterAccess(10, TimeUnit.MINUTES) .build(ImmutableContextSet::fromEntries); private static final LoadingCache> LP_TO_SPONGE_CACHE = Caffeine.newBuilder() + .expireAfterAccess(10, TimeUnit.MINUTES) .build(set -> set.toSet().stream().map(e -> new Context(e.getKey(), e.getValue())).collect(ImmutableCollectors.toImmutableSet())); public static ImmutableContextSet convertContexts(@NonNull Set contexts) { diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubjectData.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubjectData.java index 39f5b706..acb52f8a 100644 --- a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubjectData.java +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/LPSubjectData.java @@ -31,10 +31,12 @@ import com.google.common.collect.ImmutableMap; import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ImmutableContextSet; +import org.spongepowered.api.service.permission.SubjectData; + import java.util.concurrent.CompletableFuture; /** - * LuckPerms model for the Sponge {@link org.spongepowered.api.service.permission.SubjectData} + * LuckPerms model for the Sponge {@link SubjectData} */ public interface LPSubjectData { diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/SubjectReference.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/SubjectReference.java index fe4d88a8..7f0aaf8d 100644 --- a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/SubjectReference.java +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/SubjectReference.java @@ -25,103 +25,135 @@ package me.lucko.luckperms.sponge.service.model; -import lombok.EqualsAndHashCode; import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.ToString; -import com.google.common.base.Splitter; +import com.google.common.base.Preconditions; import org.spongepowered.api.service.permission.Subject; import java.lang.ref.WeakReference; -import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; -@ToString(of = {"collectionIdentifier", "subjectIdentifier"}) -@EqualsAndHashCode(of = {"collectionIdentifier", "subjectIdentifier"}) -@RequiredArgsConstructor(staticName = "of") +import javax.annotation.Nonnull; + +/** + * Represents a reference to a given Subject. + * + * Use of this class (or interface) should have no negative impact on + * performance, as {@link #resolve()} calls are cached. + */ public final class SubjectReference implements org.spongepowered.api.service.permission.SubjectReference { - @Deprecated - public static SubjectReference deserialize(LPPermissionService service, String s) { - List parts = Splitter.on('/').limit(2).splitToList(s); - return of(service, parts.get(0), parts.get(1)); - } - - public static SubjectReference of(LPPermissionService service, Subject subject) { - return of(service, subject.getContainingCollection().getIdentifier(), subject.getIdentifier()); - } - - public static SubjectReference cast(LPPermissionService service, org.spongepowered.api.service.permission.SubjectReference reference) { - if (reference instanceof SubjectReference) { - return ((SubjectReference) reference); - } else { - return of(service, reference.getCollectionIdentifier(), reference.getSubjectIdentifier()); - } - } + /** + * The time a subject instance should be cached in this reference + */ + private static final long CACHE_TIME = TimeUnit.SECONDS.toMillis(60); + /** + * Reference to the permission service + */ private final LPPermissionService service; + /** + * The identifier of the collection which holds the subject + */ @Getter + @Nonnull private final String collectionIdentifier; + /** + * The identifier of the subject + */ @Getter + @Nonnull private final String subjectIdentifier; + // cache private long lastLookup = 0L; private WeakReference cache = null; - private synchronized LPSubject resolveDirectly() { - long sinceLast = System.currentTimeMillis() - lastLookup; + SubjectReference(LPPermissionService service, String collectionIdentifier, String subjectIdentifier) { + this.service = Preconditions.checkNotNull(service); + this.collectionIdentifier = Preconditions.checkNotNull(collectionIdentifier); + this.subjectIdentifier = Preconditions.checkNotNull(subjectIdentifier); + } - // try the cache - if (sinceLast < TimeUnit.SECONDS.toMillis(10)) { + private LPSubject tryCache() { + if ((System.currentTimeMillis() - lastLookup) < CACHE_TIME) { if (cache != null) { - LPSubject s = cache.get(); - if (s != null) { - return s; - } + return cache.get(); } } - LPSubject s = service.getCollection(collectionIdentifier).loadSubject(subjectIdentifier).join(); + return null; + } + + private synchronized LPSubject resolveDirectly() { + /* As this method is synchronized, it's possible that since this was invoked + the subject has been cached. + Therefore, we check the cache again, and return if there's a value present. + This effectively means all calls to this method block, but all return the same value + at the same time once the data is loaded :) */ + + LPSubject s = tryCache(); + if (s != null) { + return s; + } + + // subject isn't cached, so make a call to load it + s = service.getCollection(collectionIdentifier).loadSubject(subjectIdentifier).join(); + + // cache the result lastLookup = System.currentTimeMillis(); cache = new WeakReference<>(s); return s; } public CompletableFuture resolveLp() { - long sinceLast = System.currentTimeMillis() - lastLookup; - - // try the cache - if (sinceLast < TimeUnit.SECONDS.toMillis(10)) { - if (cache != null) { - LPSubject s = cache.get(); - if (s != null) { - return CompletableFuture.completedFuture(s); - } - } + // check if there is a cached value before loading + LPSubject s = tryCache(); + if (s != null) { + return CompletableFuture.completedFuture(s); } + // load the subject return CompletableFuture.supplyAsync(this::resolveDirectly); } @Override public CompletableFuture resolve() { - long sinceLast = System.currentTimeMillis() - lastLookup; - - // try the cache - if (sinceLast < TimeUnit.SECONDS.toMillis(10)) { - if (cache != null) { - LPSubject s = cache.get(); - if (s != null) { - return CompletableFuture.completedFuture(s.sponge()); - } - } + // check if there is a cached value before loading + LPSubject s = tryCache(); + if (s != null) { + return CompletableFuture.completedFuture(s.sponge()); } + // load the subject return CompletableFuture.supplyAsync(() -> resolveDirectly().sponge()); } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof SubjectReference)) return false; + final SubjectReference other = (SubjectReference) o; + return this.collectionIdentifier.equals(other.collectionIdentifier) && this.subjectIdentifier.equals(other.subjectIdentifier); + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.collectionIdentifier.hashCode(); + result = result * PRIME + this.subjectIdentifier.hashCode(); + return result; + } + + @Override + public String toString() { + return "SubjectReference(" + + "collectionIdentifier=" + this.collectionIdentifier + ", " + + "subjectIdentifier=" + this.subjectIdentifier + ")"; + } } diff --git a/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/SubjectReferenceFactory.java b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/SubjectReferenceFactory.java new file mode 100644 index 00000000..7c98b6b3 --- /dev/null +++ b/sponge/sponge-service/src/main/java/me/lucko/luckperms/sponge/service/model/SubjectReferenceFactory.java @@ -0,0 +1,110 @@ +/* + * 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.model; + +import lombok.AllArgsConstructor; +import lombok.NonNull; +import lombok.experimental.UtilityClass; + +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import com.google.common.base.Splitter; + +import org.spongepowered.api.service.permission.Subject; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * Caches the creation of {@link SubjectReference}s. + */ +@UtilityClass +public final class SubjectReferenceFactory { + + /** + * Cache based factory for SubjectReferences. + * + * Using a factory and caching here makes the Subject cache in SubjectReference + * more effective. This reduces the no. of times i/o is executed due to resolve calls + * within the SubjectReference. + * + * It's perfectly ok if two instances of the same SubjectReference exist. (hence the 1 hour expiry) + */ + private static final LoadingCache REFERENCE_CACHE = Caffeine.newBuilder() + .expireAfterAccess(1, TimeUnit.HOURS) + .build(a -> new SubjectReference(a.permissionService, a.collectionId, a.id)); + + @Deprecated + public static SubjectReference deserialize(@NonNull LPPermissionService service, @NonNull String serialisedReference) { + List parts = Splitter.on('/').limit(2).splitToList(serialisedReference); + return obtain(service, parts.get(0), parts.get(1)); + } + + public static SubjectReference obtain(@NonNull LPPermissionService service, @NonNull Subject subject) { + return obtain(service, subject.getContainingCollection().getIdentifier(), subject.getIdentifier()); + } + + public static SubjectReference obtain(@NonNull LPPermissionService service, @NonNull org.spongepowered.api.service.permission.SubjectReference reference) { + if (reference instanceof SubjectReference) { + return ((SubjectReference) reference); + } else { + return SubjectReferenceFactory.obtain(service, reference.getCollectionIdentifier(), reference.getSubjectIdentifier()); + } + } + + public static SubjectReference obtain(@NonNull LPPermissionService service, @NonNull String collectionIdentifier, @NonNull String subjectIdentifier) { + return REFERENCE_CACHE.get(new SubjectReferenceAttributes(service, collectionIdentifier, subjectIdentifier)); + } + + /** + * Used as a cache key. + */ + @AllArgsConstructor + private static final class SubjectReferenceAttributes { + private final LPPermissionService permissionService; + + private final String collectionId; + private final String id; + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof SubjectReferenceAttributes)) return false; + final SubjectReferenceAttributes other = (SubjectReferenceAttributes) o; + return this.collectionId.equals(other.collectionId) && this.id.equals(other.id); + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.collectionId.hashCode(); + result = result * PRIME + this.id.hashCode(); + return result; + } + } + +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java index 7a1f2f2e..f1f50473 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongePlugin.java @@ -81,7 +81,6 @@ import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.persisted.PersistedCollection; import me.lucko.luckperms.sponge.tasks.ServiceCacheHousekeepingTask; -import me.lucko.luckperms.sponge.timings.LPTimings; import me.lucko.luckperms.sponge.utils.VersionData; import org.slf4j.Logger; @@ -122,8 +121,18 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; +/** + * LuckPerms implementation for the Sponge API. + */ @Getter -@Plugin(id = "luckperms", name = "LuckPerms", version = VersionData.VERSION, authors = {"Luck"}, description = "A permissions plugin") +@Plugin( + id = "luckperms", + name = "LuckPerms", + version = VersionData.VERSION, + authors = {"Luck"}, + description = "A permissions plugin", + url = "https://github.com/lucko/LuckPerms" +) public class LPSpongePlugin implements LuckPermsPlugin { @Inject @@ -146,7 +155,6 @@ public class LPSpongePlugin implements LuckPermsPlugin { @AsynchronousExecutor private SpongeExecutorService asyncExecutorService; - private LPTimings timings; private boolean lateLoad = false; private long startTime; @@ -186,7 +194,6 @@ public class LPSpongePlugin implements LuckPermsPlugin { verboseHandler = new VerboseHandler(scheduler.async(), getVersion()); permissionVault = new PermissionVault(scheduler.async()); logDispatcher = new LogDispatcher(this); - timings = new LPTimings(this); getLog().info("Loading configuration..."); configuration = new SpongeConfig(this); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCommand.java b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCommand.java index 752847ba..000f3eed 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCommand.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCommand.java @@ -29,7 +29,6 @@ import com.google.common.base.Splitter; import me.lucko.luckperms.common.commands.CommandManager; import me.lucko.luckperms.common.commands.utils.Util; -import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.command.CommandCallable; import org.spongepowered.api.command.CommandException; @@ -41,16 +40,13 @@ import org.spongepowered.api.text.selector.Selector; import org.spongepowered.api.world.Location; import org.spongepowered.api.world.World; -import co.aikar.timings.Timing; - import java.util.List; import java.util.ListIterator; import java.util.Optional; import javax.annotation.Nullable; -@SuppressWarnings("NullableProblems") -class SpongeCommand extends CommandManager implements CommandCallable { +public class SpongeCommand extends CommandManager implements CommandCallable { private final LPSpongePlugin plugin; SpongeCommand(LPSpongePlugin plugin) { @@ -58,56 +54,56 @@ class SpongeCommand extends CommandManager implements CommandCallable { this.plugin = plugin; } - @Override - public CommandResult process(CommandSource source, String s) throws CommandException { - try (Timing ignored = plugin.getTimings().time(LPTiming.ON_COMMAND)) { - List args = Util.stripQuotes(Splitter.on(COMMAND_SEPARATOR_PATTERN).omitEmptyStrings().splitToList(s)); + private List processArgs(CommandSource source, String s) { + List args = Util.stripQuotes(Splitter.on(COMMAND_SEPARATOR_PATTERN).omitEmptyStrings().splitToList(s)); - // resolve selectors - ListIterator it = args.listIterator(); - while (it.hasNext()) { - String element = it.next(); - if (element.startsWith("@")) { - try { - Player ret = Selector.parse(element).resolve(source).stream() - .filter(e -> e instanceof Player) - .map(e -> ((Player) e)) - .findFirst().orElse(null); + // resolve selectors + ListIterator it = args.listIterator(); + while (it.hasNext()) { + String element = it.next(); + if (element.startsWith("@")) { + try { + Player ret = Selector.parse(element).resolve(source).stream() + .filter(e -> e instanceof Player) + .map(e -> ((Player) e)) + .findFirst().orElse(null); - if (ret != null) { - it.set(ret.getUniqueId().toString()); - } - } catch (IllegalArgumentException e) { - // ignored + if (ret != null) { + it.set(ret.getUniqueId().toString()); } + } catch (IllegalArgumentException e) { + // ignored } } - - onCommand(plugin.getSenderFactory().wrap(source), "lp", args); - return CommandResult.success(); } + + return args; + } + + @Override + public CommandResult process(CommandSource source, String s) throws CommandException { + onCommand(plugin.getSenderFactory().wrap(source), "lp", processArgs(source, s)); + return CommandResult.success(); } @Override public List getSuggestions(CommandSource source, String s, @Nullable Location location) throws CommandException { - try (Timing ignored = plugin.getTimings().time(LPTiming.COMMAND_TAB_COMPLETE)) { - return onTabComplete(plugin.getSenderFactory().wrap(source), Splitter.on(' ').splitToList(s)); - } + return onTabComplete(plugin.getSenderFactory().wrap(source), processArgs(source, s)); } @Override public boolean testPermission(CommandSource source) { - return true; + return true; // we run permission checks internally } @Override public Optional getShortDescription(CommandSource source) { - return Optional.of(Text.of("LuckPerms main command.")); + return Optional.of(Text.of("Manage permissions")); } @Override public Optional getHelp(CommandSource source) { - return Optional.of(Text.of("Type /luckperms for help.")); + return Optional.of(Text.of("Run /luckperms to view usage.")); } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeListener.java b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeListener.java index 3bc1de85..f97e3141 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeListener.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeListener.java @@ -34,7 +34,6 @@ import me.lucko.luckperms.common.locale.Message; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.utils.LoginHelper; import me.lucko.luckperms.common.utils.UuidCache; -import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.entity.living.player.Player; @@ -48,8 +47,6 @@ import org.spongepowered.api.text.serializer.TextSerializers; import org.spongepowered.api.util.Tristate; import org.spongepowered.api.world.World; -import co.aikar.timings.Timing; - import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -142,52 +139,50 @@ public class SpongeListener { @Listener(order = Order.FIRST) @IsCancelled(Tristate.UNDEFINED) public void onClientLogin(ClientConnectionEvent.Login e) { - try (Timing ignored = plugin.getTimings().time(LPTiming.ON_CLIENT_LOGIN)) { - /* Called when the player starts logging into the server. + /* Called when the player starts logging into the server. 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 player = e.getProfile(); - if (plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) { - plugin.getLog().info("Processing login event for " + player.getUniqueId() + " - " + player.getName()); - } + if (plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) { + plugin.getLog().info("Processing login event for " + player.getUniqueId() + " - " + player.getName()); + } - final User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(player.getUniqueId())); + final User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(player.getUniqueId())); /* User instance is null for whatever reason. Could be that it was unloaded between asyncpre and now. */ - if (user == null) { - deniedLogin.add(player.getUniqueId()); + if (user == null) { + deniedLogin.add(player.getUniqueId()); - plugin.getLog().warn("User " + player.getUniqueId() + " - " + player.getName() + " doesn't have data pre-loaded. - denying login."); - e.setCancelled(true); - e.setMessageCancelled(false); - //noinspection deprecation - e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(Message.LOADING_ERROR.asString(plugin.getLocaleManager()))); - return; - } + plugin.getLog().warn("User " + player.getUniqueId() + " - " + player.getName() + " doesn't have data pre-loaded. - denying login."); + e.setCancelled(true); + e.setMessageCancelled(false); + //noinspection deprecation + e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(Message.LOADING_ERROR.asString(plugin.getLocaleManager()))); + return; + } - // Attempt to pre-process some permissions for the user to save time later. Might not work, but it's better than nothing. - Optional p = e.getCause().first(Player.class); - if (p.isPresent()) { - MutableContextSet context = MutableContextSet.fromSet(plugin.getContextManager().getApplicableContext(p.get())); + // Attempt to pre-process some permissions for the user to save time later. Might not work, but it's better than nothing. + Optional p = e.getCause().first(Player.class); + if (p.isPresent()) { + MutableContextSet context = MutableContextSet.fromSet(plugin.getContextManager().getApplicableContext(p.get())); - List worlds = plugin.getGame().isServerAvailable() ? plugin.getGame().getServer().getWorlds().stream() - .map(World::getName) - .collect(Collectors.toList()) : Collections.emptyList(); + List worlds = plugin.getGame().isServerAvailable() ? plugin.getGame().getServer().getWorlds().stream() + .map(World::getName) + .collect(Collectors.toList()) : Collections.emptyList(); - plugin.doAsync(() -> { - UserData data = user.getUserData(); - data.preCalculate(plugin.getService().calculateContexts(context.makeImmutable())); + plugin.doAsync(() -> { + UserData data = user.getUserData(); + data.preCalculate(plugin.getService().calculateContexts(context.makeImmutable())); - for (String world : worlds) { - MutableContextSet modified = MutableContextSet.fromSet(context); - modified.removeAll("world"); - modified.add("world", world); - data.preCalculate(plugin.getService().calculateContexts(modified.makeImmutable())); - } - }); - } + for (String world : worlds) { + MutableContextSet modified = MutableContextSet.fromSet(context); + modified.removeAll("world"); + modified.add("world", world); + data.preCalculate(plugin.getService().calculateContexts(modified.makeImmutable())); + } + }); } } @@ -218,12 +213,11 @@ public class SpongeListener { /* We don't actually remove the user instance here, as Sponge likes to keep performing checks on players when they disconnect. The instance gets cleared up on a housekeeping task after a period of inactivity. */ - try (Timing ignored = plugin.getTimings().time(LPTiming.ON_CLIENT_LEAVE)) { - final UuidCache cache = plugin.getUuidCache(); - // Unload the user from memory when they disconnect - cache.clearCache(e.getTargetEntity().getUniqueId()); - } + final UuidCache cache = plugin.getUuidCache(); + + // Unload the user from memory when they disconnect + cache.clearCache(e.getTargetEntity().getUniqueId()); } @Listener diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeCalculatorLink.java b/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeCalculatorLink.java index 789c0848..2f59a428 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeCalculatorLink.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeCalculatorLink.java @@ -60,7 +60,7 @@ public class SpongeCalculatorLink implements ContextCalculator { delegate.accumulateContexts(subject, contexts); accumulator.addAll(CompatibilityUtil.convertContexts(contexts)); } catch (Exception e) { - new RuntimeException("Exception thrown by delegate Sponge calculator: " + delegate.getClass().getName(), e).printStackTrace(); + throw new RuntimeException("Exception thrown by delegate Sponge calculator: " + delegate.getClass().getName(), e); } return accumulator; diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/SpongeMigrationUtils.java b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/SpongeMigrationUtils.java index 3d0b65b3..ae7cf69d 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/SpongeMigrationUtils.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/SpongeMigrationUtils.java @@ -47,13 +47,13 @@ import java.util.Set; @UtilityClass public class SpongeMigrationUtils { - public static void migrateSubject(Subject subject, PermissionHolder holder, int priority) { - if (holder instanceof Group) { - MigrationUtils.setGroupWeight((Group) holder, priority); + public static void migrateSubject(Subject from, PermissionHolder to, int priority) { + if (to instanceof Group) { + MigrationUtils.setGroupWeight((Group) to, priority); } // Migrate permissions - Map, Map> perms = subject.getSubjectData().getAllPermissions(); + Map, Map> perms = from.getSubjectData().getAllPermissions(); for (Map.Entry, Map> e : perms.entrySet()) { ContextSet context = CompatibilityUtil.convertContexts(e.getKey()); @@ -62,12 +62,12 @@ public class SpongeMigrationUtils { continue; } - holder.setPermission(NodeFactory.newBuilder(perm.getKey()).withExtraContext(context).setValue(perm.getValue()).build()); + to.setPermission(NodeFactory.newBuilder(perm.getKey()).withExtraContext(context).setValue(perm.getValue()).build()); } } // Migrate options - Map, Map> opts = subject.getSubjectData().getAllOptions(); + Map, Map> opts = from.getSubjectData().getAllOptions(); for (Map.Entry, Map> e : opts.entrySet()) { ContextSet context = CompatibilityUtil.convertContexts(e.getKey()); @@ -77,17 +77,17 @@ public class SpongeMigrationUtils { } if (opt.getKey().equalsIgnoreCase("prefix")) { - holder.setPermission(NodeFactory.makePrefixNode(priority, opt.getValue()).withExtraContext(context).setValue(true).build()); + to.setPermission(NodeFactory.makePrefixNode(priority, opt.getValue()).withExtraContext(context).setValue(true).build()); } else if (opt.getKey().equalsIgnoreCase("suffix")) { - holder.setPermission(NodeFactory.makeSuffixNode(priority, opt.getValue()).withExtraContext(context).setValue(true).build()); + to.setPermission(NodeFactory.makeSuffixNode(priority, opt.getValue()).withExtraContext(context).setValue(true).build()); } else { - holder.setPermission(NodeFactory.makeMetaNode(opt.getKey(), opt.getValue()).withExtraContext(context).setValue(true).build()); + to.setPermission(NodeFactory.makeMetaNode(opt.getKey(), opt.getValue()).withExtraContext(context).setValue(true).build()); } } } // Migrate parents - Map, List> parents = subject.getSubjectData().getAllParents(); + Map, List> parents = from.getSubjectData().getAllParents(); for (Map.Entry, List> e : parents.entrySet()) { ContextSet context = CompatibilityUtil.convertContexts(e.getKey()); @@ -96,7 +96,7 @@ public class SpongeMigrationUtils { continue; // LuckPerms does not support persisting other subject types. } - holder.setPermission(NodeFactory.newBuilder("group." + MigrationUtils.standardizeName(s.getIdentifier())).withExtraContext(context).setValue(true).build()); + to.setPermission(NodeFactory.newBuilder("group." + MigrationUtils.standardizeName(s.getIdentifier())).withExtraContext(context).setValue(true).build()); } } } 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 5b3f7c1d..6036bb1e 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 @@ -48,15 +48,12 @@ import me.lucko.luckperms.sponge.service.model.CompatibilityUtil; import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.model.SubjectReference; -import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.service.permission.NodeTree; import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.Subject; -import co.aikar.timings.Timing; - import java.util.List; import java.util.Map; import java.util.Optional; @@ -176,69 +173,59 @@ public class SpongeGroup extends Group { @Override public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) { - try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_PERMISSION_VALUE)) { - NodeTree nt = permissionCache.get(contexts); - Tristate t = CompatibilityUtil.convertTristate(nt.get(permission)); - if (t != Tristate.UNDEFINED) { - return t; - } - - t = plugin.getService().getGroupSubjects().getDefaults().getPermissionValue(contexts, permission); - if (t != Tristate.UNDEFINED) { - return t; - } - - t = plugin.getService().getDefaults().getPermissionValue(contexts, permission); + NodeTree nt = permissionCache.get(contexts); + Tristate t = CompatibilityUtil.convertTristate(nt.get(permission)); + if (t != Tristate.UNDEFINED) { return t; } + + t = plugin.getService().getGroupSubjects().getDefaults().getPermissionValue(contexts, permission); + if (t != Tristate.UNDEFINED) { + return t; + } + + t = plugin.getService().getDefaults().getPermissionValue(contexts, permission); + return t; } @Override public boolean isChildOf(ImmutableContextSet contexts, SubjectReference parent) { - try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_IS_CHILD_OF)) { - return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getSubjectIdentifier()).asBoolean(); - } + return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getSubjectIdentifier()).asBoolean(); } @Override public ImmutableList getParents(ImmutableContextSet contexts) { - try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_PARENTS)) { - return parentCache.get(contexts); - } + return parentCache.get(contexts); } @Override public Optional getOption(ImmutableContextSet contexts, String s) { - try (Timing ignored = plugin.getService().getPlugin().getTimings().time(LPTiming.GROUP_GET_OPTION)) { - Optional option; - if (s.equalsIgnoreCase("prefix")) { - option = getChatMeta(contexts, ChatMetaType.PREFIX); + Optional option; + if (s.equalsIgnoreCase("prefix")) { + option = getChatMeta(contexts, ChatMetaType.PREFIX); - } else if (s.equalsIgnoreCase("suffix")) { - option = getChatMeta(contexts, ChatMetaType.SUFFIX); + } else if (s.equalsIgnoreCase("suffix")) { + option = getChatMeta(contexts, ChatMetaType.SUFFIX); - } else { - option = getMeta(contexts, s); - } - - if (option.isPresent()) { - return option; - } - - option = plugin.getService().getGroupSubjects().getDefaults().getOption(contexts, s); - if (option.isPresent()) { - return option; - } - - return plugin.getService().getDefaults().getOption(contexts, s); + } else { + option = getMeta(contexts, s); } + + if (option.isPresent()) { + return option; + } + + option = plugin.getService().getGroupSubjects().getDefaults().getOption(contexts, s); + if (option.isPresent()) { + return option; + } + + return plugin.getService().getDefaults().getOption(contexts, s); } @Override public ImmutableContextSet getActiveContextSet() { - try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_ACTIVE_CONTEXTS)) { - return plugin.getContextManager().getApplicableContext(this.sponge()).makeImmutable(); - } + return plugin.getContextManager().getApplicableContext(this.sponge()).makeImmutable(); } private Optional getChatMeta(ImmutableContextSet contexts, ChatMetaType type) { 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 3338a708..5f4ec4ef 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 @@ -42,7 +42,6 @@ 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.model.SubjectReference; -import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.Sponge; import org.spongepowered.api.command.CommandSource; @@ -50,8 +49,6 @@ import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.Subject; -import co.aikar.timings.Timing; - import java.util.Optional; import java.util.UUID; @@ -129,75 +126,66 @@ public class SpongeUser extends User { @Override public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) { - try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_PERMISSION_VALUE)) { - return parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK); - } + return parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK); } @Override public boolean isChildOf(ImmutableContextSet contexts, SubjectReference parent) { - try (Timing ignored = plugin.getTimings().time(LPTiming.USER_IS_CHILD_OF)) { - return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getSubjectIdentifier()).asBoolean(); - } + return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getSubjectIdentifier()).asBoolean(); } @Override public ImmutableList getParents(ImmutableContextSet contexts) { - try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_PARENTS)) { - ImmutableSet.Builder subjects = ImmutableSet.builder(); + ImmutableSet.Builder subjects = ImmutableSet.builder(); - for (String perm : parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getImmutableBacking().keySet()) { - if (!perm.startsWith("group.")) { - continue; - } - - String groupName = perm.substring("group.".length()); - if (plugin.getGroupManager().isLoaded(groupName)) { - subjects.add(plugin.getService().getGroupSubjects().loadSubject(groupName).join().toReference()); - } + for (String perm : parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getImmutableBacking().keySet()) { + if (!perm.startsWith("group.")) { + continue; } - subjects.addAll(plugin.getService().getUserSubjects().getDefaults().getParents(contexts)); - subjects.addAll(plugin.getService().getDefaults().getParents(contexts)); - - return getService().sortSubjects(subjects.build()); + String groupName = perm.substring("group.".length()); + if (plugin.getGroupManager().isLoaded(groupName)) { + subjects.add(plugin.getService().getGroupSubjects().loadSubject(groupName).join().toReference()); + } } + + subjects.addAll(plugin.getService().getUserSubjects().getDefaults().getParents(contexts)); + subjects.addAll(plugin.getService().getDefaults().getParents(contexts)); + + return getService().sortSubjects(subjects.build()); } @Override public Optional getOption(ImmutableContextSet contexts, String s) { - try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_OPTION)) { - MetaData data = parent.getUserData().getMetaData(plugin.getService().calculateContexts(contexts)); - if (s.equalsIgnoreCase("prefix")) { - if (data.getPrefix() != null) { - return Optional.of(data.getPrefix()); - } + MetaData data = parent.getUserData().getMetaData(plugin.getService().calculateContexts(contexts)); + if (s.equalsIgnoreCase("prefix")) { + if (data.getPrefix() != null) { + return Optional.of(data.getPrefix()); } - - if (s.equalsIgnoreCase("suffix")) { - if (data.getSuffix() != null) { - return Optional.of(data.getSuffix()); - } - } - - if (data.getMeta().containsKey(s)) { - return Optional.of(data.getMeta().get(s)); - } - - Optional v = plugin.getService().getUserSubjects().getDefaults().getOption(contexts, s); - if (v.isPresent()) { - return v; - } - - return plugin.getService().getDefaults().getOption(contexts, s); } + + if (s.equalsIgnoreCase("suffix")) { + if (data.getSuffix() != null) { + return Optional.of(data.getSuffix()); + } + } + + String val = data.getMeta().get(s); + if (val != null) { + return Optional.of(val); + } + + Optional v = plugin.getService().getUserSubjects().getDefaults().getOption(contexts, s); + if (v.isPresent()) { + return v; + } + + return plugin.getService().getDefaults().getOption(contexts, s); } @Override public ImmutableContextSet getActiveContextSet() { - try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_ACTIVE_CONTEXTS)) { - return plugin.getContextManager().getApplicableContext(this.sponge()); - } + return plugin.getContextManager().getApplicableContext(this.sponge()); } } 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 1d68fb48..a51669ea 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 @@ -29,7 +29,6 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NonNull; -import com.github.benmanes.caffeine.cache.CacheLoader; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.google.common.collect.ImmutableList; @@ -58,17 +57,15 @@ import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.model.SubjectReference; +import me.lucko.luckperms.sponge.service.model.SubjectReferenceFactory; import me.lucko.luckperms.sponge.service.persisted.PersistedCollection; import me.lucko.luckperms.sponge.service.storage.SubjectStorage; -import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.plugin.PluginContainer; import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.text.Text; -import co.aikar.timings.Timing; - import java.io.File; import java.util.ArrayList; import java.util.Collection; @@ -81,7 +78,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; /** - * The LuckPerms implementation of the Sponge Permission Service + * LuckPerms implementation of the Sponge Permission Service */ @Getter public class LuckPermsService implements LPPermissionService { @@ -105,17 +102,7 @@ public class LuckPermsService implements LPPermissionService { @Getter(value = AccessLevel.NONE) private final LoadingCache collections = Caffeine.newBuilder() - .build(new CacheLoader() { - @Override - public LPSubjectCollection load(String s) { - return new PersistedCollection(LuckPermsService.this, s); - } - - @Override - public LPSubjectCollection reload(String s, LPSubjectCollection collection) { - return collection; // Never needs to be refreshed. - } - }); + .build(s -> new PersistedCollection(this, s)); public LuckPermsService(LPSpongePlugin plugin) { this.plugin = plugin; @@ -134,8 +121,8 @@ public class LuckPermsService implements LPPermissionService { defaultSubjects = new PersistedCollection(this, "defaults"); defaultSubjects.loadAll(); - collections.put(PermissionService.SUBJECTS_USER, userSubjects); - collections.put(PermissionService.SUBJECTS_GROUP, groupSubjects); + collections.put("user", userSubjects); + collections.put("group", groupSubjects); collections.put("defaults", defaultSubjects); for (String collection : storage.getSavedCollections()) { @@ -168,9 +155,7 @@ public class LuckPermsService implements LPPermissionService { @Override public LPSubjectCollection getCollection(String s) { - try (Timing ignored = plugin.getTimings().time(LPTiming.GET_SUBJECTS)) { - return collections.get(s.toLowerCase()); - } + return collections.get(s.toLowerCase()); } @Override @@ -180,7 +165,7 @@ public class LuckPermsService implements LPPermissionService { @Override public SubjectReference newSubjectReference(String collectionIdentifier, String subjectIdentifier) { - return SubjectReference.of(this, collectionIdentifier, subjectIdentifier); + return SubjectReferenceFactory.obtain(this, collectionIdentifier, subjectIdentifier); } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java index 1f7b9190..a50aebcc 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubjectData.java @@ -46,12 +46,9 @@ import me.lucko.luckperms.common.node.NodeFactory; import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.model.SubjectReference; -import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.service.permission.PermissionService; -import co.aikar.timings.Timing; - import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -75,388 +72,358 @@ public class LuckPermsSubjectData implements LPSubjectData { @Override public ImmutableMap> getAllPermissions() { - try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_PERMISSIONS)) { - Map> perms = new HashMap<>(); + Map> perms = new HashMap<>(); - for (Map.Entry> e : (enduring ? holder.getEnduringNodes() : holder.getTransientNodes()).asMap().entrySet()) { - ImmutableMap.Builder results = ImmutableMap.builder(); - for (Node n : e.getValue()) { - results.put(n.getPermission(), n.getValuePrimitive()); - } - perms.put(e.getKey(), results); + for (Map.Entry> e : (enduring ? holder.getEnduringNodes() : holder.getTransientNodes()).asMap().entrySet()) { + ImmutableMap.Builder results = ImmutableMap.builder(); + for (Node n : e.getValue()) { + results.put(n.getPermission(), n.getValuePrimitive()); } - - ImmutableMap.Builder> map = ImmutableMap.builder(); - for (Map.Entry> e : perms.entrySet()) { - map.put(e.getKey(), e.getValue().build()); - } - return map.build(); + perms.put(e.getKey(), results); } + + ImmutableMap.Builder> map = ImmutableMap.builder(); + for (Map.Entry> e : perms.entrySet()) { + map.put(e.getKey(), e.getValue().build()); + } + return map.build(); } @Override public CompletableFuture setPermission(@NonNull ImmutableContextSet contexts, @NonNull String permission, @NonNull Tristate tristate) { - try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_PERMISSION)) { - if (tristate == Tristate.UNDEFINED) { - // Unset - Node node = NodeFactory.newBuilder(permission).withExtraContext(contexts).build(); + if (tristate == Tristate.UNDEFINED) { + // Unset + Node node = NodeFactory.newBuilder(permission).withExtraContext(contexts).build(); - if (enduring) { - holder.unsetPermission(node); - } else { - holder.unsetTransientPermission(node); - } - - return objectSave(holder).thenApply(v -> true); - } - - Node node = NodeFactory.newBuilder(permission).setValue(tristate.asBoolean()).withExtraContext(contexts).build(); - - // Workaround: unset the inverse, to allow false -> true, true -> false overrides. if (enduring) { holder.unsetPermission(node); } else { holder.unsetTransientPermission(node); } - if (enduring) { - holder.setPermission(node); - } else { - holder.setTransientPermission(node); - } - return objectSave(holder).thenApply(v -> true); } + + Node node = NodeFactory.newBuilder(permission).setValue(tristate.asBoolean()).withExtraContext(contexts).build(); + + // Workaround: unset the inverse, to allow false -> true, true -> false overrides. + if (enduring) { + holder.unsetPermission(node); + } else { + holder.unsetTransientPermission(node); + } + + if (enduring) { + holder.setPermission(node); + } else { + holder.setTransientPermission(node); + } + + return objectSave(holder).thenApply(v -> true); } @Override public CompletableFuture clearPermissions() { - try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PERMISSIONS)) { - boolean ret; - if (enduring) { - ret = holder.clearNodes(); - } else { - ret = holder.clearTransientNodes(); - } - - if (!ret) { - return CompletableFuture.completedFuture(false); - } - - if (holder instanceof User) { - service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false); - } - - return objectSave(holder).thenApply(v -> true); + boolean ret; + if (enduring) { + ret = holder.clearNodes(); + } else { + ret = holder.clearTransientNodes(); } + + if (!ret) { + return CompletableFuture.completedFuture(false); + } + + if (holder instanceof User) { + service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false); + } + + return objectSave(holder).thenApply(v -> true); } @Override public CompletableFuture clearPermissions(@NonNull ImmutableContextSet set) { - try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PERMISSIONS)) { - boolean ret; + boolean ret; + if (enduring) { + ret = holder.clearNodes(set); + } else { + List toRemove = streamNodes(false) + .filter(n -> n.getFullContexts().equals(set)) + .collect(Collectors.toList()); - if (enduring) { - ret = holder.clearNodes(set); - } else { - List toRemove = streamNodes(false) - .filter(n -> n.getFullContexts().equals(set)) - .collect(Collectors.toList()); - - toRemove.forEach(makeUnsetConsumer(false)); - ret = !toRemove.isEmpty(); - } - - if (!ret) { - return CompletableFuture.completedFuture(false); - } - - if (holder instanceof User) { - service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false); - } - - return objectSave(holder).thenApply(v -> true); + toRemove.forEach(makeUnsetConsumer(false)); + ret = !toRemove.isEmpty(); } + + if (!ret) { + return CompletableFuture.completedFuture(false); + } + + if (holder instanceof User) { + service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false); + } + + return objectSave(holder).thenApply(v -> true); } @Override public ImmutableMap> getAllParents() { - try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_PARENTS)) { - Map> parents = new HashMap<>(); + Map> parents = new HashMap<>(); - for (Map.Entry> e : (enduring ? holder.getEnduringNodes() : holder.getTransientNodes()).asMap().entrySet()) { - ImmutableList.Builder results = ImmutableList.builder(); - for (Node n : e.getValue()) { - if (n.isGroupNode()) { - results.add(service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference()); - } + for (Map.Entry> e : (enduring ? holder.getEnduringNodes() : holder.getTransientNodes()).asMap().entrySet()) { + ImmutableList.Builder results = ImmutableList.builder(); + for (Node n : e.getValue()) { + if (n.isGroupNode()) { + results.add(service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference()); } - parents.put(e.getKey(), results); } - - ImmutableMap.Builder> map = ImmutableMap.builder(); - for (Map.Entry> e : parents.entrySet()) { - map.put(e.getKey(), e.getValue().build()); - } - return map.build(); + parents.put(e.getKey(), results); } + + ImmutableMap.Builder> map = ImmutableMap.builder(); + for (Map.Entry> e : parents.entrySet()) { + map.put(e.getKey(), e.getValue().build()); + } + return map.build(); } @Override public CompletableFuture addParent(@NonNull ImmutableContextSet contexts, @NonNull SubjectReference subject) { - try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_ADD_PARENT)) { - if (subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) { - return subject.resolveLp().thenCompose(sub -> { - DataMutateResult result; + if (subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) { + return subject.resolveLp().thenCompose(sub -> { + DataMutateResult result; - if (enduring) { - result = holder.setPermission(NodeFactory.newBuilder("group." + sub.getIdentifier()) - .withExtraContext(contexts) - .build()); - } else { - result = holder.setTransientPermission(NodeFactory.newBuilder("group." + sub.getIdentifier()) - .withExtraContext(contexts) - .build()); - } + if (enduring) { + result = holder.setPermission(NodeFactory.newBuilder("group." + sub.getIdentifier()) + .withExtraContext(contexts) + .build()); + } else { + result = holder.setTransientPermission(NodeFactory.newBuilder("group." + sub.getIdentifier()) + .withExtraContext(contexts) + .build()); + } - if (!result.asBoolean()) { - return CompletableFuture.completedFuture(false); - } + if (!result.asBoolean()) { + return CompletableFuture.completedFuture(false); + } - return objectSave(holder).thenApply(v -> true); - }); - } - return CompletableFuture.completedFuture(false); + return objectSave(holder).thenApply(v -> true); + }); } + return CompletableFuture.completedFuture(false); } @Override public CompletableFuture removeParent(@NonNull ImmutableContextSet contexts, @NonNull SubjectReference subject) { - try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_REMOVE_PARENT)) { - if (subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) { - subject.resolveLp().thenCompose(sub -> { - DataMutateResult result; + if (subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) { + subject.resolveLp().thenCompose(sub -> { + DataMutateResult result; - if (enduring) { - result = holder.unsetPermission(NodeFactory.newBuilder("group." + sub.getIdentifier()) - .withExtraContext(contexts) - .build()); - } else { - result = holder.unsetTransientPermission(NodeFactory.newBuilder("group." + sub.getIdentifier()) - .withExtraContext(contexts) - .build()); - } + if (enduring) { + result = holder.unsetPermission(NodeFactory.newBuilder("group." + sub.getIdentifier()) + .withExtraContext(contexts) + .build()); + } else { + result = holder.unsetTransientPermission(NodeFactory.newBuilder("group." + sub.getIdentifier()) + .withExtraContext(contexts) + .build()); + } - if (!result.asBoolean()) { - return CompletableFuture.completedFuture(false); - } + if (!result.asBoolean()) { + return CompletableFuture.completedFuture(false); + } - return objectSave(holder).thenApply(v -> true); - }); - } - return CompletableFuture.completedFuture(false); + return objectSave(holder).thenApply(v -> true); + }); } + return CompletableFuture.completedFuture(false); } @Override public CompletableFuture clearParents() { - try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PARENTS)) { - boolean ret; + boolean ret; + if (enduring) { + ret = holder.clearParents(true); + } else { + List toRemove = streamNodes(false) + .filter(Node::isGroupNode) + .collect(Collectors.toList()); - if (enduring) { - ret = holder.clearParents(true); - } else { - List toRemove = streamNodes(false) - .filter(Node::isGroupNode) - .collect(Collectors.toList()); + toRemove.forEach(makeUnsetConsumer(false)); + ret = !toRemove.isEmpty(); - toRemove.forEach(makeUnsetConsumer(false)); - ret = !toRemove.isEmpty(); - - if (ret && holder instanceof User) { - service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false); - } + if (ret && holder instanceof User) { + service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false); } - - if (!ret) { - return CompletableFuture.completedFuture(false); - } - - return objectSave(holder).thenApply(v -> true); } + + if (!ret) { + return CompletableFuture.completedFuture(false); + } + + return objectSave(holder).thenApply(v -> true); } @Override public CompletableFuture clearParents(@NonNull ImmutableContextSet set) { - try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PARENTS)) { - boolean ret; - if (enduring) { - ret = holder.clearParents(set, true); - } else { - List toRemove = streamNodes(false) - .filter(Node::isGroupNode) - .filter(n -> n.getFullContexts().equals(set)) - .collect(Collectors.toList()); + boolean ret; + if (enduring) { + ret = holder.clearParents(set, true); + } else { + List toRemove = streamNodes(false) + .filter(Node::isGroupNode) + .filter(n -> n.getFullContexts().equals(set)) + .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(false)); - ret = !toRemove.isEmpty(); + toRemove.forEach(makeUnsetConsumer(false)); + ret = !toRemove.isEmpty(); - if (ret && holder instanceof User) { - service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false); - } + if (ret && holder instanceof User) { + service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false); } - - if (!ret) { - return CompletableFuture.completedFuture(false); - } - - return objectSave(holder).thenApply(v -> true); } + + if (!ret) { + return CompletableFuture.completedFuture(false); + } + + return objectSave(holder).thenApply(v -> true); } @Override public ImmutableMap> getAllOptions() { - try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_OPTIONS)) { - Map> options = new HashMap<>(); - Map minPrefixPriority = new HashMap<>(); - Map minSuffixPriority = new HashMap<>(); + Map> options = new HashMap<>(); + Map minPrefixPriority = new HashMap<>(); + Map minSuffixPriority = new HashMap<>(); - for (Node n : enduring ? holder.getEnduringNodes().values() : holder.getTransientNodes().values()) { - if (!n.getValuePrimitive()) continue; - if (!n.isMeta() && !n.isPrefix() && !n.isSuffix()) continue; + for (Node n : enduring ? holder.getEnduringNodes().values() : holder.getTransientNodes().values()) { + if (!n.getValuePrimitive()) continue; + if (!n.isMeta() && !n.isPrefix() && !n.isSuffix()) continue; - ImmutableContextSet immutableContexts = n.getFullContexts().makeImmutable(); + ImmutableContextSet immutableContexts = n.getFullContexts().makeImmutable(); - if (!options.containsKey(immutableContexts)) { - options.put(immutableContexts, new HashMap<>()); - minPrefixPriority.put(immutableContexts, Integer.MIN_VALUE); - minSuffixPriority.put(immutableContexts, Integer.MIN_VALUE); - } - - if (n.isPrefix()) { - Map.Entry value = n.getPrefix(); - if (value.getKey() > minPrefixPriority.get(immutableContexts)) { - options.get(immutableContexts).put("prefix", value.getValue()); - minPrefixPriority.put(immutableContexts, value.getKey()); - } - continue; - } - - if (n.isSuffix()) { - Map.Entry value = n.getSuffix(); - if (value.getKey() > minSuffixPriority.get(immutableContexts)) { - options.get(immutableContexts).put("suffix", value.getValue()); - minSuffixPriority.put(immutableContexts, value.getKey()); - } - continue; - } - - if (n.isMeta()) { - Map.Entry meta = n.getMeta(); - options.get(immutableContexts).put(meta.getKey(), meta.getValue()); - } + if (!options.containsKey(immutableContexts)) { + options.put(immutableContexts, new HashMap<>()); + minPrefixPriority.put(immutableContexts, Integer.MIN_VALUE); + minSuffixPriority.put(immutableContexts, Integer.MIN_VALUE); } - ImmutableMap.Builder> map = ImmutableMap.builder(); - for (Map.Entry> e : options.entrySet()) { - map.put(e.getKey(), ImmutableMap.copyOf(e.getValue())); + if (n.isPrefix()) { + Map.Entry value = n.getPrefix(); + if (value.getKey() > minPrefixPriority.get(immutableContexts)) { + options.get(immutableContexts).put("prefix", value.getValue()); + minPrefixPriority.put(immutableContexts, value.getKey()); + } + continue; + } + + if (n.isSuffix()) { + Map.Entry value = n.getSuffix(); + if (value.getKey() > minSuffixPriority.get(immutableContexts)) { + options.get(immutableContexts).put("suffix", value.getValue()); + minSuffixPriority.put(immutableContexts, value.getKey()); + } + continue; + } + + if (n.isMeta()) { + Map.Entry meta = n.getMeta(); + options.get(immutableContexts).put(meta.getKey(), meta.getValue()); } - return map.build(); } + + ImmutableMap.Builder> map = ImmutableMap.builder(); + for (Map.Entry> e : options.entrySet()) { + map.put(e.getKey(), ImmutableMap.copyOf(e.getValue())); + } + return map.build(); } @Override public CompletableFuture setOption(@NonNull ImmutableContextSet context, @NonNull String key, @NonNull String value) { - try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_OPTION)) { - if (key.equalsIgnoreCase("prefix") || key.equalsIgnoreCase("suffix")) { - // special handling. - ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase()); + if (key.equalsIgnoreCase("prefix") || key.equalsIgnoreCase("suffix")) { + // special handling. + ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase()); - // remove all prefixes/suffixes from the user - List toRemove = streamNodes(enduring) - .filter(type::matches) - .filter(n -> n.getFullContexts().equals(context)) - .collect(Collectors.toList()); + // remove all prefixes/suffixes from the user + List toRemove = streamNodes(enduring) + .filter(type::matches) + .filter(n -> n.getFullContexts().equals(context)) + .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(enduring)); + toRemove.forEach(makeUnsetConsumer(enduring)); - MetaAccumulator metaAccumulator = holder.accumulateMeta(null, null, ExtractedContexts.generate(service.calculateContexts(context))); - int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0); - priority += 10; - - if (enduring) { - holder.setPermission(NodeFactory.makeChatMetaNode(type, priority, value).withExtraContext(context).build()); - } else { - holder.setTransientPermission(NodeFactory.makeChatMetaNode(type, priority, value).withExtraContext(context).build()); - } + MetaAccumulator metaAccumulator = holder.accumulateMeta(null, null, ExtractedContexts.generate(service.calculateContexts(context))); + int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0); + priority += 10; + if (enduring) { + holder.setPermission(NodeFactory.makeChatMetaNode(type, priority, value).withExtraContext(context).build()); } else { - // standard remove - List toRemove = streamNodes(enduring) - .filter(n -> n.isMeta() && n.getMeta().getKey().equals(key)) - .filter(n -> n.getFullContexts().equals(context)) - .collect(Collectors.toList()); - - toRemove.forEach(makeUnsetConsumer(enduring)); - - if (enduring) { - holder.setPermission(NodeFactory.makeMetaNode(key, value).withExtraContext(context).build()); - } else { - holder.setTransientPermission(NodeFactory.makeMetaNode(key, value).withExtraContext(context).build()); - } + holder.setTransientPermission(NodeFactory.makeChatMetaNode(type, priority, value).withExtraContext(context).build()); } - return objectSave(holder).thenApply(v -> true); + } else { + // standard remove + List toRemove = streamNodes(enduring) + .filter(n -> n.isMeta() && n.getMeta().getKey().equals(key)) + .filter(n -> n.getFullContexts().equals(context)) + .collect(Collectors.toList()); + + toRemove.forEach(makeUnsetConsumer(enduring)); + + if (enduring) { + holder.setPermission(NodeFactory.makeMetaNode(key, value).withExtraContext(context).build()); + } else { + holder.setTransientPermission(NodeFactory.makeMetaNode(key, value).withExtraContext(context).build()); + } } + + return objectSave(holder).thenApply(v -> true); } @Override public CompletableFuture unsetOption(ImmutableContextSet set, String key) { - try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_OPTION)) { - List toRemove = streamNodes(enduring) - .filter(n -> { - if (key.equalsIgnoreCase("prefix")) { - return n.isPrefix(); - } else if (key.equalsIgnoreCase("suffix")) { - return n.isSuffix(); - } else { - return n.isMeta() && n.getMeta().getKey().equals(key); - } - }) - .filter(n -> n.getFullContexts().equals(set)) - .collect(Collectors.toList()); + List toRemove = streamNodes(enduring) + .filter(n -> { + if (key.equalsIgnoreCase("prefix")) { + return n.isPrefix(); + } else if (key.equalsIgnoreCase("suffix")) { + return n.isSuffix(); + } else { + return n.isMeta() && n.getMeta().getKey().equals(key); + } + }) + .filter(n -> n.getFullContexts().equals(set)) + .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(enduring)); + toRemove.forEach(makeUnsetConsumer(enduring)); - return objectSave(holder).thenApply(v -> true); - } + return objectSave(holder).thenApply(v -> true); } @Override public CompletableFuture clearOptions(@NonNull ImmutableContextSet set) { - try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_OPTIONS)) { - List toRemove = streamNodes(enduring) - .filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix()) - .filter(n -> n.getFullContexts().equals(set)) - .collect(Collectors.toList()); + List toRemove = streamNodes(enduring) + .filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix()) + .filter(n -> n.getFullContexts().equals(set)) + .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(enduring)); + toRemove.forEach(makeUnsetConsumer(enduring)); - return objectSave(holder).thenApply(v -> !toRemove.isEmpty()); - } + return objectSave(holder).thenApply(v -> !toRemove.isEmpty()); } @Override public CompletableFuture clearOptions() { - try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_OPTIONS)) { - List toRemove = streamNodes(enduring) - .filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix()) - .collect(Collectors.toList()); + List toRemove = streamNodes(enduring) + .filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix()) + .collect(Collectors.toList()); - toRemove.forEach(makeUnsetConsumer(enduring)); + toRemove.forEach(makeUnsetConsumer(enduring)); - return objectSave(holder).thenApply(v -> !toRemove.isEmpty()); - } + return objectSave(holder).thenApply(v -> !toRemove.isEmpty()); } private Stream streamNodes(boolean enduring) { 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 d42d1177..6866607f 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 @@ -40,6 +40,7 @@ import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.common.calculators.PermissionCalculator; 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.verbose.CheckOrigin; @@ -49,7 +50,6 @@ import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.model.SubjectReference; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -65,7 +65,6 @@ import java.util.concurrent.TimeUnit; */ @RequiredArgsConstructor public class CalculatedSubjectData implements LPSubjectData { - private static final ContextComparator CONTEXT_COMPARATOR = new ContextComparator(); @Getter private final LPSubject parentSubject; @@ -87,7 +86,7 @@ public class CalculatedSubjectData implements LPSubjectData { processors.add(new SpongeWildcardProcessor()); CalculatorHolder holder = new CalculatorHolder(new PermissionCalculator(service.getPlugin(), PermissionCalculatorMetadata.of(calculatorDisplayName, contexts), processors.build())); - holder.setPermissions(flattenMap(contexts, permissions)); + holder.setPermissions(flattenMap(getRelevantEntries(contexts, permissions))); return holder; } @@ -290,11 +289,10 @@ public class CalculatedSubjectData implements LPSubjectData { return CompletableFuture.completedFuture(!map.isEmpty()); } - private static Map flattenMap(ContextSet contexts, Map> source) { + private static Map flattenMap(SortedMap> data) { Map map = new HashMap<>(); - SortedMap> ret = getRelevantEntries(contexts, source); - for (Map m : ret.values()) { + for (Map m : data.values()) { for (Map.Entry e : m.entrySet()) { map.putIfAbsent(e.getKey(), e.getValue()); } @@ -304,7 +302,7 @@ public class CalculatedSubjectData implements LPSubjectData { } private static SortedMap> getRelevantEntries(ContextSet set, Map> map) { - ImmutableSortedMap.Builder> perms = ImmutableSortedMap.orderedBy(CONTEXT_COMPARATOR); + ImmutableSortedMap.Builder> perms = ImmutableSortedMap.orderedBy(ContextSetComparator.reverse()); for (Map.Entry> e : map.entrySet()) { if (!e.getKey().isSatisfiedBy(set)) { @@ -321,15 +319,6 @@ public class CalculatedSubjectData implements LPSubjectData { return a == null && b == null || a != null && b != null && a.equalsIgnoreCase(b); } - private static class ContextComparator implements Comparator { - - @Override - public int compare(ImmutableContextSet o1, ImmutableContextSet o2) { - int i = Integer.compare(o1.size(), o2.size()); - return i == 0 ? 1 : i; - } - } - private static class CalculatorHolder { @Getter 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 index cfd14639..a04d80b7 100644 --- 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 @@ -29,7 +29,7 @@ import lombok.ToString; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.sponge.service.model.LPPermissionService; -import me.lucko.luckperms.sponge.service.model.SubjectReference; +import me.lucko.luckperms.sponge.service.model.SubjectReferenceFactory; import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel; import java.util.List; @@ -66,7 +66,7 @@ public class SubjectDataHolder { parents.entrySet().stream() .collect(Collectors.toMap( k -> ImmutableContextSet.fromMap(k.getKey()), - v -> v.getValue().stream().map(s -> SubjectReference.deserialize(service, s)).collect(Collectors.toList()) + 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/PersistedSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubject.java index 5bc7ec1e..81c5a3b3 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 @@ -44,13 +44,10 @@ import me.lucko.luckperms.sponge.service.calculated.PermissionLookup; import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.SubjectReference; import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel; -import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.service.permission.Subject; -import co.aikar.timings.Timing; - import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -246,46 +243,36 @@ public class PersistedSubject implements LPSubject { @Override public Tristate getPermissionValue(@NonNull ImmutableContextSet contexts, @NonNull String node) { - try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_PERMISSION_VALUE)) { - Tristate t = permissionLookupCache.get(PermissionLookup.of(node, contexts)); - service.getPlugin().getVerboseHandler().offerCheckData(CheckOrigin.INTERNAL, "local:" + getParentCollection().getIdentifier() + "/" + identifier, contexts, node, t); - return t; - } + Tristate t = permissionLookupCache.get(PermissionLookup.of(node, contexts)); + service.getPlugin().getVerboseHandler().offerCheckData(CheckOrigin.INTERNAL, "local:" + getParentCollection().getIdentifier() + "/" + identifier, contexts, node, t); + return t; } @Override public boolean isChildOf(@NonNull ImmutableContextSet contexts, @NonNull SubjectReference subject) { - try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_IS_CHILD_OF)) { - if (getParentCollection().getIdentifier().equalsIgnoreCase("defaults")) { - return subjectData.getParents(contexts).contains(subject) || - transientSubjectData.getParents(contexts).contains(subject); - } else { - return subjectData.getParents(contexts).contains(subject) || - transientSubjectData.getParents(contexts).contains(subject) || - getParentCollection().getDefaults().getParents(contexts).contains(subject) || - service.getDefaults().getParents(contexts).contains(subject); - } + if (getParentCollection().getIdentifier().equalsIgnoreCase("defaults")) { + return subjectData.getParents(contexts).contains(subject) || + transientSubjectData.getParents(contexts).contains(subject); + } else { + return subjectData.getParents(contexts).contains(subject) || + transientSubjectData.getParents(contexts).contains(subject) || + getParentCollection().getDefaults().getParents(contexts).contains(subject) || + service.getDefaults().getParents(contexts).contains(subject); } } @Override public ImmutableList getParents(@NonNull ImmutableContextSet contexts) { - try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_PARENTS)) { - return parentLookupCache.get(contexts); - } + return parentLookupCache.get(contexts); } @Override public Optional getOption(ImmutableContextSet contexts, String key) { - try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_OPTION)) { - return optionLookupCache.get(OptionLookup.of(key, contexts)); - } + return optionLookupCache.get(OptionLookup.of(key, contexts)); } @Override public ImmutableContextSet getActiveContextSet() { - try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_ACTIVE_CONTEXTS)) { - return service.getPlugin().getContextManager().getApplicableContext(sponge()).makeImmutable(); - } + return service.getPlugin().getContextManager().getApplicableContext(sponge()).makeImmutable(); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/storage/SubjectStorageModel.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/storage/SubjectStorageModel.java index 76f56bc5..fc679b92 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/storage/SubjectStorageModel.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/storage/SubjectStorageModel.java @@ -41,6 +41,7 @@ import me.lucko.luckperms.common.node.NodeWithContextComparator; import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData; import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.SubjectReference; +import me.lucko.luckperms.sponge.service.model.SubjectReferenceFactory; import java.util.ArrayList; import java.util.List; @@ -164,7 +165,7 @@ public class SubjectStorageModel { String collection = parent.get("collection").getAsString(); String subject = parent.get("subject").getAsString(); - pars.add(SubjectReference.of(service, collection, subject)); + pars.add(SubjectReferenceFactory.obtain(service, collection, subject)); } parentsBuilder.put(contextSet, pars.build()); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/timings/LPTiming.java b/sponge/src/main/java/me/lucko/luckperms/sponge/timings/LPTiming.java deleted file mode 100644 index 7d3c978f..00000000 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/timings/LPTiming.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of LuckPerms, licensed under the MIT License. - * - * Copyright (c) lucko (Luck) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.lucko.luckperms.sponge.timings; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum LPTiming { - - GET_SUBJECTS("getSubjects"), - - USER_COLLECTION_GET("userCollectionGet"), - GROUP_COLLECTION_GET("groupCollectionGet"), - - USER_GET_PERMISSION_VALUE("userGetPermissionValue"), - USER_GET_PARENTS("userGetParents"), - USER_IS_CHILD_OF("userIsChildOf"), - USER_GET_OPTION("userGetOption"), - USER_GET_ACTIVE_CONTEXTS("userGetActiveContexts"), - - GROUP_GET_PERMISSION_VALUE("groupGetPermissionValue"), - GROUP_GET_PARENTS("groupGetParents"), - GROUP_IS_CHILD_OF("groupIsChildOf"), - GROUP_GET_OPTION("groupGetOption"), - GROUP_GET_ACTIVE_CONTEXTS("groupGetActiveContexts"), - - LP_SUBJECT_GET_PERMISSIONS("lpSubjectGetPermissions"), - LP_SUBJECT_SET_PERMISSION("lpSubjectSetPermission"), - LP_SUBJECT_CLEAR_PERMISSIONS("lpSubjectClearPermissions"), - LP_SUBJECT_GET_PARENTS("lpSubjectGetParents"), - LP_SUBJECT_ADD_PARENT("lpSubjectAddParent"), - LP_SUBJECT_REMOVE_PARENT("lpSubjectRemoveParent"), - LP_SUBJECT_CLEAR_PARENTS("lpSubjectClearParents"), - LP_SUBJECT_GET_OPTIONS("lpSubjectGetOptions"), - LP_SUBJECT_SET_OPTION("lpSubjectSetOption"), - LP_SUBJECT_CLEAR_OPTIONS("lpSubjectClearOptions"), - - INTERNAL_SUBJECT_GET_PERMISSION_VALUE("internalSubjectGetPermissionValue"), - INTERNAL_SUBJECT_IS_CHILD_OF("internalSubjectIsChildOf"), - INTERNAL_SUBJECT_GET_PARENTS("internalSubjectGetParents"), - INTERNAL_SUBJECT_GET_OPTION("internalSubjectGetOption"), - INTERNAL_SUBJECT_GET_ACTIVE_CONTEXTS("internalSubjectGetActiveContexts"), - - ON_COMMAND("onCommand"), - COMMAND_TAB_COMPLETE("commandTabComplete"), - ON_CLIENT_LOGIN("onClientLogin"), - ON_CLIENT_LEAVE("onClientLeave"); - - private final String id; - -} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/timings/LPTimings.java b/sponge/src/main/java/me/lucko/luckperms/sponge/timings/LPTimings.java deleted file mode 100644 index 6ef3da28..00000000 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/timings/LPTimings.java +++ /dev/null @@ -1,56 +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.timings; - -import lombok.NonNull; - -import com.google.common.collect.ImmutableMap; - -import me.lucko.luckperms.sponge.LPSpongePlugin; - -import co.aikar.timings.Timing; -import co.aikar.timings.Timings; - -import java.util.Map; - -public class LPTimings { - private final Map timings; - - public LPTimings(LPSpongePlugin plugin) { - ImmutableMap.Builder map = ImmutableMap.builder(); - for (LPTiming t : LPTiming.values()) { - map.put(t, Timings.of(plugin, t.getId())); - } - - timings = map.build(); - } - - public Timing time(@NonNull LPTiming timing) { - Timing t = timings.get(timing); - t.startTimingIfSync(); - return t; - } -}