Cache SubjectReference instances, general cleanup
This commit is contained in:
@@ -81,7 +81,6 @@ import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.persisted.PersistedCollection;
|
||||
import me.lucko.luckperms.sponge.tasks.ServiceCacheHousekeepingTask;
|
||||
import me.lucko.luckperms.sponge.timings.LPTimings;
|
||||
import me.lucko.luckperms.sponge.utils.VersionData;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -122,8 +121,18 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* LuckPerms implementation for the Sponge API.
|
||||
*/
|
||||
@Getter
|
||||
@Plugin(id = "luckperms", name = "LuckPerms", version = VersionData.VERSION, authors = {"Luck"}, description = "A permissions plugin")
|
||||
@Plugin(
|
||||
id = "luckperms",
|
||||
name = "LuckPerms",
|
||||
version = VersionData.VERSION,
|
||||
authors = {"Luck"},
|
||||
description = "A permissions plugin",
|
||||
url = "https://github.com/lucko/LuckPerms"
|
||||
)
|
||||
public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
|
||||
@Inject
|
||||
@@ -146,7 +155,6 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
@AsynchronousExecutor
|
||||
private SpongeExecutorService asyncExecutorService;
|
||||
|
||||
private LPTimings timings;
|
||||
private boolean lateLoad = false;
|
||||
private long startTime;
|
||||
|
||||
@@ -186,7 +194,6 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
verboseHandler = new VerboseHandler(scheduler.async(), getVersion());
|
||||
permissionVault = new PermissionVault(scheduler.async());
|
||||
logDispatcher = new LogDispatcher(this);
|
||||
timings = new LPTimings(this);
|
||||
|
||||
getLog().info("Loading configuration...");
|
||||
configuration = new SpongeConfig(this);
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.google.common.base.Splitter;
|
||||
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
import org.spongepowered.api.command.CommandCallable;
|
||||
import org.spongepowered.api.command.CommandException;
|
||||
@@ -41,16 +40,13 @@ import org.spongepowered.api.text.selector.Selector;
|
||||
import org.spongepowered.api.world.Location;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
class SpongeCommand extends CommandManager implements CommandCallable {
|
||||
public class SpongeCommand extends CommandManager implements CommandCallable {
|
||||
private final LPSpongePlugin plugin;
|
||||
|
||||
SpongeCommand(LPSpongePlugin plugin) {
|
||||
@@ -58,56 +54,56 @@ class SpongeCommand extends CommandManager implements CommandCallable {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult process(CommandSource source, String s) throws CommandException {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.ON_COMMAND)) {
|
||||
List<String> args = Util.stripQuotes(Splitter.on(COMMAND_SEPARATOR_PATTERN).omitEmptyStrings().splitToList(s));
|
||||
private List<String> processArgs(CommandSource source, String s) {
|
||||
List<String> args = Util.stripQuotes(Splitter.on(COMMAND_SEPARATOR_PATTERN).omitEmptyStrings().splitToList(s));
|
||||
|
||||
// resolve selectors
|
||||
ListIterator<String> it = args.listIterator();
|
||||
while (it.hasNext()) {
|
||||
String element = it.next();
|
||||
if (element.startsWith("@")) {
|
||||
try {
|
||||
Player ret = Selector.parse(element).resolve(source).stream()
|
||||
.filter(e -> e instanceof Player)
|
||||
.map(e -> ((Player) e))
|
||||
.findFirst().orElse(null);
|
||||
// resolve selectors
|
||||
ListIterator<String> it = args.listIterator();
|
||||
while (it.hasNext()) {
|
||||
String element = it.next();
|
||||
if (element.startsWith("@")) {
|
||||
try {
|
||||
Player ret = Selector.parse(element).resolve(source).stream()
|
||||
.filter(e -> e instanceof Player)
|
||||
.map(e -> ((Player) e))
|
||||
.findFirst().orElse(null);
|
||||
|
||||
if (ret != null) {
|
||||
it.set(ret.getUniqueId().toString());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
// ignored
|
||||
if (ret != null) {
|
||||
it.set(ret.getUniqueId().toString());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
onCommand(plugin.getSenderFactory().wrap(source), "lp", args);
|
||||
return CommandResult.success();
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult process(CommandSource source, String s) throws CommandException {
|
||||
onCommand(plugin.getSenderFactory().wrap(source), "lp", processArgs(source, s));
|
||||
return CommandResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(CommandSource source, String s, @Nullable Location<World> location) throws CommandException {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.COMMAND_TAB_COMPLETE)) {
|
||||
return onTabComplete(plugin.getSenderFactory().wrap(source), Splitter.on(' ').splitToList(s));
|
||||
}
|
||||
return onTabComplete(plugin.getSenderFactory().wrap(source), processArgs(source, s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandSource source) {
|
||||
return true;
|
||||
return true; // we run permission checks internally
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Text> getShortDescription(CommandSource source) {
|
||||
return Optional.of(Text.of("LuckPerms main command."));
|
||||
return Optional.of(Text.of("Manage permissions"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Text> getHelp(CommandSource source) {
|
||||
return Optional.of(Text.of("Type /luckperms for help."));
|
||||
return Optional.of(Text.of("Run /luckperms to view usage."));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -34,7 +34,6 @@ import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.utils.LoginHelper;
|
||||
import me.lucko.luckperms.common.utils.UuidCache;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
@@ -48,8 +47,6 @@ import org.spongepowered.api.text.serializer.TextSerializers;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -142,52 +139,50 @@ public class SpongeListener {
|
||||
@Listener(order = Order.FIRST)
|
||||
@IsCancelled(Tristate.UNDEFINED)
|
||||
public void onClientLogin(ClientConnectionEvent.Login e) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.ON_CLIENT_LOGIN)) {
|
||||
/* Called when the player starts logging into the server.
|
||||
/* Called when the player starts logging into the server.
|
||||
At this point, the users data should be present and loaded.
|
||||
Listening on LOW priority to allow plugins to further modify data here. (auth plugins, etc.) */
|
||||
|
||||
final GameProfile player = e.getProfile();
|
||||
final GameProfile player = e.getProfile();
|
||||
|
||||
if (plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
|
||||
plugin.getLog().info("Processing login event for " + player.getUniqueId() + " - " + player.getName());
|
||||
}
|
||||
if (plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
|
||||
plugin.getLog().info("Processing login event for " + player.getUniqueId() + " - " + player.getName());
|
||||
}
|
||||
|
||||
final User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
final User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
|
||||
/* User instance is null for whatever reason. Could be that it was unloaded between asyncpre and now. */
|
||||
if (user == null) {
|
||||
deniedLogin.add(player.getUniqueId());
|
||||
if (user == null) {
|
||||
deniedLogin.add(player.getUniqueId());
|
||||
|
||||
plugin.getLog().warn("User " + player.getUniqueId() + " - " + player.getName() + " doesn't have data pre-loaded. - denying login.");
|
||||
e.setCancelled(true);
|
||||
e.setMessageCancelled(false);
|
||||
//noinspection deprecation
|
||||
e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(Message.LOADING_ERROR.asString(plugin.getLocaleManager())));
|
||||
return;
|
||||
}
|
||||
plugin.getLog().warn("User " + player.getUniqueId() + " - " + player.getName() + " doesn't have data pre-loaded. - denying login.");
|
||||
e.setCancelled(true);
|
||||
e.setMessageCancelled(false);
|
||||
//noinspection deprecation
|
||||
e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(Message.LOADING_ERROR.asString(plugin.getLocaleManager())));
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt to pre-process some permissions for the user to save time later. Might not work, but it's better than nothing.
|
||||
Optional<Player> p = e.getCause().first(Player.class);
|
||||
if (p.isPresent()) {
|
||||
MutableContextSet context = MutableContextSet.fromSet(plugin.getContextManager().getApplicableContext(p.get()));
|
||||
// Attempt to pre-process some permissions for the user to save time later. Might not work, but it's better than nothing.
|
||||
Optional<Player> p = e.getCause().first(Player.class);
|
||||
if (p.isPresent()) {
|
||||
MutableContextSet context = MutableContextSet.fromSet(plugin.getContextManager().getApplicableContext(p.get()));
|
||||
|
||||
List<String> worlds = plugin.getGame().isServerAvailable() ? plugin.getGame().getServer().getWorlds().stream()
|
||||
.map(World::getName)
|
||||
.collect(Collectors.toList()) : Collections.emptyList();
|
||||
List<String> worlds = plugin.getGame().isServerAvailable() ? plugin.getGame().getServer().getWorlds().stream()
|
||||
.map(World::getName)
|
||||
.collect(Collectors.toList()) : Collections.emptyList();
|
||||
|
||||
plugin.doAsync(() -> {
|
||||
UserData data = user.getUserData();
|
||||
data.preCalculate(plugin.getService().calculateContexts(context.makeImmutable()));
|
||||
plugin.doAsync(() -> {
|
||||
UserData data = user.getUserData();
|
||||
data.preCalculate(plugin.getService().calculateContexts(context.makeImmutable()));
|
||||
|
||||
for (String world : worlds) {
|
||||
MutableContextSet modified = MutableContextSet.fromSet(context);
|
||||
modified.removeAll("world");
|
||||
modified.add("world", world);
|
||||
data.preCalculate(plugin.getService().calculateContexts(modified.makeImmutable()));
|
||||
}
|
||||
});
|
||||
}
|
||||
for (String world : worlds) {
|
||||
MutableContextSet modified = MutableContextSet.fromSet(context);
|
||||
modified.removeAll("world");
|
||||
modified.add("world", world);
|
||||
data.preCalculate(plugin.getService().calculateContexts(modified.makeImmutable()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,12 +213,11 @@ public class SpongeListener {
|
||||
/* We don't actually remove the user instance here, as Sponge likes to keep performing checks
|
||||
on players when they disconnect. The instance gets cleared up on a housekeeping task
|
||||
after a period of inactivity. */
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.ON_CLIENT_LEAVE)) {
|
||||
final UuidCache cache = plugin.getUuidCache();
|
||||
|
||||
// Unload the user from memory when they disconnect
|
||||
cache.clearCache(e.getTargetEntity().getUniqueId());
|
||||
}
|
||||
final UuidCache cache = plugin.getUuidCache();
|
||||
|
||||
// Unload the user from memory when they disconnect
|
||||
cache.clearCache(e.getTargetEntity().getUniqueId());
|
||||
}
|
||||
|
||||
@Listener
|
||||
|
||||
@@ -60,7 +60,7 @@ public class SpongeCalculatorLink implements ContextCalculator<Subject> {
|
||||
delegate.accumulateContexts(subject, contexts);
|
||||
accumulator.addAll(CompatibilityUtil.convertContexts(contexts));
|
||||
} catch (Exception e) {
|
||||
new RuntimeException("Exception thrown by delegate Sponge calculator: " + delegate.getClass().getName(), e).printStackTrace();
|
||||
throw new RuntimeException("Exception thrown by delegate Sponge calculator: " + delegate.getClass().getName(), e);
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
|
||||
+11
-11
@@ -47,13 +47,13 @@ import java.util.Set;
|
||||
@UtilityClass
|
||||
public class SpongeMigrationUtils {
|
||||
|
||||
public static void migrateSubject(Subject subject, PermissionHolder holder, int priority) {
|
||||
if (holder instanceof Group) {
|
||||
MigrationUtils.setGroupWeight((Group) holder, priority);
|
||||
public static void migrateSubject(Subject from, PermissionHolder to, int priority) {
|
||||
if (to instanceof Group) {
|
||||
MigrationUtils.setGroupWeight((Group) to, priority);
|
||||
}
|
||||
|
||||
// Migrate permissions
|
||||
Map<Set<Context>, Map<String, Boolean>> perms = subject.getSubjectData().getAllPermissions();
|
||||
Map<Set<Context>, Map<String, Boolean>> perms = from.getSubjectData().getAllPermissions();
|
||||
for (Map.Entry<Set<Context>, Map<String, Boolean>> e : perms.entrySet()) {
|
||||
ContextSet context = CompatibilityUtil.convertContexts(e.getKey());
|
||||
|
||||
@@ -62,12 +62,12 @@ public class SpongeMigrationUtils {
|
||||
continue;
|
||||
}
|
||||
|
||||
holder.setPermission(NodeFactory.newBuilder(perm.getKey()).withExtraContext(context).setValue(perm.getValue()).build());
|
||||
to.setPermission(NodeFactory.newBuilder(perm.getKey()).withExtraContext(context).setValue(perm.getValue()).build());
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate options
|
||||
Map<Set<Context>, Map<String, String>> opts = subject.getSubjectData().getAllOptions();
|
||||
Map<Set<Context>, Map<String, String>> opts = from.getSubjectData().getAllOptions();
|
||||
for (Map.Entry<Set<Context>, Map<String, String>> e : opts.entrySet()) {
|
||||
ContextSet context = CompatibilityUtil.convertContexts(e.getKey());
|
||||
|
||||
@@ -77,17 +77,17 @@ public class SpongeMigrationUtils {
|
||||
}
|
||||
|
||||
if (opt.getKey().equalsIgnoreCase("prefix")) {
|
||||
holder.setPermission(NodeFactory.makePrefixNode(priority, opt.getValue()).withExtraContext(context).setValue(true).build());
|
||||
to.setPermission(NodeFactory.makePrefixNode(priority, opt.getValue()).withExtraContext(context).setValue(true).build());
|
||||
} else if (opt.getKey().equalsIgnoreCase("suffix")) {
|
||||
holder.setPermission(NodeFactory.makeSuffixNode(priority, opt.getValue()).withExtraContext(context).setValue(true).build());
|
||||
to.setPermission(NodeFactory.makeSuffixNode(priority, opt.getValue()).withExtraContext(context).setValue(true).build());
|
||||
} else {
|
||||
holder.setPermission(NodeFactory.makeMetaNode(opt.getKey(), opt.getValue()).withExtraContext(context).setValue(true).build());
|
||||
to.setPermission(NodeFactory.makeMetaNode(opt.getKey(), opt.getValue()).withExtraContext(context).setValue(true).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate parents
|
||||
Map<Set<Context>, List<Subject>> parents = subject.getSubjectData().getAllParents();
|
||||
Map<Set<Context>, List<Subject>> parents = from.getSubjectData().getAllParents();
|
||||
for (Map.Entry<Set<Context>, List<Subject>> e : parents.entrySet()) {
|
||||
ContextSet context = CompatibilityUtil.convertContexts(e.getKey());
|
||||
|
||||
@@ -96,7 +96,7 @@ public class SpongeMigrationUtils {
|
||||
continue; // LuckPerms does not support persisting other subject types.
|
||||
}
|
||||
|
||||
holder.setPermission(NodeFactory.newBuilder("group." + MigrationUtils.standardizeName(s.getIdentifier())).withExtraContext(context).setValue(true).build());
|
||||
to.setPermission(NodeFactory.newBuilder("group." + MigrationUtils.standardizeName(s.getIdentifier())).withExtraContext(context).setValue(true).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,15 +48,12 @@ import me.lucko.luckperms.sponge.service.model.CompatibilityUtil;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.service.permission.NodeTree;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -176,69 +173,59 @@ public class SpongeGroup extends Group {
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_PERMISSION_VALUE)) {
|
||||
NodeTree nt = permissionCache.get(contexts);
|
||||
Tristate t = CompatibilityUtil.convertTristate(nt.get(permission));
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
|
||||
t = plugin.getService().getGroupSubjects().getDefaults().getPermissionValue(contexts, permission);
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
|
||||
t = plugin.getService().getDefaults().getPermissionValue(contexts, permission);
|
||||
NodeTree nt = permissionCache.get(contexts);
|
||||
Tristate t = CompatibilityUtil.convertTristate(nt.get(permission));
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
|
||||
t = plugin.getService().getGroupSubjects().getDefaults().getPermissionValue(contexts, permission);
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
|
||||
t = plugin.getService().getDefaults().getPermissionValue(contexts, permission);
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(ImmutableContextSet contexts, SubjectReference parent) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_IS_CHILD_OF)) {
|
||||
return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getSubjectIdentifier()).asBoolean();
|
||||
}
|
||||
return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getSubjectIdentifier()).asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<SubjectReference> getParents(ImmutableContextSet contexts) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_PARENTS)) {
|
||||
return parentCache.get(contexts);
|
||||
}
|
||||
return parentCache.get(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(ImmutableContextSet contexts, String s) {
|
||||
try (Timing ignored = plugin.getService().getPlugin().getTimings().time(LPTiming.GROUP_GET_OPTION)) {
|
||||
Optional<String> option;
|
||||
if (s.equalsIgnoreCase("prefix")) {
|
||||
option = getChatMeta(contexts, ChatMetaType.PREFIX);
|
||||
Optional<String> option;
|
||||
if (s.equalsIgnoreCase("prefix")) {
|
||||
option = getChatMeta(contexts, ChatMetaType.PREFIX);
|
||||
|
||||
} else if (s.equalsIgnoreCase("suffix")) {
|
||||
option = getChatMeta(contexts, ChatMetaType.SUFFIX);
|
||||
} else if (s.equalsIgnoreCase("suffix")) {
|
||||
option = getChatMeta(contexts, ChatMetaType.SUFFIX);
|
||||
|
||||
} else {
|
||||
option = getMeta(contexts, s);
|
||||
}
|
||||
|
||||
if (option.isPresent()) {
|
||||
return option;
|
||||
}
|
||||
|
||||
option = plugin.getService().getGroupSubjects().getDefaults().getOption(contexts, s);
|
||||
if (option.isPresent()) {
|
||||
return option;
|
||||
}
|
||||
|
||||
return plugin.getService().getDefaults().getOption(contexts, s);
|
||||
} else {
|
||||
option = getMeta(contexts, s);
|
||||
}
|
||||
|
||||
if (option.isPresent()) {
|
||||
return option;
|
||||
}
|
||||
|
||||
option = plugin.getService().getGroupSubjects().getDefaults().getOption(contexts, s);
|
||||
if (option.isPresent()) {
|
||||
return option;
|
||||
}
|
||||
|
||||
return plugin.getService().getDefaults().getOption(contexts, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableContextSet getActiveContextSet() {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_ACTIVE_CONTEXTS)) {
|
||||
return plugin.getContextManager().getApplicableContext(this.sponge()).makeImmutable();
|
||||
}
|
||||
return plugin.getContextManager().getApplicableContext(this.sponge()).makeImmutable();
|
||||
}
|
||||
|
||||
private Optional<String> getChatMeta(ImmutableContextSet contexts, ChatMetaType type) {
|
||||
|
||||
@@ -42,7 +42,6 @@ import me.lucko.luckperms.sponge.service.ProxyFactory;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
@@ -50,8 +49,6 @@ import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -129,75 +126,66 @@ public class SpongeUser extends User {
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(ImmutableContextSet contexts, String permission) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_PERMISSION_VALUE)) {
|
||||
return parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
}
|
||||
return parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(ImmutableContextSet contexts, SubjectReference parent) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_IS_CHILD_OF)) {
|
||||
return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getSubjectIdentifier()).asBoolean();
|
||||
}
|
||||
return parent.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getSubjectIdentifier()).asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<SubjectReference> getParents(ImmutableContextSet contexts) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_PARENTS)) {
|
||||
ImmutableSet.Builder<SubjectReference> subjects = ImmutableSet.builder();
|
||||
ImmutableSet.Builder<SubjectReference> subjects = ImmutableSet.builder();
|
||||
|
||||
for (String perm : parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getImmutableBacking().keySet()) {
|
||||
if (!perm.startsWith("group.")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String groupName = perm.substring("group.".length());
|
||||
if (plugin.getGroupManager().isLoaded(groupName)) {
|
||||
subjects.add(plugin.getService().getGroupSubjects().loadSubject(groupName).join().toReference());
|
||||
}
|
||||
for (String perm : parent.getUserData().getPermissionData(plugin.getService().calculateContexts(contexts)).getImmutableBacking().keySet()) {
|
||||
if (!perm.startsWith("group.")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
subjects.addAll(plugin.getService().getUserSubjects().getDefaults().getParents(contexts));
|
||||
subjects.addAll(plugin.getService().getDefaults().getParents(contexts));
|
||||
|
||||
return getService().sortSubjects(subjects.build());
|
||||
String groupName = perm.substring("group.".length());
|
||||
if (plugin.getGroupManager().isLoaded(groupName)) {
|
||||
subjects.add(plugin.getService().getGroupSubjects().loadSubject(groupName).join().toReference());
|
||||
}
|
||||
}
|
||||
|
||||
subjects.addAll(plugin.getService().getUserSubjects().getDefaults().getParents(contexts));
|
||||
subjects.addAll(plugin.getService().getDefaults().getParents(contexts));
|
||||
|
||||
return getService().sortSubjects(subjects.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(ImmutableContextSet contexts, String s) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_OPTION)) {
|
||||
MetaData data = parent.getUserData().getMetaData(plugin.getService().calculateContexts(contexts));
|
||||
if (s.equalsIgnoreCase("prefix")) {
|
||||
if (data.getPrefix() != null) {
|
||||
return Optional.of(data.getPrefix());
|
||||
}
|
||||
MetaData data = parent.getUserData().getMetaData(plugin.getService().calculateContexts(contexts));
|
||||
if (s.equalsIgnoreCase("prefix")) {
|
||||
if (data.getPrefix() != null) {
|
||||
return Optional.of(data.getPrefix());
|
||||
}
|
||||
|
||||
if (s.equalsIgnoreCase("suffix")) {
|
||||
if (data.getSuffix() != null) {
|
||||
return Optional.of(data.getSuffix());
|
||||
}
|
||||
}
|
||||
|
||||
if (data.getMeta().containsKey(s)) {
|
||||
return Optional.of(data.getMeta().get(s));
|
||||
}
|
||||
|
||||
Optional<String> v = plugin.getService().getUserSubjects().getDefaults().getOption(contexts, s);
|
||||
if (v.isPresent()) {
|
||||
return v;
|
||||
}
|
||||
|
||||
return plugin.getService().getDefaults().getOption(contexts, s);
|
||||
}
|
||||
|
||||
if (s.equalsIgnoreCase("suffix")) {
|
||||
if (data.getSuffix() != null) {
|
||||
return Optional.of(data.getSuffix());
|
||||
}
|
||||
}
|
||||
|
||||
String val = data.getMeta().get(s);
|
||||
if (val != null) {
|
||||
return Optional.of(val);
|
||||
}
|
||||
|
||||
Optional<String> v = plugin.getService().getUserSubjects().getDefaults().getOption(contexts, s);
|
||||
if (v.isPresent()) {
|
||||
return v;
|
||||
}
|
||||
|
||||
return plugin.getService().getDefaults().getOption(contexts, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableContextSet getActiveContextSet() {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_ACTIVE_CONTEXTS)) {
|
||||
return plugin.getContextManager().getApplicableContext(this.sponge());
|
||||
}
|
||||
return plugin.getContextManager().getApplicableContext(this.sponge());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -58,17 +57,15 @@ import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReferenceFactory;
|
||||
import me.lucko.luckperms.sponge.service.persisted.PersistedCollection;
|
||||
import me.lucko.luckperms.sponge.service.storage.SubjectStorage;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
import org.spongepowered.api.plugin.PluginContainer;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.text.Text;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -81,7 +78,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* The LuckPerms implementation of the Sponge Permission Service
|
||||
* LuckPerms implementation of the Sponge Permission Service
|
||||
*/
|
||||
@Getter
|
||||
public class LuckPermsService implements LPPermissionService {
|
||||
@@ -105,17 +102,7 @@ public class LuckPermsService implements LPPermissionService {
|
||||
|
||||
@Getter(value = AccessLevel.NONE)
|
||||
private final LoadingCache<String, LPSubjectCollection> collections = Caffeine.newBuilder()
|
||||
.build(new CacheLoader<String, LPSubjectCollection>() {
|
||||
@Override
|
||||
public LPSubjectCollection load(String s) {
|
||||
return new PersistedCollection(LuckPermsService.this, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPSubjectCollection reload(String s, LPSubjectCollection collection) {
|
||||
return collection; // Never needs to be refreshed.
|
||||
}
|
||||
});
|
||||
.build(s -> new PersistedCollection(this, s));
|
||||
|
||||
public LuckPermsService(LPSpongePlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -134,8 +121,8 @@ public class LuckPermsService implements LPPermissionService {
|
||||
defaultSubjects = new PersistedCollection(this, "defaults");
|
||||
defaultSubjects.loadAll();
|
||||
|
||||
collections.put(PermissionService.SUBJECTS_USER, userSubjects);
|
||||
collections.put(PermissionService.SUBJECTS_GROUP, groupSubjects);
|
||||
collections.put("user", userSubjects);
|
||||
collections.put("group", groupSubjects);
|
||||
collections.put("defaults", defaultSubjects);
|
||||
|
||||
for (String collection : storage.getSavedCollections()) {
|
||||
@@ -168,9 +155,7 @@ public class LuckPermsService implements LPPermissionService {
|
||||
|
||||
@Override
|
||||
public LPSubjectCollection getCollection(String s) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.GET_SUBJECTS)) {
|
||||
return collections.get(s.toLowerCase());
|
||||
}
|
||||
return collections.get(s.toLowerCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -180,7 +165,7 @@ public class LuckPermsService implements LPPermissionService {
|
||||
|
||||
@Override
|
||||
public SubjectReference newSubjectReference(String collectionIdentifier, String subjectIdentifier) {
|
||||
return SubjectReference.of(this, collectionIdentifier, subjectIdentifier);
|
||||
return SubjectReferenceFactory.obtain(this, collectionIdentifier, subjectIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+244
-277
@@ -46,12 +46,9 @@ import me.lucko.luckperms.common.node.NodeFactory;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -75,388 +72,358 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
|
||||
@Override
|
||||
public ImmutableMap<ImmutableContextSet, ImmutableMap<String, Boolean>> getAllPermissions() {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_PERMISSIONS)) {
|
||||
Map<ImmutableContextSet, ImmutableMap.Builder<String, Boolean>> perms = new HashMap<>();
|
||||
Map<ImmutableContextSet, ImmutableMap.Builder<String, Boolean>> perms = new HashMap<>();
|
||||
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> e : (enduring ? holder.getEnduringNodes() : holder.getTransientNodes()).asMap().entrySet()) {
|
||||
ImmutableMap.Builder<String, Boolean> results = ImmutableMap.builder();
|
||||
for (Node n : e.getValue()) {
|
||||
results.put(n.getPermission(), n.getValuePrimitive());
|
||||
}
|
||||
perms.put(e.getKey(), results);
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> e : (enduring ? holder.getEnduringNodes() : holder.getTransientNodes()).asMap().entrySet()) {
|
||||
ImmutableMap.Builder<String, Boolean> results = ImmutableMap.builder();
|
||||
for (Node n : e.getValue()) {
|
||||
results.put(n.getPermission(), n.getValuePrimitive());
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableMap<String, Boolean>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, ImmutableMap.Builder<String, Boolean>> e : perms.entrySet()) {
|
||||
map.put(e.getKey(), e.getValue().build());
|
||||
}
|
||||
return map.build();
|
||||
perms.put(e.getKey(), results);
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableMap<String, Boolean>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, ImmutableMap.Builder<String, Boolean>> e : perms.entrySet()) {
|
||||
map.put(e.getKey(), e.getValue().build());
|
||||
}
|
||||
return map.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> setPermission(@NonNull ImmutableContextSet contexts, @NonNull String permission, @NonNull Tristate tristate) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_PERMISSION)) {
|
||||
if (tristate == Tristate.UNDEFINED) {
|
||||
// Unset
|
||||
Node node = NodeFactory.newBuilder(permission).withExtraContext(contexts).build();
|
||||
if (tristate == Tristate.UNDEFINED) {
|
||||
// Unset
|
||||
Node node = NodeFactory.newBuilder(permission).withExtraContext(contexts).build();
|
||||
|
||||
if (enduring) {
|
||||
holder.unsetPermission(node);
|
||||
} else {
|
||||
holder.unsetTransientPermission(node);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
Node node = NodeFactory.newBuilder(permission).setValue(tristate.asBoolean()).withExtraContext(contexts).build();
|
||||
|
||||
// Workaround: unset the inverse, to allow false -> true, true -> false overrides.
|
||||
if (enduring) {
|
||||
holder.unsetPermission(node);
|
||||
} else {
|
||||
holder.unsetTransientPermission(node);
|
||||
}
|
||||
|
||||
if (enduring) {
|
||||
holder.setPermission(node);
|
||||
} else {
|
||||
holder.setTransientPermission(node);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
Node node = NodeFactory.newBuilder(permission).setValue(tristate.asBoolean()).withExtraContext(contexts).build();
|
||||
|
||||
// Workaround: unset the inverse, to allow false -> true, true -> false overrides.
|
||||
if (enduring) {
|
||||
holder.unsetPermission(node);
|
||||
} else {
|
||||
holder.unsetTransientPermission(node);
|
||||
}
|
||||
|
||||
if (enduring) {
|
||||
holder.setPermission(node);
|
||||
} else {
|
||||
holder.setTransientPermission(node);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> clearPermissions() {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PERMISSIONS)) {
|
||||
boolean ret;
|
||||
if (enduring) {
|
||||
ret = holder.clearNodes();
|
||||
} else {
|
||||
ret = holder.clearTransientNodes();
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
if (holder instanceof User) {
|
||||
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
boolean ret;
|
||||
if (enduring) {
|
||||
ret = holder.clearNodes();
|
||||
} else {
|
||||
ret = holder.clearTransientNodes();
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
if (holder instanceof User) {
|
||||
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> clearPermissions(@NonNull ImmutableContextSet set) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PERMISSIONS)) {
|
||||
boolean ret;
|
||||
boolean ret;
|
||||
if (enduring) {
|
||||
ret = holder.clearNodes(set);
|
||||
} else {
|
||||
List<Node> toRemove = streamNodes(false)
|
||||
.filter(n -> n.getFullContexts().equals(set))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (enduring) {
|
||||
ret = holder.clearNodes(set);
|
||||
} else {
|
||||
List<Node> toRemove = streamNodes(false)
|
||||
.filter(n -> n.getFullContexts().equals(set))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(false));
|
||||
ret = !toRemove.isEmpty();
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
if (holder instanceof User) {
|
||||
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
toRemove.forEach(makeUnsetConsumer(false));
|
||||
ret = !toRemove.isEmpty();
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
if (holder instanceof User) {
|
||||
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableMap<ImmutableContextSet, ImmutableList<SubjectReference>> getAllParents() {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_PARENTS)) {
|
||||
Map<ImmutableContextSet, ImmutableList.Builder<SubjectReference>> parents = new HashMap<>();
|
||||
Map<ImmutableContextSet, ImmutableList.Builder<SubjectReference>> parents = new HashMap<>();
|
||||
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> e : (enduring ? holder.getEnduringNodes() : holder.getTransientNodes()).asMap().entrySet()) {
|
||||
ImmutableList.Builder<SubjectReference> results = ImmutableList.builder();
|
||||
for (Node n : e.getValue()) {
|
||||
if (n.isGroupNode()) {
|
||||
results.add(service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference());
|
||||
}
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> e : (enduring ? holder.getEnduringNodes() : holder.getTransientNodes()).asMap().entrySet()) {
|
||||
ImmutableList.Builder<SubjectReference> results = ImmutableList.builder();
|
||||
for (Node n : e.getValue()) {
|
||||
if (n.isGroupNode()) {
|
||||
results.add(service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference());
|
||||
}
|
||||
parents.put(e.getKey(), results);
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableList<SubjectReference>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, ImmutableList.Builder<SubjectReference>> e : parents.entrySet()) {
|
||||
map.put(e.getKey(), e.getValue().build());
|
||||
}
|
||||
return map.build();
|
||||
parents.put(e.getKey(), results);
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableList<SubjectReference>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, ImmutableList.Builder<SubjectReference>> e : parents.entrySet()) {
|
||||
map.put(e.getKey(), e.getValue().build());
|
||||
}
|
||||
return map.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> addParent(@NonNull ImmutableContextSet contexts, @NonNull SubjectReference subject) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_ADD_PARENT)) {
|
||||
if (subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) {
|
||||
return subject.resolveLp().thenCompose(sub -> {
|
||||
DataMutateResult result;
|
||||
if (subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) {
|
||||
return subject.resolveLp().thenCompose(sub -> {
|
||||
DataMutateResult result;
|
||||
|
||||
if (enduring) {
|
||||
result = holder.setPermission(NodeFactory.newBuilder("group." + sub.getIdentifier())
|
||||
.withExtraContext(contexts)
|
||||
.build());
|
||||
} else {
|
||||
result = holder.setTransientPermission(NodeFactory.newBuilder("group." + sub.getIdentifier())
|
||||
.withExtraContext(contexts)
|
||||
.build());
|
||||
}
|
||||
if (enduring) {
|
||||
result = holder.setPermission(NodeFactory.newBuilder("group." + sub.getIdentifier())
|
||||
.withExtraContext(contexts)
|
||||
.build());
|
||||
} else {
|
||||
result = holder.setTransientPermission(NodeFactory.newBuilder("group." + sub.getIdentifier())
|
||||
.withExtraContext(contexts)
|
||||
.build());
|
||||
}
|
||||
|
||||
if (!result.asBoolean()) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
if (!result.asBoolean()) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
});
|
||||
}
|
||||
return CompletableFuture.completedFuture(false);
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
});
|
||||
}
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> removeParent(@NonNull ImmutableContextSet contexts, @NonNull SubjectReference subject) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_REMOVE_PARENT)) {
|
||||
if (subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) {
|
||||
subject.resolveLp().thenCompose(sub -> {
|
||||
DataMutateResult result;
|
||||
if (subject.getCollectionIdentifier().equals(PermissionService.SUBJECTS_GROUP)) {
|
||||
subject.resolveLp().thenCompose(sub -> {
|
||||
DataMutateResult result;
|
||||
|
||||
if (enduring) {
|
||||
result = holder.unsetPermission(NodeFactory.newBuilder("group." + sub.getIdentifier())
|
||||
.withExtraContext(contexts)
|
||||
.build());
|
||||
} else {
|
||||
result = holder.unsetTransientPermission(NodeFactory.newBuilder("group." + sub.getIdentifier())
|
||||
.withExtraContext(contexts)
|
||||
.build());
|
||||
}
|
||||
if (enduring) {
|
||||
result = holder.unsetPermission(NodeFactory.newBuilder("group." + sub.getIdentifier())
|
||||
.withExtraContext(contexts)
|
||||
.build());
|
||||
} else {
|
||||
result = holder.unsetTransientPermission(NodeFactory.newBuilder("group." + sub.getIdentifier())
|
||||
.withExtraContext(contexts)
|
||||
.build());
|
||||
}
|
||||
|
||||
if (!result.asBoolean()) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
if (!result.asBoolean()) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
});
|
||||
}
|
||||
return CompletableFuture.completedFuture(false);
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
});
|
||||
}
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> clearParents() {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PARENTS)) {
|
||||
boolean ret;
|
||||
boolean ret;
|
||||
if (enduring) {
|
||||
ret = holder.clearParents(true);
|
||||
} else {
|
||||
List<Node> toRemove = streamNodes(false)
|
||||
.filter(Node::isGroupNode)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (enduring) {
|
||||
ret = holder.clearParents(true);
|
||||
} else {
|
||||
List<Node> toRemove = streamNodes(false)
|
||||
.filter(Node::isGroupNode)
|
||||
.collect(Collectors.toList());
|
||||
toRemove.forEach(makeUnsetConsumer(false));
|
||||
ret = !toRemove.isEmpty();
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(false));
|
||||
ret = !toRemove.isEmpty();
|
||||
|
||||
if (ret && holder instanceof User) {
|
||||
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
|
||||
}
|
||||
if (ret && holder instanceof User) {
|
||||
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> clearParents(@NonNull ImmutableContextSet set) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PARENTS)) {
|
||||
boolean ret;
|
||||
if (enduring) {
|
||||
ret = holder.clearParents(set, true);
|
||||
} else {
|
||||
List<Node> toRemove = streamNodes(false)
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(n -> n.getFullContexts().equals(set))
|
||||
.collect(Collectors.toList());
|
||||
boolean ret;
|
||||
if (enduring) {
|
||||
ret = holder.clearParents(set, true);
|
||||
} else {
|
||||
List<Node> toRemove = streamNodes(false)
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(n -> n.getFullContexts().equals(set))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(false));
|
||||
ret = !toRemove.isEmpty();
|
||||
toRemove.forEach(makeUnsetConsumer(false));
|
||||
ret = !toRemove.isEmpty();
|
||||
|
||||
if (ret && holder instanceof User) {
|
||||
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
|
||||
}
|
||||
if (ret && holder instanceof User) {
|
||||
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableMap<ImmutableContextSet, ImmutableMap<String, String>> getAllOptions() {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_OPTIONS)) {
|
||||
Map<ImmutableContextSet, Map<String, String>> options = new HashMap<>();
|
||||
Map<ImmutableContextSet, Integer> minPrefixPriority = new HashMap<>();
|
||||
Map<ImmutableContextSet, Integer> minSuffixPriority = new HashMap<>();
|
||||
Map<ImmutableContextSet, Map<String, String>> options = new HashMap<>();
|
||||
Map<ImmutableContextSet, Integer> minPrefixPriority = new HashMap<>();
|
||||
Map<ImmutableContextSet, Integer> minSuffixPriority = new HashMap<>();
|
||||
|
||||
for (Node n : enduring ? holder.getEnduringNodes().values() : holder.getTransientNodes().values()) {
|
||||
if (!n.getValuePrimitive()) continue;
|
||||
if (!n.isMeta() && !n.isPrefix() && !n.isSuffix()) continue;
|
||||
for (Node n : enduring ? holder.getEnduringNodes().values() : holder.getTransientNodes().values()) {
|
||||
if (!n.getValuePrimitive()) continue;
|
||||
if (!n.isMeta() && !n.isPrefix() && !n.isSuffix()) continue;
|
||||
|
||||
ImmutableContextSet immutableContexts = n.getFullContexts().makeImmutable();
|
||||
ImmutableContextSet immutableContexts = n.getFullContexts().makeImmutable();
|
||||
|
||||
if (!options.containsKey(immutableContexts)) {
|
||||
options.put(immutableContexts, new HashMap<>());
|
||||
minPrefixPriority.put(immutableContexts, Integer.MIN_VALUE);
|
||||
minSuffixPriority.put(immutableContexts, Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
if (n.isPrefix()) {
|
||||
Map.Entry<Integer, String> value = n.getPrefix();
|
||||
if (value.getKey() > minPrefixPriority.get(immutableContexts)) {
|
||||
options.get(immutableContexts).put("prefix", value.getValue());
|
||||
minPrefixPriority.put(immutableContexts, value.getKey());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n.isSuffix()) {
|
||||
Map.Entry<Integer, String> value = n.getSuffix();
|
||||
if (value.getKey() > minSuffixPriority.get(immutableContexts)) {
|
||||
options.get(immutableContexts).put("suffix", value.getValue());
|
||||
minSuffixPriority.put(immutableContexts, value.getKey());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n.isMeta()) {
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
options.get(immutableContexts).put(meta.getKey(), meta.getValue());
|
||||
}
|
||||
if (!options.containsKey(immutableContexts)) {
|
||||
options.put(immutableContexts, new HashMap<>());
|
||||
minPrefixPriority.put(immutableContexts, Integer.MIN_VALUE);
|
||||
minSuffixPriority.put(immutableContexts, Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableMap<String, String>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, Map<String, String>> e : options.entrySet()) {
|
||||
map.put(e.getKey(), ImmutableMap.copyOf(e.getValue()));
|
||||
if (n.isPrefix()) {
|
||||
Map.Entry<Integer, String> value = n.getPrefix();
|
||||
if (value.getKey() > minPrefixPriority.get(immutableContexts)) {
|
||||
options.get(immutableContexts).put("prefix", value.getValue());
|
||||
minPrefixPriority.put(immutableContexts, value.getKey());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n.isSuffix()) {
|
||||
Map.Entry<Integer, String> value = n.getSuffix();
|
||||
if (value.getKey() > minSuffixPriority.get(immutableContexts)) {
|
||||
options.get(immutableContexts).put("suffix", value.getValue());
|
||||
minSuffixPriority.put(immutableContexts, value.getKey());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n.isMeta()) {
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
options.get(immutableContexts).put(meta.getKey(), meta.getValue());
|
||||
}
|
||||
return map.build();
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableMap<String, String>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, Map<String, String>> e : options.entrySet()) {
|
||||
map.put(e.getKey(), ImmutableMap.copyOf(e.getValue()));
|
||||
}
|
||||
return map.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> setOption(@NonNull ImmutableContextSet context, @NonNull String key, @NonNull String value) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_OPTION)) {
|
||||
if (key.equalsIgnoreCase("prefix") || key.equalsIgnoreCase("suffix")) {
|
||||
// special handling.
|
||||
ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase());
|
||||
if (key.equalsIgnoreCase("prefix") || key.equalsIgnoreCase("suffix")) {
|
||||
// special handling.
|
||||
ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase());
|
||||
|
||||
// remove all prefixes/suffixes from the user
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(type::matches)
|
||||
.filter(n -> n.getFullContexts().equals(context))
|
||||
.collect(Collectors.toList());
|
||||
// remove all prefixes/suffixes from the user
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(type::matches)
|
||||
.filter(n -> n.getFullContexts().equals(context))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, null, ExtractedContexts.generate(service.calculateContexts(context)));
|
||||
int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0);
|
||||
priority += 10;
|
||||
|
||||
if (enduring) {
|
||||
holder.setPermission(NodeFactory.makeChatMetaNode(type, priority, value).withExtraContext(context).build());
|
||||
} else {
|
||||
holder.setTransientPermission(NodeFactory.makeChatMetaNode(type, priority, value).withExtraContext(context).build());
|
||||
}
|
||||
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, null, ExtractedContexts.generate(service.calculateContexts(context)));
|
||||
int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0);
|
||||
priority += 10;
|
||||
|
||||
if (enduring) {
|
||||
holder.setPermission(NodeFactory.makeChatMetaNode(type, priority, value).withExtraContext(context).build());
|
||||
} else {
|
||||
// standard remove
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(n -> n.isMeta() && n.getMeta().getKey().equals(key))
|
||||
.filter(n -> n.getFullContexts().equals(context))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
if (enduring) {
|
||||
holder.setPermission(NodeFactory.makeMetaNode(key, value).withExtraContext(context).build());
|
||||
} else {
|
||||
holder.setTransientPermission(NodeFactory.makeMetaNode(key, value).withExtraContext(context).build());
|
||||
}
|
||||
holder.setTransientPermission(NodeFactory.makeChatMetaNode(type, priority, value).withExtraContext(context).build());
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
} else {
|
||||
// standard remove
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(n -> n.isMeta() && n.getMeta().getKey().equals(key))
|
||||
.filter(n -> n.getFullContexts().equals(context))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
if (enduring) {
|
||||
holder.setPermission(NodeFactory.makeMetaNode(key, value).withExtraContext(context).build());
|
||||
} else {
|
||||
holder.setTransientPermission(NodeFactory.makeMetaNode(key, value).withExtraContext(context).build());
|
||||
}
|
||||
}
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> unsetOption(ImmutableContextSet set, String key) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_OPTION)) {
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(n -> {
|
||||
if (key.equalsIgnoreCase("prefix")) {
|
||||
return n.isPrefix();
|
||||
} else if (key.equalsIgnoreCase("suffix")) {
|
||||
return n.isSuffix();
|
||||
} else {
|
||||
return n.isMeta() && n.getMeta().getKey().equals(key);
|
||||
}
|
||||
})
|
||||
.filter(n -> n.getFullContexts().equals(set))
|
||||
.collect(Collectors.toList());
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(n -> {
|
||||
if (key.equalsIgnoreCase("prefix")) {
|
||||
return n.isPrefix();
|
||||
} else if (key.equalsIgnoreCase("suffix")) {
|
||||
return n.isSuffix();
|
||||
} else {
|
||||
return n.isMeta() && n.getMeta().getKey().equals(key);
|
||||
}
|
||||
})
|
||||
.filter(n -> n.getFullContexts().equals(set))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> clearOptions(@NonNull ImmutableContextSet set) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_OPTIONS)) {
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix())
|
||||
.filter(n -> n.getFullContexts().equals(set))
|
||||
.collect(Collectors.toList());
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix())
|
||||
.filter(n -> n.getFullContexts().equals(set))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
return objectSave(holder).thenApply(v -> !toRemove.isEmpty());
|
||||
}
|
||||
return objectSave(holder).thenApply(v -> !toRemove.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> clearOptions() {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_OPTIONS)) {
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix())
|
||||
.collect(Collectors.toList());
|
||||
List<Node> toRemove = streamNodes(enduring)
|
||||
.filter(n -> n.isMeta() || n.isPrefix() || n.isSuffix())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
return objectSave(holder).thenApply(v -> !toRemove.isEmpty());
|
||||
}
|
||||
return objectSave(holder).thenApply(v -> !toRemove.isEmpty());
|
||||
}
|
||||
|
||||
private Stream<Node> streamNodes(boolean enduring) {
|
||||
|
||||
+5
-16
@@ -40,6 +40,7 @@ import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||
import me.lucko.luckperms.common.contexts.ContextSetComparator;
|
||||
import me.lucko.luckperms.common.processors.MapProcessor;
|
||||
import me.lucko.luckperms.common.processors.PermissionProcessor;
|
||||
import me.lucko.luckperms.common.verbose.CheckOrigin;
|
||||
@@ -49,7 +50,6 @@ import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReference;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -65,7 +65,6 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class CalculatedSubjectData implements LPSubjectData {
|
||||
private static final ContextComparator CONTEXT_COMPARATOR = new ContextComparator();
|
||||
|
||||
@Getter
|
||||
private final LPSubject parentSubject;
|
||||
@@ -87,7 +86,7 @@ public class CalculatedSubjectData implements LPSubjectData {
|
||||
processors.add(new SpongeWildcardProcessor());
|
||||
|
||||
CalculatorHolder holder = new CalculatorHolder(new PermissionCalculator(service.getPlugin(), PermissionCalculatorMetadata.of(calculatorDisplayName, contexts), processors.build()));
|
||||
holder.setPermissions(flattenMap(contexts, permissions));
|
||||
holder.setPermissions(flattenMap(getRelevantEntries(contexts, permissions)));
|
||||
|
||||
return holder;
|
||||
}
|
||||
@@ -290,11 +289,10 @@ public class CalculatedSubjectData implements LPSubjectData {
|
||||
return CompletableFuture.completedFuture(!map.isEmpty());
|
||||
}
|
||||
|
||||
private static <V> Map<String, V> flattenMap(ContextSet contexts, Map<ImmutableContextSet, Map<String, V>> source) {
|
||||
private static <V> Map<String, V> flattenMap(SortedMap<ImmutableContextSet, Map<String, V>> data) {
|
||||
Map<String, V> map = new HashMap<>();
|
||||
|
||||
SortedMap<ImmutableContextSet, Map<String, V>> ret = getRelevantEntries(contexts, source);
|
||||
for (Map<String, V> m : ret.values()) {
|
||||
for (Map<String, V> m : data.values()) {
|
||||
for (Map.Entry<String, V> e : m.entrySet()) {
|
||||
map.putIfAbsent(e.getKey(), e.getValue());
|
||||
}
|
||||
@@ -304,7 +302,7 @@ public class CalculatedSubjectData implements LPSubjectData {
|
||||
}
|
||||
|
||||
private static <K, V> SortedMap<ImmutableContextSet, Map<K, V>> getRelevantEntries(ContextSet set, Map<ImmutableContextSet, Map<K, V>> map) {
|
||||
ImmutableSortedMap.Builder<ImmutableContextSet, Map<K, V>> perms = ImmutableSortedMap.orderedBy(CONTEXT_COMPARATOR);
|
||||
ImmutableSortedMap.Builder<ImmutableContextSet, Map<K, V>> perms = ImmutableSortedMap.orderedBy(ContextSetComparator.reverse());
|
||||
|
||||
for (Map.Entry<ImmutableContextSet, Map<K, V>> e : map.entrySet()) {
|
||||
if (!e.getKey().isSatisfiedBy(set)) {
|
||||
@@ -321,15 +319,6 @@ public class CalculatedSubjectData implements LPSubjectData {
|
||||
return a == null && b == null || a != null && b != null && a.equalsIgnoreCase(b);
|
||||
}
|
||||
|
||||
private static class ContextComparator implements Comparator<ImmutableContextSet> {
|
||||
|
||||
@Override
|
||||
public int compare(ImmutableContextSet o1, ImmutableContextSet o2) {
|
||||
int i = Integer.compare(o1.size(), o2.size());
|
||||
return i == 0 ? 1 : i;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CalculatorHolder {
|
||||
|
||||
@Getter
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReferenceFactory;
|
||||
import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel;
|
||||
|
||||
import java.util.List;
|
||||
@@ -66,7 +66,7 @@ public class SubjectDataHolder {
|
||||
parents.entrySet().stream()
|
||||
.collect(Collectors.toMap(
|
||||
k -> ImmutableContextSet.fromMap(k.getKey()),
|
||||
v -> v.getValue().stream().map(s -> SubjectReference.deserialize(service, s)).collect(Collectors.toList())
|
||||
v -> v.getValue().stream().map(s -> SubjectReferenceFactory.deserialize(service, s)).collect(Collectors.toList())
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
+14
-27
@@ -44,13 +44,10 @@ import me.lucko.luckperms.sponge.service.calculated.PermissionLookup;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -246,46 +243,36 @@ public class PersistedSubject implements LPSubject {
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(@NonNull ImmutableContextSet contexts, @NonNull String node) {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_PERMISSION_VALUE)) {
|
||||
Tristate t = permissionLookupCache.get(PermissionLookup.of(node, contexts));
|
||||
service.getPlugin().getVerboseHandler().offerCheckData(CheckOrigin.INTERNAL, "local:" + getParentCollection().getIdentifier() + "/" + identifier, contexts, node, t);
|
||||
return t;
|
||||
}
|
||||
Tristate t = permissionLookupCache.get(PermissionLookup.of(node, contexts));
|
||||
service.getPlugin().getVerboseHandler().offerCheckData(CheckOrigin.INTERNAL, "local:" + getParentCollection().getIdentifier() + "/" + identifier, contexts, node, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(@NonNull ImmutableContextSet contexts, @NonNull SubjectReference subject) {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_IS_CHILD_OF)) {
|
||||
if (getParentCollection().getIdentifier().equalsIgnoreCase("defaults")) {
|
||||
return subjectData.getParents(contexts).contains(subject) ||
|
||||
transientSubjectData.getParents(contexts).contains(subject);
|
||||
} else {
|
||||
return subjectData.getParents(contexts).contains(subject) ||
|
||||
transientSubjectData.getParents(contexts).contains(subject) ||
|
||||
getParentCollection().getDefaults().getParents(contexts).contains(subject) ||
|
||||
service.getDefaults().getParents(contexts).contains(subject);
|
||||
}
|
||||
if (getParentCollection().getIdentifier().equalsIgnoreCase("defaults")) {
|
||||
return subjectData.getParents(contexts).contains(subject) ||
|
||||
transientSubjectData.getParents(contexts).contains(subject);
|
||||
} else {
|
||||
return subjectData.getParents(contexts).contains(subject) ||
|
||||
transientSubjectData.getParents(contexts).contains(subject) ||
|
||||
getParentCollection().getDefaults().getParents(contexts).contains(subject) ||
|
||||
service.getDefaults().getParents(contexts).contains(subject);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<SubjectReference> getParents(@NonNull ImmutableContextSet contexts) {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_PARENTS)) {
|
||||
return parentLookupCache.get(contexts);
|
||||
}
|
||||
return parentLookupCache.get(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(ImmutableContextSet contexts, String key) {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_OPTION)) {
|
||||
return optionLookupCache.get(OptionLookup.of(key, contexts));
|
||||
}
|
||||
return optionLookupCache.get(OptionLookup.of(key, contexts));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableContextSet getActiveContextSet() {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_ACTIVE_CONTEXTS)) {
|
||||
return service.getPlugin().getContextManager().getApplicableContext(sponge()).makeImmutable();
|
||||
}
|
||||
return service.getPlugin().getContextManager().getApplicableContext(sponge()).makeImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -41,6 +41,7 @@ import me.lucko.luckperms.common.node.NodeWithContextComparator;
|
||||
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.service.model.SubjectReferenceFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -164,7 +165,7 @@ public class SubjectStorageModel {
|
||||
String collection = parent.get("collection").getAsString();
|
||||
String subject = parent.get("subject").getAsString();
|
||||
|
||||
pars.add(SubjectReference.of(service, collection, subject));
|
||||
pars.add(SubjectReferenceFactory.obtain(service, collection, subject));
|
||||
}
|
||||
|
||||
parentsBuilder.put(contextSet, pars.build());
|
||||
|
||||
@@ -1,76 +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.timings;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum LPTiming {
|
||||
|
||||
GET_SUBJECTS("getSubjects"),
|
||||
|
||||
USER_COLLECTION_GET("userCollectionGet"),
|
||||
GROUP_COLLECTION_GET("groupCollectionGet"),
|
||||
|
||||
USER_GET_PERMISSION_VALUE("userGetPermissionValue"),
|
||||
USER_GET_PARENTS("userGetParents"),
|
||||
USER_IS_CHILD_OF("userIsChildOf"),
|
||||
USER_GET_OPTION("userGetOption"),
|
||||
USER_GET_ACTIVE_CONTEXTS("userGetActiveContexts"),
|
||||
|
||||
GROUP_GET_PERMISSION_VALUE("groupGetPermissionValue"),
|
||||
GROUP_GET_PARENTS("groupGetParents"),
|
||||
GROUP_IS_CHILD_OF("groupIsChildOf"),
|
||||
GROUP_GET_OPTION("groupGetOption"),
|
||||
GROUP_GET_ACTIVE_CONTEXTS("groupGetActiveContexts"),
|
||||
|
||||
LP_SUBJECT_GET_PERMISSIONS("lpSubjectGetPermissions"),
|
||||
LP_SUBJECT_SET_PERMISSION("lpSubjectSetPermission"),
|
||||
LP_SUBJECT_CLEAR_PERMISSIONS("lpSubjectClearPermissions"),
|
||||
LP_SUBJECT_GET_PARENTS("lpSubjectGetParents"),
|
||||
LP_SUBJECT_ADD_PARENT("lpSubjectAddParent"),
|
||||
LP_SUBJECT_REMOVE_PARENT("lpSubjectRemoveParent"),
|
||||
LP_SUBJECT_CLEAR_PARENTS("lpSubjectClearParents"),
|
||||
LP_SUBJECT_GET_OPTIONS("lpSubjectGetOptions"),
|
||||
LP_SUBJECT_SET_OPTION("lpSubjectSetOption"),
|
||||
LP_SUBJECT_CLEAR_OPTIONS("lpSubjectClearOptions"),
|
||||
|
||||
INTERNAL_SUBJECT_GET_PERMISSION_VALUE("internalSubjectGetPermissionValue"),
|
||||
INTERNAL_SUBJECT_IS_CHILD_OF("internalSubjectIsChildOf"),
|
||||
INTERNAL_SUBJECT_GET_PARENTS("internalSubjectGetParents"),
|
||||
INTERNAL_SUBJECT_GET_OPTION("internalSubjectGetOption"),
|
||||
INTERNAL_SUBJECT_GET_ACTIVE_CONTEXTS("internalSubjectGetActiveContexts"),
|
||||
|
||||
ON_COMMAND("onCommand"),
|
||||
COMMAND_TAB_COMPLETE("commandTabComplete"),
|
||||
ON_CLIENT_LOGIN("onClientLogin"),
|
||||
ON_CLIENT_LEAVE("onClientLeave");
|
||||
|
||||
private final String id;
|
||||
|
||||
}
|
||||
@@ -1,56 +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.timings;
|
||||
|
||||
import lombok.NonNull;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
import co.aikar.timings.Timings;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class LPTimings {
|
||||
private final Map<LPTiming, Timing> timings;
|
||||
|
||||
public LPTimings(LPSpongePlugin plugin) {
|
||||
ImmutableMap.Builder<LPTiming, Timing> map = ImmutableMap.builder();
|
||||
for (LPTiming t : LPTiming.values()) {
|
||||
map.put(t, Timings.of(plugin, t.getId()));
|
||||
}
|
||||
|
||||
timings = map.build();
|
||||
}
|
||||
|
||||
public Timing time(@NonNull LPTiming timing) {
|
||||
Timing t = timings.get(timing);
|
||||
t.startTimingIfSync();
|
||||
return t;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user