diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCalculatorFactory.java b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCalculatorFactory.java index 298cb9248..b0d4721f8 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCalculatorFactory.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeCalculatorFactory.java @@ -34,7 +34,6 @@ import me.lucko.luckperms.common.calculators.processors.WildcardProcessor; import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.sponge.calculators.DefaultsProcessor; import me.lucko.luckperms.sponge.calculators.SpongeWildcardProcessor; -import me.lucko.luckperms.sponge.service.LuckPermsService; @AllArgsConstructor public class SpongeCalculatorFactory extends AbstractCalculatorFactory { @@ -51,7 +50,7 @@ public class SpongeCalculatorFactory extends AbstractCalculatorFactory { if (plugin.getConfiguration().isApplyingRegex()) { processors.add(new RegexProcessor()); } - processors.add(new DefaultsProcessor(plugin.getService(), LuckPermsService.convertContexts(contexts.getContexts()))); + processors.add(new DefaultsProcessor(plugin.getService(), contexts.getContexts())); return registerCalculator(new PermissionCalculator(plugin, user.getName(), processors.build())); } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/calculators/DefaultsProcessor.java b/sponge/src/main/java/me/lucko/luckperms/sponge/calculators/DefaultsProcessor.java index 205941bf3..4b4acdb90 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/calculators/DefaultsProcessor.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/calculators/DefaultsProcessor.java @@ -23,34 +23,31 @@ package me.lucko.luckperms.sponge.calculators; import lombok.AllArgsConstructor; +import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.calculators.PermissionProcessor; import me.lucko.luckperms.sponge.service.LuckPermsService; -import org.spongepowered.api.service.context.Context; -import org.spongepowered.api.util.Tristate; import java.util.Map; -import java.util.Set; - -import static me.lucko.luckperms.sponge.service.LuckPermsService.convertTristate; @AllArgsConstructor public class DefaultsProcessor implements PermissionProcessor { private final LuckPermsService service; - private final Set contexts; + private final ContextSet contexts; @Override - public me.lucko.luckperms.api.Tristate hasPermission(String permission) { - Tristate t = service.getUserSubjects().getDefaults().getPermissionValue(contexts, permission); + public Tristate hasPermission(String permission) { + Tristate t = service.getUserSubjects().getDefaultSubject().resolve(service).getPermissionValue(contexts, permission); if (t != Tristate.UNDEFINED) { - return convertTristate(t); + return t; } Tristate t2 = service.getDefaults().getPermissionValue(contexts, permission); if (t2 != Tristate.UNDEFINED) { - return convertTristate(t); + return t; } - return me.lucko.luckperms.api.Tristate.UNDEFINED; + return Tristate.UNDEFINED; } @Override 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 112b8ea80..00faafde6 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 @@ -25,7 +25,7 @@ package me.lucko.luckperms.sponge.contexts; import lombok.AllArgsConstructor; import me.lucko.luckperms.api.context.ContextCalculator; import me.lucko.luckperms.api.context.MutableContextSet; -import me.lucko.luckperms.sponge.service.LuckPermsService; +import me.lucko.luckperms.sponge.service.base.Util; import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.permission.Subject; @@ -38,11 +38,11 @@ public class SpongeCalculatorLink extends ContextCalculator { @Override public MutableContextSet giveApplicableContext(Subject subject, MutableContextSet accumulator) { - Set contexts = LuckPermsService.convertContexts(accumulator); + Set contexts = Util.convertContexts(accumulator); calculator.accumulateContexts(subject, contexts); accumulator.clear(); - accumulator.addAll(LuckPermsService.convertContexts(contexts)); + accumulator.addAll(Util.convertContexts(contexts)); return accumulator; } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeGroupManager.java b/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeGroupManager.java index 2e17139da..6bc9c032e 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeGroupManager.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeGroupManager.java @@ -30,6 +30,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.NonNull; +import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.managers.GroupManager; @@ -38,18 +39,16 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.model.SpongeGroup; import me.lucko.luckperms.sponge.service.LuckPermsService; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.base.LPSubjectCollection; +import me.lucko.luckperms.sponge.service.references.SubjectReference; import me.lucko.luckperms.sponge.timings.LPTiming; -import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.permission.PermissionService; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.service.permission.SubjectCollection; -import org.spongepowered.api.service.permission.SubjectData; -import org.spongepowered.api.util.Tristate; +import java.util.Collection; import java.util.Map; -import java.util.Set; -public class SpongeGroupManager implements GroupManager, SubjectCollection { +public class SpongeGroupManager implements GroupManager, LPSubjectCollection { private final LPSpongePlugin plugin; private final LoadingCache objects = CacheBuilder.newBuilder() @@ -120,7 +119,12 @@ public class SpongeGroupManager implements GroupManager, SubjectCollection { } @Override - public Subject get(@NonNull String id) { + public LuckPermsService getService() { + return plugin.getService(); + } + + @Override + public LPSubject get(@NonNull String id) { // Special Sponge method. This call will actually load the group from the datastore if not already present. try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_COLLECTION_GET)) { @@ -159,26 +163,20 @@ public class SpongeGroupManager implements GroupManager, SubjectCollection { } @Override - public Iterable getAllSubjects() { + public Collection getSubjects() { return objects.asMap().values().stream().map(SpongeGroup::getSpongeData).collect(ImmutableCollectors.toImmutableList()); } @Override - public Map getAllWithPermission(@NonNull String id) { - return getAllWithPermission(SubjectData.GLOBAL_CONTEXT, id); - } - - @Override - public Map getAllWithPermission(@NonNull Set contexts, @NonNull String node) { - ContextSet cs = LuckPermsService.convertContexts(contexts); + public Map getWithPermission(@NonNull ContextSet contexts, @NonNull String node) { return objects.asMap().values().stream() .map(SpongeGroup::getSpongeData) - .filter(sub -> sub.getPermissionValue(cs, node) != Tristate.UNDEFINED) - .collect(ImmutableCollectors.toImmutableMap(sub -> sub, sub -> sub.getPermissionValue(cs, node).asBoolean())); + .filter(sub -> sub.getPermissionValue(contexts, node) != Tristate.UNDEFINED) + .collect(ImmutableCollectors.toImmutableMap(sub -> sub, sub -> sub.getPermissionValue(contexts, node).asBoolean())); } @Override - public Subject getDefaults() { - return plugin.getService().getDefaultSubjects().get(getIdentifier()); + public SubjectReference getDefaultSubject() { + return SubjectReference.of("defaults", getIdentifier()); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeUserManager.java b/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeUserManager.java index 026579683..22a25ffee 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeUserManager.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/managers/SpongeUserManager.java @@ -30,6 +30,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.NonNull; +import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.commands.utils.Util; import me.lucko.luckperms.common.core.UserIdentifier; @@ -40,19 +41,18 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.model.SpongeUser; import me.lucko.luckperms.sponge.service.LuckPermsService; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.base.LPSubjectCollection; +import me.lucko.luckperms.sponge.service.references.SubjectReference; import me.lucko.luckperms.sponge.timings.LPTiming; -import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.permission.PermissionService; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.service.permission.SubjectCollection; -import org.spongepowered.api.service.permission.SubjectData; -import org.spongepowered.api.util.Tristate; +import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.UUID; -public class SpongeUserManager implements UserManager, SubjectCollection { +public class SpongeUserManager implements UserManager, LPSubjectCollection { private final LPSpongePlugin plugin; private final LoadingCache objects = CacheBuilder.newBuilder() @@ -170,7 +170,12 @@ public class SpongeUserManager implements UserManager, SubjectCollection { } @Override - public Subject get(@NonNull String id) { + public LuckPermsService getService() { + return plugin.getService(); + } + + @Override + public LPSubject get(@NonNull String id) { // Special Sponge method. This call will actually load the user from the datastore if not already present. try (Timing ignored = plugin.getTimings().time(LPTiming.USER_COLLECTION_GET)) { @@ -217,26 +222,20 @@ public class SpongeUserManager implements UserManager, SubjectCollection { } @Override - public Iterable getAllSubjects() { + public Collection getSubjects() { return objects.asMap().values().stream().map(SpongeUser::getSpongeData).collect(ImmutableCollectors.toImmutableList()); } @Override - public Map getAllWithPermission(@NonNull String id) { - return getAllWithPermission(SubjectData.GLOBAL_CONTEXT, id); - } - - @Override - public Map getAllWithPermission(@NonNull Set contexts, @NonNull String node) { - ContextSet cs = LuckPermsService.convertContexts(contexts); + public Map getWithPermission(@NonNull ContextSet contexts, @NonNull String node) { return objects.asMap().values().stream() .map(SpongeUser::getSpongeData) - .filter(sub -> sub.getPermissionValue(cs, node) != Tristate.UNDEFINED) - .collect(ImmutableCollectors.toImmutableMap(sub -> sub, sub -> sub.getPermissionValue(cs, node).asBoolean())); + .filter(sub -> sub.getPermissionValue(contexts, node) != Tristate.UNDEFINED) + .collect(ImmutableCollectors.toImmutableMap(sub -> sub, sub -> sub.getPermissionValue(contexts, node).asBoolean())); } @Override - public Subject getDefaults() { - return plugin.getService().getDefaultSubjects().get(getIdentifier()); + public SubjectReference getDefaultSubject() { + return SubjectReference.of("defaults", getIdentifier()); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationUtils.java b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationUtils.java index f3f0b8679..d71da2281 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationUtils.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationUtils.java @@ -29,7 +29,7 @@ import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.utils.ExtractedContexts; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; -import me.lucko.luckperms.sponge.service.LuckPermsService; +import me.lucko.luckperms.sponge.service.base.Util; import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.Subject; @@ -47,7 +47,7 @@ public class MigrationUtils { // Migrate permissions Map, Map> perms = subject.getSubjectData().getAllPermissions(); for (Map.Entry, Map> e : perms.entrySet()) { - ContextSet context = LuckPermsService.convertContexts(e.getKey()); + ContextSet context = Util.convertContexts(e.getKey()); ExtractedContexts extractedContexts = ExtractedContexts.generate(context); ContextSet contexts = extractedContexts.getContextSet(); @@ -65,7 +65,7 @@ public class MigrationUtils { try { Map, Map> opts = subject.getSubjectData().getAllOptions(); for (Map.Entry, Map> e : opts.entrySet()) { - ContextSet context = LuckPermsService.convertContexts(e.getKey()); + ContextSet context = Util.convertContexts(e.getKey()); ExtractedContexts extractedContexts = ExtractedContexts.generate(context); ContextSet contexts = extractedContexts.getContextSet(); @@ -96,7 +96,7 @@ public class MigrationUtils { // Migrate parents Map, List> parents = subject.getSubjectData().getAllParents(); for (Map.Entry, List> e : parents.entrySet()) { - ContextSet context = LuckPermsService.convertContexts(e.getKey()); + ContextSet context = Util.convertContexts(e.getKey()); ExtractedContexts extractedContexts = ExtractedContexts.generate(context); ContextSet contexts = extractedContexts.getContextSet(); 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 59e33be2b..57ba54cbd 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 @@ -23,28 +23,30 @@ package me.lucko.luckperms.sponge.model; import co.aikar.timings.Timing; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import lombok.Getter; import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.MetaUtils; import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.utils.ExtractedContexts; import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.service.LuckPermsService; -import me.lucko.luckperms.sponge.service.LuckPermsSubject; import me.lucko.luckperms.sponge.service.LuckPermsSubjectData; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.base.Util; +import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference; +import me.lucko.luckperms.sponge.service.references.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.Subject; -import org.spongepowered.api.service.permission.SubjectCollection; -import org.spongepowered.api.util.Tristate; +import org.spongepowered.api.service.permission.PermissionService; -import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; public class SpongeGroup extends Group { @@ -57,7 +59,7 @@ public class SpongeGroup extends Group { this.spongeData = new GroupSubject(plugin, this); } - public static class GroupSubject extends LuckPermsSubject { + public static class GroupSubject implements LPSubject { private final SpongeGroup parent; private final LPSpongePlugin plugin; @@ -79,59 +81,71 @@ public class SpongeGroup extends Group { return parent.getObjectName(); } + @Override + public Optional getFriendlyIdentifier() { + return Optional.of(parent.getFriendlyName()); + } + @Override public Optional getCommandSource() { return Optional.empty(); } @Override - public SubjectCollection getContainingCollection() { - return plugin.getService().getGroupSubjects(); + public SubjectCollectionReference getParentCollection() { + return plugin.getService().getGroupSubjects().toReference(); + } + + @Override + public LuckPermsService getService() { + return plugin.getService(); } @Override public Tristate getPermissionValue(ContextSet contexts, String permission) { try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_PERMISSION_VALUE)) { + // TODO move this away from NodeTree Map permissions = parent.getAllNodesFiltered(ExtractedContexts.generate(plugin.getService().calculateContexts(contexts))).stream() .map(LocalizedNode::getNode) .collect(Collectors.toMap(Node::getPermission, Node::getValue)); - Tristate t = NodeTree.of(permissions).get(permission); + Tristate t = Util.convertTristate(NodeTree.of(permissions).get(permission)); if (t != Tristate.UNDEFINED) { return t; } - t = plugin.getService().getGroupSubjects().getDefaults().getPermissionValue(LuckPermsService.convertContexts(contexts), permission); + t = plugin.getService().getGroupSubjects().getDefaultSubject().resolve(getService()).getPermissionValue(contexts, permission); if (t != Tristate.UNDEFINED) { return t; } - t = plugin.getService().getDefaults().getPermissionValue(LuckPermsService.convertContexts(contexts), permission); + t = plugin.getService().getDefaults().getPermissionValue(contexts, permission); return t; } } @Override - public boolean isChildOf(ContextSet contexts, Subject parent) { + public boolean isChildOf(ContextSet contexts, SubjectReference parent) { try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_IS_CHILD_OF)) { - return parent instanceof SpongeGroup && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean(); + return parent.getCollection().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean(); } } @Override - public List getParents(ContextSet contexts) { + public Set getParents(ContextSet contexts) { try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_PARENTS)) { - List subjects = parent.getAllNodesFiltered(ExtractedContexts.generate(plugin.getService().calculateContexts(contexts))).stream() + Set subjects = parent.getAllNodesFiltered(ExtractedContexts.generate(plugin.getService().calculateContexts(contexts))).stream() .map(LocalizedNode::getNode) .filter(Node::isGroupNode) .map(Node::getGroupName) .map(s -> plugin.getService().getGroupSubjects().get(s)) - .collect(Collectors.toList()); + .map(LPSubject::toReference) + .collect(Collectors.toSet()); - subjects.addAll(plugin.getService().getGroupSubjects().getDefaults().getParents(LuckPermsService.convertContexts(contexts))); - subjects.addAll(plugin.getService().getDefaults().getParents(LuckPermsService.convertContexts(contexts))); + subjects.addAll(plugin.getService().getGroupSubjects().getDefaultSubject().resolve(getService()).getParents(contexts)); + subjects.addAll(plugin.getService().getDefaults().getParents(contexts)); - return ImmutableList.copyOf(subjects); + return ImmutableSet.copyOf(subjects); } } @@ -153,12 +167,12 @@ public class SpongeGroup extends Group { return option; } - option = plugin.getService().getGroupSubjects().getDefaults().getOption(LuckPermsService.convertContexts(contexts), s); + option = plugin.getService().getGroupSubjects().getDefaultSubject().resolve(getService()).getOption(contexts, s); if (option.isPresent()) { return option; } - return plugin.getService().getDefaults().getOption(LuckPermsService.convertContexts(contexts), s); + return plugin.getService().getDefaults().getOption(contexts, s); } } 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 346b6de11..5dfbfbbb4 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 @@ -23,25 +23,26 @@ package me.lucko.luckperms.sponge.model; import co.aikar.timings.Timing; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import lombok.Getter; +import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.caching.MetaData; import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.service.LuckPermsService; -import me.lucko.luckperms.sponge.service.LuckPermsSubject; import me.lucko.luckperms.sponge.service.LuckPermsSubjectData; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference; +import me.lucko.luckperms.sponge.service.references.SubjectReference; import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.Sponge; import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.entity.living.player.Player; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.service.permission.SubjectCollection; -import org.spongepowered.api.util.Tristate; +import org.spongepowered.api.service.permission.PermissionService; -import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.UUID; public class SpongeUser extends User { @@ -59,7 +60,7 @@ public class SpongeUser extends User { this.spongeData = new UserSubject(plugin, this); } - public static class UserSubject extends LuckPermsSubject { + public static class UserSubject implements LPSubject { private final SpongeUser parent; private final LPSpongePlugin plugin; @@ -98,8 +99,13 @@ public class SpongeUser extends User { } @Override - public SubjectCollection getContainingCollection() { - return plugin.getService().getUserSubjects(); + public SubjectCollectionReference getParentCollection() { + return plugin.getService().getUserSubjects().toReference(); + } + + @Override + public LuckPermsService getService() { + return plugin.getService(); } @Override @@ -109,21 +115,21 @@ public class SpongeUser extends User { return Tristate.UNDEFINED; } - return LuckPermsService.convertTristate(parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getPermissionValue(permission)); + return parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getPermissionValue(permission); } } @Override - public boolean isChildOf(ContextSet contexts, Subject parent) { + public boolean isChildOf(ContextSet contexts, SubjectReference parent) { try (Timing ignored = plugin.getTimings().time(LPTiming.USER_IS_CHILD_OF)) { - return parent instanceof SpongeGroup && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean(); + return parent.getCollection().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean(); } } @Override - public List getParents(ContextSet contexts) { + public Set getParents(ContextSet contexts) { try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_PARENTS)) { - ImmutableList.Builder subjects = ImmutableList.builder(); + ImmutableSet.Builder subjects = ImmutableSet.builder(); if (hasData()) { for (String perm : parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getImmutableBacking().keySet()) { @@ -133,13 +139,13 @@ public class SpongeUser extends User { String groupName = perm.substring("group.".length()); if (plugin.getGroupManager().isLoaded(groupName)) { - subjects.add(plugin.getService().getGroupSubjects().get(groupName)); + subjects.add(plugin.getService().getGroupSubjects().get(groupName).toReference()); } } } - subjects.addAll(plugin.getService().getUserSubjects().getDefaults().getParents(LuckPermsService.convertContexts(contexts))); - subjects.addAll(plugin.getService().getDefaults().getParents(LuckPermsService.convertContexts(contexts))); + subjects.addAll(plugin.getService().getUserSubjects().getDefaultSubject().resolve(getService()).getParents(contexts)); + subjects.addAll(plugin.getService().getDefaults().getParents(contexts)); return subjects.build(); } @@ -167,12 +173,12 @@ public class SpongeUser extends User { } } - Optional v = plugin.getService().getUserSubjects().getDefaults().getOption(LuckPermsService.convertContexts(contexts), s); + Optional v = plugin.getService().getUserSubjects().getDefaultSubject().resolve(getService()).getOption(contexts, s); if (v.isPresent()) { return v; } - return plugin.getService().getDefaults().getOption(LuckPermsService.convertContexts(contexts), s); + return plugin.getService().getDefaults().getOption(contexts, s); } } @@ -184,5 +190,4 @@ public class SpongeUser extends User { } } - } 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 88f1254ad..b466cf1ba 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 @@ -28,31 +28,40 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; +import com.google.common.collect.MapMaker; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.*; import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.contexts.SpongeCalculatorLink; import me.lucko.luckperms.sponge.managers.SpongeGroupManager; import me.lucko.luckperms.sponge.managers.SpongeUserManager; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.base.LPSubjectCollection; +import me.lucko.luckperms.sponge.service.base.LPSubjectData; +import me.lucko.luckperms.sponge.service.calculated.OptionLookup; +import me.lucko.luckperms.sponge.service.calculated.PermissionLookup; import me.lucko.luckperms.sponge.service.persisted.PersistedCollection; import me.lucko.luckperms.sponge.service.persisted.SubjectStorage; +import me.lucko.luckperms.sponge.service.references.SubjectReference; import me.lucko.luckperms.sponge.service.simple.SimpleCollection; import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.plugin.PluginContainer; import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.context.ContextCalculator; -import org.spongepowered.api.service.permission.*; +import org.spongepowered.api.service.permission.PermissionDescription; +import org.spongepowered.api.service.permission.PermissionService; +import org.spongepowered.api.service.permission.Subject; +import org.spongepowered.api.service.permission.SubjectCollection; import org.spongepowered.api.text.Text; -import org.spongepowered.api.util.Tristate; import java.io.File; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; /** * The LuckPerms implementation of the Sponge Permission Service @@ -70,16 +79,20 @@ public class LuckPermsService implements PermissionService { private final PersistedCollection defaultSubjects; private final Set descriptionSet; + private final Set> localPermissionCaches; + private final Set, List>> localParentCaches; + private final Set>> localOptionCaches; + @Getter(value = AccessLevel.NONE) - private final LoadingCache collections = CacheBuilder.newBuilder() - .build(new CacheLoader() { + private final LoadingCache collections = CacheBuilder.newBuilder() + .build(new CacheLoader() { @Override - public SubjectCollection load(String s) { + public LPSubjectCollection load(String s) { return new SimpleCollection(LuckPermsService.this, s); } @Override - public ListenableFuture reload(String s, SubjectCollection collection) { + public ListenableFuture reload(String s, LPSubjectCollection collection) { return Futures.immediateFuture(collection); // Never needs to be refreshed. } }); @@ -87,6 +100,10 @@ public class LuckPermsService implements PermissionService { public LuckPermsService(LPSpongePlugin plugin) { this.plugin = plugin; + localPermissionCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + localParentCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + localOptionCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + storage = new SubjectStorage(new File(plugin.getDataFolder(), "local")); userSubjects = plugin.getUserManager(); @@ -105,25 +122,30 @@ public class LuckPermsService implements PermissionService { descriptionSet = ConcurrentHashMap.newKeySet(); } - public SubjectData getDefaultData() { + public LPSubjectData getDefaultData() { return getDefaults().getSubjectData(); } @Override - public Subject getDefaults() { + public LPSubject getDefaults() { return getDefaultSubjects().get("default"); } @Override - public SubjectCollection getSubjects(String s) { + public LPSubjectCollection getSubjects(String s) { try (Timing ignored = plugin.getTimings().time(LPTiming.GET_SUBJECTS)) { return collections.getUnchecked(s.toLowerCase()); } } + public Map getCollections() { + return ImmutableMap.copyOf(collections.asMap()); + } + + @Deprecated @Override public Map getKnownSubjects() { - return ImmutableMap.copyOf(collections.asMap()); + return getCollections().entrySet().stream().collect(ImmutableCollectors.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)); } @Override @@ -169,36 +191,6 @@ public class LuckPermsService implements PermissionService { ); } - public static ContextSet convertContexts(Set contexts) { - return ContextSet.fromEntries(contexts.stream().map(c -> Maps.immutableEntry(c.getKey(), c.getValue())).collect(Collectors.toSet())); - } - - public static Set convertContexts(ContextSet contexts) { - return contexts.toSet().stream().map(e -> new Context(e.getKey(), e.getValue())).collect(Collectors.toSet()); - } - - public static Tristate convertTristate(me.lucko.luckperms.api.Tristate tristate) { - switch (tristate) { - case TRUE: - return Tristate.TRUE; - case FALSE: - return Tristate.FALSE; - default: - return Tristate.UNDEFINED; - } - } - - public static me.lucko.luckperms.api.Tristate convertTristate(Tristate tristate) { - switch (tristate) { - case TRUE: - return me.lucko.luckperms.api.Tristate.TRUE; - case FALSE: - return me.lucko.luckperms.api.Tristate.FALSE; - default: - return me.lucko.luckperms.api.Tristate.UNDEFINED; - } - } - @RequiredArgsConstructor @EqualsAndHashCode @ToString @@ -241,10 +233,10 @@ public class LuckPermsService implements PermissionService { service.getDescriptionSet().add(d); // Set role-templates - SubjectCollection subjects = service.getSubjects(PermissionService.SUBJECTS_ROLE_TEMPLATE); + LPSubjectCollection subjects = service.getSubjects(PermissionService.SUBJECTS_ROLE_TEMPLATE); for (Map.Entry assignment : roles.entrySet()) { - Subject subject = subjects.get(assignment.getKey()); - subject.getTransientSubjectData().setPermission(SubjectData.GLOBAL_CONTEXT, id, assignment.getValue()); + LPSubject subject = subjects.get(assignment.getKey()); + subject.getTransientSubjectData().setPermission(ContextSet.empty(), id, assignment.getValue()); } service.getPlugin().getPermissionCache().offer(id); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubject.java deleted file mode 100644 index 388b5d423..000000000 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/LuckPermsSubject.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2016 Lucko (Luck) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.lucko.luckperms.sponge.service; - -import com.google.common.collect.ImmutableSet; -import lombok.NonNull; -import me.lucko.luckperms.api.context.ContextSet; -import org.spongepowered.api.service.context.Context; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.util.Tristate; - -import java.util.List; -import java.util.Optional; -import java.util.Set; - -public abstract class LuckPermsSubject implements Subject { - - public abstract Tristate getPermissionValue(ContextSet contexts, String permission); - public abstract boolean isChildOf(ContextSet contexts, Subject parent); - public abstract List getParents(ContextSet contexts); - public abstract Optional getOption(ContextSet contexts, String s); - public abstract ContextSet getActiveContextSet(); - - @Override - @Deprecated - public Tristate getPermissionValue(@NonNull Set contexts, @NonNull String permission) { - return getPermissionValue(LuckPermsService.convertContexts(contexts), permission); - } - - @Override - @Deprecated - public boolean hasPermission(@NonNull Set contexts, @NonNull String permission) { - return getPermissionValue(LuckPermsService.convertContexts(contexts), permission).asBoolean(); - } - - @Override - @Deprecated - public boolean hasPermission(@NonNull String permission) { - return getPermissionValue(getActiveContextSet(), permission).asBoolean(); - } - - @Override - @Deprecated - public boolean isChildOf(@NonNull Set contexts, @NonNull Subject parent) { - return isChildOf(LuckPermsService.convertContexts(contexts), parent); - } - - @Override - @Deprecated - public boolean isChildOf(@NonNull Subject parent) { - return isChildOf(getActiveContextSet(), parent); - } - - @Override - @Deprecated - public List getParents(@NonNull Set contexts) { - return getParents(LuckPermsService.convertContexts(contexts)); - } - - @Override - @Deprecated - public List getParents() { - return getParents(getActiveContextSet()); - } - - @Override - @Deprecated - public Optional getOption(@NonNull Set contexts, @NonNull String s) { - return getOption(LuckPermsService.convertContexts(contexts), s); - } - - @Override - @Deprecated - public Optional getOption(@NonNull String key) { - return getOption(getActiveContextSet(), key); - } - - @Override - @Deprecated - public Set getActiveContexts() { - return ImmutableSet.copyOf(LuckPermsService.convertContexts(getActiveContextSet())); - } - -} 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 6af7b1bbf..07ea0bcd2 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 @@ -23,14 +23,15 @@ package me.lucko.luckperms.sponge.service; import co.aikar.timings.Timing; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NonNull; import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.api.context.MutableContextSet; import me.lucko.luckperms.common.core.NodeBuilder; import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.model.Group; @@ -39,18 +40,19 @@ import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.sponge.model.SpongeGroup; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.base.LPSubjectData; +import me.lucko.luckperms.sponge.service.references.SubjectReference; import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.service.context.Context; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.service.permission.SubjectData; -import org.spongepowered.api.util.Tristate; +import org.spongepowered.api.service.permission.PermissionService; import java.util.*; import java.util.stream.Collectors; @SuppressWarnings({"OptionalGetWithoutIsPresent", "unused"}) @AllArgsConstructor -public class LuckPermsSubjectData implements SubjectData { +public class LuckPermsSubjectData implements LPSubjectData { private final boolean enduring; private final LuckPermsService service; @@ -69,12 +71,17 @@ public class LuckPermsSubjectData implements SubjectData { } @Override - public Map, Map> getAllPermissions() { + public LPSubject getParentSubject() { + return null; + } + + @Override + public Map> getPermissions() { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_PERMISSIONS)) { - Map, Map> perms = new HashMap<>(); + Map> perms = new HashMap<>(); for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) { - Set contexts = LuckPermsService.convertContexts(n.getContexts()); + MutableContextSet contexts = MutableContextSet.fromSet(n.getContexts()); if (n.isServerSpecific()) { contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get())); @@ -85,41 +92,32 @@ public class LuckPermsSubjectData implements SubjectData { } if (!perms.containsKey(contexts)) { - perms.put(contexts, new HashMap<>()); + perms.put(contexts.makeImmutable(), new HashMap<>()); } perms.get(contexts).put(n.getPermission(), n.getValue()); } - ImmutableMap.Builder, Map> map = ImmutableMap.builder(); - for (Map.Entry, Map> e : perms.entrySet()) { - map.put(ImmutableSet.copyOf(e.getKey()), ImmutableMap.copyOf(e.getValue())); + ImmutableMap.Builder> map = ImmutableMap.builder(); + for (Map.Entry> e : perms.entrySet()) { + map.put(e.getKey().makeImmutable(), ImmutableMap.copyOf(e.getValue())); } return map.build(); } } @Override - public Map getPermissions(@NonNull Set contexts) { - return getAllPermissions().getOrDefault(contexts, ImmutableMap.of()); - } - - @Override - public boolean setPermission(@NonNull Set contexts, @NonNull String permission, @NonNull Tristate tristate) { + public boolean setPermission(@NonNull ContextSet 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.Builder builder = new NodeBuilder(permission); - - for (Context ct : contexts) { - builder.withExtraContext(ct.getKey(), ct.getValue()); - } + Node node = new NodeBuilder(permission).withExtraContext(contexts).build(); try { if (enduring) { - holder.unsetPermission(builder.build()); + holder.unsetPermission(node); } else { - holder.unsetTransientPermission(builder.build()); + holder.unsetTransientPermission(node); } } catch (ObjectLacksException ignored) {} @@ -127,14 +125,7 @@ public class LuckPermsSubjectData implements SubjectData { return true; } - Node.Builder builder = new NodeBuilder(permission) - .setValue(tristate.asBoolean()); - - for (Context ct : contexts) { - builder.withExtraContext(ct.getKey(), ct.getValue()); - } - - Node node = builder.build(); + Node node = new NodeBuilder(permission).setValue(tristate.asBoolean()).withExtraContext(contexts).build(); // Workaround: unset the inverse, to allow false -> true, true -> false overrides. try { @@ -172,11 +163,11 @@ public class LuckPermsSubjectData implements SubjectData { } @Override - public boolean clearPermissions(@NonNull Set c) { + public boolean clearPermissions(@NonNull ContextSet c) { try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PERMISSIONS)) { List toRemove = new ArrayList<>(); for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) { - Set contexts = LuckPermsService.convertContexts(n.getContexts()); + MutableContextSet contexts = MutableContextSet.fromSet(n.getContexts()); if (n.isServerSpecific()) { contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get())); @@ -211,16 +202,16 @@ public class LuckPermsSubjectData implements SubjectData { } @Override - public Map, List> getAllParents() { + public Map> getParents() { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_PARENTS)) { - Map, List> parents = new HashMap<>(); + Map> parents = new HashMap<>(); for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) { if (!n.isGroupNode()) { continue; } - Set contexts = LuckPermsService.convertContexts(n.getContexts()); + MutableContextSet contexts = MutableContextSet.fromSet(n.getContexts()); if (n.isServerSpecific()) { contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get())); @@ -231,31 +222,25 @@ public class LuckPermsSubjectData implements SubjectData { } if (!parents.containsKey(contexts)) { - parents.put(contexts, new ArrayList<>()); + parents.put(contexts.makeImmutable(), new HashSet<>()); } - parents.get(contexts).add(service.getGroupSubjects().get(n.getGroupName())); + parents.get(contexts).add(service.getGroupSubjects().get(n.getGroupName()).toReference()); } - ImmutableMap.Builder, List> map = ImmutableMap.builder(); - for (Map.Entry, List> e : parents.entrySet()) { - map.put(ImmutableSet.copyOf(e.getKey()), ImmutableList.copyOf(e.getValue())); + ImmutableMap.Builder> map = ImmutableMap.builder(); + for (Map.Entry> e : parents.entrySet()) { + map.put(e.getKey().makeImmutable(), ImmutableSet.copyOf(e.getValue())); } return map.build(); } } @Override - public List getParents(@NonNull Set contexts) { - return getAllParents().getOrDefault(contexts, ImmutableList.of()); - } - - @Override - public boolean addParent(@NonNull Set set, @NonNull Subject subject) { + public boolean addParent(@NonNull ContextSet contexts, @NonNull SubjectReference subject) { try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_ADD_PARENT)) { - if (subject instanceof SpongeGroup) { - SpongeGroup permsSubject = ((SpongeGroup) subject); - ContextSet contexts = LuckPermsService.convertContexts(set); + if (subject.getCollection().equals(PermissionService.SUBJECTS_GROUP)) { + SpongeGroup permsSubject = ((SpongeGroup) subject.resolve(service)); try { if (enduring) { @@ -277,11 +262,10 @@ public class LuckPermsSubjectData implements SubjectData { } @Override - public boolean removeParent(@NonNull Set set, @NonNull Subject subject) { + public boolean removeParent(@NonNull ContextSet contexts, @NonNull SubjectReference subject) { try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_REMOVE_PARENT)) { - if (subject instanceof SpongeGroup) { - SpongeGroup permsSubject = ((SpongeGroup) subject); - ContextSet contexts = LuckPermsService.convertContexts(set); + if (subject.getCollection().equals(PermissionService.SUBJECTS_GROUP)) { + SpongeGroup permsSubject = ((SpongeGroup) subject.resolve(service)); try { if (enduring) { @@ -329,7 +313,7 @@ public class LuckPermsSubjectData implements SubjectData { } @Override - public boolean clearParents(@NonNull Set set) { + public boolean clearParents(@NonNull ContextSet set) { try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PARENTS)) { List toRemove = new ArrayList<>(); for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) { @@ -337,7 +321,7 @@ public class LuckPermsSubjectData implements SubjectData { continue; } - Set contexts = LuckPermsService.convertContexts(n.getContexts()); + MutableContextSet contexts = MutableContextSet.fromSet(n.getContexts()); if (n.isServerSpecific()) { contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get())); @@ -372,11 +356,11 @@ public class LuckPermsSubjectData implements SubjectData { } @Override - public Map, Map> getAllOptions() { + public Map> getOptions() { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_OPTIONS)) { - Map, Map> options = new HashMap<>(); - Map, Integer> minPrefixPriority = new HashMap<>(); - Map, Integer> minSuffixPriority = new HashMap<>(); + Map> options = new HashMap<>(); + Map minPrefixPriority = new HashMap<>(); + Map minSuffixPriority = new HashMap<>(); for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) { if (!n.getValue()) { @@ -387,7 +371,7 @@ public class LuckPermsSubjectData implements SubjectData { continue; } - Set contexts = LuckPermsService.convertContexts(n.getContexts()); + MutableContextSet contexts = MutableContextSet.fromSet(n.getContexts()); if (n.isServerSpecific()) { contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get())); @@ -427,24 +411,17 @@ public class LuckPermsSubjectData implements SubjectData { } } - ImmutableMap.Builder, Map> map = ImmutableMap.builder(); - for (Map.Entry, Map> e : options.entrySet()) { - map.put(ImmutableSet.copyOf(e.getKey()), ImmutableMap.copyOf(e.getValue())); + ImmutableMap.Builder> map = ImmutableMap.builder(); + for (Map.Entry> e : options.entrySet()) { + map.put(e.getKey().makeImmutable(), ImmutableMap.copyOf(e.getValue())); } return map.build(); } } @Override - public Map getOptions(@NonNull Set set) { - return getAllOptions().getOrDefault(set, ImmutableMap.of()); - } - - @Override - public boolean setOption(@NonNull Set set, @NonNull String key, @NonNull String value) { + public boolean setOption(@NonNull ContextSet context, @NonNull String key, @NonNull String value) { try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_OPTION)) { - ContextSet context = LuckPermsService.convertContexts(set); - List toRemove = holder.getNodes().stream() .filter(n -> n.isMeta() && n.getMeta().getKey().equals(key)) .collect(Collectors.toList()); @@ -468,7 +445,25 @@ public class LuckPermsSubjectData implements SubjectData { } @Override - public boolean clearOptions(@NonNull Set set) { + public boolean unsetOption(ContextSet contexts, String key) { + try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_OPTION)) { + List toRemove = holder.getNodes().stream() + .filter(n -> n.isMeta() && n.getMeta().getKey().equals(key)) + .collect(Collectors.toList()); + + toRemove.forEach(n -> { + try { + holder.unsetPermission(n); + } catch (ObjectLacksException ignored) {} + }); + + objectSave(holder); + return true; + } + } + + @Override + public boolean clearOptions(@NonNull ContextSet set) { try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_OPTIONS)) { List toRemove = new ArrayList<>(); for (Node n : enduring ? holder.getNodes() : holder.getTransientNodes()) { @@ -476,7 +471,7 @@ public class LuckPermsSubjectData implements SubjectData { continue; } - Set contexts = LuckPermsService.convertContexts(n.getContexts()); + MutableContextSet contexts = MutableContextSet.fromSet(n.getContexts()); if (n.isServerSpecific()) { contexts.add(new Context(LuckPermsService.SERVER_CONTEXT, n.getServer().get())); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/LPSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/LPSubject.java new file mode 100644 index 000000000..33f41d52e --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/LPSubject.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.sponge.service.base; + +import lombok.NonNull; +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.common.utils.ImmutableCollectors; +import me.lucko.luckperms.sponge.service.LuckPermsService; +import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference; +import me.lucko.luckperms.sponge.service.references.SubjectReference; +import org.spongepowered.api.command.CommandSource; +import org.spongepowered.api.service.context.Context; +import org.spongepowered.api.service.permission.Subject; +import org.spongepowered.api.util.Tristate; + +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import static me.lucko.luckperms.sponge.service.base.Util.convertContexts; +import static me.lucko.luckperms.sponge.service.base.Util.convertTristate; + +public interface LPSubject extends Subject { + + @Override + String getIdentifier(); + + default Optional getFriendlyIdentifier() { + return Optional.empty(); + } + + @Override + default Optional getCommandSource() { + return Optional.empty(); + } + + SubjectCollectionReference getParentCollection(); + + LuckPermsService getService(); + + default SubjectReference toReference() { + return SubjectReference.of(getParentCollection().getCollection(), getIdentifier()); + } + + @Override + LPSubjectData getSubjectData(); + + @Override + LPSubjectData getTransientSubjectData(); + + me.lucko.luckperms.api.Tristate getPermissionValue(ContextSet contexts, String permission); + + boolean isChildOf(ContextSet contexts, SubjectReference parent); + + Set getParents(ContextSet contexts); + + Optional getOption(ContextSet contexts, String key); + + ContextSet getActiveContextSet(); + + + /* Compat */ + + @Deprecated + @Override + default LPSubjectCollection getContainingCollection() { + return getParentCollection().resolve(getService()); + } + + @Deprecated + @Override + default boolean hasPermission(@NonNull Set contexts, @NonNull String permission) { + return getPermissionValue(convertContexts(contexts), permission).asBoolean(); + } + + @Deprecated + @Override + default boolean hasPermission(@NonNull String permission) { + return getPermissionValue(getActiveContextSet(), permission).asBoolean(); + } + + @Deprecated + @Override + default Tristate getPermissionValue(@NonNull Set contexts, @NonNull String permission) { + return convertTristate(getPermissionValue(convertContexts(contexts), permission)); + } + + @Deprecated + @Override + default boolean isChildOf(@NonNull Subject parent) { + return isChildOf(getActiveContextSet(), SubjectReference.of(parent)); + } + + @Deprecated + @Override + default boolean isChildOf(@NonNull Set contexts, @NonNull Subject parent) { + return isChildOf(convertContexts(contexts), SubjectReference.of(parent)); + } + + @Deprecated + @Override + default List getParents() { + return getParents(getActiveContextSet()).stream().map(s -> s.resolve(getService())).collect(ImmutableCollectors.toImmutableList()); + } + + @Deprecated + @Override + default List getParents(@NonNull Set contexts) { + return getParents(convertContexts(contexts)).stream().map(s -> s.resolve(getService())).collect(ImmutableCollectors.toImmutableList()); + } + + @Deprecated + @Override + default Optional getOption(@NonNull String key) { + return getOption(getActiveContextSet(), key); + } + + @Deprecated + @Override + default Optional getOption(@NonNull Set contexts, @NonNull String key) { + return getOption(getActiveContextSet(), key); + } + + @Deprecated + @Override + default Set getActiveContexts() { + return convertContexts(getActiveContextSet()); + } +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/LPSubjectCollection.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/LPSubjectCollection.java new file mode 100644 index 000000000..9bc9340de --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/LPSubjectCollection.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.sponge.service.base; + +import lombok.NonNull; +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.common.utils.ImmutableCollectors; +import me.lucko.luckperms.sponge.service.LuckPermsService; +import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference; +import me.lucko.luckperms.sponge.service.references.SubjectReference; +import org.spongepowered.api.service.context.Context; +import org.spongepowered.api.service.permission.Subject; +import org.spongepowered.api.service.permission.SubjectCollection; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import static me.lucko.luckperms.sponge.service.base.Util.convertContexts; + +public interface LPSubjectCollection extends SubjectCollection { + + @Override + String getIdentifier(); + + LuckPermsService getService(); + + default SubjectCollectionReference toReference() { + return SubjectCollectionReference.of(getIdentifier()); + } + + @Override + LPSubject get(String identifier); + + @Override + boolean hasRegistered(String identifier); + + Collection getSubjects(); + + default Map getWithPermission(String permission) { + return getWithPermission(ContextSet.empty(), permission); + } + + Map getWithPermission(ContextSet contexts, String permission); + + SubjectReference getDefaultSubject(); + + @Deprecated + @Override + default Subject getDefaults() { + return getDefaultSubject().resolve(getService()); + } + + @Deprecated + @Override + default Iterable getAllSubjects() { + return getSubjects().stream().collect(ImmutableCollectors.toImmutableList()); + } + + @Deprecated + @Override + default Map getAllWithPermission(@NonNull String permission) { + return getWithPermission(permission).entrySet().stream().collect(ImmutableCollectors.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + @Deprecated + @Override + default Map getAllWithPermission(@NonNull Set contexts, @NonNull String permission) { + return getWithPermission(convertContexts(contexts), permission).entrySet().stream().collect(ImmutableCollectors.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)); + } + +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/LPSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/LPSubjectData.java new file mode 100644 index 000000000..fde2c36fd --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/LPSubjectData.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.sponge.service.base; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.common.utils.ImmutableCollectors; +import me.lucko.luckperms.sponge.service.references.SubjectReference; +import org.spongepowered.api.service.context.Context; +import org.spongepowered.api.service.permission.Subject; +import org.spongepowered.api.service.permission.SubjectData; +import org.spongepowered.api.util.Tristate; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static me.lucko.luckperms.sponge.service.base.Util.convertContexts; +import static me.lucko.luckperms.sponge.service.base.Util.convertTristate; + +public interface LPSubjectData extends SubjectData { + + LPSubject getParentSubject(); + + Map> getPermissions(); + + default Map getPermissions(ContextSet contexts) { + return ImmutableMap.copyOf(getPermissions().getOrDefault(contexts, ImmutableMap.of())); + } + + boolean setPermission(ContextSet contexts, String permission, me.lucko.luckperms.api.Tristate value); + + @Override + boolean clearPermissions(); + + boolean clearPermissions(ContextSet contexts); + + Map> getParents(); + + default Set getParents(ContextSet contexts) { + return ImmutableSet.copyOf(getParents().getOrDefault(contexts, ImmutableSet.of())); + } + + boolean addParent(ContextSet contexts, SubjectReference parent); + + boolean removeParent(ContextSet contexts, SubjectReference parent); + + @Override + boolean clearParents(); + + boolean clearParents(ContextSet contexts); + + Map> getOptions(); + + default Map getOptions(ContextSet contexts) { + return ImmutableMap.copyOf(getOptions().getOrDefault(contexts, ImmutableMap.of())); + } + + boolean setOption(ContextSet contexts, String key, String value); + + boolean unsetOption(ContextSet contexts, String key); + + boolean clearOptions(ContextSet contexts); + + @Override + boolean clearOptions(); + + + + /* Compat */ + + @Deprecated + @Override + default Map, Map> getAllPermissions() { + return getPermissions().entrySet().stream() + .collect(ImmutableCollectors.toImmutableMap( + e -> convertContexts(e.getKey()), + e -> ImmutableMap.copyOf(e.getValue())) + ); + } + + @Deprecated + @Override + default Map getPermissions(Set contexts) { + return ImmutableMap.copyOf(getPermissions(convertContexts(contexts))); + } + + @Deprecated + @Override + default boolean setPermission(Set contexts, String permission, Tristate value) { + return setPermission(convertContexts(contexts), permission, convertTristate(value)); + } + + @Deprecated + @Override + default boolean clearPermissions(Set contexts) { + return clearPermissions(convertContexts(contexts)); + } + + @Deprecated + @Override + default Map, List> getAllParents() { + return getParents().entrySet().stream() + .collect(ImmutableCollectors.toImmutableMap( + e -> convertContexts(e.getKey()), + e -> e.getValue().stream() + .map(s -> s.resolve(getParentSubject().getService())) + .collect(ImmutableCollectors.toImmutableList()) + ) + ); + } + + @Deprecated + @Override + default List getParents(Set contexts) { + return getParents(convertContexts(contexts)).stream().map(s -> s.resolve(getParentSubject().getService())).collect(ImmutableCollectors.toImmutableList()); + } + + @Deprecated + @Override + default boolean addParent(Set contexts, Subject parent) { + return addParent(convertContexts(contexts), SubjectReference.of(parent)); + } + + @Deprecated + @Override + default boolean removeParent(Set contexts, Subject parent) { + return removeParent(convertContexts(contexts), SubjectReference.of(parent)); + } + + @Deprecated + @Override + default boolean clearParents(Set contexts) { + return clearParents(convertContexts(contexts)); + } + + @Deprecated + @Override + default Map, Map> getAllOptions() { + return getOptions().entrySet().stream() + .collect(ImmutableCollectors.toImmutableMap( + e -> convertContexts(e.getKey()), + e -> ImmutableMap.copyOf(e.getValue())) + ); + } + + @Deprecated + @Override + default Map getOptions(Set contexts) { + return ImmutableMap.copyOf(getOptions(convertContexts(contexts))); + } + + @Deprecated + @Override + default boolean setOption(Set contexts, String key, @Nullable String value) { + return value == null ? unsetOption(convertContexts(contexts), key) : setOption(convertContexts(contexts), key, value); + } + + @Deprecated + @Override + default boolean clearOptions(Set contexts) { + return clearOptions(convertContexts(contexts)); + } + +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/Util.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/Util.java new file mode 100644 index 000000000..869069d97 --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/base/Util.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.sponge.service.base; + +import com.google.common.collect.Maps; +import lombok.experimental.UtilityClass; +import me.lucko.luckperms.api.context.ContextSet; +import me.lucko.luckperms.common.utils.ImmutableCollectors; +import org.spongepowered.api.service.context.Context; +import org.spongepowered.api.util.Tristate; + +import java.util.Set; +import java.util.stream.Collectors; + +@UtilityClass +public class Util { + + public static ContextSet convertContexts(Set contexts) { + return ContextSet.fromEntries(contexts.stream().map(c -> Maps.immutableEntry(c.getKey(), c.getValue())).collect(Collectors.toSet())); + } + + public static Set convertContexts(ContextSet contexts) { + return contexts.toSet().stream().map(e -> new Context(e.getKey(), e.getValue())).collect(ImmutableCollectors.toImmutableSet()); + } + + public static Tristate convertTristate(me.lucko.luckperms.api.Tristate tristate) { + switch (tristate) { + case TRUE: + return Tristate.TRUE; + case FALSE: + return Tristate.FALSE; + default: + return Tristate.UNDEFINED; + } + } + + public static me.lucko.luckperms.api.Tristate convertTristate(Tristate tristate) { + switch (tristate) { + case TRUE: + return me.lucko.luckperms.api.Tristate.TRUE; + case FALSE: + return me.lucko.luckperms.api.Tristate.FALSE; + default: + return me.lucko.luckperms.api.Tristate.UNDEFINED; + } + } + +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/data/CalculatedSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java similarity index 55% rename from sponge/src/main/java/me/lucko/luckperms/sponge/service/data/CalculatedSubjectData.java rename to sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java index ca54a40b5..a8d16a08f 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/data/CalculatedSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/CalculatedSubjectData.java @@ -20,7 +20,7 @@ * SOFTWARE. */ -package me.lucko.luckperms.sponge.service.data; +package me.lucko.luckperms.sponge.service.calculated; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; @@ -31,32 +31,34 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; import lombok.Getter; import lombok.RequiredArgsConstructor; +import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.calculators.PermissionCalculator; import me.lucko.luckperms.common.calculators.PermissionProcessor; import me.lucko.luckperms.common.calculators.processors.MapProcessor; -import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.sponge.calculators.SpongeWildcardProcessor; import me.lucko.luckperms.sponge.service.LuckPermsService; -import org.spongepowered.api.service.context.Context; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.service.permission.SubjectData; -import org.spongepowered.api.util.Tristate; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.base.LPSubjectData; +import me.lucko.luckperms.sponge.service.references.SubjectReference; -import javax.annotation.Nullable; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @RequiredArgsConstructor -public class CalculatedSubjectData implements SubjectData { +public class CalculatedSubjectData implements LPSubjectData { private static final ContextComparator CONTEXT_COMPARATOR = new ContextComparator(); + @Getter + private final LPSubject parentSubject; + private final LuckPermsService service; private final String calculatorDisplayName; - private final LoadingCache, CalculatorHolder> permissionCache = CacheBuilder.newBuilder() - .build(new CacheLoader, CalculatorHolder>() { + private final LoadingCache permissionCache = CacheBuilder.newBuilder() + .build(new CacheLoader() { @Override - public CalculatorHolder load(Set contexts) { + public CalculatorHolder load(ContextSet contexts) { ImmutableList.Builder processors = ImmutableList.builder(); processors.add(new MapProcessor()); processors.add(new SpongeWildcardProcessor()); @@ -68,77 +70,69 @@ public class CalculatedSubjectData implements SubjectData { } }); - private final LoadingCache, Map> optionCache = CacheBuilder.newBuilder() - .build(new CacheLoader, Map>() { + private final LoadingCache> optionCache = CacheBuilder.newBuilder() + .build(new CacheLoader>() { @Override - public Map load(Set contexts) { + public Map load(ContextSet contexts) { return flattenMap(contexts, options); } }); - private final Map, Map> permissions = new ConcurrentHashMap<>(); - private final Map, Set> parents = new ConcurrentHashMap<>(); - private final Map, Map> options = new ConcurrentHashMap<>(); + private final Map> permissions = new ConcurrentHashMap<>(); + private final Map> parents = new ConcurrentHashMap<>(); + private final Map> options = new ConcurrentHashMap<>(); - public Tristate getPermissionValue(Set contexts, String permission) { - return LuckPermsService.convertTristate(permissionCache.getUnchecked(contexts).getCalculator().getPermissionValue(permission)); + public Tristate getPermissionValue(ContextSet contexts, String permission) { + return permissionCache.getUnchecked(contexts).getCalculator().getPermissionValue(permission); } - public Map, Set> getParents() { - ImmutableMap.Builder, Set> map = ImmutableMap.builder(); - for (Map.Entry, Set> e : parents.entrySet()) { - map.put(ImmutableSet.copyOf(e.getKey()), ImmutableSet.copyOf(e.getValue())); - } - return map.build(); - } - - public void replacePermissions(Map, Map> map) { + public void replacePermissions(Map> map) { permissions.clear(); - for (Map.Entry, Map> e : map.entrySet()) { - permissions.put(ImmutableSet.copyOf(e.getKey()), new ConcurrentHashMap<>(e.getValue())); + for (Map.Entry> e : map.entrySet()) { + permissions.put(e.getKey().makeImmutable(), new ConcurrentHashMap<>(e.getValue())); } permissionCache.invalidateAll(); } - public void replaceParents(Map, Set> map) { + public void replaceParents(Map> map) { parents.clear(); - for (Map.Entry, Set> e : map.entrySet()) { + for (Map.Entry> e : map.entrySet()) { Set set = ConcurrentHashMap.newKeySet(); set.addAll(e.getValue()); - parents.put(ImmutableSet.copyOf(e.getKey()), set); + parents.put(e.getKey().makeImmutable(), set); } } - public void replaceOptions(Map, Map> map) { + public void replaceOptions(Map> map) { options.clear(); - for (Map.Entry, Map> e : map.entrySet()) { - options.put(ImmutableSet.copyOf(e.getKey()), new ConcurrentHashMap<>(e.getValue())); + for (Map.Entry> e : map.entrySet()) { + options.put(e.getKey().makeImmutable(), new ConcurrentHashMap<>(e.getValue())); } optionCache.invalidateAll(); } @Override - public Map, Map> getAllPermissions() { - ImmutableMap.Builder, Map> map = ImmutableMap.builder(); - for (Map.Entry, Map> e : permissions.entrySet()) { - map.put(ImmutableSet.copyOf(e.getKey()), ImmutableMap.copyOf(e.getValue())); + public Map> getPermissions() { + ImmutableMap.Builder> map = ImmutableMap.builder(); + for (Map.Entry> e : permissions.entrySet()) { + map.put(e.getKey().makeImmutable(), ImmutableMap.copyOf(e.getValue())); } return map.build(); } @Override - public Map getPermissions(Set contexts) { + public Map getPermissions(ContextSet contexts) { return ImmutableMap.copyOf(permissions.getOrDefault(contexts, ImmutableMap.of())); } @Override - public boolean setPermission(Set contexts, String permission, Tristate value) { + public boolean setPermission(ContextSet contexts, String permission, Tristate value) { boolean b; if (value == Tristate.UNDEFINED) { Map perms = permissions.get(contexts); b = perms != null && perms.remove(permission.toLowerCase()) != null; } else { - Map perms = permissions.computeIfAbsent(ImmutableSet.copyOf(contexts), c -> new ConcurrentHashMap<>()); + Map perms = permissions.computeIfAbsent(contexts.makeImmutable(), c -> new ConcurrentHashMap<>()); b = !Objects.equals(perms.put(permission.toLowerCase(), value.asBoolean()), value.asBoolean()); } if (b) { @@ -159,7 +153,7 @@ public class CalculatedSubjectData implements SubjectData { } @Override - public boolean clearPermissions(Set contexts) { + public boolean clearPermissions(ContextSet contexts) { Map perms = permissions.get(contexts); if (perms == null) { return false; @@ -174,34 +168,29 @@ public class CalculatedSubjectData implements SubjectData { } @Override - public Map, List> getAllParents() { - ImmutableMap.Builder, List> map = ImmutableMap.builder(); - for (Map.Entry, Set> e : parents.entrySet()) { - map.put( - ImmutableSet.copyOf(e.getKey()), - e.getValue().stream().map(s -> s.resolve(service)).collect(ImmutableCollectors.toImmutableList()) - ); + public Map> getParents() { + ImmutableMap.Builder> map = ImmutableMap.builder(); + for (Map.Entry> e : parents.entrySet()) { + map.put(e.getKey().makeImmutable(), ImmutableSet.copyOf(e.getValue())); } return map.build(); } @Override - public List getParents(Set contexts) { - return parents.getOrDefault(contexts, ImmutableSet.of()).stream() - .map(s -> s.resolve(service)) - .collect(ImmutableCollectors.toImmutableList()); + public Set getParents(ContextSet contexts) { + return ImmutableSet.copyOf(parents.getOrDefault(contexts, ImmutableSet.of())); } @Override - public boolean addParent(Set contexts, Subject parent) { - Set set = parents.computeIfAbsent(ImmutableSet.copyOf(contexts), c -> ConcurrentHashMap.newKeySet()); - return set.add(SubjectReference.of(parent)); + public boolean addParent(ContextSet contexts, SubjectReference parent) { + Set set = parents.computeIfAbsent(contexts.makeImmutable(), c -> ConcurrentHashMap.newKeySet()); + return set.add(parent); } @Override - public boolean removeParent(Set contexts, Subject parent) { + public boolean removeParent(ContextSet contexts, SubjectReference parent) { Set set = parents.get(contexts); - return set != null && set.remove(SubjectReference.of(parent)); + return set != null && set.remove(parent); } @Override @@ -215,7 +204,7 @@ public class CalculatedSubjectData implements SubjectData { } @Override - public boolean clearParents(Set contexts) { + public boolean clearParents(ContextSet contexts) { Set set = parents.get(contexts); if (set == null) { return false; @@ -226,29 +215,33 @@ public class CalculatedSubjectData implements SubjectData { } @Override - public Map, Map> getAllOptions() { - ImmutableMap.Builder, Map> map = ImmutableMap.builder(); - for (Map.Entry, Map> e : options.entrySet()) { - map.put(ImmutableSet.copyOf(e.getKey()), ImmutableMap.copyOf(e.getValue())); + public Map> getOptions() { + ImmutableMap.Builder> map = ImmutableMap.builder(); + for (Map.Entry> e : options.entrySet()) { + map.put(e.getKey().makeImmutable(), ImmutableMap.copyOf(e.getValue())); } return map.build(); } @Override - public Map getOptions(Set contexts) { + public Map getOptions(ContextSet contexts) { return ImmutableMap.copyOf(options.getOrDefault(contexts, ImmutableMap.of())); } @Override - public boolean setOption(Set contexts, String key, @Nullable String value) { - boolean b; - if (value == null) { - Map options = this.options.get(contexts); - b = options != null && options.remove(key.toLowerCase()) != null; - } else { - Map options = this.options.computeIfAbsent(ImmutableSet.copyOf(contexts), c -> new ConcurrentHashMap<>()); - b = !stringEquals(options.put(key.toLowerCase(), value), value); + public boolean setOption(ContextSet contexts, String key, String value) { + Map options = this.options.computeIfAbsent(contexts.makeImmutable(), c -> new ConcurrentHashMap<>()); + boolean b = !stringEquals(options.put(key.toLowerCase(), value), value); + if (b) { + optionCache.invalidateAll(); } + return b; + } + + @Override + public boolean unsetOption(ContextSet contexts, String key) { + Map options = this.options.get(contexts); + boolean b = options != null && options.remove(key.toLowerCase()) != null; if (b) { optionCache.invalidateAll(); } @@ -267,7 +260,7 @@ public class CalculatedSubjectData implements SubjectData { } @Override - public boolean clearOptions(Set contexts) { + public boolean clearOptions(ContextSet contexts) { Map map = options.get(contexts); if (map == null) { return false; @@ -281,10 +274,10 @@ public class CalculatedSubjectData implements SubjectData { return false; } - private static Map flattenMap(Set contexts, Map, Map> source) { + private static Map flattenMap(ContextSet contexts, Map> source) { Map map = new HashMap<>(); - SortedMap, Map> ret = getRelevantEntries(contexts, source); + SortedMap> ret = getRelevantEntries(contexts, source); for (Map m : ret.values()) { for (Map.Entry e : m.entrySet()) { if (!map.containsKey(e.getKey())) { @@ -296,18 +289,19 @@ public class CalculatedSubjectData implements SubjectData { return ImmutableMap.copyOf(map); } - private static SortedMap, Map> getRelevantEntries(Set set, Map, Map> map) { - ImmutableSortedMap.Builder, Map> perms = ImmutableSortedMap.orderedBy(CONTEXT_COMPARATOR); + private static SortedMap> getRelevantEntries(ContextSet set, Map> map) { + ImmutableSortedMap.Builder> perms = ImmutableSortedMap.orderedBy(CONTEXT_COMPARATOR); loop: - for (Map.Entry, Map> e : map.entrySet()) { - for (Context c : e.getKey()) { - if (!set.contains(c)) { + for (Map.Entry> e : map.entrySet()) { + + for (Map.Entry c : e.getKey().toSet()) { + if (!set.has(c.getKey(), c.getValue())) { continue loop; } } - perms.put(ImmutableSet.copyOf(e.getKey()), ImmutableMap.copyOf(e.getValue())); + perms.put(e.getKey().makeImmutable(), ImmutableMap.copyOf(e.getValue())); } return perms.build(); @@ -317,10 +311,10 @@ public class CalculatedSubjectData implements SubjectData { return a == null && b == null || a != null && b != null && a.equalsIgnoreCase(b); } - private static class ContextComparator implements Comparator> { + private static class ContextComparator implements Comparator { @Override - public int compare(Set o1, Set o2) { + public int compare(ContextSet o1, ContextSet o2) { int i = Integer.compare(o1.size(), o2.size()); return i == 0 ? 1 : i; } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/OptionLookup.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/OptionLookup.java new file mode 100644 index 000000000..d39646fc1 --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/OptionLookup.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.sponge.service.calculated; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import me.lucko.luckperms.api.context.ContextSet; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor(staticName = "of") +public class OptionLookup { + + private final String key; + private final ContextSet contexts; + +} \ No newline at end of file diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/PermissionLookup.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/PermissionLookup.java new file mode 100644 index 000000000..43b4f2b1d --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/calculated/PermissionLookup.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.sponge.service.calculated; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import me.lucko.luckperms.api.context.ContextSet; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor(staticName = "of") +public class PermissionLookup { + + private final String node; + private final ContextSet contexts; + +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java index f5dee5142..390ed8840 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedCollection.java @@ -26,30 +26,31 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; +import lombok.AccessLevel; import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.sponge.service.LuckPermsService; -import org.spongepowered.api.service.context.Context; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.service.permission.SubjectCollection; -import org.spongepowered.api.util.Tristate; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.base.LPSubjectCollection; +import me.lucko.luckperms.sponge.service.references.SubjectReference; +import java.util.Collection; import java.util.Map; -import java.util.Set; /** * A simple persistable subject collection */ +@Getter @RequiredArgsConstructor -public class PersistedCollection implements SubjectCollection { +public class PersistedCollection implements LPSubjectCollection { private final LuckPermsService service; - - @Getter private final String identifier; + @Getter(AccessLevel.NONE) private final LoadingCache subjects = CacheBuilder.newBuilder() .build(new CacheLoader() { @Override @@ -77,19 +78,14 @@ public class PersistedCollection implements SubjectCollection { } @Override - public Iterable getAllSubjects() { - return subjects.asMap().values().stream().map(s -> (Subject) s).collect(ImmutableCollectors.toImmutableList()); + public Collection getSubjects() { + return subjects.asMap().values().stream().map(s -> (LPSubject) s).collect(ImmutableCollectors.toImmutableList()); } @Override - public Map getAllWithPermission(@NonNull String id) { - return getAllWithPermission(ImmutableSet.of(), id); - } - - @Override - public Map getAllWithPermission(@NonNull Set contexts, @NonNull String node) { - ImmutableMap.Builder m = ImmutableMap.builder(); - for (Subject subject : subjects.asMap().values()) { + public Map getWithPermission(@NonNull ContextSet contexts, @NonNull String node) { + ImmutableMap.Builder m = ImmutableMap.builder(); + for (LPSubject subject : subjects.asMap().values()) { Tristate ts = subject.getPermissionValue(contexts, node); if (ts != Tristate.UNDEFINED) { m.put(subject, ts.asBoolean()); @@ -100,7 +96,7 @@ public class PersistedCollection implements SubjectCollection { } @Override - public Subject getDefaults() { - return service.getDefaultSubjects().get(identifier); + public SubjectReference getDefaultSubject() { + return SubjectReference.of("defaults", identifier); } } 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 64a64e67b..9ec1165db 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 @@ -23,22 +23,22 @@ package me.lucko.luckperms.sponge.service.persisted; import co.aikar.timings.Timing; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import lombok.Getter; import lombok.NonNull; +import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.utils.BufferedRequest; import me.lucko.luckperms.sponge.service.LuckPermsService; -import me.lucko.luckperms.sponge.service.data.CalculatedSubjectData; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData; +import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference; +import me.lucko.luckperms.sponge.service.references.SubjectReference; import me.lucko.luckperms.sponge.timings.LPTiming; import org.spongepowered.api.command.CommandSource; -import org.spongepowered.api.service.context.Context; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.util.Tristate; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import java.util.HashSet; import java.util.Optional; import java.util.Set; @@ -46,11 +46,12 @@ import java.util.Set; * A simple persistable Subject implementation */ @Getter -public class PersistedSubject implements Subject { +public class PersistedSubject implements LPSubject { private final String identifier; + @Getter private final LuckPermsService service; - private final PersistedCollection containingCollection; + private final SubjectCollectionReference parentCollection; private final PersistedSubjectData subjectData; private final CalculatedSubjectData transientSubjectData; private final BufferedRequest saveBuffer = new BufferedRequest(1000L, r -> PersistedSubject.this.service.getPlugin().doAsync(r)) { @@ -70,9 +71,9 @@ public class PersistedSubject implements Subject { public PersistedSubject(String identifier, LuckPermsService service, PersistedCollection containingCollection) { this.identifier = identifier; this.service = service; - this.containingCollection = containingCollection; + this.parentCollection = containingCollection.toReference(); this.subjectData = new PersistedSubjectData(service, "local:" + containingCollection.getIdentifier() + "/" + identifier + "(p)", this); - this.transientSubjectData = new CalculatedSubjectData(service, "local:" + containingCollection.getIdentifier() + "/" + identifier + "(t)"); + this.transientSubjectData = new CalculatedSubjectData(this, service, "local:" + containingCollection.getIdentifier() + "/" + identifier + "(t)"); } public void loadData(SubjectDataHolder dataHolder) { @@ -91,12 +92,7 @@ public class PersistedSubject implements Subject { } @Override - public boolean hasPermission(@NonNull Set contexts, @NonNull String node) { - return getPermissionValue(contexts, node).asBoolean(); - } - - @Override - public Tristate getPermissionValue(@NonNull Set contexts, @NonNull String node) { + public Tristate getPermissionValue(@NonNull ContextSet contexts, @NonNull String node) { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.PERSISTED_SUBJECT_GET_PERMISSION_VALUE)) { Tristate res = subjectData.getPermissionValue(contexts, node); if (res != Tristate.UNDEFINED) { @@ -108,18 +104,18 @@ public class PersistedSubject implements Subject { return res; } - for (Subject parent : getParents(contexts)) { - Tristate tempRes = parent.getPermissionValue(contexts, node); + for (SubjectReference parent : getParents(contexts)) { + Tristate tempRes = parent.resolve(service).getPermissionValue(contexts, node); if (tempRes != Tristate.UNDEFINED) { return tempRes; } } - if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) { + if (getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")) { return Tristate.UNDEFINED; } - res = service.getGroupSubjects().getDefaults().getPermissionValue(contexts, node); + res = service.getGroupSubjects().getDefaultSubject().resolve(service).getPermissionValue(contexts, node); if (res != Tristate.UNDEFINED) { return res; } @@ -130,61 +126,61 @@ public class PersistedSubject implements Subject { } @Override - public boolean isChildOf(@NonNull Set contexts, @NonNull Subject subject) { + public boolean isChildOf(@NonNull ContextSet contexts, @NonNull SubjectReference subject) { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.PERSISTED_SUBJECT_IS_CHILD_OF)) { - if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) { + if (getParentCollection().resolve(service).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) || - getContainingCollection().getDefaults().getParents(contexts).contains(subject) || + getParentCollection().resolve(service).getDefaultSubject().resolve(service).getParents(contexts).contains(subject) || service.getDefaults().getParents(contexts).contains(subject); } } } @Override - public List getParents(@NonNull Set contexts) { + public Set getParents(@NonNull ContextSet contexts) { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.PERSISTED_SUBJECT_GET_PARENTS)) { - List s = new ArrayList<>(); + Set s = new HashSet<>(); s.addAll(subjectData.getParents(contexts)); s.addAll(transientSubjectData.getParents(contexts)); - if (!getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) { - s.addAll(getContainingCollection().getDefaults().getParents(contexts)); + if (!getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")) { + s.addAll(getParentCollection().resolve(service).getDefaultSubject().resolve(service).getParents(contexts)); s.addAll(service.getDefaults().getParents(contexts)); } - return ImmutableList.copyOf(s); + return ImmutableSet.copyOf(s); } } @Override - public Optional getOption(Set set, String key) { + public Optional getOption(ContextSet set, String key) { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.PERSISTED_SUBJECT_GET_OPTION)) { - Optional res = Optional.ofNullable(subjectData.getOptions(getActiveContexts()).get(key)); + Optional res = Optional.ofNullable(subjectData.getOptions(getActiveContextSet()).get(key)); if (res.isPresent()) { return res; } - res = Optional.ofNullable(transientSubjectData.getOptions(getActiveContexts()).get(key)); + res = Optional.ofNullable(transientSubjectData.getOptions(getActiveContextSet()).get(key)); if (res.isPresent()) { return res; } - for (Subject parent : getParents(getActiveContexts())) { - Optional tempRes = parent.getOption(getActiveContexts(), key); + for (SubjectReference parent : getParents(getActiveContextSet())) { + Optional tempRes = parent.resolve(service).getOption(getActiveContextSet(), key); if (tempRes.isPresent()) { return tempRes; } } - if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) { + if (getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")) { return Optional.empty(); } - res = getContainingCollection().getDefaults().getOption(set, key); + res = getParentCollection().resolve(service).getDefaultSubject().resolve(service).getOption(set, key); if (res.isPresent()) { return res; } @@ -194,9 +190,9 @@ public class PersistedSubject implements Subject { } @Override - public Set getActiveContexts() { + public ContextSet getActiveContextSet() { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.PERSISTED_SUBJECT_GET_ACTIVE_CONTEXTS)) { - return ImmutableSet.copyOf(LuckPermsService.convertContexts(service.getPlugin().getContextManager().getApplicableContext(this))); + return service.getPlugin().getContextManager().getApplicableContext(this); } } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubjectData.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubjectData.java index fb7bda009..34392b2a2 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubjectData.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/PersistedSubjectData.java @@ -24,14 +24,10 @@ package me.lucko.luckperms.sponge.service.persisted; import lombok.Getter; import lombok.Setter; +import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.sponge.service.LuckPermsService; -import me.lucko.luckperms.sponge.service.data.CalculatedSubjectData; -import org.spongepowered.api.service.context.Context; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.util.Tristate; - -import javax.annotation.Nullable; -import java.util.Set; +import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData; +import me.lucko.luckperms.sponge.service.references.SubjectReference; /** * Extension of MemorySubjectData which persists data when modified @@ -44,7 +40,7 @@ public class PersistedSubjectData extends CalculatedSubjectData { private boolean save = true; public PersistedSubjectData(LuckPermsService service, String calculatorDisplayName, PersistedSubject subject) { - super(service, calculatorDisplayName); + super(subject, service, calculatorDisplayName); this.subject = subject; } @@ -59,7 +55,7 @@ public class PersistedSubjectData extends CalculatedSubjectData { } @Override - public boolean setPermission(Set contexts, String permission, Tristate value) { + public boolean setPermission(ContextSet contexts, String permission, me.lucko.luckperms.api.Tristate value) { boolean r = super.setPermission(contexts, permission, value); save(); return r; @@ -73,21 +69,21 @@ public class PersistedSubjectData extends CalculatedSubjectData { } @Override - public boolean clearPermissions(Set context) { - boolean r = super.clearPermissions(context); + public boolean clearPermissions(ContextSet contexts) { + boolean r = super.clearPermissions(contexts); save(); return r; } @Override - public boolean addParent(Set contexts, Subject parent) { + public boolean addParent(ContextSet contexts, SubjectReference parent) { boolean r = super.addParent(contexts, parent); save(); return r; } @Override - public boolean removeParent(Set contexts, Subject parent) { + public boolean removeParent(ContextSet contexts, SubjectReference parent) { boolean r = super.removeParent(contexts, parent); save(); return r; @@ -101,21 +97,28 @@ public class PersistedSubjectData extends CalculatedSubjectData { } @Override - public boolean clearParents(Set contexts) { + public boolean clearParents(ContextSet contexts) { boolean r = super.clearParents(contexts); save(); return r; } @Override - public boolean setOption(Set contexts, String key, @Nullable String value) { + public boolean setOption(ContextSet contexts, String key, String value) { boolean r = super.setOption(contexts, key, value); save(); return r; } @Override - public boolean clearOptions(Set contexts) { + public boolean unsetOption(ContextSet contexts, String key) { + boolean r = super.unsetOption(contexts, key); + save(); + return r; + } + + @Override + public boolean clearOptions(ContextSet contexts) { boolean r = super.clearOptions(contexts); save(); return r; diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/SubjectDataHolder.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/SubjectDataHolder.java index 4d8e15cb1..bd88b706f 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/SubjectDataHolder.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/persisted/SubjectDataHolder.java @@ -24,9 +24,8 @@ package me.lucko.luckperms.sponge.service.persisted; import lombok.ToString; import me.lucko.luckperms.api.context.ContextSet; -import me.lucko.luckperms.sponge.service.data.CalculatedSubjectData; -import me.lucko.luckperms.sponge.service.data.SubjectReference; -import org.spongepowered.api.service.context.Context; +import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData; +import me.lucko.luckperms.sponge.service.references.SubjectReference; import java.util.HashMap; import java.util.List; @@ -34,8 +33,6 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import static me.lucko.luckperms.sponge.service.LuckPermsService.convertContexts; - /** * Holds SubjectData in a "gson friendly" format for serialization */ @@ -45,45 +42,45 @@ public class SubjectDataHolder { private final Map, Map> options; private final Map, List> parents; - public SubjectDataHolder(Map, Map> options, Map, Map> permissions, Map, Set> parents) { + public SubjectDataHolder(Map> options, Map> permissions, Map> parents) { this.options = new HashMap<>(); - for (Map.Entry, Map> e : options.entrySet()) { - this.options.put(convertContexts(e.getKey()).toMap(), new HashMap<>(e.getValue())); + for (Map.Entry> e : options.entrySet()) { + this.options.put(e.getKey().toMap(), new HashMap<>(e.getValue())); } this.permissions = new HashMap<>(); - for (Map.Entry, Map> e : permissions.entrySet()) { - this.permissions.put(convertContexts(e.getKey()).toMap(), new HashMap<>(e.getValue())); + for (Map.Entry> e : permissions.entrySet()) { + this.permissions.put(e.getKey().toMap(), new HashMap<>(e.getValue())); } this.parents = new HashMap<>(); - for (Map.Entry, Set> e : parents.entrySet()) { - this.parents.put(convertContexts(e.getKey()).toMap(), e.getValue().stream().map(SubjectReference::serialize).collect(Collectors.toList())); + for (Map.Entry> e : parents.entrySet()) { + this.parents.put(e.getKey().toMap(), e.getValue().stream().map(SubjectReference::serialize).collect(Collectors.toList())); } } public SubjectDataHolder(CalculatedSubjectData data) { - this(data.getAllOptions(), data.getAllPermissions(), data.getParents()); + this(data.getOptions(), data.getPermissions(), data.getParents()); } public void copyTo(CalculatedSubjectData subjectData) { subjectData.replacePermissions(permissions.entrySet().stream() .collect(Collectors.toMap( - k -> convertContexts(ContextSet.fromMap(k.getKey())), + k -> ContextSet.fromMap(k.getKey()), Map.Entry::getValue )) ); subjectData.replaceOptions(options.entrySet().stream() .collect(Collectors.toMap( - k -> convertContexts(ContextSet.fromMap(k.getKey())), + k -> ContextSet.fromMap(k.getKey()), Map.Entry::getValue )) ); subjectData.replaceParents(parents.entrySet().stream() .collect(Collectors.toMap( - k -> convertContexts(ContextSet.fromMap(k.getKey())), + k -> ContextSet.fromMap(k.getKey()), v -> v.getValue().stream().map(SubjectReference::deserialize).collect(Collectors.toSet()) )) ); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/references/SubjectCollectionReference.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/references/SubjectCollectionReference.java new file mode 100644 index 000000000..fd5d47ca0 --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/references/SubjectCollectionReference.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Lucko (Luck) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.sponge.service.references; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import me.lucko.luckperms.sponge.service.LuckPermsService; +import me.lucko.luckperms.sponge.service.base.LPSubjectCollection; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor(staticName = "of") +public class SubjectCollectionReference { + + private final String collection; + + public LPSubjectCollection resolve(LuckPermsService service) { + return service.getSubjects(collection); + } +} diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/data/SubjectReference.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/references/SubjectReference.java similarity index 82% rename from sponge/src/main/java/me/lucko/luckperms/sponge/service/data/SubjectReference.java rename to sponge/src/main/java/me/lucko/luckperms/sponge/service/references/SubjectReference.java index b834587ca..11b95be87 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/data/SubjectReference.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/references/SubjectReference.java @@ -20,14 +20,16 @@ * SOFTWARE. */ -package me.lucko.luckperms.sponge.service.data; +package me.lucko.luckperms.sponge.service.references; import com.google.common.base.Splitter; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.ToString; -import org.spongepowered.api.service.permission.PermissionService; +import me.lucko.luckperms.sponge.service.LuckPermsService; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.base.LPSubjectCollection; import org.spongepowered.api.service.permission.Subject; import java.util.List; @@ -49,10 +51,14 @@ public class SubjectReference { private final String collection; private final String identifier; - public Subject resolve(PermissionService service) { + public LPSubject resolve(LuckPermsService service) { return service.getSubjects(collection).get(identifier); } + public LPSubjectCollection resolveCollection(LuckPermsService service) { + return service.getSubjects(collection); + } + public String serialize() { return collection + "/" + identifier; } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/simple/SimpleCollection.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/simple/SimpleCollection.java index 8da03a6a5..44fb811c1 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/simple/SimpleCollection.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/simple/SimpleCollection.java @@ -26,30 +26,31 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; +import lombok.AccessLevel; import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.sponge.service.LuckPermsService; -import org.spongepowered.api.service.context.Context; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.service.permission.SubjectCollection; -import org.spongepowered.api.util.Tristate; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.base.LPSubjectCollection; +import me.lucko.luckperms.sponge.service.references.SubjectReference; +import java.util.Collection; import java.util.Map; -import java.util.Set; /** * Super simple SubjectCollection implementation */ +@Getter @RequiredArgsConstructor -public class SimpleCollection implements SubjectCollection { +public class SimpleCollection implements LPSubjectCollection { private final LuckPermsService service; - - @Getter private final String identifier; + @Getter(AccessLevel.NONE) private final LoadingCache subjects = CacheBuilder.newBuilder() .build(new CacheLoader() { @Override @@ -59,7 +60,7 @@ public class SimpleCollection implements SubjectCollection { }); @Override - public Subject get(@NonNull String id) { + public LPSubject get(@NonNull String id) { return subjects.getUnchecked(id.toLowerCase()); } @@ -69,19 +70,14 @@ public class SimpleCollection implements SubjectCollection { } @Override - public Iterable getAllSubjects() { - return subjects.asMap().values().stream().map(s -> (Subject) s).collect(ImmutableCollectors.toImmutableList()); + public Collection getSubjects() { + return subjects.asMap().values().stream().map(s -> (LPSubject) s).collect(ImmutableCollectors.toImmutableList()); } @Override - public Map getAllWithPermission(@NonNull String id) { - return getAllWithPermission(ImmutableSet.of(), id); - } - - @Override - public Map getAllWithPermission(@NonNull Set contexts, @NonNull String node) { - ImmutableMap.Builder m = ImmutableMap.builder(); - for (Subject subject : subjects.asMap().values()) { + public Map getWithPermission(@NonNull ContextSet contexts, @NonNull String node) { + ImmutableMap.Builder m = ImmutableMap.builder(); + for (LPSubject subject : subjects.asMap().values()) { Tristate ts = subject.getPermissionValue(contexts, node); if (ts != Tristate.UNDEFINED) { m.put(subject, ts.asBoolean()); @@ -92,7 +88,7 @@ public class SimpleCollection implements SubjectCollection { } @Override - public Subject getDefaults() { - return service.getDefaultSubjects().get(identifier); + public SubjectReference getDefaultSubject() { + return SubjectReference.of("defaults", identifier); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/service/simple/SimpleSubject.java b/sponge/src/main/java/me/lucko/luckperms/sponge/service/simple/SimpleSubject.java index 524c30179..76b0fdd12 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/service/simple/SimpleSubject.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/service/simple/SimpleSubject.java @@ -23,20 +23,24 @@ package me.lucko.luckperms.sponge.service.simple; import co.aikar.timings.Timing; -import com.google.common.collect.ImmutableList; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableSet; import lombok.Getter; import lombok.NonNull; +import me.lucko.luckperms.api.Tristate; +import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.sponge.service.LuckPermsService; -import me.lucko.luckperms.sponge.service.data.CalculatedSubjectData; +import me.lucko.luckperms.sponge.service.base.LPSubject; +import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData; +import me.lucko.luckperms.sponge.service.calculated.OptionLookup; +import me.lucko.luckperms.sponge.service.calculated.PermissionLookup; +import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference; +import me.lucko.luckperms.sponge.service.references.SubjectReference; import me.lucko.luckperms.sponge.timings.LPTiming; -import org.spongepowered.api.command.CommandSource; -import org.spongepowered.api.service.context.Context; -import org.spongepowered.api.service.permission.Subject; -import org.spongepowered.api.util.Tristate; -import java.util.ArrayList; -import java.util.List; +import java.util.HashSet; import java.util.Optional; import java.util.Set; @@ -44,126 +48,153 @@ import java.util.Set; * Super simple Subject implementation. */ @Getter -public class SimpleSubject implements Subject { +public class SimpleSubject implements LPSubject { private final String identifier; private final LuckPermsService service; - private final SimpleCollection containingCollection; + private final SubjectCollectionReference parentCollection; private final CalculatedSubjectData subjectData; private final CalculatedSubjectData transientSubjectData; + private final LoadingCache permissionLookupCache = CacheBuilder.newBuilder() + .build(new CacheLoader() { + @Override + public Tristate load(PermissionLookup lookup) { + return lookupPermissionValue(lookup.getContexts(), lookup.getNode()); + } + }); + + private final LoadingCache> parentLookupCache = CacheBuilder.newBuilder() + .build(new CacheLoader>() { + @Override + public Set load(ContextSet contexts) { + return lookupParents(contexts); + } + }); + + private final LoadingCache> optionLookupCache = CacheBuilder.newBuilder() + .build(new CacheLoader>() { + @Override + public Optional load(OptionLookup lookup) { + return lookupOptionValue(lookup.getContexts(), lookup.getKey()); + } + }); + public SimpleSubject(String identifier, LuckPermsService service, SimpleCollection containingCollection) { this.identifier = identifier; this.service = service; - this.containingCollection = containingCollection; - this.subjectData = new CalculatedSubjectData(service, "local:" + containingCollection.getIdentifier() + "/" + identifier + "(p)"); - this.transientSubjectData = new CalculatedSubjectData(service, "local:" + containingCollection.getIdentifier() + "/" + identifier + "(t)"); + this.parentCollection = containingCollection.toReference(); + this.subjectData = new CalculatedSubjectData(this, service, "local:" + containingCollection.getIdentifier() + "/" + identifier + "(p)"); + this.transientSubjectData = new CalculatedSubjectData(this, service, "local:" + containingCollection.getIdentifier() + "/" + identifier + "(t)"); + service.getLocalPermissionCaches().add(permissionLookupCache); } - @Override - public Optional getCommandSource() { - return Optional.empty(); - } - - @Override - public boolean hasPermission(@NonNull Set contexts, @NonNull String node) { - return getPermissionValue(contexts, node).asBoolean(); - } - - @Override - public Tristate getPermissionValue(@NonNull Set contexts, @NonNull String node) { - try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_GET_PERMISSION_VALUE)) { - Tristate res = transientSubjectData.getPermissionValue(contexts, node); - if (res != Tristate.UNDEFINED) { - return res; - } - - res = subjectData.getPermissionValue(contexts, node); - if (res != Tristate.UNDEFINED) { - return res; - } - - for (Subject parent : getParents(contexts)) { - res = parent.getPermissionValue(contexts, node); - if (res != Tristate.UNDEFINED) { - return res; - } - } - - if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) { - return Tristate.UNDEFINED; - } - - res = getContainingCollection().getDefaults().getPermissionValue(contexts, node); - if (res != Tristate.UNDEFINED) { - return res; - } - - res = service.getDefaults().getPermissionValue(contexts, node); + private Tristate lookupPermissionValue(ContextSet contexts, String node) { + Tristate res = transientSubjectData.getPermissionValue(contexts, node); + if (res != Tristate.UNDEFINED) { return res; } + + res = subjectData.getPermissionValue(contexts, node); + if (res != Tristate.UNDEFINED) { + return res; + } + + for (SubjectReference parent : getParents(contexts)) { + res = parent.resolve(service).getPermissionValue(contexts, node); + if (res != Tristate.UNDEFINED) { + return res; + } + } + + if (getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")) { + return Tristate.UNDEFINED; + } + + res = getParentCollection().resolve(service).getDefaultSubject().resolve(service).getPermissionValue(contexts, node); + if (res != Tristate.UNDEFINED) { + return res; + } + + res = service.getDefaults().getPermissionValue(contexts, node); + return res; + } + + private Set lookupParents(ContextSet contexts) { + Set s = new HashSet<>(); + s.addAll(subjectData.getParents(contexts)); + + if (!getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")){ + s.addAll(getParentCollection().resolve(service).getDefaultSubject().resolve(service).getParents(contexts)); + s.addAll(service.getDefaults().getParents(contexts)); + } + + return ImmutableSet.copyOf(s); + } + + private Optional lookupOptionValue(ContextSet contexts, String key) { + Optional res = Optional.ofNullable(subjectData.getOptions(contexts).get(key)); + if (res.isPresent()) { + return res; + } + + for (SubjectReference parent : getParents(getActiveContextSet())) { + Optional tempRes = parent.resolve(service).getOption(contexts, key); + if (tempRes.isPresent()) { + return tempRes; + } + } + + if (getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")) { + return Optional.empty(); + } + + res = getParentCollection().resolve(service).getDefaultSubject().resolve(service).getOption(contexts, key); + if (res.isPresent()) { + return res; + } + + return service.getDefaults().getOption(contexts, key); + } + + @Override + public Tristate getPermissionValue(@NonNull ContextSet contexts, @NonNull String node) { + try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_GET_PERMISSION_VALUE)) { + return permissionLookupCache.getUnchecked(PermissionLookup.of(node, contexts)); + } } @Override - public boolean isChildOf(@NonNull Set contexts, @NonNull Subject subject) { + public boolean isChildOf(@NonNull ContextSet contexts, @NonNull SubjectReference subject) { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_IS_CHILD_OF)) { - if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) { + if (getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")) { return subjectData.getParents(contexts).contains(subject); } else { return subjectData.getParents(contexts).contains(subject) || - getContainingCollection().getDefaults().getParents(contexts).contains(subject) || + getParentCollection().resolve(service).getDefaultSubject().resolve(service).getParents(contexts).contains(subject) || service.getDefaults().getParents(contexts).contains(subject); } } } @Override - public List getParents(@NonNull Set contexts) { + public Set getParents(@NonNull ContextSet contexts) { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_GET_PARENTS)) { - List s = new ArrayList<>(); - s.addAll(subjectData.getParents(contexts)); - - if (!getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")){ - s.addAll(getContainingCollection().getDefaults().getParents(contexts)); - s.addAll(service.getDefaults().getParents(contexts)); - } - - return ImmutableList.copyOf(s); + return parentLookupCache.getUnchecked(contexts); } } @Override - public Optional getOption(Set set, String key) { + public Optional getOption(ContextSet contexts, String key) { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_GET_OPTION)) { - Optional res = Optional.ofNullable(subjectData.getOptions(getActiveContexts()).get(key)); - if (res.isPresent()) { - return res; - } - - for (Subject parent : getParents(getActiveContexts())) { - Optional tempRes = parent.getOption(getActiveContexts(), key); - if (tempRes.isPresent()) { - return tempRes; - } - } - - if (getContainingCollection().getIdentifier().equalsIgnoreCase("defaults")) { - return Optional.empty(); - } - - res = getContainingCollection().getDefaults().getOption(set, key); - if (res.isPresent()) { - return res; - } - - return service.getDefaults().getOption(set, key); + return optionLookupCache.getUnchecked(OptionLookup.of(key, contexts)); } } @Override - public Set getActiveContexts() { + public ContextSet getActiveContextSet() { try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.SIMPLE_SUBJECT_GET_ACTIVE_CONTEXTS)) { - return ImmutableSet.copyOf(LuckPermsService.convertContexts(service.getPlugin().getContextManager().getApplicableContext(this))); + return service.getPlugin().getContextManager().getApplicableContext(this); } } }