Further improvements to the Sponge service design

This commit is contained in:
Luck 2018-03-08 21:51:25 +00:00
parent 1b98667365
commit f6c440c172
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
49 changed files with 609 additions and 503 deletions

View File

@ -25,19 +25,10 @@
package me.lucko.luckperms.common.inheritance; package me.lucko.luckperms.common.inheritance;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LookupSetting;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.graph.Graph; import me.lucko.luckperms.common.graph.Graph;
import me.lucko.luckperms.common.graph.GraphTraversers; import me.lucko.luckperms.common.graph.GraphTraversers;
import me.lucko.luckperms.common.graph.TraversalAlgorithm; import me.lucko.luckperms.common.graph.TraversalAlgorithm;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/** /**
* A {@link Graph} which represents an "inheritance tree". * A {@link Graph} which represents an "inheritance tree".
@ -56,57 +47,4 @@ public interface InheritanceGraph extends Graph<PermissionHolder> {
return GraphTraversers.traverseUsing(algorithm, this, startNode); return GraphTraversers.traverseUsing(algorithm, this, startNode);
} }
final class NonContextual implements InheritanceGraph {
private final LuckPermsPlugin plugin;
NonContextual(LuckPermsPlugin plugin) {
this.plugin = plugin;
}
@Override
public Iterable<? extends PermissionHolder> successors(PermissionHolder holder) {
Set<Group> successors = new TreeSet<>(holder.getInheritanceComparator());
List<Node> nodes = holder.getOwnGroupNodes();
for (Node n : nodes) {
Group g = this.plugin.getGroupManager().getIfLoaded(n.getGroupName());
if (g != null) {
successors.add(g);
}
}
return successors;
}
}
final class Contextual implements InheritanceGraph {
private final LuckPermsPlugin plugin;
/**
* The contexts to resolve inheritance in.
*/
private final Contexts context;
Contextual(LuckPermsPlugin plugin, Contexts context) {
this.plugin = plugin;
this.context = context;
}
@Override
public Iterable<? extends PermissionHolder> successors(PermissionHolder holder) {
Set<Group> successors = new TreeSet<>(holder.getInheritanceComparator());
List<Node> nodes = holder.getOwnGroupNodes(this.context.getContexts());
for (Node n : nodes) {
// effectively: if not (we're applying global groups or it's specific anyways)
if (!((this.context.hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER) || n.isServerSpecific()) && (this.context.hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD) || n.isWorldSpecific()))) {
continue;
}
Group g = this.plugin.getGroupManager().getIfLoaded(n.getGroupName());
if (g != null) {
successors.add(g);
}
}
return successors;
}
}
} }

View File

@ -29,8 +29,15 @@ import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache; import com.github.benmanes.caffeine.cache.LoadingCache;
import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LookupSetting;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -51,10 +58,10 @@ public class InheritanceHandler {
public InheritanceHandler(LuckPermsPlugin plugin) { public InheritanceHandler(LuckPermsPlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
this.nonContextualGraph = new InheritanceGraph.NonContextual(plugin); this.nonContextualGraph = new NonContextualGraph(plugin);
this.contextualGraphs = Caffeine.newBuilder() this.contextualGraphs = Caffeine.newBuilder()
.expireAfterAccess(10, TimeUnit.MINUTES) .expireAfterAccess(10, TimeUnit.MINUTES)
.build(key -> new InheritanceGraph.Contextual(this.plugin, key)); .build(key -> new ContextualGraph(this.plugin, key));
} }
public InheritanceGraph getGraph() { public InheritanceGraph getGraph() {
@ -65,4 +72,57 @@ public class InheritanceHandler {
return this.contextualGraphs.get(contexts); return this.contextualGraphs.get(contexts);
} }
private static final class NonContextualGraph implements InheritanceGraph {
private final LuckPermsPlugin plugin;
NonContextualGraph(LuckPermsPlugin plugin) {
this.plugin = plugin;
}
@Override
public Iterable<? extends PermissionHolder> successors(PermissionHolder holder) {
Set<Group> successors = new TreeSet<>(holder.getInheritanceComparator());
List<Node> nodes = holder.getOwnGroupNodes();
for (Node n : nodes) {
Group g = this.plugin.getGroupManager().getIfLoaded(n.getGroupName());
if (g != null) {
successors.add(g);
}
}
return successors;
}
}
private static final class ContextualGraph implements InheritanceGraph {
private final LuckPermsPlugin plugin;
/**
* The contexts to resolve inheritance in.
*/
private final Contexts context;
ContextualGraph(LuckPermsPlugin plugin, Contexts context) {
this.plugin = plugin;
this.context = context;
}
@Override
public Iterable<? extends PermissionHolder> successors(PermissionHolder holder) {
Set<Group> successors = new TreeSet<>(holder.getInheritanceComparator());
List<Node> nodes = holder.getOwnGroupNodes(this.context.getContexts());
for (Node n : nodes) {
// effectively: if not (we're applying global groups or it's specific anyways)
if (!((this.context.hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER) || n.isServerSpecific()) && (this.context.hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD) || n.isWorldSpecific()))) {
continue;
}
Group g = this.plugin.getGroupManager().getIfLoaded(n.getGroupName());
if (g != null) {
successors.add(g);
}
}
return successors;
}
}
} }

View File

@ -53,7 +53,7 @@ import javax.annotation.Nonnull;
public class LuckPermsMessagingService implements InternalMessagingService, IncomingMessageConsumer { public class LuckPermsMessagingService implements InternalMessagingService, IncomingMessageConsumer {
private final LuckPermsPlugin plugin; private final LuckPermsPlugin plugin;
private final Set<UUID> receivedMessages; private final Set<UUID> receivedMessages;
private final BufferedRequest<Void> updateBuffer; private final PushUpdateBuffer updateBuffer;
private final MessengerProvider messengerProvider; private final MessengerProvider messengerProvider;
private final Messenger messenger; private final Messenger messenger;

View File

@ -53,7 +53,7 @@ public class Group extends PermissionHolder implements Identifiable<String> {
*/ */
private final GroupCachedData cachedData; private final GroupCachedData cachedData;
private final BufferedRequest<Void> refreshBuffer; private final GroupRefreshBuffer refreshBuffer;
public Group(String name, LuckPermsPlugin plugin) { public Group(String name, LuckPermsPlugin plugin) {
super(name, plugin); super(name, plugin);

View File

@ -62,7 +62,7 @@ public class User extends PermissionHolder implements Identifiable<UserIdentifie
*/ */
private final UserCachedData cachedData; private final UserCachedData cachedData;
private final BufferedRequest<Void> refreshBuffer; private final UserRefreshBuffer refreshBuffer;
public User(UUID uuid, String name, LuckPermsPlugin plugin) { public User(UUID uuid, String name, LuckPermsPlugin plugin) {
super(uuid.toString(), plugin); super(uuid.toString(), plugin);

View File

@ -44,14 +44,14 @@ import java.util.Objects;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public final class LPDescriptionBuilder implements PermissionDescription.Builder { public final class DescriptionBuilder implements PermissionDescription.Builder {
@Nonnull private final LPPermissionService service; @Nonnull private final LPPermissionService service;
@Nonnull private final PluginContainer container; @Nonnull private final PluginContainer container;
@Nonnull private final Map<String, Tristate> roles = new HashMap<>(); @Nonnull private final Map<String, Tristate> roles = new HashMap<>();
@Nullable private String id = null; @Nullable private String id = null;
@Nullable private Text description = null; @Nullable private Text description = null;
public LPDescriptionBuilder(@Nonnull LPPermissionService service, @Nonnull PluginContainer container) { public DescriptionBuilder(@Nonnull LPPermissionService service, @Nonnull PluginContainer container) {
this.service = Objects.requireNonNull(service, "service"); this.service = Objects.requireNonNull(service, "service");
this.container = Objects.requireNonNull(container, "container"); this.container = Objects.requireNonNull(container, "container");
} }
@ -107,8 +107,8 @@ public final class LPDescriptionBuilder implements PermissionDescription.Builder
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (!(o instanceof LPDescriptionBuilder)) return false; if (!(o instanceof DescriptionBuilder)) return false;
final LPDescriptionBuilder other = (LPDescriptionBuilder) o; final DescriptionBuilder other = (DescriptionBuilder) o;
return this.container.equals(other.container) && return this.container.equals(other.container) &&
this.roles.equals(other.roles) && this.roles.equals(other.roles) &&

View File

@ -65,7 +65,7 @@ public final class PermissionServiceProxy implements PermissionService {
@Nonnull @Nonnull
@Override @Override
public Subject getDefaults() { public Subject getDefaults() {
return this.handle.getDefaults().sponge(); return this.handle.getRootDefaults().sponge();
} }
@Nonnull @Nonnull
@ -91,7 +91,7 @@ public final class PermissionServiceProxy implements PermissionService {
throw new IllegalArgumentException("Couldn't find a plugin container for " + o.getClass().getSimpleName()); throw new IllegalArgumentException("Couldn't find a plugin container for " + o.getClass().getSimpleName());
} }
return Optional.of(new LPDescriptionBuilder(this.handle, container.get())); return Optional.of(new DescriptionBuilder(this.handle, container.get()));
} }
@Nonnull @Nonnull

View File

@ -30,7 +30,6 @@ import me.lucko.luckperms.sponge.service.CompatibilityUtil;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory;
import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.Subject;
@ -79,7 +78,7 @@ public final class SubjectCollectionProxy implements SubjectCollection {
// this behaviour should be replaced when CompletableFutures are added to Sponge // this behaviour should be replaced when CompletableFutures are added to Sponge
return (List) this.handle.getAllIdentifiers() return (List) this.handle.getAllIdentifiers()
.thenApply(ids -> ids.stream() .thenApply(ids -> ids.stream()
.map(s -> new SubjectProxy(this.service, SubjectReferenceFactory.obtain(this.service, getIdentifier(), s))) .map(s -> new SubjectProxy(this.service, this.service.getReferenceFactory().obtain(getIdentifier(), s)))
.collect(ImmutableCollectors.toList()) .collect(ImmutableCollectors.toList())
).join(); ).join();
} }

View File

@ -30,8 +30,7 @@ import me.lucko.luckperms.sponge.service.CompatibilityUtil;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.model.LPSubjectData;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory;
import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.Subject;
@ -126,7 +125,7 @@ public final class SubjectDataProxy implements SubjectData {
public boolean addParent(@Nonnull Set<Context> contexts, @Nonnull Subject parent) { public boolean addParent(@Nonnull Set<Context> contexts, @Nonnull Subject parent) {
handle().thenCompose(handle -> handle.addParent( handle().thenCompose(handle -> handle.addParent(
CompatibilityUtil.convertContexts(contexts), CompatibilityUtil.convertContexts(contexts),
SubjectReferenceFactory.obtain(this.service, parent) this.service.getReferenceFactory().obtain(parent)
)); ));
return true; return true;
} }
@ -135,7 +134,7 @@ public final class SubjectDataProxy implements SubjectData {
public boolean removeParent(@Nonnull Set<Context> contexts, @Nonnull Subject parent) { public boolean removeParent(@Nonnull Set<Context> contexts, @Nonnull Subject parent) {
handle().thenCompose(handle -> handle.removeParent( handle().thenCompose(handle -> handle.removeParent(
CompatibilityUtil.convertContexts(contexts), CompatibilityUtil.convertContexts(contexts),
SubjectReferenceFactory.obtain(this.service, parent) this.service.getReferenceFactory().obtain(parent)
)); ));
return true; return true;
} }

View File

@ -30,9 +30,8 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.sponge.service.CompatibilityUtil; import me.lucko.luckperms.sponge.service.CompatibilityUtil;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.model.ProxiedSubject; import me.lucko.luckperms.sponge.service.model.ProxiedSubject;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory;
import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.context.Context;
@ -110,7 +109,7 @@ public final class SubjectProxy implements Subject, ProxiedSubject {
public boolean isChildOf(@Nonnull Subject parent) { public boolean isChildOf(@Nonnull Subject parent) {
return handle().thenApply(handle -> handle.isChildOf( return handle().thenApply(handle -> handle.isChildOf(
ImmutableContextSet.empty(), ImmutableContextSet.empty(),
SubjectReferenceFactory.obtain(this.service, parent) this.service.getReferenceFactory().obtain(parent)
)).join(); )).join();
} }
@ -118,7 +117,7 @@ public final class SubjectProxy implements Subject, ProxiedSubject {
public boolean isChildOf(@Nonnull Set<Context> contexts, @Nonnull Subject parent) { public boolean isChildOf(@Nonnull Set<Context> contexts, @Nonnull Subject parent) {
return handle().thenApply(handle -> handle.isChildOf( return handle().thenApply(handle -> handle.isChildOf(
CompatibilityUtil.convertContexts(contexts), CompatibilityUtil.convertContexts(contexts),
SubjectReferenceFactory.obtain(this.service, parent) this.service.getReferenceFactory().obtain(parent)
)).join(); )).join();
} }

View File

@ -44,14 +44,14 @@ import java.util.Objects;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public final class LPDescriptionBuilder implements PermissionDescription.Builder { public final class DescriptionBuilder implements PermissionDescription.Builder {
@Nonnull private final LPPermissionService service; @Nonnull private final LPPermissionService service;
@Nonnull private final PluginContainer container; @Nonnull private final PluginContainer container;
@Nonnull private final Map<String, Tristate> roles = new HashMap<>(); @Nonnull private final Map<String, Tristate> roles = new HashMap<>();
@Nullable private String id = null; @Nullable private String id = null;
@Nullable private Text description = null; @Nullable private Text description = null;
public LPDescriptionBuilder(LPPermissionService service, PluginContainer container) { public DescriptionBuilder(LPPermissionService service, PluginContainer container) {
this.service = Objects.requireNonNull(service, "service"); this.service = Objects.requireNonNull(service, "service");
this.container = Objects.requireNonNull(container, "container"); this.container = Objects.requireNonNull(container, "container");
} }
@ -107,8 +107,8 @@ public final class LPDescriptionBuilder implements PermissionDescription.Builder
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (!(o instanceof LPDescriptionBuilder)) return false; if (!(o instanceof DescriptionBuilder)) return false;
final LPDescriptionBuilder other = (LPDescriptionBuilder) o; final DescriptionBuilder other = (DescriptionBuilder) o;
return this.container.equals(other.container) && return this.container.equals(other.container) &&
this.roles.equals(other.roles) && this.roles.equals(other.roles) &&

View File

@ -31,7 +31,6 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.sponge.service.model.LPPermissionDescription; import me.lucko.luckperms.sponge.service.model.LPPermissionDescription;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory;
import org.spongepowered.api.Sponge; import org.spongepowered.api.Sponge;
import org.spongepowered.api.plugin.PluginContainer; import org.spongepowered.api.plugin.PluginContainer;
@ -74,7 +73,7 @@ public final class PermissionServiceProxy implements PermissionService {
@Nonnull @Nonnull
@Override @Override
public Subject getDefaults() { public Subject getDefaults() {
return this.handle.getDefaults().sponge(); return this.handle.getRootDefaults().sponge();
} }
@Nonnull @Nonnull
@ -129,7 +128,7 @@ public final class PermissionServiceProxy implements PermissionService {
} }
// obtain a reference // obtain a reference
return SubjectReferenceFactory.obtain(this.handle, collectionIdentifier, subjectIdentifier); return this.handle.getReferenceFactory().obtain(collectionIdentifier, subjectIdentifier);
} }
@Override @Override
@ -139,7 +138,7 @@ public final class PermissionServiceProxy implements PermissionService {
throw new IllegalArgumentException("Couldn't find a plugin container for " + o.getClass().getSimpleName()); throw new IllegalArgumentException("Couldn't find a plugin container for " + o.getClass().getSimpleName());
} }
return new LPDescriptionBuilder(this.handle, container.get()); return new DescriptionBuilder(this.handle, container.get());
} }
@Nonnull @Nonnull

View File

@ -29,7 +29,6 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.sponge.service.CompatibilityUtil; import me.lucko.luckperms.sponge.service.CompatibilityUtil;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory;
import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.Subject;
@ -110,7 +109,7 @@ public final class SubjectCollectionProxy implements SubjectCollection {
throw new IllegalArgumentException("Subject identifier '" + subjectIdentifier + "' does not pass the validity predicate"); throw new IllegalArgumentException("Subject identifier '" + subjectIdentifier + "' does not pass the validity predicate");
} }
return SubjectReferenceFactory.obtain(this.handle.getService(), getIdentifier(), subjectIdentifier); return this.handle.getService().getReferenceFactory().obtain(getIdentifier(), subjectIdentifier);
} }
@Nonnull @Nonnull

View File

@ -30,8 +30,7 @@ import me.lucko.luckperms.sponge.service.CompatibilityUtil;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.model.LPSubjectData;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory;
import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.SubjectData; import org.spongepowered.api.service.permission.SubjectData;
@ -120,13 +119,13 @@ public final class SubjectDataProxy implements SubjectData {
@Nonnull @Nonnull
@Override @Override
public CompletableFuture<Boolean> addParent(@Nonnull Set<Context> contexts, @Nonnull org.spongepowered.api.service.permission.SubjectReference ref) { public CompletableFuture<Boolean> addParent(@Nonnull Set<Context> contexts, @Nonnull org.spongepowered.api.service.permission.SubjectReference ref) {
return handle().thenCompose(handle -> handle.addParent(CompatibilityUtil.convertContexts(contexts), SubjectReferenceFactory.obtain(this.service, ref))); return handle().thenCompose(handle -> handle.addParent(CompatibilityUtil.convertContexts(contexts), this.service.getReferenceFactory().obtain(ref)));
} }
@Nonnull @Nonnull
@Override @Override
public CompletableFuture<Boolean> removeParent(@Nonnull Set<Context> contexts, @Nonnull org.spongepowered.api.service.permission.SubjectReference ref) { public CompletableFuture<Boolean> removeParent(@Nonnull Set<Context> contexts, @Nonnull org.spongepowered.api.service.permission.SubjectReference ref) {
return handle().thenCompose(handle -> handle.removeParent(CompatibilityUtil.convertContexts(contexts), SubjectReferenceFactory.obtain(this.service, ref))); return handle().thenCompose(handle -> handle.removeParent(CompatibilityUtil.convertContexts(contexts), this.service.getReferenceFactory().obtain(ref)));
} }
@Nonnull @Nonnull

View File

@ -29,9 +29,8 @@ import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.sponge.service.CompatibilityUtil; import me.lucko.luckperms.sponge.service.CompatibilityUtil;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.model.ProxiedSubject; import me.lucko.luckperms.sponge.service.model.ProxiedSubject;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory;
import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.context.Context; import org.spongepowered.api.service.context.Context;
@ -113,12 +112,12 @@ public final class SubjectProxy implements Subject, ProxiedSubject {
@Override @Override
public boolean isChildOf(@Nonnull SubjectReference parent) { public boolean isChildOf(@Nonnull SubjectReference parent) {
return handle().thenApply(handle -> handle.isChildOf(ImmutableContextSet.empty(), SubjectReferenceFactory.obtain(this.service, parent))).join(); return handle().thenApply(handle -> handle.isChildOf(ImmutableContextSet.empty(), this.service.getReferenceFactory().obtain(parent))).join();
} }
@Override @Override
public boolean isChildOf(@Nonnull Set<Context> contexts, @Nonnull SubjectReference parent) { public boolean isChildOf(@Nonnull Set<Context> contexts, @Nonnull SubjectReference parent) {
return handle().thenApply(handle -> handle.isChildOf(CompatibilityUtil.convertContexts(contexts), SubjectReferenceFactory.obtain(this.service, parent))).join(); return handle().thenApply(handle -> handle.isChildOf(CompatibilityUtil.convertContexts(contexts), this.service.getReferenceFactory().obtain(parent))).join();
} }
@Nonnull @Nonnull

View File

@ -25,8 +25,6 @@
package me.lucko.luckperms.sponge.service.model; package me.lucko.luckperms.sponge.service.model;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference;
import org.spongepowered.api.plugin.PluginContainer; import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.service.permission.PermissionDescription; import org.spongepowered.api.service.permission.PermissionDescription;
import org.spongepowered.api.text.Text; import org.spongepowered.api.text.Text;

View File

@ -60,7 +60,7 @@ public interface LPPermissionService {
LPSubjectCollection getDefaultSubjects(); LPSubjectCollection getDefaultSubjects();
LPSubject getDefaults(); LPSubject getRootDefaults();
Predicate<String> getIdentifierValidityPredicate(); Predicate<String> getIdentifierValidityPredicate();

View File

@ -29,8 +29,6 @@ import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory;
import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.Subject;
@ -49,12 +47,10 @@ public interface LPSubject {
String getIdentifier(); String getIdentifier();
default LPSubjectReference toReference() { default LPSubjectReference toReference() {
return SubjectReferenceFactory.obtain(getService(), this); return getService().getReferenceFactory().obtain(this);
} }
default LPSubject getDefaults() { LPSubject getDefaults();
return getService().getDefaultSubjects().loadSubject(getIdentifier()).join();
}
default Optional<String> getFriendlyIdentifier() { default Optional<String> getFriendlyIdentifier() {
return Optional.empty(); return Optional.empty();

View File

@ -30,7 +30,6 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference;
import org.spongepowered.api.service.permission.SubjectCollection; import org.spongepowered.api.service.permission.SubjectCollection;

View File

@ -31,7 +31,6 @@ import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference;
import org.spongepowered.api.service.permission.SubjectData; import org.spongepowered.api.service.permission.SubjectData;

View File

@ -23,9 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.sponge.service.reference; package me.lucko.luckperms.sponge.service.model;
import me.lucko.luckperms.sponge.service.model.LPSubject;
import org.spongepowered.api.service.permission.SubjectReference; import org.spongepowered.api.service.permission.SubjectReference;

View File

@ -25,8 +25,6 @@
package me.lucko.luckperms.sponge.service.model; package me.lucko.luckperms.sponge.service.model;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference;
import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.Subject;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@ -25,9 +25,19 @@
package me.lucko.luckperms.sponge.service.model; package me.lucko.luckperms.sponge.service.model;
/**
* Defines in what order data should be resolved.
*/
public enum ResolutionOrder { public enum ResolutionOrder {
/**
* Marks that transient data should be considered before enduring data
*/
TRANSIENT_FIRST, TRANSIENT_FIRST,
/**
* Marks that transient data should be considered after enduring data
*/
TRANSIENT_LAST TRANSIENT_LAST
} }

View File

@ -27,6 +27,7 @@ package me.lucko.luckperms.sponge.service.reference;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.Subject;
@ -43,7 +44,7 @@ import javax.annotation.Nonnull;
* Use of this class (or interface) should have no negative impact on * Use of this class (or interface) should have no negative impact on
* performance, as {@link #resolve()} calls are cached. * performance, as {@link #resolve()} calls are cached.
*/ */
final class LuckPermsSubjectReference implements LPSubjectReference { final class CachedSubjectReference implements LPSubjectReference {
/** /**
* The time a subject instance should be cached in this reference * The time a subject instance should be cached in this reference
@ -71,7 +72,7 @@ final class LuckPermsSubjectReference implements LPSubjectReference {
private long lastLookup = 0L; private long lastLookup = 0L;
private WeakReference<LPSubject> cache = null; private WeakReference<LPSubject> cache = null;
LuckPermsSubjectReference(LPPermissionService service, String collectionIdentifier, String subjectIdentifier) { CachedSubjectReference(LPPermissionService service, String collectionIdentifier, String subjectIdentifier) {
this.service = Objects.requireNonNull(service); this.service = Objects.requireNonNull(service);
this.collectionIdentifier = Objects.requireNonNull(collectionIdentifier); this.collectionIdentifier = Objects.requireNonNull(collectionIdentifier);
this.subjectIdentifier = Objects.requireNonNull(subjectIdentifier); this.subjectIdentifier = Objects.requireNonNull(subjectIdentifier);

View File

@ -31,6 +31,7 @@ import com.google.common.base.Splitter;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.model.ProxiedSubject; import me.lucko.luckperms.sponge.service.model.ProxiedSubject;
import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.Subject;
@ -45,34 +46,6 @@ import java.util.concurrent.TimeUnit;
*/ */
public final class SubjectReferenceFactory { public final class SubjectReferenceFactory {
// static util access
@Deprecated
public static LPSubjectReference deserialize(LPPermissionService service, String serializedReference) {
Objects.requireNonNull(service, "service");
return service.getReferenceFactory().deserialize(serializedReference);
}
public static LPSubjectReference obtain(LPPermissionService service, LPSubject subject) {
Objects.requireNonNull(service, "service");
return service.getReferenceFactory().obtain(subject);
}
public static LPSubjectReference obtain(LPPermissionService service, Subject subject) {
Objects.requireNonNull(service, "service");
return service.getReferenceFactory().obtain(subject);
}
public static LPSubjectReference obtain(LPPermissionService service, SubjectReference reference) {
Objects.requireNonNull(service, "service");
return service.getReferenceFactory().obtain(reference);
}
public static LPSubjectReference obtain(LPPermissionService service, String collectionIdentifier, String subjectIdentifier) {
Objects.requireNonNull(service, "service");
return service.getReferenceFactory().obtain(collectionIdentifier, subjectIdentifier);
}
/** /**
* The permission service to obtain real subject instances from * The permission service to obtain real subject instances from
*/ */
@ -87,9 +60,9 @@ public final class SubjectReferenceFactory {
* *
* It's perfectly ok if two instances of the same SubjectReference exist. (hence the 1 hour expiry) * It's perfectly ok if two instances of the same SubjectReference exist. (hence the 1 hour expiry)
*/ */
private final LoadingCache<SubjectReferenceAttributes, LuckPermsSubjectReference> referenceCache = Caffeine.newBuilder() private final LoadingCache<SubjectReferenceAttributes, CachedSubjectReference> referenceCache = Caffeine.newBuilder()
.expireAfterAccess(1, TimeUnit.HOURS) .expireAfterAccess(1, TimeUnit.HOURS)
.build(a -> new LuckPermsSubjectReference(SubjectReferenceFactory.this.service, a.collectionId, a.id)); .build(a -> new CachedSubjectReference(SubjectReferenceFactory.this.service, a.collectionId, a.id));
public SubjectReferenceFactory(LPPermissionService service) { public SubjectReferenceFactory(LPPermissionService service) {
this.service = service; this.service = service;
@ -105,7 +78,7 @@ public final class SubjectReferenceFactory {
public LPSubjectReference obtain(LPSubject subject) { public LPSubjectReference obtain(LPSubject subject) {
Objects.requireNonNull(subject, "subject"); Objects.requireNonNull(subject, "subject");
LPSubjectReference ret = obtain(subject.getParentCollection().getIdentifier(), subject.getIdentifier()); LPSubjectReference ret = obtain(subject.getParentCollection().getIdentifier(), subject.getIdentifier());
((LuckPermsSubjectReference) ret).fillCache(subject); ((CachedSubjectReference) ret).fillCache(subject);
return ret; return ret;
} }

View File

@ -156,7 +156,6 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin {
} else { } else {
this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, LPPermissionService.class, this.service); this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, LPPermissionService.class, this.service);
this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, PermissionService.class, this.service.sponge()); this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, PermissionService.class, this.service.sponge());
this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, LuckPermsService.class, this.service);
} }
} }
@ -185,7 +184,6 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin {
getLogger().info("Providing late registration of PermissionService..."); getLogger().info("Providing late registration of PermissionService...");
this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, LPPermissionService.class, this.service); this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, LPPermissionService.class, this.service);
this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, PermissionService.class, this.service.sponge()); this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, PermissionService.class, this.service.sponge());
this.bootstrap.getGame().getServiceManager().setProvider(this.bootstrap, LuckPermsService.class, this.service);
} }
} }

View File

@ -39,7 +39,7 @@ import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.model.LPSubjectData;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

View File

@ -29,7 +29,7 @@ import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils; import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.CommandUtils; import me.lucko.luckperms.common.commands.utils.CommandUtils;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

View File

@ -42,11 +42,10 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.LPSpongePlugin;
import me.lucko.luckperms.sponge.model.SpongeGroup; import me.lucko.luckperms.sponge.model.SpongeGroup;
import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.service.ProxyFactory;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory; import me.lucko.luckperms.sponge.service.proxy.ProxyFactory;
import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.SubjectCollection; import org.spongepowered.api.service.permission.SubjectCollection;
@ -191,7 +190,7 @@ public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implem
List<HeldPermission<String>> lookup = this.plugin.getStorage().getGroupsWithPermission(permission).join(); List<HeldPermission<String>> lookup = this.plugin.getStorage().getGroupsWithPermission(permission).join();
for (HeldPermission<String> holder : lookup) { for (HeldPermission<String> holder : lookup) {
if (holder.asNode().getFullContexts().equals(ImmutableContextSet.empty())) { if (holder.asNode().getFullContexts().equals(ImmutableContextSet.empty())) {
ret.put(SubjectReferenceFactory.obtain(getService(), getIdentifier(), holder.getHolder()), holder.getValue()); ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder()), holder.getValue());
} }
} }
@ -207,7 +206,7 @@ public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implem
List<HeldPermission<String>> lookup = this.plugin.getStorage().getGroupsWithPermission(permission).join(); List<HeldPermission<String>> lookup = this.plugin.getStorage().getGroupsWithPermission(permission).join();
for (HeldPermission<String> holder : lookup) { for (HeldPermission<String> holder : lookup) {
if (holder.asNode().getFullContexts().equals(contexts)) { if (holder.asNode().getFullContexts().equals(contexts)) {
ret.put(SubjectReferenceFactory.obtain(getService(), getIdentifier(), holder.getHolder()), holder.getValue()); ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder()), holder.getValue());
} }
} }
@ -235,7 +234,7 @@ public class SpongeGroupManager extends AbstractGroupManager<SpongeGroup> implem
@Override @Override
public LPSubject getDefaults() { public LPSubject getDefaults() {
return getService().getDefaultSubjects().loadSubject(getIdentifier()).join(); return getService().getDefaultSubjects().getTypeDefaults(getIdentifier());
} }
} }

View File

@ -43,11 +43,10 @@ import me.lucko.luckperms.common.utils.Uuids;
import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.LPSpongePlugin;
import me.lucko.luckperms.sponge.model.SpongeUser; import me.lucko.luckperms.sponge.model.SpongeUser;
import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.service.ProxyFactory;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory; import me.lucko.luckperms.sponge.service.proxy.ProxyFactory;
import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.SubjectCollection; import org.spongepowered.api.service.permission.SubjectCollection;
@ -216,7 +215,7 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
List<HeldPermission<UUID>> lookup = this.plugin.getStorage().getUsersWithPermission(permission).join(); List<HeldPermission<UUID>> lookup = this.plugin.getStorage().getUsersWithPermission(permission).join();
for (HeldPermission<UUID> holder : lookup) { for (HeldPermission<UUID> holder : lookup) {
if (holder.asNode().getFullContexts().equals(ImmutableContextSet.empty())) { if (holder.asNode().getFullContexts().equals(ImmutableContextSet.empty())) {
ret.put(SubjectReferenceFactory.obtain(getService(), getIdentifier(), holder.getHolder().toString()), holder.getValue()); ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder().toString()), holder.getValue());
} }
} }
@ -232,7 +231,7 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
List<HeldPermission<UUID>> lookup = this.plugin.getStorage().getUsersWithPermission(permission).join(); List<HeldPermission<UUID>> lookup = this.plugin.getStorage().getUsersWithPermission(permission).join();
for (HeldPermission<UUID> holder : lookup) { for (HeldPermission<UUID> holder : lookup) {
if (holder.asNode().getFullContexts().equals(contexts)) { if (holder.asNode().getFullContexts().equals(contexts)) {
ret.put(SubjectReferenceFactory.obtain(getService(), getIdentifier(), holder.getHolder().toString()), holder.getValue()); ret.put(getService().getReferenceFactory().obtain(getIdentifier(), holder.getHolder().toString()), holder.getValue());
} }
} }
@ -260,7 +259,7 @@ public class SpongeUserManager extends AbstractUserManager<SpongeUser> implement
@Override @Override
public LPSubject getDefaults() { public LPSubject getDefaults() {
return getService().getDefaultSubjects().loadSubject(getIdentifier()).join(); return getService().getDefaultSubjects().getTypeDefaults(getIdentifier());
} }
} }

View File

@ -32,7 +32,7 @@ import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
public abstract class DefaultsProcessor implements PermissionProcessor { public abstract class DefaultsProcessor implements PermissionProcessor {
private final LPPermissionService service; protected final LPPermissionService service;
private final ImmutableContextSet contexts; private final ImmutableContextSet contexts;
public DefaultsProcessor(LPPermissionService service, ImmutableContextSet contexts) { public DefaultsProcessor(LPPermissionService service, ImmutableContextSet contexts) {
@ -40,16 +40,16 @@ public abstract class DefaultsProcessor implements PermissionProcessor {
this.contexts = contexts; this.contexts = contexts;
} }
protected abstract LPSubject getTypeDefaults(LPPermissionService service); protected abstract LPSubject getTypeDefaults();
@Override @Override
public Tristate hasPermission(String permission) { public Tristate hasPermission(String permission) {
Tristate t = getTypeDefaults(this.service).getPermissionValue(this.contexts, permission); Tristate t = getTypeDefaults().getPermissionValue(this.contexts, permission);
if (t != Tristate.UNDEFINED) { if (t != Tristate.UNDEFINED) {
return t; return t;
} }
t = this.service.getDefaults().getPermissionValue(this.contexts, permission); t = this.service.getRootDefaults().getPermissionValue(this.contexts, permission);
if (t != Tristate.UNDEFINED) { if (t != Tristate.UNDEFINED) {
return t; return t;
} }

View File

@ -38,7 +38,7 @@ public class FixedDefaultsProcessor extends DefaultsProcessor {
} }
@Override @Override
protected LPSubject getTypeDefaults(LPPermissionService service) { protected LPSubject getTypeDefaults() {
return this.defaultsSubject; return this.defaultsSubject;
} }
} }

View File

@ -36,7 +36,7 @@ public class GroupDefaultsProcessor extends DefaultsProcessor implements Permiss
} }
@Override @Override
protected LPSubject getTypeDefaults(LPPermissionService service) { protected LPSubject getTypeDefaults() {
return service.getGroupSubjects().getDefaults(); return this.service.getGroupSubjects().getDefaults();
} }
} }

View File

@ -36,7 +36,7 @@ public class UserDefaultsProcessor extends DefaultsProcessor implements Permissi
} }
@Override @Override
protected LPSubject getTypeDefaults(LPPermissionService service) { protected LPSubject getTypeDefaults() {
return service.getUserSubjects().getDefaults(); return this.service.getUserSubjects().getDefaults();
} }
} }

View File

@ -36,13 +36,17 @@ import me.lucko.luckperms.sponge.LPSpongePlugin;
import me.lucko.luckperms.sponge.contexts.SpongeProxiedContextCalculator; import me.lucko.luckperms.sponge.contexts.SpongeProxiedContextCalculator;
import me.lucko.luckperms.sponge.managers.SpongeGroupManager; import me.lucko.luckperms.sponge.managers.SpongeGroupManager;
import me.lucko.luckperms.sponge.managers.SpongeUserManager; import me.lucko.luckperms.sponge.managers.SpongeUserManager;
import me.lucko.luckperms.sponge.service.misc.SimplePermissionDescription;
import me.lucko.luckperms.sponge.service.model.LPPermissionDescription; import me.lucko.luckperms.sponge.service.model.LPPermissionDescription;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.persisted.DefaultsCollection;
import me.lucko.luckperms.sponge.service.persisted.PersistedCollection; import me.lucko.luckperms.sponge.service.persisted.PersistedCollection;
import me.lucko.luckperms.sponge.service.persisted.SubjectStorage;
import me.lucko.luckperms.sponge.service.proxy.ProxyFactory;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory; import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory;
import me.lucko.luckperms.sponge.service.storage.SubjectStorage;
import org.spongepowered.api.plugin.PluginContainer; import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.service.context.ContextCalculator; import org.spongepowered.api.service.context.ContextCalculator;
@ -63,17 +67,39 @@ import java.util.function.Predicate;
*/ */
public class LuckPermsService implements LPPermissionService { public class LuckPermsService implements LPPermissionService {
/**
* The plugin
*/
private final LPSpongePlugin plugin; private final LPSpongePlugin plugin;
/**
* A cached proxy of this instance
*/
private final PermissionService spongeProxy; private final PermissionService spongeProxy;
/**
* Reference factory, used to obtain {@link LPSubjectReference}s.
*/
private final SubjectReferenceFactory referenceFactory; private final SubjectReferenceFactory referenceFactory;
private final SubjectStorage storage;
private final SpongeUserManager userSubjects;
private final SpongeGroupManager groupSubjects;
private final PersistedCollection defaultSubjects;
private final Set<LPPermissionDescription> descriptionSet;
/**
* Subject storage, used to save PersistedSubjects to a file
*/
private final SubjectStorage storage;
/**
* The defaults subject collection
*/
private final DefaultsCollection defaultSubjects;
/**
* A set of registered permission description instances
*/
private final Set<LPPermissionDescription> permissionDescriptions;
/**
* The loaded collections in this service
*/
private final LoadingCache<String, LPSubjectCollection> collections = Caffeine.newBuilder() private final LoadingCache<String, LPSubjectCollection> collections = Caffeine.newBuilder()
.build(s -> new PersistedCollection(this, s)); .build(s -> new PersistedCollection(this, s));
@ -81,29 +107,33 @@ public class LuckPermsService implements LPPermissionService {
this.plugin = plugin; this.plugin = plugin;
this.referenceFactory = new SubjectReferenceFactory(this); this.referenceFactory = new SubjectReferenceFactory(this);
this.spongeProxy = ProxyFactory.toSponge(this); this.spongeProxy = ProxyFactory.toSponge(this);
this.permissionDescriptions = ConcurrentHashMap.newKeySet();
// init subject storage
this.storage = new SubjectStorage(this, new File(plugin.getBootstrap().getDataDirectory(), "sponge-data")); this.storage = new SubjectStorage(this, new File(plugin.getBootstrap().getDataDirectory(), "sponge-data"));
this.userSubjects = plugin.getUserManager(); // load defaults collection
this.groupSubjects = plugin.getGroupManager(); this.defaultSubjects = new DefaultsCollection(this);
this.defaultSubjects = new PersistedCollection(this, "defaults");
this.defaultSubjects.loadAll(); this.defaultSubjects.loadAll();
this.collections.put("user", this.userSubjects); // pre-populate collections map with the default types
this.collections.put("group", this.groupSubjects); this.collections.put("user", plugin.getUserManager());
this.collections.put("group", plugin.getGroupManager());
this.collections.put("defaults", this.defaultSubjects); this.collections.put("defaults", this.defaultSubjects);
for (String collection : this.storage.getSavedCollections()) { // load known collections
if (this.collections.asMap().containsKey(collection.toLowerCase())) { for (String identifier : this.storage.getSavedCollections()) {
if (this.collections.asMap().containsKey(identifier.toLowerCase())) {
continue; continue;
} }
PersistedCollection c = new PersistedCollection(this, collection.toLowerCase()); // load data
c.loadAll(); PersistedCollection collection = new PersistedCollection(this, identifier.toLowerCase());
this.collections.put(c.getIdentifier(), c); collection.loadAll();
}
this.descriptionSet = ConcurrentHashMap.newKeySet(); // cache in this instance
this.collections.put(collection.getIdentifier(), collection);
}
} }
@Override @Override
@ -132,22 +162,22 @@ public class LuckPermsService implements LPPermissionService {
@Override @Override
public SpongeUserManager getUserSubjects() { public SpongeUserManager getUserSubjects() {
return this.userSubjects; return this.plugin.getUserManager();
} }
@Override @Override
public SpongeGroupManager getGroupSubjects() { public SpongeGroupManager getGroupSubjects() {
return this.groupSubjects; return this.plugin.getGroupManager();
} }
@Override @Override
public PersistedCollection getDefaultSubjects() { public DefaultsCollection getDefaultSubjects() {
return this.defaultSubjects; return this.defaultSubjects;
} }
@Override @Override
public LPSubject getDefaults() { public LPSubject getRootDefaults() {
return getDefaultSubjects().loadSubject("default").join(); return this.defaultSubjects.getRootSubject();
} }
@Override @Override
@ -168,15 +198,15 @@ public class LuckPermsService implements LPPermissionService {
@Override @Override
public LPPermissionDescription registerPermissionDescription(String id, Text description, PluginContainer owner) { public LPPermissionDescription registerPermissionDescription(String id, Text description, PluginContainer owner) {
LuckPermsPermissionDescription desc = new LuckPermsPermissionDescription(this, id, description, owner); SimplePermissionDescription desc = new SimplePermissionDescription(this, id, description, owner);
this.descriptionSet.add(desc); this.permissionDescriptions.add(desc);
return desc; return desc;
} }
@Override @Override
public Optional<LPPermissionDescription> getDescription(String s) { public Optional<LPPermissionDescription> getDescription(String s) {
Objects.requireNonNull(s); Objects.requireNonNull(s);
for (LPPermissionDescription d : this.descriptionSet) { for (LPPermissionDescription d : this.permissionDescriptions) {
if (d.getId().equals(s)) { if (d.getId().equals(s)) {
return Optional.of(d); return Optional.of(d);
} }
@ -187,11 +217,11 @@ public class LuckPermsService implements LPPermissionService {
@Override @Override
public ImmutableSet<LPPermissionDescription> getDescriptions() { public ImmutableSet<LPPermissionDescription> getDescriptions() {
Set<LPPermissionDescription> descriptions = new HashSet<>(this.descriptionSet); Set<LPPermissionDescription> descriptions = new HashSet<>(this.permissionDescriptions);
// collect known values from the permission vault // collect known values from the permission vault
for (String knownPermission : this.plugin.getPermissionVault().getKnownPermissions()) { for (String knownPermission : this.plugin.getPermissionVault().getKnownPermissions()) {
LPPermissionDescription desc = new LuckPermsPermissionDescription(this, knownPermission, null, null); LPPermissionDescription desc = new SimplePermissionDescription(this, knownPermission, null, null);
// don't override plugin defined values // don't override plugin defined values
if (!descriptions.contains(desc)) { if (!descriptions.contains(desc)) {

View File

@ -1,71 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.sponge.service;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.sponge.service.internal.GroupSubject;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference;
import org.spongepowered.api.service.permission.PermissionService;
import java.util.Comparator;
public class SubjectComparator implements Comparator<LPSubjectReference> {
private static final Comparator<LPSubjectReference> INSTANCE = new SubjectComparator();
private static final Comparator<LPSubjectReference> REVERSE = INSTANCE.reversed();
public static Comparator<LPSubjectReference> normal() {
return INSTANCE;
}
public static Comparator<LPSubjectReference> reverse() {
return REVERSE;
}
@Override
public int compare(LPSubjectReference o1, LPSubjectReference o2) {
if (o1.equals(o2)) {
return 0;
}
boolean o1isGroup = o1.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP);
boolean o2isGroup = o2.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP);
if (o1isGroup != o2isGroup) {
return o1isGroup ? 1 : -1;
}
// Neither are groups
if (!o1isGroup) {
return 1;
}
Group g1 = ((GroupSubject) o1.resolveLp().join()).getParent();
Group g2 = ((GroupSubject) o2.resolveLp().join()).getParent();
return Integer.compare(g1.getWeight().orElse(0), g2.getWeight().orElse(0)) == 1 ? 1 : -1;
}
}

View File

@ -29,29 +29,16 @@ import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.caching.MetaContexts;
import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.common.caching.AbstractCachedData;
import me.lucko.luckperms.common.caching.type.MetaAccumulator; import me.lucko.luckperms.common.caching.type.MetaAccumulator;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.calculators.PermissionCalculator;
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
import me.lucko.luckperms.common.graph.TraversalAlgorithm; import me.lucko.luckperms.common.graph.TraversalAlgorithm;
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
import me.lucko.luckperms.common.metastacking.StandardStackElements;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.processors.MapProcessor;
import me.lucko.luckperms.common.processors.PermissionProcessor;
import me.lucko.luckperms.common.processors.WildcardProcessor;
import me.lucko.luckperms.common.verbose.CheckOrigin; import me.lucko.luckperms.common.verbose.CheckOrigin;
import me.lucko.luckperms.sponge.processors.FixedDefaultsProcessor; import me.lucko.luckperms.sponge.LPSpongePlugin;
import me.lucko.luckperms.sponge.processors.SpongeWildcardProcessor;
import me.lucko.luckperms.sponge.service.inheritance.SubjectInheritanceGraph; import me.lucko.luckperms.sponge.service.inheritance.SubjectInheritanceGraph;
import me.lucko.luckperms.sponge.service.inheritance.SubjectInheritanceGraphs; import me.lucko.luckperms.sponge.service.inheritance.SubjectInheritanceGraphs;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -60,17 +47,17 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
public abstract class CalculatedSubject implements LPSubject { public abstract class CalculatedSubject implements LPSubject {
private static final MetaStackDefinition DEFAULT_META_STACK = new SimpleMetaStackDefinition( private final LPSpongePlugin plugin;
ImmutableList.of(StandardStackElements.HIGHEST_PRIORITY),
"", "", ""
);
private final LuckPermsPlugin plugin;
private final SubjectCachedData cachedData; private final SubjectCachedData cachedData;
protected CalculatedSubject(LuckPermsPlugin plugin) { protected CalculatedSubject(LPSpongePlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
this.cachedData = new SubjectCachedData(plugin); this.cachedData = new SubjectCachedData(this, plugin);
}
@Override
public LPSubject getDefaults() {
return this.plugin.getService().getDefaultSubjects().getTypeDefaults(getParentCollection().getIdentifier());
} }
public abstract CalculatedSubjectData getSubjectData(); public abstract CalculatedSubjectData getSubjectData();
@ -353,58 +340,4 @@ public abstract class CalculatedSubject implements LPSubject {
this.cachedData.invalidateCaches(); this.cachedData.invalidateCaches();
} }
private final class SubjectCachedData extends AbstractCachedData implements CalculatorFactory {
private SubjectCachedData(LuckPermsPlugin plugin) {
super(plugin);
}
@Override
protected PermissionCalculatorMetadata getMetadataForContexts(Contexts contexts) {
return PermissionCalculatorMetadata.of(null, getParentCollection().getIdentifier() + "/" + getIdentifier(), contexts.getContexts());
}
@Override
protected CalculatorFactory getCalculatorFactory() {
return this;
}
@Override
protected MetaContexts getDefaultMetaContexts(Contexts contexts) {
return MetaContexts.of(contexts, DEFAULT_META_STACK, DEFAULT_META_STACK);
}
@Override
protected Map<String, Boolean> resolvePermissions() {
return resolveAllPermissions();
}
@Override
protected Map<String, Boolean> resolvePermissions(Contexts contexts) {
return resolveAllPermissions(contexts.getContexts().makeImmutable());
}
@Override
protected void resolveMeta(MetaAccumulator accumulator) {
resolveAllOptions(accumulator);
}
@Override
protected void resolveMeta(MetaAccumulator accumulator, MetaContexts contexts) {
resolveAllOptions(accumulator, contexts.getContexts().getContexts().makeImmutable());
}
@Override
public PermissionCalculator build(Contexts contexts, PermissionCalculatorMetadata metadata) {
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
processors.add(new MapProcessor());
processors.add(new SpongeWildcardProcessor());
processors.add(new WildcardProcessor());
if (!getParentCollection().isDefaultsCollection()) {
processors.add(new FixedDefaultsProcessor(getService(), contexts.getContexts().makeImmutable(), getDefaults()));
}
return new PermissionCalculator(this.plugin, metadata, processors.build());
}
}
} }

View File

@ -33,12 +33,11 @@ import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.common.contexts.ContextSetComparator; import me.lucko.luckperms.common.contexts.ContextSetComparator;
import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.sponge.service.ProxyFactory;
import me.lucko.luckperms.sponge.service.SubjectComparator;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.model.LPSubjectData;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.proxy.ProxyFactory;
import org.spongepowered.api.service.permission.SubjectData; import org.spongepowered.api.service.permission.SubjectData;
@ -207,7 +206,7 @@ public class CalculatedSubjectData implements LPSubjectData {
public ImmutableMap<ImmutableContextSet, ImmutableList<LPSubjectReference>> getAllParents() { public ImmutableMap<ImmutableContextSet, ImmutableList<LPSubjectReference>> getAllParents() {
ImmutableMap.Builder<ImmutableContextSet, ImmutableList<LPSubjectReference>> map = ImmutableMap.builder(); ImmutableMap.Builder<ImmutableContextSet, ImmutableList<LPSubjectReference>> map = ImmutableMap.builder();
for (Map.Entry<ImmutableContextSet, Set<LPSubjectReference>> e : this.parents.entrySet()) { for (Map.Entry<ImmutableContextSet, Set<LPSubjectReference>> e : this.parents.entrySet()) {
map.put(e.getKey(), ImmutableList.sortedCopyOf(SubjectComparator.reverse(), e.getValue())); map.put(e.getKey(), ImmutableList.copyOf(e.getValue()));
} }
return map.build(); return map.build();
} }

View File

@ -30,78 +30,77 @@ import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
/** /**
* Extension of CalculatedSubjectData which allows subclasses to respond to updates * Extension of CalculatedSubjectData which allows subclasses to respond to updates
*/ */
public abstract class MonitoredSubjectData extends CalculatedSubjectData { public abstract class MonitoredSubjectData extends CalculatedSubjectData {
private final Function<Boolean, Boolean> saveFunction = b -> {
onUpdate(b);
return b;
};
public MonitoredSubjectData(LPSubject subject, NodeMapType type, LuckPermsService service) { public MonitoredSubjectData(LPSubject subject, NodeMapType type, LuckPermsService service) {
super(subject, type, service); super(subject, type, service);
} }
private boolean callUpdate(boolean success) {
onUpdate(success);
return success;
}
protected abstract void onUpdate(boolean success); protected abstract void onUpdate(boolean success);
@Override @Override
public CompletableFuture<Boolean> setPermission(ImmutableContextSet contexts, String permission, Tristate value) { public CompletableFuture<Boolean> setPermission(ImmutableContextSet contexts, String permission, Tristate value) {
return super.setPermission(contexts, permission, value).thenApply(this.saveFunction); return super.setPermission(contexts, permission, value).thenApply(this::callUpdate);
} }
@Override @Override
public CompletableFuture<Boolean> clearPermissions() { public CompletableFuture<Boolean> clearPermissions() {
return super.clearPermissions().thenApply(this.saveFunction); return super.clearPermissions().thenApply(this::callUpdate);
} }
@Override @Override
public CompletableFuture<Boolean> clearPermissions(ImmutableContextSet contexts) { public CompletableFuture<Boolean> clearPermissions(ImmutableContextSet contexts) {
return super.clearPermissions(contexts).thenApply(this.saveFunction); return super.clearPermissions(contexts).thenApply(this::callUpdate);
} }
@Override @Override
public CompletableFuture<Boolean> addParent(ImmutableContextSet contexts, LPSubjectReference parent) { public CompletableFuture<Boolean> addParent(ImmutableContextSet contexts, LPSubjectReference parent) {
return super.addParent(contexts, parent).thenApply(this.saveFunction); return super.addParent(contexts, parent).thenApply(this::callUpdate);
} }
@Override @Override
public CompletableFuture<Boolean> removeParent(ImmutableContextSet contexts, LPSubjectReference parent) { public CompletableFuture<Boolean> removeParent(ImmutableContextSet contexts, LPSubjectReference parent) {
return super.removeParent(contexts, parent).thenApply(this.saveFunction); return super.removeParent(contexts, parent).thenApply(this::callUpdate);
} }
@Override @Override
public CompletableFuture<Boolean> clearParents() { public CompletableFuture<Boolean> clearParents() {
return super.clearParents().thenApply(this.saveFunction); return super.clearParents().thenApply(this::callUpdate);
} }
@Override @Override
public CompletableFuture<Boolean> clearParents(ImmutableContextSet contexts) { public CompletableFuture<Boolean> clearParents(ImmutableContextSet contexts) {
return super.clearParents(contexts).thenApply(this.saveFunction); return super.clearParents(contexts).thenApply(this::callUpdate);
} }
@Override @Override
public CompletableFuture<Boolean> setOption(ImmutableContextSet contexts, String key, String value) { public CompletableFuture<Boolean> setOption(ImmutableContextSet contexts, String key, String value) {
return super.setOption(contexts, key, value).thenApply(this.saveFunction); return super.setOption(contexts, key, value).thenApply(this::callUpdate);
} }
@Override @Override
public CompletableFuture<Boolean> unsetOption(ImmutableContextSet contexts, String key) { public CompletableFuture<Boolean> unsetOption(ImmutableContextSet contexts, String key) {
return super.unsetOption(contexts, key).thenApply(this.saveFunction); return super.unsetOption(contexts, key).thenApply(this::callUpdate);
} }
@Override @Override
public CompletableFuture<Boolean> clearOptions() { public CompletableFuture<Boolean> clearOptions() {
return super.clearOptions().thenApply(this.saveFunction); return super.clearOptions().thenApply(this::callUpdate);
} }
@Override @Override
public CompletableFuture<Boolean> clearOptions(ImmutableContextSet contexts) { public CompletableFuture<Boolean> clearOptions(ImmutableContextSet contexts) {
return super.clearOptions(contexts).thenApply(this.saveFunction); return super.clearOptions(contexts).thenApply(this::callUpdate);
} }
} }

View File

@ -0,0 +1,110 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.sponge.service.calculated;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.caching.MetaContexts;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.common.caching.AbstractCachedData;
import me.lucko.luckperms.common.caching.type.MetaAccumulator;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.calculators.PermissionCalculator;
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
import me.lucko.luckperms.common.metastacking.StandardStackElements;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.processors.MapProcessor;
import me.lucko.luckperms.common.processors.PermissionProcessor;
import me.lucko.luckperms.common.processors.WildcardProcessor;
import me.lucko.luckperms.sponge.processors.FixedDefaultsProcessor;
import me.lucko.luckperms.sponge.processors.SpongeWildcardProcessor;
import java.util.Map;
public class SubjectCachedData extends AbstractCachedData implements CalculatorFactory {
private static final MetaStackDefinition DEFAULT_META_STACK = new SimpleMetaStackDefinition(
ImmutableList.of(StandardStackElements.HIGHEST_PRIORITY),
"", "", ""
);
private final CalculatedSubject subject;
SubjectCachedData(CalculatedSubject subject, LuckPermsPlugin plugin) {
super(plugin);
this.subject = subject;
}
@Override
protected PermissionCalculatorMetadata getMetadataForContexts(Contexts contexts) {
return PermissionCalculatorMetadata.of(null, this.subject.getParentCollection().getIdentifier() + "/" + this.subject.getIdentifier(), contexts.getContexts());
}
@Override
protected CalculatorFactory getCalculatorFactory() {
return this;
}
@Override
protected MetaContexts getDefaultMetaContexts(Contexts contexts) {
return MetaContexts.of(contexts, DEFAULT_META_STACK, DEFAULT_META_STACK);
}
@Override
protected Map<String, Boolean> resolvePermissions() {
return this.subject.resolveAllPermissions();
}
@Override
protected Map<String, Boolean> resolvePermissions(Contexts contexts) {
return this.subject.resolveAllPermissions(contexts.getContexts().makeImmutable());
}
@Override
protected void resolveMeta(MetaAccumulator accumulator) {
this.subject.resolveAllOptions(accumulator);
}
@Override
protected void resolveMeta(MetaAccumulator accumulator, MetaContexts contexts) {
this.subject.resolveAllOptions(accumulator, contexts.getContexts().getContexts().makeImmutable());
}
@Override
public PermissionCalculator build(Contexts contexts, PermissionCalculatorMetadata metadata) {
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
processors.add(new MapProcessor());
processors.add(new SpongeWildcardProcessor());
processors.add(new WildcardProcessor());
if (!this.subject.getParentCollection().isDefaultsCollection()) {
processors.add(new FixedDefaultsProcessor(this.subject.getService(), contexts.getContexts().makeImmutable(), this.subject.getDefaults()));
}
return new PermissionCalculator(this.plugin, metadata, processors.build());
}
}

View File

@ -27,26 +27,27 @@ package me.lucko.luckperms.sponge.service.internal;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.caching.MetaData; import me.lucko.luckperms.api.caching.MetaData;
import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.common.graph.TraversalAlgorithm;
import me.lucko.luckperms.common.inheritance.InheritanceGraph;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.common.model.PermissionHolder; import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.node.NodeFactory; import me.lucko.luckperms.common.node.NodeFactory;
import me.lucko.luckperms.common.verbose.CheckOrigin; import me.lucko.luckperms.common.verbose.CheckOrigin;
import me.lucko.luckperms.sponge.LPSpongePlugin; 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.LuckPermsService;
import me.lucko.luckperms.sponge.service.ProxyFactory;
import me.lucko.luckperms.sponge.service.SubjectComparator;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.proxy.ProxyFactory;
import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.Subject;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
/** /**
@ -86,6 +87,11 @@ public abstract class HolderSubject<T extends PermissionHolder> implements LPSub
return this.plugin.getService(); return this.plugin.getService();
} }
@Override
public LPSubject getDefaults() {
return this.plugin.getService().getDefaultSubjects().getTypeDefaults(getParentCollection().getIdentifier());
}
@Override @Override
public HolderSubjectData getSubjectData() { public HolderSubjectData getSubjectData() {
return this.subjectData; return this.subjectData;
@ -98,38 +104,30 @@ public abstract class HolderSubject<T extends PermissionHolder> implements LPSub
@Override @Override
public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) { public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) {
return this.parent.getCachedData().getPermissionData(this.plugin.getContextManager().formContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK); Contexts lookupContexts = this.plugin.getContextManager().formContexts(contexts);
return this.parent.getCachedData().getPermissionData(lookupContexts).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK);
} }
@Override @Override
public boolean isChildOf(ImmutableContextSet contexts, LPSubjectReference parent) { public boolean isChildOf(ImmutableContextSet contexts, LPSubjectReference parent) {
return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, NodeFactory.groupNode(parent.getSubjectIdentifier())).asBoolean(); return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) &&
getPermissionValue(contexts, NodeFactory.groupNode(parent.getSubjectIdentifier())).asBoolean();
} }
@Override @Override
public ImmutableList<LPSubjectReference> getParents(ImmutableContextSet contexts) { public ImmutableList<LPSubjectReference> getParents(ImmutableContextSet contexts) {
List<LPSubjectReference> subjects = new ArrayList<>(); InheritanceGraph graph = this.plugin.getInheritanceHandler().getGraph(this.plugin.getContextManager().formContexts(contexts));
Iterable<PermissionHolder> traversal = graph.traverse(TraversalAlgorithm.DEPTH_FIRST_PRE_ORDER, this.parent);
for (Map.Entry<String, Boolean> entry : this.parent.getCachedData().getPermissionData(this.plugin.getContextManager().formContexts(contexts)).getImmutableBacking().entrySet()) { ImmutableList.Builder<LPSubjectReference> subjects = ImmutableList.builder();
if (!entry.getValue()) { for (PermissionHolder parent : traversal) {
if (!(parent instanceof Group)) {
continue; continue;
} }
String groupName = NodeFactory.parseGroupNode(entry.getKey()); subjects.add(((SpongeGroup) parent).sponge().toReference());
if (groupName == null) {
continue;
}
if (this.plugin.getGroupManager().isLoaded(groupName)) {
subjects.add(this.plugin.getService().getGroupSubjects().loadSubject(groupName).join().toReference());
}
} }
return subjects.build();
subjects.addAll(getParentCollection().getDefaults().getParents(contexts));
subjects.addAll(this.plugin.getService().getDefaults().getParents(contexts));
subjects.sort(SubjectComparator.reverse());
return ImmutableList.copyOf(subjects);
} }
@Override @Override
@ -157,7 +155,7 @@ public abstract class HolderSubject<T extends PermissionHolder> implements LPSub
return v; return v;
} }
return this.plugin.getService().getDefaults().getOption(contexts, s); return this.plugin.getService().getRootDefaults().getOption(contexts, s);
} }
@Override @Override

View File

@ -40,10 +40,10 @@ import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.NodeFactory; import me.lucko.luckperms.common.node.NodeFactory;
import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.service.ProxyFactory;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.model.LPSubjectData;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.proxy.ProxyFactory;
import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.SubjectData; import org.spongepowered.api.service.permission.SubjectData;

View File

@ -23,13 +23,14 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.sponge.service; package me.lucko.luckperms.sponge.service.misc;
import me.lucko.luckperms.sponge.service.model.LPPermissionDescription; import me.lucko.luckperms.sponge.service.model.LPPermissionDescription;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.proxy.ProxyFactory;
import org.spongepowered.api.plugin.PluginContainer; import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.service.permission.PermissionDescription; import org.spongepowered.api.service.permission.PermissionDescription;
@ -42,7 +43,7 @@ import java.util.concurrent.CompletableFuture;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public final class LuckPermsPermissionDescription implements LPPermissionDescription { public final class SimplePermissionDescription implements LPPermissionDescription {
private final LPPermissionService service; private final LPPermissionService service;
private final String id; private final String id;
@ -51,7 +52,7 @@ public final class LuckPermsPermissionDescription implements LPPermissionDescrip
private PermissionDescription spongeProxy = null; private PermissionDescription spongeProxy = null;
public LuckPermsPermissionDescription(LPPermissionService service, String id, @Nullable Text description, @Nullable PluginContainer owner) { public SimplePermissionDescription(LPPermissionService service, String id, @Nullable Text description, @Nullable PluginContainer owner) {
this.service = service; this.service = service;
this.id = Objects.requireNonNull(id, "id"); this.id = Objects.requireNonNull(id, "id");
this.description = description; this.description = description;
@ -102,8 +103,8 @@ public final class LuckPermsPermissionDescription implements LPPermissionDescrip
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (!(o instanceof LuckPermsPermissionDescription)) return false; if (!(o instanceof SimplePermissionDescription)) return false;
final LuckPermsPermissionDescription other = (LuckPermsPermissionDescription) o; final SimplePermissionDescription other = (SimplePermissionDescription) o;
return this.id.equals(other.id); return this.id.equals(other.id);
} }
@ -114,7 +115,7 @@ public final class LuckPermsPermissionDescription implements LPPermissionDescrip
@Override @Override
public String toString() { public String toString() {
return "LuckPermsPermissionDescription(" + return "PermissionDescription(" +
"id=" + this.id + ", " + "id=" + this.id + ", " +
"description=" + this.description + ", " + "description=" + this.description + ", " +
"owner=" + this.owner + ")"; "owner=" + this.owner + ")";

View File

@ -23,16 +23,25 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.sponge.service.model; package me.lucko.luckperms.sponge.service.persisted;
import me.lucko.luckperms.common.contexts.ContextManager; import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.sponge.service.model.LPSubject;
import org.spongepowered.api.service.permission.Subject; /**
* Subject collection used for storing default subjects
*/
public class DefaultsCollection extends PersistedCollection {
public DefaultsCollection(LuckPermsService service) {
super(service, "defaults");
}
public interface LuckPermsSpongePlugin extends LuckPermsPlugin { public LPSubject getRootSubject() {
return obtainSubject("default");
}
@Override public LPSubject getTypeDefaults(String collectionIdentifier) {
ContextManager<Subject> getContextManager(); return obtainSubject(collectionIdentifier);
}
} }

View File

@ -37,11 +37,10 @@ import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.service.ProxyFactory;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection; import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel; import me.lucko.luckperms.sponge.service.proxy.ProxyFactory;
import org.spongepowered.api.service.permission.SubjectCollection; import org.spongepowered.api.service.permission.SubjectCollection;
@ -57,24 +56,38 @@ import java.util.function.Predicate;
*/ */
public class PersistedCollection implements LPSubjectCollection { public class PersistedCollection implements LPSubjectCollection {
private final LuckPermsService service; private final LuckPermsService service;
private final String identifier;
private final boolean defaultsCollection;
/**
* The collection identifier
*/
private final String identifier;
/**
* If the collection is the defaults collection
*/
private final boolean isDefaultsCollection;
/**
* Cached sponge proxy instance
*/
private final SubjectCollection spongeProxy; private final SubjectCollection spongeProxy;
/**
* The contained subjects
*/
private final LoadingCache<String, PersistedSubject> subjects = Caffeine.newBuilder() private final LoadingCache<String, PersistedSubject> subjects = Caffeine.newBuilder()
.build(s -> new PersistedSubject(s, getService(), this)); .build(s -> new PersistedSubject(getService(), this, s));
public PersistedCollection(LuckPermsService service, String identifier) { public PersistedCollection(LuckPermsService service, String identifier) {
this.service = service; this.service = service;
this.identifier = identifier; this.identifier = identifier;
this.defaultsCollection = identifier.equals("defaults"); this.isDefaultsCollection = identifier.equals("defaults");
this.spongeProxy = ProxyFactory.toSponge(this); this.spongeProxy = ProxyFactory.toSponge(this);
} }
public void loadAll() { public void loadAll() {
Map<String, SubjectStorageModel> holders = this.service.getStorage().loadAllFromFile(this.identifier); Map<String, SubjectDataContainer> holders = this.service.getStorage().loadAllFromFile(this.identifier);
for (Map.Entry<String, SubjectStorageModel> e : holders.entrySet()) { for (Map.Entry<String, SubjectDataContainer> e : holders.entrySet()) {
PersistedSubject subject = this.subjects.get(e.getKey().toLowerCase()); PersistedSubject subject = this.subjects.get(e.getKey().toLowerCase());
if (subject != null) { if (subject != null) {
subject.loadData(e.getValue()); subject.loadData(e.getValue());
@ -104,17 +117,23 @@ public class PersistedCollection implements LPSubjectCollection {
@Override @Override
public boolean isDefaultsCollection() { public boolean isDefaultsCollection() {
return this.defaultsCollection; return this.isDefaultsCollection;
}
public LPSubject obtainSubject(String identifier) {
return this.subjects.get(identifier.toLowerCase());
} }
@Override @Override
@Deprecated // not necessary to wrap with a completablefuture
public CompletableFuture<LPSubject> loadSubject(String identifier) { public CompletableFuture<LPSubject> loadSubject(String identifier) {
return CompletableFuture.completedFuture(this.subjects.get(identifier.toLowerCase())); return CompletableFuture.completedFuture(obtainSubject(identifier));
} }
@Override @Override
@Deprecated // not necessary to wrap with an optional
public Optional<LPSubject> getSubject(String identifier) { public Optional<LPSubject> getSubject(String identifier) {
return Optional.of(Objects.requireNonNull(this.subjects.get(identifier.toLowerCase()))); return Optional.of(Objects.requireNonNull(obtainSubject(identifier)));
} }
@Override @Override
@ -181,7 +200,7 @@ public class PersistedCollection implements LPSubjectCollection {
@Override @Override
public LPSubject getDefaults() { public LPSubject getDefaults() {
return this.service.getDefaultSubjects().loadSubject(getIdentifier()).join(); return this.service.getDefaultSubjects().getTypeDefaults(getIdentifier());
} }
} }

View File

@ -27,14 +27,14 @@ package me.lucko.luckperms.sponge.service.persisted;
import me.lucko.luckperms.common.buffers.BufferedRequest; import me.lucko.luckperms.common.buffers.BufferedRequest;
import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.LuckPermsService;
import me.lucko.luckperms.sponge.service.ProxyFactory;
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubject; import me.lucko.luckperms.sponge.service.calculated.CalculatedSubject;
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData; import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
import me.lucko.luckperms.sponge.service.calculated.MonitoredSubjectData; import me.lucko.luckperms.sponge.service.calculated.MonitoredSubjectData;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.model.LPSubjectData;
import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel; import me.lucko.luckperms.sponge.service.proxy.ProxyFactory;
import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.permission.Subject; import org.spongepowered.api.service.permission.Subject;
@ -46,31 +46,33 @@ import java.util.Optional;
* A simple persistable Subject implementation * A simple persistable Subject implementation
*/ */
public class PersistedSubject extends CalculatedSubject implements LPSubject { public class PersistedSubject extends CalculatedSubject implements LPSubject {
private final LuckPermsService service;
/**
* The subjects identifier
*/
private final String identifier; private final String identifier;
private final LuckPermsService service; /**
* The parent collection
*/
private final PersistedCollection parentCollection; private final PersistedCollection parentCollection;
// subject data instances
private final PersistedSubjectData subjectData; private final PersistedSubjectData subjectData;
private final CalculatedSubjectData transientSubjectData; private final CalculatedSubjectData transientSubjectData;
private final BufferedRequest<Void> saveBuffer = new BufferedRequest<Void>(1000L, 500L, r -> PersistedSubject.this.service.getPlugin().getBootstrap().getScheduler().doAsync(r)) { /**
@Override * The save buffer instance for saving changes to disk
protected Void perform() { */
try { private final SaveBuffer saveBuffer;
PersistedSubject.this.service.getStorage().saveToFile(PersistedSubject.this);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
public PersistedSubject(String identifier, LuckPermsService service, PersistedCollection parentCollection) { public PersistedSubject(LuckPermsService service, PersistedCollection parentCollection, String identifier) {
super(service.getPlugin()); super(service.getPlugin());
this.identifier = identifier;
this.service = service; this.service = service;
this.parentCollection = parentCollection; this.parentCollection = parentCollection;
this.identifier = identifier;
this.subjectData = new PersistedSubjectData(this, NodeMapType.ENDURING, service) { this.subjectData = new PersistedSubjectData(this, NodeMapType.ENDURING, service) {
@Override @Override
protected void onUpdate(boolean success) { protected void onUpdate(boolean success) {
@ -88,18 +90,34 @@ public class PersistedSubject extends CalculatedSubject implements LPSubject {
} }
} }
}; };
this.saveBuffer = new SaveBuffer(service.getPlugin());
} }
/**
* Calls the subject data update event for the given {@link LPSubjectData} instance.
*
* @param subjectData the subject data
*/
private void fireUpdateEvent(LPSubjectData subjectData) { private void fireUpdateEvent(LPSubjectData subjectData) {
this.service.getPlugin().getUpdateEventHandler().fireUpdateEvent(subjectData); this.service.getPlugin().getUpdateEventHandler().fireUpdateEvent(subjectData);
} }
public void loadData(SubjectStorageModel dataHolder) { /**
* Loads data into this {@link PersistedSubject} from the given
* {@link SubjectDataContainer} container
*
* @param container the container to load from
*/
public void loadData(SubjectDataContainer container) {
this.subjectData.setSave(false); this.subjectData.setSave(false);
dataHolder.applyToData(this.subjectData); container.applyToData(this.subjectData);
this.subjectData.setSave(true); this.subjectData.setSave(true);
} }
/**
* Requests that this subjects data is saved to disk
*/
public void save() { public void save() {
this.saveBuffer.request(); this.saveBuffer.request();
} }
@ -138,4 +156,20 @@ public class PersistedSubject extends CalculatedSubject implements LPSubject {
public Optional<CommandSource> getCommandSource() { public Optional<CommandSource> getCommandSource() {
return Optional.empty(); return Optional.empty();
} }
private final class SaveBuffer extends BufferedRequest<Void> {
public SaveBuffer(LuckPermsPlugin plugin) {
super(1000L, 500L, plugin.getBootstrap().getScheduler().async());
}
@Override
protected Void perform() {
try {
PersistedSubject.this.service.getStorage().saveToFile(PersistedSubject.this);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
} }

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.sponge.service.storage; package me.lucko.luckperms.sponge.service.persisted;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -38,25 +38,44 @@ import me.lucko.luckperms.common.contexts.ContextSetJsonSerializer;
import me.lucko.luckperms.common.utils.CollationKeyCache; import me.lucko.luckperms.common.utils.CollationKeyCache;
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData; import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.reference.LPSubjectReference; import me.lucko.luckperms.sponge.service.model.LPSubjectData;
import me.lucko.luckperms.sponge.service.reference.SubjectReferenceFactory; import me.lucko.luckperms.sponge.service.model.LPSubjectReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* Used for converting a SubjectData instance to and from JSON * Immutable container for a subjects persisted data
*/ */
public class SubjectStorageModel { public class SubjectDataContainer {
private final LPPermissionService service;
/**
* Creates a {@link SubjectDataContainer} container for the given {@link LPSubjectData}.
*
* @param subjectData the subject data to copy from
* @return a new container
*/
public static SubjectDataContainer copyOf(LPSubjectData subjectData) {
return new SubjectDataContainer(subjectData.getAllPermissions(), subjectData.getAllOptions(), subjectData.getAllParents());
}
/**
* Deserializes a {@link SubjectDataContainer} container from a json object
*
* @param service the permission service
* @param root the root json object
* @return a container representing the json data
*/
public static SubjectDataContainer derserialize(LPPermissionService service, JsonObject root) {
return new SubjectDataContainer(service, root);
}
private final Map<ImmutableContextSet, Map<String, Boolean>> permissions; private final Map<ImmutableContextSet, Map<String, Boolean>> permissions;
private final Map<ImmutableContextSet, Map<String, String>> options; private final Map<ImmutableContextSet, Map<String, String>> options;
private final Map<ImmutableContextSet, List<LPSubjectReference>> parents; private final Map<ImmutableContextSet, List<LPSubjectReference>> parents;
public SubjectStorageModel(LPPermissionService service, Map<ImmutableContextSet, ? extends Map<String, Boolean>> permissions, Map<ImmutableContextSet, ? extends Map<String, String>> options, Map<ImmutableContextSet, ? extends List<LPSubjectReference>> parents) { private SubjectDataContainer(Map<ImmutableContextSet, ? extends Map<String, Boolean>> permissions, Map<ImmutableContextSet, ? extends Map<String, String>> options, Map<ImmutableContextSet, ? extends List<LPSubjectReference>> parents) {
this.service = service;
ImmutableMap.Builder<ImmutableContextSet, Map<String, Boolean>> permissionsBuilder = ImmutableMap.builder(); ImmutableMap.Builder<ImmutableContextSet, Map<String, Boolean>> permissionsBuilder = ImmutableMap.builder();
for (Map.Entry<ImmutableContextSet, ? extends Map<String, Boolean>> e : permissions.entrySet()) { for (Map.Entry<ImmutableContextSet, ? extends Map<String, Boolean>> e : permissions.entrySet()) {
permissionsBuilder.put(e.getKey(), ImmutableMap.copyOf(e.getValue())); permissionsBuilder.put(e.getKey(), ImmutableMap.copyOf(e.getValue()));
@ -76,13 +95,7 @@ public class SubjectStorageModel {
this.parents = parentsBuilder.build(); this.parents = parentsBuilder.build();
} }
public SubjectStorageModel(CalculatedSubjectData data) { private SubjectDataContainer(LPPermissionService service, JsonObject root) {
this(data.getParentSubject().getService(), data.getAllPermissions(), data.getAllOptions(), data.getAllParents());
}
public SubjectStorageModel(LPPermissionService service, JsonObject root) {
this.service = service;
Preconditions.checkArgument(root.get("permissions").isJsonArray()); Preconditions.checkArgument(root.get("permissions").isJsonArray());
Preconditions.checkArgument(root.get("options").isJsonArray()); Preconditions.checkArgument(root.get("options").isJsonArray());
Preconditions.checkArgument(root.get("parents").isJsonArray()); Preconditions.checkArgument(root.get("parents").isJsonArray());
@ -162,7 +175,7 @@ public class SubjectStorageModel {
String collection = parent.get("collection").getAsString(); String collection = parent.get("collection").getAsString();
String subject = parent.get("subject").getAsString(); String subject = parent.get("subject").getAsString();
pars.add(SubjectReferenceFactory.obtain(service, collection, subject)); pars.add(service.getReferenceFactory().obtain(collection, subject));
} }
parentsBuilder.put(contextSet, pars.build()); parentsBuilder.put(contextSet, pars.build());
@ -170,13 +183,12 @@ public class SubjectStorageModel {
this.parents = parentsBuilder.build(); this.parents = parentsBuilder.build();
} }
private static <T> List<Map.Entry<ImmutableContextSet, T>> sortContextMap(Map<ImmutableContextSet, T> map) { /**
List<Map.Entry<ImmutableContextSet, T>> entries = new ArrayList<>(map.entrySet()); * Converts this container to json
entries.sort((o1, o2) -> ContextSetComparator.reverse().compare(o1.getKey(), o2.getKey())); *
return entries; * @return a json serialisation of the data in this container
} */
public JsonObject serialize() {
public JsonObject toJson() {
JsonObject root = new JsonObject(); JsonObject root = new JsonObject();
JsonArray permissions = new JsonArray(); JsonArray permissions = new JsonArray();
@ -252,14 +264,22 @@ public class SubjectStorageModel {
return root; return root;
} }
/**
* Applies the data encapsulated by this container to the given
* {@link CalculatedSubjectData}.
*
* @param subjectData the data to apply to
*/
public void applyToData(CalculatedSubjectData subjectData) { public void applyToData(CalculatedSubjectData subjectData) {
subjectData.replacePermissions(this.permissions); subjectData.replacePermissions(this.permissions);
subjectData.replaceOptions(this.options); subjectData.replaceOptions(this.options);
subjectData.replaceParents(this.parents); subjectData.replaceParents(this.parents);
} }
public LPPermissionService getService() { private static <T> List<Map.Entry<ImmutableContextSet, T>> sortContextMap(Map<ImmutableContextSet, T> map) {
return this.service; List<Map.Entry<ImmutableContextSet, T>> entries = new ArrayList<>(map.entrySet());
entries.sort((o1, o2) -> ContextSetComparator.reverse().compare(o1.getKey(), o2.getKey()));
return entries;
} }
} }

View File

@ -23,16 +23,14 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.sponge.service.storage; package me.lucko.luckperms.sponge.service.persisted;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import me.lucko.luckperms.sponge.service.model.LPPermissionService; import me.lucko.luckperms.sponge.service.model.LPPermissionService;
import me.lucko.luckperms.sponge.service.persisted.PersistedSubject;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -50,8 +48,20 @@ import java.util.stream.Collectors;
* Handles persisted Subject I/O and (de)serialization * Handles persisted Subject I/O and (de)serialization
*/ */
public class SubjectStorage { public class SubjectStorage {
/**
* The permission service
*/
private final LPPermissionService service; private final LPPermissionService service;
/**
* Gson instance
*/
private final Gson gson; private final Gson gson;
/**
* The root directory used to store files
*/
private final File container; private final File container;
public SubjectStorage(LPPermissionService service, File container) { public SubjectStorage(LPPermissionService service, File container) {
@ -65,6 +75,11 @@ public class SubjectStorage {
this.container.getParentFile().mkdirs(); this.container.getParentFile().mkdirs();
} }
/**
* Returns a set of all known collections
*
* @return the identifiers of all known collections
*/
public Set<String> getSavedCollections() { public Set<String> getSavedCollections() {
checkContainer(); checkContainer();
@ -76,22 +91,42 @@ public class SubjectStorage {
return ImmutableSet.copyOf(dirs).stream().map(File::getName).collect(Collectors.toSet()); return ImmutableSet.copyOf(dirs).stream().map(File::getName).collect(Collectors.toSet());
} }
public File resolveFile(String collectionName, String subjectName) { /**
* Returns the file where a subjects data should be stored
*
* @param collectionIdentifier the identifier of the subjects collection
* @param subjectIdentifier the identifier of the subject
* @return a file
*/
private File resolveFile(String collectionIdentifier, String subjectIdentifier) {
checkContainer(); checkContainer();
File collection = new File(this.container, collectionName); File collection = new File(this.container, collectionIdentifier);
if (!collection.exists()) { if (!collection.exists()) {
collection.mkdirs(); collection.mkdirs();
} }
return new File(collection, subjectName + ".json"); return new File(collection, subjectIdentifier + ".json");
} }
/**
* Saves a subject
*
* @param subject the subject to save
* @throws IOException if the write fails
*/
public void saveToFile(PersistedSubject subject) throws IOException { public void saveToFile(PersistedSubject subject) throws IOException {
File subjectFile = resolveFile(subject.getParentCollection().getIdentifier(), subject.getIdentifier()); File subjectFile = resolveFile(subject.getParentCollection().getIdentifier(), subject.getIdentifier());
saveToFile(new SubjectStorageModel(subject.getSubjectData()), subjectFile); saveToFile(SubjectDataContainer.copyOf(subject.getSubjectData()), subjectFile);
} }
public void saveToFile(SubjectStorageModel model, File file) throws IOException { /**
* Saves subject data to a specific file
*
* @param container the data
* @param file the file
* @throws IOException if the write fails
*/
public void saveToFile(SubjectDataContainer container, File file) throws IOException {
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
if (file.exists()) { if (file.exists()) {
file.delete(); file.delete();
@ -99,14 +134,20 @@ public class SubjectStorage {
file.createNewFile(); file.createNewFile();
try (BufferedWriter writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) { try (BufferedWriter writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) {
this.gson.toJson(model.toJson(), writer); this.gson.toJson(container.serialize(), writer);
writer.flush(); writer.flush();
} }
} }
public Map<String, SubjectStorageModel> loadAllFromFile(String collectionName) { /**
* Loads all known subjects for a given collection
*
* @param collectionIdentifier the collection identifier
* @return a map of found subjects
*/
public Map<String, SubjectDataContainer> loadAllFromFile(String collectionIdentifier) {
checkContainer(); checkContainer();
File collection = new File(this.container, collectionName); File collection = new File(this.container, collectionIdentifier);
if (!collection.exists()) { if (!collection.exists()) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
@ -114,14 +155,14 @@ public class SubjectStorage {
String[] fileNames = collection.list((dir, name) -> name.endsWith(".json")); String[] fileNames = collection.list((dir, name) -> name.endsWith(".json"));
if (fileNames == null) return Collections.emptyMap(); if (fileNames == null) return Collections.emptyMap();
Map<String, SubjectStorageModel> holders = new HashMap<>(); Map<String, SubjectDataContainer> holders = new HashMap<>();
for (String name : fileNames) { for (String name : fileNames) {
File subject = new File(collection, name); File subjectFile = new File(collection, name);
try { try {
Map.Entry<String, SubjectStorageModel> s = loadFromFile(subject); LoadedSubject s = loadFromFile(subjectFile);
if (s != null) { if (s != null) {
holders.put(s.getKey(), s.getValue()); holders.put(s.identifier, s.data);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -131,18 +172,33 @@ public class SubjectStorage {
return holders; return holders;
} }
public Map.Entry<String, SubjectStorageModel> loadFromFile(String collectionName, String subjectName) throws IOException { /**
* Loads a subject
*
* @param collectionIdentifier the collection id
* @param subjectIdentifier the subject id
* @return a loaded subject
* @throws IOException if the read fails
*/
public LoadedSubject loadFromFile(String collectionIdentifier, String subjectIdentifier) throws IOException {
checkContainer(); checkContainer();
File collection = new File(this.container, collectionName); File collection = new File(this.container, collectionIdentifier);
if (!collection.exists()) { if (!collection.exists()) {
return null; return null;
} }
File subject = new File(collection, subjectName + ".json"); File subject = new File(collection, subjectIdentifier + ".json");
return Maps.immutableEntry(subjectName, loadFromFile(subject).getValue()); return new LoadedSubject(subjectIdentifier, loadFromFile(subject).data);
} }
public Map.Entry<String, SubjectStorageModel> loadFromFile(File file) throws IOException { /**
* Loads a subject from a particular file
*
* @param file the file to load from
* @return a loaded subject
* @throws IOException if the read fails
*/
public LoadedSubject loadFromFile(File file) throws IOException {
if (!file.exists()) { if (!file.exists()) {
return null; return null;
} }
@ -151,8 +207,18 @@ public class SubjectStorage {
try (BufferedReader reader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) { try (BufferedReader reader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
JsonObject data = this.gson.fromJson(reader, JsonObject.class); JsonObject data = this.gson.fromJson(reader, JsonObject.class);
SubjectStorageModel model = new SubjectStorageModel(this.service, data); SubjectDataContainer model = SubjectDataContainer.derserialize(this.service, data);
return Maps.immutableEntry(subjectName, model); return new LoadedSubject(subjectName, model);
}
}
private static final class LoadedSubject {
private final String identifier;
private final SubjectDataContainer data;
private LoadedSubject(String identifier, SubjectDataContainer data) {
this.identifier = identifier;
this.data = data;
} }
} }
} }

View File

@ -23,7 +23,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.sponge.service; package me.lucko.luckperms.sponge.service.proxy;
import me.lucko.luckperms.common.model.NodeMapType; import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.sponge.service.model.LPPermissionDescription; import me.lucko.luckperms.sponge.service.model.LPPermissionDescription;