mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-27 21:29:47 +01:00
Refactor LP PermissionService to implement a modified API & add proxied classes
This commit is contained in:
parent
163e6e0f2a
commit
8326539d40
@ -153,7 +153,7 @@ public class BukkitListener implements Listener {
|
||||
}
|
||||
|
||||
final Player player = e.getPlayer();
|
||||
final User user = plugin.getUserManager().get(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) {
|
||||
|
@ -337,7 +337,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
for (Player player : getServer().getOnlinePlayers()) {
|
||||
scheduler.doAsync(() -> {
|
||||
LoginHelper.loadUser(this, player.getUniqueId(), player.getName(), false);
|
||||
User user = getUserManager().get(getUuidCache().getUUID(player.getUniqueId()));
|
||||
User user = getUserManager().getIfLoaded(getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (user != null) {
|
||||
scheduler.doSync(() -> {
|
||||
try {
|
||||
@ -371,7 +371,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
player.setOp(false);
|
||||
}
|
||||
|
||||
final User user = getUserManager().get(getUuidCache().getUUID(player.getUniqueId()));
|
||||
final User user = getUserManager().getIfLoaded(getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (user != null) {
|
||||
user.unregisterData();
|
||||
getUserManager().unload(user);
|
||||
|
@ -172,7 +172,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
|
||||
|
||||
// Make a LuckPerms user for the one being migrated.
|
||||
plugin.getStorage().loadUser(uuid, "null").join();
|
||||
User lpUser = plugin.getUserManager().get(uuid);
|
||||
User lpUser = plugin.getUserManager().getIfLoaded(uuid);
|
||||
|
||||
migrateHolder(world, user, lpUser);
|
||||
|
||||
|
@ -261,7 +261,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
for (Map.Entry<UUID, Set<Node>> e : users.entrySet()) {
|
||||
plugin.getStorage().loadUser(e.getKey(), "null").join();
|
||||
me.lucko.luckperms.common.core.model.User user = plugin.getUserManager().get(e.getKey());
|
||||
me.lucko.luckperms.common.core.model.User user = plugin.getUserManager().getIfLoaded(e.getKey());
|
||||
|
||||
for (Node node : e.getValue()) {
|
||||
user.setPermission(node);
|
||||
|
@ -191,7 +191,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
}
|
||||
|
||||
plugin.getStorage().loadUser(u, user.getName()).join();
|
||||
User lpUser = plugin.getUserManager().get(u);
|
||||
User lpUser = plugin.getUserManager().getIfLoaded(u);
|
||||
|
||||
try {
|
||||
for (String node : user.getOwnPermissions(null)) {
|
||||
|
@ -230,7 +230,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
|
||||
// Create a LuckPerms user for the UUID
|
||||
plugin.getStorage().loadUser(uuid, "null").join();
|
||||
User user = plugin.getUserManager().get(uuid);
|
||||
User user = plugin.getUserManager().getIfLoaded(uuid);
|
||||
|
||||
List<Permission> permissions = joinFuture(pm.getPlayerOwnPermissions(uuid));
|
||||
|
||||
|
@ -133,7 +133,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
|
||||
}
|
||||
|
||||
plugin.getStorage().loadUser(u, username).join();
|
||||
User user = plugin.getUserManager().get(u);
|
||||
User user = plugin.getUserManager().getIfLoaded(u);
|
||||
migrateEntity(user, entity, internalService.getGroups(u));
|
||||
user.getPrimaryGroup().setStoredValue(MigrationUtils.standardizeName(service.getPlayerPrimaryGroup(u)));
|
||||
|
||||
|
@ -131,7 +131,7 @@ public class BungeeListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerPostLogin(PostLoginEvent e) {
|
||||
final ProxiedPlayer player = e.getPlayer();
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
|
||||
final User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
|
||||
|
||||
if (user == null) {
|
||||
plugin.getProxy().getScheduler().schedule(plugin, () -> {
|
||||
@ -159,7 +159,7 @@ public class BungeeListener implements Listener {
|
||||
|
||||
final ProxiedPlayer player = ((ProxiedPlayer) e.getSender());
|
||||
|
||||
User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (user == null) {
|
||||
e.setHasPermission(false);
|
||||
return;
|
||||
@ -194,7 +194,7 @@ public class BungeeListener implements Listener {
|
||||
set.add("server", plugin.getConfiguration().get(ConfigKeys.SERVER));
|
||||
set.add("world", serverName);
|
||||
|
||||
User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(uuid));
|
||||
User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(uuid));
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
|
||||
|
||||
// Make a LuckPerms user for the one being migrated.
|
||||
plugin.getStorage().loadUser(u.getUUID(), u.getName()).join();
|
||||
me.lucko.luckperms.common.core.model.User user = plugin.getUserManager().get(u.getUUID());
|
||||
me.lucko.luckperms.common.core.model.User user = plugin.getUserManager().getIfLoaded(u.getUUID());
|
||||
|
||||
// Migrate global perms
|
||||
for (String perm : u.getPerms()) {
|
||||
|
@ -123,7 +123,7 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public User getUser(@NonNull UUID uuid) {
|
||||
final me.lucko.luckperms.common.core.model.User user = plugin.getUserManager().get(uuid);
|
||||
final me.lucko.luckperms.common.core.model.User user = plugin.getUserManager().getIfLoaded(uuid);
|
||||
return user == null ? null : user.getDelegate();
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ public class CheckCommand extends SingleCommand {
|
||||
User user;
|
||||
UUID u = Util.parseUuid(target);
|
||||
if (u != null) {
|
||||
user = plugin.getUserManager().get(u);
|
||||
user = plugin.getUserManager().getIfLoaded(u);
|
||||
} else {
|
||||
user = plugin.getUserManager().getByUsername(target);
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ public class TreeCommand extends SingleCommand {
|
||||
User user;
|
||||
UUID u = Util.parseUuid(player);
|
||||
if (u != null) {
|
||||
user = plugin.getUserManager().get(u);
|
||||
user = plugin.getUserManager().getIfLoaded(u);
|
||||
} else {
|
||||
user = plugin.getUserManager().getByUsername(player);
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ public class UserMainCommand extends MainCommand<User> {
|
||||
Message.LOADING_ERROR.send(sender);
|
||||
}
|
||||
|
||||
User user = plugin.getUserManager().get(u);
|
||||
User user = plugin.getUserManager().getIfLoaded(u);
|
||||
if (user == null) {
|
||||
Message.LOADING_ERROR.send(sender);
|
||||
return null;
|
||||
|
@ -30,7 +30,7 @@ import lombok.Getter;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.utils.ArgumentChecker;
|
||||
@ -214,9 +214,9 @@ public class ArgumentUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static ContextSet handleContexts(int fromIndex, List<String> args) {
|
||||
public static ImmutableContextSet handleContexts(int fromIndex, List<String> args) {
|
||||
if (args.size() <= fromIndex) {
|
||||
return ContextSet.empty();
|
||||
return ImmutableContextSet.empty();
|
||||
}
|
||||
|
||||
MutableContextSet contextSet = MutableContextSet.create();
|
||||
|
@ -216,7 +216,7 @@ public class Exporter implements Runnable {
|
||||
List<String> output = new ArrayList<>();
|
||||
|
||||
plugin.getStorage().loadUser(uuid, "null").join();
|
||||
User user = plugin.getUserManager().get(uuid);
|
||||
User user = plugin.getUserManager().getIfLoaded(uuid);
|
||||
output.add("# Export user: " + user.getUuid().toString() + " - " + user.getName().orElse("unknown username"));
|
||||
|
||||
boolean inDefault = false;
|
||||
|
@ -48,6 +48,8 @@ public interface Manager<I, T extends Identifiable<I>> extends Function<I, T> {
|
||||
/**
|
||||
* Gets or creates an object by id
|
||||
*
|
||||
* <p>Should only every be called by the storage implementation.</p>
|
||||
*
|
||||
* @param id The id to search by
|
||||
* @return a {@link T} object if the object is loaded or makes and returns a new object
|
||||
*/
|
||||
|
@ -47,7 +47,7 @@ public interface UserManager extends Manager<UserIdentifier, User> {
|
||||
* @param uuid The uuid to search by
|
||||
* @return a {@link User} object if the user is loaded, returns null if the user is not loaded
|
||||
*/
|
||||
User get(UUID uuid);
|
||||
User getIfLoaded(UUID uuid);
|
||||
|
||||
/**
|
||||
* Gives the user the default group if necessary.
|
||||
|
@ -123,7 +123,7 @@ public class GenericUserManager extends AbstractManager<UserIdentifier, User> im
|
||||
}
|
||||
|
||||
@Override
|
||||
public User get(UUID uuid) {
|
||||
public User getIfLoaded(UUID uuid) {
|
||||
return getIfLoaded(UserIdentifier.of(uuid, null));
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ public class GenericUserManager extends AbstractManager<UserIdentifier, User> im
|
||||
@Override
|
||||
public void scheduleUnload(UUID uuid) {
|
||||
plugin.getScheduler().doAsyncLater(() -> {
|
||||
User user = get(plugin.getUuidCache().getUUID(uuid));
|
||||
User user = getIfLoaded(plugin.getUuidCache().getUUID(uuid));
|
||||
if (user != null && !plugin.isPlayerOnline(uuid)) {
|
||||
user.unregisterData();
|
||||
unload(user);
|
||||
|
@ -104,7 +104,7 @@ public class AbstractStorage implements Storage {
|
||||
public CompletableFuture<Boolean> loadUser(UUID uuid, String username) {
|
||||
return makeFuture(() -> {
|
||||
if (backing.loadUser(uuid, username)) {
|
||||
plugin.getApiProvider().getEventFactory().handleUserLoad(plugin.getUserManager().get(uuid));
|
||||
plugin.getApiProvider().getEventFactory().handleUserLoad(plugin.getUserManager().getIfLoaded(uuid));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -178,7 +178,7 @@ public abstract class FlatfileBacking extends AbstractBacking {
|
||||
return;
|
||||
}
|
||||
|
||||
User u = plugin.getUserManager().get(uuid);
|
||||
User u = plugin.getUserManager().getIfLoaded(uuid);
|
||||
if (u != null) {
|
||||
plugin.getLog().info("[FileWatcher] Refreshing user " + u.getFriendlyName());
|
||||
plugin.getStorage().loadUser(uuid, "null");
|
||||
|
@ -73,7 +73,7 @@ public class LoginHelper {
|
||||
}
|
||||
|
||||
plugin.getStorage().force().loadUser(cache.getUUID(u), username).join();
|
||||
User user = plugin.getUserManager().get(cache.getUUID(u));
|
||||
User user = plugin.getUserManager().getIfLoaded(cache.getUUID(u));
|
||||
if (user == null) {
|
||||
plugin.getLog().warn("Failed to load user: " + username);
|
||||
throw new RuntimeException("Failed to load user");
|
||||
@ -101,7 +101,7 @@ public class LoginHelper {
|
||||
}
|
||||
|
||||
public static void refreshPlayer(LuckPermsPlugin plugin, UUID uuid) {
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(uuid));
|
||||
final User user = plugin.getUserManager().getIfLoaded(plugin.getUuidCache().getUUID(uuid));
|
||||
if (user != null) {
|
||||
user.getRefreshBuffer().requestDirectly();
|
||||
}
|
||||
|
@ -74,8 +74,9 @@ import me.lucko.luckperms.sponge.managers.SpongeUserManager;
|
||||
import me.lucko.luckperms.sponge.messaging.BungeeMessagingService;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.ServiceCacheHousekeepingTask;
|
||||
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.service.proxy.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.timings.LPTimings;
|
||||
import me.lucko.luckperms.sponge.utils.VersionData;
|
||||
|
||||
@ -99,21 +100,19 @@ import org.spongepowered.api.scheduler.SynchronousExecutor;
|
||||
import org.spongepowered.api.service.permission.PermissionDescription;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
import org.spongepowered.api.text.Text;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@Getter
|
||||
@Plugin(id = "luckperms", name = "LuckPerms", version = VersionData.VERSION, authors = {"Luck"}, description = "A permissions plugin")
|
||||
@ -283,7 +282,8 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
getLog().warn("Delaying LuckPerms PermissionService registration.");
|
||||
lateLoad = true;
|
||||
} else {
|
||||
game.getServiceManager().setProvider(this, PermissionService.class, service);
|
||||
game.getServiceManager().setProvider(this, LPPermissionService.class, service);
|
||||
game.getServiceManager().setProvider(this, PermissionService.class, service.sponge());
|
||||
game.getServiceManager().setProvider(this, LuckPermsService.class, service);
|
||||
}
|
||||
|
||||
@ -308,7 +308,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
scheduler.doAsyncRepeating(new ExpireTemporaryTask(this), 60L);
|
||||
scheduler.doAsyncRepeating(new CacheHousekeepingTask(this), 2400L);
|
||||
scheduler.doAsyncRepeating(new ServiceCacheHousekeepingTask(service), 2400L);
|
||||
scheduler.doAsyncRepeating(() -> userManager.performCleanup(), 2400L);
|
||||
// scheduler.doAsyncRepeating(() -> userManager.performCleanup(), 2400L);
|
||||
|
||||
getLog().info("Successfully loaded.");
|
||||
}
|
||||
@ -317,7 +317,8 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
public void onLateEnable(GamePreInitializationEvent event) {
|
||||
if (lateLoad) {
|
||||
getLog().info("Providing late registration of PermissionService...");
|
||||
game.getServiceManager().setProvider(this, PermissionService.class, service);
|
||||
game.getServiceManager().setProvider(this, LPPermissionService.class, service);
|
||||
game.getServiceManager().setProvider(this, PermissionService.class, service.sponge());
|
||||
game.getServiceManager().setProvider(this, LuckPermsService.class, service);
|
||||
}
|
||||
}
|
||||
@ -359,7 +360,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
|
||||
@Override
|
||||
public void onPostUpdate() {
|
||||
for (LPSubjectCollection collection : service.getCollections().values()) {
|
||||
for (LPSubjectCollection collection : service.getLoadedCollections().values()) {
|
||||
if (collection instanceof PersistedCollection) {
|
||||
((PersistedCollection) collection).loadAll();
|
||||
}
|
||||
@ -475,23 +476,21 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
@Override
|
||||
public LinkedHashMap<String, Object> getExtraInfo() {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("SubjectCollection count", service.getCollections().size());
|
||||
map.put("SubjectCollection count", service.getLoadedCollections().size());
|
||||
map.put("Subject count",
|
||||
service.getCollections().values().stream()
|
||||
.map(SubjectCollection::getAllSubjects)
|
||||
.flatMap(subjects -> StreamSupport.stream(subjects.spliterator(), false))
|
||||
.count()
|
||||
service.getLoadedCollections().values().stream()
|
||||
.map(LPSubjectCollection::getLoadedSubjects)
|
||||
.mapToInt(AbstractCollection::size)
|
||||
.sum()
|
||||
);
|
||||
map.put("PermissionDescription count", service.getDescriptions().size());
|
||||
return map;
|
||||
}
|
||||
|
||||
private void registerPermission(LuckPermsService p, String node) {
|
||||
Optional<PermissionDescription.Builder> builder = p.newDescriptionBuilder(this);
|
||||
if (!builder.isPresent()) return;
|
||||
|
||||
PermissionDescription.Builder builder = p.newDescriptionBuilder(this);
|
||||
try {
|
||||
builder.get().assign(PermissionDescription.ROLE_ADMIN, true).description(Text.of(node)).id(node).register();
|
||||
builder.assign(PermissionDescription.ROLE_ADMIN, true).description(Text.of(node)).id(node).register();
|
||||
} catch (IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public class SpongeCalculatorFactory extends AbstractCalculatorFactory {
|
||||
}
|
||||
|
||||
if (plugin.getConfiguration().get(ConfigKeys.APPLY_SPONGE_DEFAULT_SUBJECTS)) {
|
||||
processors.add(new DefaultsProcessor(plugin.getService(), contexts.getContexts()));
|
||||
processors.add(new DefaultsProcessor(plugin.getService(), contexts.getContexts().makeImmutable()));
|
||||
}
|
||||
|
||||
return registerCalculator(new PermissionCalculator(plugin, user.getFriendlyName(), processors.build()));
|
||||
|
@ -154,7 +154,7 @@ public class SpongeListener {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = plugin.getUserManager().get(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) {
|
||||
@ -179,13 +179,13 @@ public class SpongeListener {
|
||||
|
||||
plugin.doAsync(() -> {
|
||||
UserData data = user.getUserData();
|
||||
data.preCalculate(plugin.getService().calculateContexts(context));
|
||||
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));
|
||||
data.preCalculate(plugin.getService().calculateContexts(modified.makeImmutable()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ package me.lucko.luckperms.sponge.calculators;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.calculators.PermissionProcessor;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
|
||||
@ -37,11 +37,11 @@ import java.util.Map;
|
||||
@AllArgsConstructor
|
||||
public class DefaultsProcessor implements PermissionProcessor {
|
||||
private final LuckPermsService service;
|
||||
private final ContextSet contexts;
|
||||
private final ImmutableContextSet contexts;
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
Tristate t = service.getUserSubjects().getDefaultSubject().resolve(service).getPermissionValue(contexts, permission);
|
||||
Tristate t = service.getUserSubjects().getDefaults().getPermissionValue(contexts, permission);
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
@ -36,7 +36,7 @@ import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -51,7 +51,7 @@ public class OptionClear extends SubCommand<LPSubjectData> {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
if (contextSet.isEmpty()) {
|
||||
subjectData.clearOptions();
|
||||
Util.sendPluginMessage(sender, "&aCleared options matching contexts &bANY&a.");
|
||||
|
@ -25,7 +25,8 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
@ -37,7 +38,7 @@ import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -51,16 +52,16 @@ public class OptionInfo extends SubCommand<LPSubjectData> {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
if (contextSet.isEmpty()) {
|
||||
Util.sendPluginMessage(sender, "&aShowing options matching contexts &bANY&a.");
|
||||
Map<ImmutableContextSet, Map<String, String>> options = subjectData.getOptions();
|
||||
Map<ImmutableContextSet, ImmutableMap<String, String>> options = subjectData.getAllOptions();
|
||||
if (options.isEmpty()) {
|
||||
Util.sendPluginMessage(sender, "That subject does not have any options defined.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
for (Map.Entry<ImmutableContextSet, Map<String, String>> e : options.entrySet()) {
|
||||
for (Map.Entry<ImmutableContextSet, ImmutableMap<String, String>> e : options.entrySet()) {
|
||||
Util.sendPluginMessage(sender, "&3>> &bContext: " + SpongeUtils.contextToString(e.getKey()) + "\n" + SpongeUtils.optionsToString(e.getValue()));
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
@ -36,7 +36,7 @@ import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -55,9 +55,9 @@ public class OptionSet extends SubCommand<LPSubjectData> {
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
String key = args.get(0);
|
||||
String value = args.get(1);
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(2, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(2, args);
|
||||
|
||||
if (subjectData.setOption(contextSet, key, value)) {
|
||||
if (subjectData.setOption(contextSet, key, value).join()) {
|
||||
Util.sendPluginMessage(sender, "&aSet &f\"" + key + "&f\"&a to &f\"" + value + "&f\"&a in context " + SpongeUtils.contextToString(contextSet));
|
||||
} else {
|
||||
Util.sendPluginMessage(sender, "Unable to set option. Does the Subject already have it set?");
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
@ -36,7 +36,7 @@ import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -53,9 +53,9 @@ public class OptionUnset extends SubCommand<LPSubjectData> {
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
String key = args.get(0);
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(1, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(1, args);
|
||||
|
||||
if (subjectData.setOption(contextSet, key, null)) {
|
||||
if (subjectData.unsetOption(contextSet, key).join()) {
|
||||
Util.sendPluginMessage(sender, "&aUnset &f\"" + key + "&f\"&a in context " + SpongeUtils.contextToString(contextSet));
|
||||
} else {
|
||||
Util.sendPluginMessage(sender, "Unable to unset option. Are you sure the Subject has it set?");
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
@ -37,9 +37,9 @@ import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import org.spongepowered.api.Sponge;
|
||||
|
||||
@ -60,22 +60,22 @@ public class ParentAdd extends SubCommand<LPSubjectData> {
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
String collection = args.get(0);
|
||||
String name = args.get(1);
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(2, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(2, args);
|
||||
|
||||
LuckPermsService service = Sponge.getServiceManager().provideUnchecked(LuckPermsService.class);
|
||||
if (service.getCollections().keySet().stream().map(String::toLowerCase).noneMatch(s -> s.equalsIgnoreCase(collection))) {
|
||||
if (service.getLoadedCollections().keySet().stream().map(String::toLowerCase).noneMatch(s -> s.equalsIgnoreCase(collection))) {
|
||||
Util.sendPluginMessage(sender, "Warning: SubjectCollection '&4" + collection + "&c' doesn't already exist.");
|
||||
}
|
||||
|
||||
LPSubjectCollection c = service.getSubjects(collection);
|
||||
if (!c.hasRegistered(name)) {
|
||||
LPSubjectCollection c = service.getCollection(collection);
|
||||
if (!c.hasRegistered(name).join()) {
|
||||
Util.sendPluginMessage(sender, "Warning: Subject '&4" + name + "&c' doesn't already exist.");
|
||||
}
|
||||
|
||||
LPSubject subject = c.get(name);
|
||||
LPSubject subject = c.loadSubject(name).join();
|
||||
|
||||
if (subjectData.addParent(contextSet, subject.toReference())) {
|
||||
Util.sendPluginMessage(sender, "&aAdded parent &b" + subject.getContainingCollection().getIdentifier() +
|
||||
if (subjectData.addParent(contextSet, subject.toReference()).join()) {
|
||||
Util.sendPluginMessage(sender, "&aAdded parent &b" + subject.getParentCollection().getIdentifier() +
|
||||
"&a/&b" + subject.getIdentifier() + "&a in context " + SpongeUtils.contextToString(contextSet));
|
||||
} else {
|
||||
Util.sendPluginMessage(sender, "Unable to add parent. Does the Subject already have it added?");
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
@ -36,7 +36,7 @@ import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -51,7 +51,7 @@ public class ParentClear extends SubCommand<LPSubjectData> {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
if (contextSet.isEmpty()) {
|
||||
subjectData.clearParents();
|
||||
Util.sendPluginMessage(sender, "&aCleared parents matching contexts &bANY&a.");
|
||||
|
@ -25,7 +25,8 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
@ -37,12 +38,11 @@ import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class ParentInfo extends SubCommand<LPSubjectData> {
|
||||
public ParentInfo() {
|
||||
@ -53,21 +53,21 @@ public class ParentInfo extends SubCommand<LPSubjectData> {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
if (contextSet.isEmpty()) {
|
||||
Util.sendPluginMessage(sender, "&aShowing parents matching contexts &bANY&a.");
|
||||
Map<ImmutableContextSet, Set<SubjectReference>> parents = subjectData.getParents();
|
||||
Map<ImmutableContextSet, ImmutableList<SubjectReference>> parents = subjectData.getAllParents();
|
||||
if (parents.isEmpty()) {
|
||||
Util.sendPluginMessage(sender, "That subject does not have any parents defined.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
for (Map.Entry<ImmutableContextSet, Set<SubjectReference>> e : parents.entrySet()) {
|
||||
for (Map.Entry<ImmutableContextSet, ImmutableList<SubjectReference>> e : parents.entrySet()) {
|
||||
Util.sendPluginMessage(sender, "&3>> &bContext: " + SpongeUtils.contextToString(e.getKey()) + "\n" + SpongeUtils.parentsToString(e.getValue()));
|
||||
}
|
||||
|
||||
} else {
|
||||
Set<SubjectReference> parents = subjectData.getParents(contextSet);
|
||||
List<SubjectReference> parents = subjectData.getParents(contextSet);
|
||||
if (parents.isEmpty()) {
|
||||
Util.sendPluginMessage(sender, "That subject does not have any parents defined in those contexts.");
|
||||
return CommandResult.SUCCESS;
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
@ -37,9 +37,9 @@ import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import org.spongepowered.api.Sponge;
|
||||
|
||||
@ -60,22 +60,22 @@ public class ParentRemove extends SubCommand<LPSubjectData> {
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
String collection = args.get(0);
|
||||
String name = args.get(1);
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(2, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(2, args);
|
||||
|
||||
LuckPermsService service = Sponge.getServiceManager().provideUnchecked(LuckPermsService.class);
|
||||
if (service.getCollections().keySet().stream().map(String::toLowerCase).noneMatch(s -> s.equalsIgnoreCase(collection))) {
|
||||
if (service.getLoadedCollections().keySet().stream().map(String::toLowerCase).noneMatch(s -> s.equalsIgnoreCase(collection))) {
|
||||
Util.sendPluginMessage(sender, "Warning: SubjectCollection '&4" + collection + "&c' doesn't exist.");
|
||||
}
|
||||
|
||||
LPSubjectCollection c = service.getSubjects(collection);
|
||||
if (!c.hasRegistered(name)) {
|
||||
LPSubjectCollection c = service.getCollection(collection);
|
||||
if (!c.hasRegistered(name).join()) {
|
||||
Util.sendPluginMessage(sender, "Warning: Subject '&4" + name + "&c' doesn't exist.");
|
||||
}
|
||||
|
||||
LPSubject subject = c.get(name);
|
||||
LPSubject subject = c.loadSubject(name).join();
|
||||
|
||||
if (subjectData.removeParent(contextSet, subject.toReference())) {
|
||||
Util.sendPluginMessage(sender, "&aRemoved parent &b" + subject.getContainingCollection().getIdentifier() +
|
||||
if (subjectData.removeParent(contextSet, subject.toReference()).join()) {
|
||||
Util.sendPluginMessage(sender, "&aRemoved parent &b" + subject.getParentCollection().getIdentifier() +
|
||||
"&a/&b" + subject.getIdentifier() + "&a in context " + SpongeUtils.contextToString(contextSet));
|
||||
} else {
|
||||
Util.sendPluginMessage(sender, "Unable to remove parent. Are you sure the Subject has it added?");
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
@ -36,7 +36,7 @@ import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -51,7 +51,7 @@ public class PermissionClear extends SubCommand<LPSubjectData> {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
if (contextSet.isEmpty()) {
|
||||
subjectData.clearPermissions();
|
||||
Util.sendPluginMessage(sender, "&aCleared permissions matching contexts &bANY&a.");
|
||||
|
@ -25,7 +25,8 @@
|
||||
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
@ -37,7 +38,7 @@ import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -51,16 +52,16 @@ public class PermissionInfo extends SubCommand<LPSubjectData> {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(0, args);
|
||||
if (contextSet.isEmpty()) {
|
||||
Util.sendPluginMessage(sender, "&aShowing permissions matching contexts &bANY&a.");
|
||||
Map<ImmutableContextSet, Map<String, Boolean>> permissions = subjectData.getPermissions();
|
||||
Map<ImmutableContextSet, ImmutableMap<String, Boolean>> permissions = subjectData.getAllPermissions();
|
||||
if (permissions.isEmpty()) {
|
||||
Util.sendPluginMessage(sender, "That subject does not have any permissions defined.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
for (Map.Entry<ImmutableContextSet, Map<String, Boolean>> e : permissions.entrySet()) {
|
||||
for (Map.Entry<ImmutableContextSet, ImmutableMap<String, Boolean>> e : permissions.entrySet()) {
|
||||
Util.sendPluginMessage(sender, "&3>> &bContext: " + SpongeUtils.contextToString(e.getKey()) + "\n" + SpongeUtils.nodesToString(e.getValue()));
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
package me.lucko.luckperms.sponge.commands;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
@ -37,7 +37,7 @@ import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -56,9 +56,9 @@ public class PermissionSet extends SubCommand<LPSubjectData> {
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, LPSubjectData subjectData, List<String> args, String label) throws CommandException {
|
||||
String node = args.get(0);
|
||||
Tristate tristate = SpongeUtils.parseTristate(1, args);
|
||||
ContextSet contextSet = ArgumentUtils.handleContexts(2, args);
|
||||
ImmutableContextSet contextSet = ArgumentUtils.handleContexts(2, args);
|
||||
|
||||
if (subjectData.setPermission(contextSet, node, tristate)) {
|
||||
if (subjectData.setPermission(contextSet, node, tristate).join()) {
|
||||
Util.sendPluginMessage(sender, "&aSet &b" + node + "&a to &b" + tristate.toString().toLowerCase() + "&a in context " + SpongeUtils.contextToString(contextSet));
|
||||
} else {
|
||||
Util.sendPluginMessage(sender, "Unable to set permission. Does the Subject already have it set?");
|
||||
|
@ -41,9 +41,9 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -100,7 +100,7 @@ public class SpongeMainCommand extends Command<Void, LPSubjectData> {
|
||||
|
||||
if (args.size() < 1) {
|
||||
Util.sendPluginMessage(sender, "&aCurrent Subject Collections:\n" +
|
||||
Util.toCommaSep(service.getCollections().keySet().stream()
|
||||
Util.toCommaSep(service.getLoadedCollections().keySet().stream()
|
||||
.filter(s -> !s.equalsIgnoreCase("user") && !s.equalsIgnoreCase("group"))
|
||||
.sorted()
|
||||
.collect(Collectors.toList())
|
||||
@ -116,14 +116,14 @@ public class SpongeMainCommand extends Command<Void, LPSubjectData> {
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
if (service.getCollections().keySet().stream().map(String::toLowerCase).noneMatch(s -> s.equalsIgnoreCase(subjectCollection))) {
|
||||
if (service.getLoadedCollections().keySet().stream().map(String::toLowerCase).noneMatch(s -> s.equalsIgnoreCase(subjectCollection))) {
|
||||
Util.sendPluginMessage(sender, "Warning: SubjectCollection '&4" + subjectCollection + "&c' doesn't already exist. Creating it now.");
|
||||
}
|
||||
|
||||
LPSubjectCollection collection = service.getSubjects(subjectCollection);
|
||||
LPSubjectCollection collection = service.getCollection(subjectCollection);
|
||||
|
||||
if (args.size() < 2) {
|
||||
List<String> subjects = collection.getSubjects().stream()
|
||||
List<String> subjects = collection.getLoadedSubjects().stream()
|
||||
.map(LPSubject::getIdentifier)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
@ -183,11 +183,11 @@ public class SpongeMainCommand extends Command<Void, LPSubjectData> {
|
||||
}
|
||||
|
||||
String subjectId = args.get(1);
|
||||
if (!collection.hasRegistered(subjectId)) {
|
||||
if (!collection.hasRegistered(subjectId).join()) {
|
||||
Util.sendPluginMessage(sender, "Warning: Subject '&4" + subjectId + "&c' doesn't already exist. Creating it now.");
|
||||
}
|
||||
|
||||
LPSubject subject = collection.get(subjectId);
|
||||
LPSubject subject = collection.loadSubject(subjectId).join();
|
||||
LPSubjectData subjectData = persistent ? subject.getSubjectData() : subject.getTransientSubjectData();
|
||||
|
||||
CommandResult result;
|
||||
|
@ -35,7 +35,6 @@ import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@UtilityClass
|
||||
public class SpongeUtils {
|
||||
@ -77,7 +76,7 @@ public class SpongeUtils {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String parentsToString(Set<SubjectReference> parents) {
|
||||
public static String parentsToString(Iterable<SubjectReference> parents) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (SubjectReference s : parents) {
|
||||
sb.append("&3> &a")
|
||||
|
@ -29,7 +29,7 @@ import lombok.AllArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextCalculator;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.sponge.service.proxy.Util;
|
||||
import me.lucko.luckperms.sponge.service.model.CompatibilityUtil;
|
||||
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
@ -46,7 +46,7 @@ public class SpongeCalculatorLink implements ContextCalculator<Subject> {
|
||||
Set<Context> contexts = new HashSet<>();
|
||||
calculator.accumulateContexts(subject, contexts);
|
||||
|
||||
accumulator.addAll(Util.convertContexts(contexts));
|
||||
accumulator.addAll(CompatibilityUtil.convertContexts(contexts));
|
||||
return accumulator;
|
||||
}
|
||||
}
|
||||
|
@ -26,41 +26,50 @@
|
||||
package me.lucko.luckperms.sponge.managers;
|
||||
|
||||
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.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import me.lucko.luckperms.api.HeldPermission;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.api.event.cause.CreationCause;
|
||||
import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.managers.GroupManager;
|
||||
import me.lucko.luckperms.common.utils.ArgumentChecker;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
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.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.proxy.SubjectCollectionProxy;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
|
||||
|
||||
@Getter
|
||||
private final LPSpongePlugin plugin;
|
||||
|
||||
private SubjectCollectionProxy spongeProxy = null;
|
||||
|
||||
private final LoadingCache<String, SpongeGroup> objects = Caffeine.newBuilder()
|
||||
.build(new CacheLoader<String, SpongeGroup>() {
|
||||
@Override
|
||||
@ -77,20 +86,26 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
|
||||
private final LoadingCache<String, LPSubject> subjectLoadingCache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.MINUTES)
|
||||
.build(s -> {
|
||||
if (isLoaded(s)) {
|
||||
return getIfLoaded(s).getSpongeData();
|
||||
SpongeGroup group = getIfLoaded(s);
|
||||
if (group != null) {
|
||||
// they're already loaded, but the data might not actually be there yet
|
||||
// if stuff is being loaded, then the user's i/o lock will be locked by the storage impl
|
||||
group.getIoLock().lock();
|
||||
group.getIoLock().unlock();
|
||||
|
||||
return group.sponge();
|
||||
}
|
||||
|
||||
// Request load
|
||||
getPlugin().getStorage().createAndLoadGroup(s, CreationCause.INTERNAL).join();
|
||||
|
||||
SpongeGroup group = getIfLoaded(s);
|
||||
group = getIfLoaded(s);
|
||||
if (group == null) {
|
||||
getPlugin().getLog().severe("Error whilst loading group '" + s + "'.");
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
return group.getSpongeData();
|
||||
return group.sponge();
|
||||
});
|
||||
|
||||
public SpongeGroupManager(LPSpongePlugin plugin) {
|
||||
@ -150,8 +165,11 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
|
||||
* ------------------------------------------ */
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return PermissionService.SUBJECTS_GROUP;
|
||||
public synchronized SubjectCollection sponge() {
|
||||
if (spongeProxy == null) {
|
||||
spongeProxy = new SubjectCollectionProxy(Preconditions.checkNotNull(plugin.getService(), "service"), this);
|
||||
}
|
||||
return spongeProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -160,52 +178,119 @@ public class SpongeGroupManager implements GroupManager, LPSubjectCollection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPSubject get(@NonNull String id) {
|
||||
// Special Sponge method. This call will actually load the group from the datastore if not already present.
|
||||
public String getIdentifier() {
|
||||
return PermissionService.SUBJECTS_GROUP;
|
||||
}
|
||||
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_COLLECTION_GET)) {
|
||||
id = id.toLowerCase();
|
||||
if (ArgumentChecker.checkNameWithSpace(id)) {
|
||||
plugin.getLog().warn("Couldn't get group subject for id: " + id + " (invalid name)");
|
||||
return plugin.getService().getFallbackGroupSubjects().get(id); // fallback to transient collection
|
||||
}
|
||||
@Override
|
||||
public Predicate<String> getIdentifierValidityPredicate() {
|
||||
// TODO change this to use the actual limitations
|
||||
return Predicates.alwaysTrue();
|
||||
}
|
||||
|
||||
try {
|
||||
return subjectLoadingCache.get(id);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
plugin.getLog().warn("Couldn't get group subject for id: " + id);
|
||||
return plugin.getService().getFallbackGroupSubjects().get(id); // fallback to the transient collection
|
||||
}
|
||||
@Override
|
||||
public CompletableFuture<LPSubject> loadSubject(String identifier) {
|
||||
LPSubject present = subjectLoadingCache.getIfPresent(identifier.toLowerCase());
|
||||
if (present != null) {
|
||||
return CompletableFuture.completedFuture(present);
|
||||
}
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> subjectLoadingCache.get(identifier.toLowerCase()), plugin.getScheduler().getAsyncExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<LPSubject> getSubject(String identifier) {
|
||||
return Optional.ofNullable(getIfLoaded(identifier.toLowerCase())).map(SpongeGroup::sponge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> hasRegistered(String identifier) {
|
||||
if (isLoaded(identifier.toLowerCase())) {
|
||||
return CompletableFuture.completedFuture(true);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRegistered(@NonNull String id) {
|
||||
id = id.toLowerCase();
|
||||
return !ArgumentChecker.checkName(id) && isLoaded(id);
|
||||
public CompletableFuture<ImmutableCollection<LPSubject>> loadSubjects(Set<String> identifiers) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ImmutableSet.Builder<LPSubject> ret = ImmutableSet.builder();
|
||||
for (String id : identifiers) {
|
||||
ret.add(loadSubject(id.toLowerCase()).join());
|
||||
}
|
||||
|
||||
return ret.build();
|
||||
}, plugin.getScheduler().getAsyncExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<LPSubject> getSubjects() {
|
||||
return objects.asMap().values().stream().map(SpongeGroup::getSpongeData).collect(ImmutableCollectors.toImmutableList());
|
||||
public ImmutableCollection<LPSubject> getLoadedSubjects() {
|
||||
return getAll().values().stream().map(SpongeGroup::sponge).collect(ImmutableCollectors.toImmutableSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<LPSubject, Boolean> getWithPermission(@NonNull ContextSet contexts, @NonNull String node) {
|
||||
public CompletableFuture<ImmutableSet<String>> getAllIdentifiers() {
|
||||
return CompletableFuture.completedFuture(ImmutableSet.copyOf(getAll().keySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ImmutableMap<SubjectReference, Boolean>> getAllWithPermission(String permission) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ImmutableMap.Builder<SubjectReference, Boolean> ret = ImmutableMap.builder();
|
||||
|
||||
List<HeldPermission<String>> lookup = plugin.getStorage().getGroupsWithPermission(permission).join();
|
||||
for (HeldPermission<String> holder : lookup) {
|
||||
if (holder.asNode().getFullContexts().equals(ImmutableContextSet.empty())) {
|
||||
ret.put(getService().newSubjectReference(getIdentifier(), holder.getHolder()), holder.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return ret.build();
|
||||
}, plugin.getScheduler().getAsyncExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ImmutableMap<SubjectReference, Boolean>> getAllWithPermission(ImmutableContextSet contexts, String permission) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ImmutableMap.Builder<SubjectReference, Boolean> ret = ImmutableMap.builder();
|
||||
|
||||
List<HeldPermission<String>> lookup = plugin.getStorage().getGroupsWithPermission(permission).join();
|
||||
for (HeldPermission<String> holder : lookup) {
|
||||
if (holder.asNode().getFullContexts().equals(contexts)) {
|
||||
ret.put(getService().newSubjectReference(getIdentifier(), holder.getHolder()), holder.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return ret.build();
|
||||
}, plugin.getScheduler().getAsyncExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(String permission) {
|
||||
return objects.asMap().values().stream()
|
||||
.map(SpongeGroup::getSpongeData)
|
||||
.filter(sub -> sub.getPermissionValue(contexts, node) != Tristate.UNDEFINED)
|
||||
.collect(ImmutableCollectors.toImmutableMap(sub -> sub, sub -> sub.getPermissionValue(contexts, node).asBoolean()));
|
||||
.map(SpongeGroup::sponge)
|
||||
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(ImmutableContextSet.empty(), permission)))
|
||||
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
||||
.collect(ImmutableCollectors.toImmutableMap(Map.Entry::getKey, sub -> sub.getValue().asBoolean()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectReference getDefaultSubject() {
|
||||
return SubjectReference.of("defaults", getIdentifier());
|
||||
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(ImmutableContextSet contexts, String permission) {
|
||||
return objects.asMap().values().stream()
|
||||
.map(SpongeGroup::sponge)
|
||||
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(contexts, permission)))
|
||||
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
||||
.collect(ImmutableCollectors.toImmutableMap(Map.Entry::getKey, sub -> sub.getValue().asBoolean()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTransientHasPriority() {
|
||||
return true;
|
||||
public LPSubject getDefaults() {
|
||||
return getService().getDefaultSubjects().loadSubject(getIdentifier()).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestUnload(String identifier) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
@ -26,16 +26,19 @@
|
||||
package me.lucko.luckperms.sponge.managers;
|
||||
|
||||
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.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import me.lucko.luckperms.api.HeldPermission;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.core.UserIdentifier;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.common.managers.UserManager;
|
||||
@ -44,28 +47,30 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
import me.lucko.luckperms.sponge.model.SpongeUser;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.proxy.SubjectCollectionProxy;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
||||
|
||||
@Getter
|
||||
private final LPSpongePlugin plugin;
|
||||
|
||||
|
||||
private SubjectCollectionProxy spongeProxy = null;
|
||||
|
||||
private final LoadingCache<UserIdentifier, SpongeUser> objects = Caffeine.newBuilder()
|
||||
.build(new CacheLoader<UserIdentifier, SpongeUser>() {
|
||||
@Override
|
||||
@ -82,23 +87,29 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
||||
private final LoadingCache<UUID, LPSubject> subjectLoadingCache = Caffeine.<UUID, LPSubject>newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.MINUTES)
|
||||
.build(u -> {
|
||||
if (isLoaded(UserIdentifier.of(u, null))) {
|
||||
SpongeUser user = get(u);
|
||||
// check if the user instance is already loaded.
|
||||
SpongeUser user = getIfLoaded(u);
|
||||
if (user != null) {
|
||||
// they're already loaded, but the data might not actually be there yet
|
||||
// if stuff is being loaded, then the user's i/o lock will be locked by the storage impl
|
||||
user.getIoLock().lock();
|
||||
user.getIoLock().unlock();
|
||||
|
||||
// ok, data is here, let's do the pre-calculation stuff.
|
||||
user.preCalculateData(false);
|
||||
return get(u).getSpongeData();
|
||||
return user.sponge();
|
||||
}
|
||||
|
||||
// Request load
|
||||
getPlugin().getStorage().loadUser(u, "null").join();
|
||||
|
||||
SpongeUser user = get(u);
|
||||
getPlugin().getStorage().loadUser(u, null).join();
|
||||
user = getIfLoaded(u);
|
||||
if (user == null) {
|
||||
getPlugin().getLog().severe("Error whilst loading user '" + u + "'.");
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
user.preCalculateData(false);
|
||||
return user.getSpongeData();
|
||||
return user.sponge();
|
||||
});
|
||||
|
||||
public SpongeUserManager(LPSpongePlugin plugin) {
|
||||
@ -112,18 +123,6 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
||||
new SpongeUser(id.getUuid(), id.getUsername().get(), plugin);
|
||||
}
|
||||
|
||||
public void performCleanup() {
|
||||
Set<UserIdentifier> set = new HashSet<>();
|
||||
for (Map.Entry<UserIdentifier, SpongeUser> user : objects.asMap().entrySet()) {
|
||||
if (user.getValue().getSpongeData().shouldCleanup()) {
|
||||
user.getValue().unregisterData();
|
||||
set.add(user.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
objects.invalidateAll(set);
|
||||
}
|
||||
|
||||
/* ------------------------------------------
|
||||
* Manager methods
|
||||
* ------------------------------------------ */
|
||||
@ -183,7 +182,7 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpongeUser get(UUID uuid) {
|
||||
public SpongeUser getIfLoaded(UUID uuid) {
|
||||
return getIfLoaded(UserIdentifier.of(uuid, null));
|
||||
}
|
||||
|
||||
@ -220,8 +219,11 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
||||
* ------------------------------------------ */
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return PermissionService.SUBJECTS_USER;
|
||||
public synchronized SubjectCollection sponge() {
|
||||
if (spongeProxy == null) {
|
||||
spongeProxy = new SubjectCollectionProxy(Preconditions.checkNotNull(plugin.getService(), "service"), this);
|
||||
}
|
||||
return spongeProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -230,58 +232,166 @@ public class SpongeUserManager implements UserManager, LPSubjectCollection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPSubject get(@NonNull String id) {
|
||||
// Special Sponge method. This call will actually load the user from the datastore if not already present.
|
||||
public String getIdentifier() {
|
||||
return PermissionService.SUBJECTS_USER;
|
||||
}
|
||||
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_COLLECTION_GET)) {
|
||||
UUID uuid = Util.parseUuid(id);
|
||||
if (uuid == null) {
|
||||
plugin.getLog().warn("Couldn't get user subject for id: " + id + " (not a uuid)");
|
||||
return plugin.getService().getFallbackUserSubjects().get(id); // fallback to the transient collection
|
||||
}
|
||||
|
||||
UUID u = plugin.getUuidCache().getUUID(uuid);
|
||||
@Override
|
||||
public Predicate<String> getIdentifierValidityPredicate() {
|
||||
return s -> {
|
||||
try {
|
||||
return subjectLoadingCache.get(u);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
plugin.getLog().warn("Couldn't get user subject for id: " + id);
|
||||
return plugin.getService().getFallbackUserSubjects().get(id); // fallback to the transient collection
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
UUID.fromString(s);
|
||||
return true;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRegistered(@NonNull String id) {
|
||||
UUID uuid = Util.parseUuid(id);
|
||||
public CompletableFuture<LPSubject> loadSubject(String identifier) {
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = UUID.fromString(identifier);
|
||||
} catch (IllegalArgumentException e) {
|
||||
CompletableFuture<LPSubject> fut = new CompletableFuture<>();
|
||||
fut.completeExceptionally(e);
|
||||
return fut;
|
||||
}
|
||||
|
||||
LPSubject present = subjectLoadingCache.getIfPresent(uuid);
|
||||
if (present != null) {
|
||||
return CompletableFuture.completedFuture(present);
|
||||
}
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> subjectLoadingCache.get(uuid), plugin.getScheduler().getAsyncExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<LPSubject> getSubject(String identifier) {
|
||||
UUID uuid = UUID.fromString(identifier);
|
||||
return Optional.ofNullable(getIfLoaded(uuid)).map(SpongeUser::sponge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> hasRegistered(String identifier) {
|
||||
UUID uuid = null;
|
||||
IllegalArgumentException ex = null;
|
||||
try {
|
||||
uuid = UUID.fromString(identifier);
|
||||
} catch (IllegalArgumentException e) {
|
||||
ex = e;
|
||||
}
|
||||
|
||||
if (uuid != null && isLoaded(UserIdentifier.of(uuid, null))) {
|
||||
return CompletableFuture.completedFuture(true);
|
||||
}
|
||||
|
||||
if (uuid == null) {
|
||||
return false;
|
||||
CompletableFuture<Boolean> fut = new CompletableFuture<>();
|
||||
fut.completeExceptionally(ex);
|
||||
return fut;
|
||||
}
|
||||
|
||||
UUID internal = plugin.getUuidCache().getUUID(uuid);
|
||||
return isLoaded(UserIdentifier.of(internal, null));
|
||||
UUID finalUuid = uuid;
|
||||
return plugin.getStorage().getUniqueUsers().thenApply(set -> set.contains(finalUuid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<LPSubject> getSubjects() {
|
||||
return objects.asMap().values().stream().map(SpongeUser::getSpongeData).collect(ImmutableCollectors.toImmutableList());
|
||||
public CompletableFuture<ImmutableCollection<LPSubject>> loadSubjects(Set<String> identifiers) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ImmutableSet.Builder<LPSubject> ret = ImmutableSet.builder();
|
||||
for (String id : identifiers) {
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = UUID.fromString(id);
|
||||
} catch (IllegalArgumentException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.add(loadSubject(uuid.toString()).join());
|
||||
}
|
||||
|
||||
return ret.build();
|
||||
}, plugin.getScheduler().getAsyncExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<LPSubject, Boolean> getWithPermission(@NonNull ContextSet contexts, @NonNull String node) {
|
||||
public ImmutableCollection<LPSubject> getLoadedSubjects() {
|
||||
return getAll().values().stream().map(SpongeUser::sponge).collect(ImmutableCollectors.toImmutableSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ImmutableSet<String>> getAllIdentifiers() {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ImmutableSet.Builder<String> ids = ImmutableSet.builder();
|
||||
|
||||
getAll().keySet().forEach(uuid -> ids.add(uuid.getUuid().toString()));
|
||||
plugin.getStorage().getUniqueUsers().join().forEach(uuid -> ids.add(uuid.toString()));
|
||||
|
||||
return ids.build();
|
||||
}, plugin.getScheduler().getAsyncExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ImmutableMap<SubjectReference, Boolean>> getAllWithPermission(String permission) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ImmutableMap.Builder<SubjectReference, Boolean> ret = ImmutableMap.builder();
|
||||
|
||||
List<HeldPermission<UUID>> lookup = plugin.getStorage().getUsersWithPermission(permission).join();
|
||||
for (HeldPermission<UUID> holder : lookup) {
|
||||
if (holder.asNode().getFullContexts().equals(ImmutableContextSet.empty())) {
|
||||
ret.put(getService().newSubjectReference(getIdentifier(), holder.getHolder().toString()), holder.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return ret.build();
|
||||
}, plugin.getScheduler().getAsyncExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ImmutableMap<SubjectReference, Boolean>> getAllWithPermission(ImmutableContextSet contexts, String permission) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
ImmutableMap.Builder<SubjectReference, Boolean> ret = ImmutableMap.builder();
|
||||
|
||||
List<HeldPermission<UUID>> lookup = plugin.getStorage().getUsersWithPermission(permission).join();
|
||||
for (HeldPermission<UUID> holder : lookup) {
|
||||
if (holder.asNode().getFullContexts().equals(contexts)) {
|
||||
ret.put(getService().newSubjectReference(getIdentifier(), holder.getHolder().toString()), holder.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return ret.build();
|
||||
}, plugin.getScheduler().getAsyncExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(String permission) {
|
||||
return objects.asMap().values().stream()
|
||||
.map(SpongeUser::getSpongeData)
|
||||
.filter(sub -> sub.getPermissionValue(contexts, node) != Tristate.UNDEFINED)
|
||||
.collect(ImmutableCollectors.toImmutableMap(sub -> sub, sub -> sub.getPermissionValue(contexts, node).asBoolean()));
|
||||
.map(SpongeUser::sponge)
|
||||
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(ImmutableContextSet.empty(), permission)))
|
||||
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
||||
.collect(ImmutableCollectors.toImmutableMap(Map.Entry::getKey, sub -> sub.getValue().asBoolean()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectReference getDefaultSubject() {
|
||||
return SubjectReference.of("defaults", getIdentifier());
|
||||
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(ImmutableContextSet contexts, String permission) {
|
||||
return objects.asMap().values().stream()
|
||||
.map(SpongeUser::sponge)
|
||||
.map(sub -> Maps.immutableEntry(sub, sub.getPermissionValue(contexts, permission)))
|
||||
.filter(pair -> pair.getValue() != Tristate.UNDEFINED)
|
||||
.collect(ImmutableCollectors.toImmutableMap(Map.Entry::getKey, sub -> sub.getValue().asBoolean()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTransientHasPriority() {
|
||||
return true;
|
||||
public LPSubject getDefaults() {
|
||||
return getService().getDefaultSubjects().loadSubject(getIdentifier()).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestUnload(String identifier) {
|
||||
// noop
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -93,10 +93,10 @@ public class MigrationPermissionManager extends SubCommand<Object> {
|
||||
for (SubjectCollection collection : pmService.getKnownSubjects().values()) {
|
||||
SpongeMigrationUtils.migrateSubjectData(
|
||||
collection.getDefaults().getSubjectData(),
|
||||
lpService.getSubjects("defaults").get(collection.getIdentifier()).getSubjectData()
|
||||
lpService.getCollection("defaults").loadSubject(collection.getIdentifier()).join().sponge().getSubjectData()
|
||||
);
|
||||
}
|
||||
SpongeMigrationUtils.migrateSubjectData(pmService.getDefaults().getSubjectData(), lpService.getDefaults().getSubjectData());
|
||||
SpongeMigrationUtils.migrateSubjectData(pmService.getDefaults().getSubjectData(), lpService.getDefaults().sponge().getSubjectData());
|
||||
|
||||
// Migrate groups
|
||||
log.log("Starting group migration.");
|
||||
@ -126,7 +126,7 @@ public class MigrationPermissionManager extends SubCommand<Object> {
|
||||
|
||||
// Make a LuckPerms user for the one being migrated
|
||||
plugin.getStorage().loadUser(uuid, "null").join();
|
||||
User user = plugin.getUserManager().get(uuid);
|
||||
User user = plugin.getUserManager().getIfLoaded(uuid);
|
||||
if (user.getNodes().size() <= 1) {
|
||||
user.clearNodes(false);
|
||||
}
|
||||
|
@ -90,10 +90,10 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
for (SubjectCollection collection : pexService.getKnownSubjects().values()) {
|
||||
SpongeMigrationUtils.migrateSubjectData(
|
||||
collection.getDefaults().getSubjectData(),
|
||||
lpService.getSubjects("defaults").get(collection.getIdentifier()).getSubjectData()
|
||||
lpService.getCollection("defaults").loadSubject(collection.getIdentifier()).join().sponge().getSubjectData()
|
||||
);
|
||||
}
|
||||
SpongeMigrationUtils.migrateSubjectData(pexService.getDefaults().getSubjectData(), lpService.getDefaults().getSubjectData());
|
||||
SpongeMigrationUtils.migrateSubjectData(pexService.getDefaults().getSubjectData(), lpService.getDefaults().sponge().getSubjectData());
|
||||
|
||||
log.log("Calculating group weightings.");
|
||||
int maxWeight = 0;
|
||||
@ -182,7 +182,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
|
||||
// Make a LuckPerms user for the one being migrated
|
||||
plugin.getStorage().loadUser(uuid, "null").join();
|
||||
User user = plugin.getUserManager().get(uuid);
|
||||
User user = plugin.getUserManager().getIfLoaded(uuid);
|
||||
if (user.getNodes().size() <= 1) {
|
||||
user.clearNodes(false);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.core.NodeFactory;
|
||||
import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.sponge.service.proxy.Util;
|
||||
import me.lucko.luckperms.sponge.service.model.CompatibilityUtil;
|
||||
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
@ -55,7 +55,7 @@ public class SpongeMigrationUtils {
|
||||
// Migrate permissions
|
||||
Map<Set<Context>, Map<String, Boolean>> perms = subject.getSubjectData().getAllPermissions();
|
||||
for (Map.Entry<Set<Context>, Map<String, Boolean>> e : perms.entrySet()) {
|
||||
ContextSet context = Util.convertContexts(e.getKey());
|
||||
ContextSet context = CompatibilityUtil.convertContexts(e.getKey());
|
||||
|
||||
for (Map.Entry<String, Boolean> perm : e.getValue().entrySet()) {
|
||||
if (perm.getKey().isEmpty()) {
|
||||
@ -69,7 +69,7 @@ public class SpongeMigrationUtils {
|
||||
// Migrate options
|
||||
Map<Set<Context>, Map<String, String>> opts = subject.getSubjectData().getAllOptions();
|
||||
for (Map.Entry<Set<Context>, Map<String, String>> e : opts.entrySet()) {
|
||||
ContextSet context = Util.convertContexts(e.getKey());
|
||||
ContextSet context = CompatibilityUtil.convertContexts(e.getKey());
|
||||
|
||||
for (Map.Entry<String, String> opt : e.getValue().entrySet()) {
|
||||
if (opt.getKey().isEmpty() || opt.getValue().isEmpty()) {
|
||||
@ -89,7 +89,7 @@ public class SpongeMigrationUtils {
|
||||
// Migrate parents
|
||||
Map<Set<Context>, List<Subject>> parents = subject.getSubjectData().getAllParents();
|
||||
for (Map.Entry<Set<Context>, List<Subject>> e : parents.entrySet()) {
|
||||
ContextSet context = Util.convertContexts(e.getKey());
|
||||
ContextSet context = CompatibilityUtil.convertContexts(e.getKey());
|
||||
|
||||
for (Subject s : e.getValue()) {
|
||||
if (!s.getContainingCollection().getIdentifier().equalsIgnoreCase(PermissionService.SUBJECTS_GROUP)) {
|
||||
|
@ -29,21 +29,21 @@ import lombok.Getter;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.caching.MetaAccumulator;
|
||||
import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.utils.ExtractedContexts;
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.Util;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference;
|
||||
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.references.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
@ -61,7 +61,6 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class SpongeGroup extends Group {
|
||||
|
||||
@Getter
|
||||
private final GroupSubject spongeData;
|
||||
|
||||
public SpongeGroup(String name, LPSpongePlugin plugin) {
|
||||
@ -69,6 +68,10 @@ public class SpongeGroup extends Group {
|
||||
this.spongeData = new GroupSubject(plugin, this);
|
||||
}
|
||||
|
||||
public GroupSubject sponge() {
|
||||
return this.spongeData;
|
||||
}
|
||||
|
||||
public static class GroupSubject implements LPSubject {
|
||||
|
||||
@Getter
|
||||
@ -83,7 +86,7 @@ public class SpongeGroup extends Group {
|
||||
@Getter
|
||||
private final LuckPermsSubjectData transientSubjectData;
|
||||
|
||||
private final LoadingCache<ContextSet, NodeTree> permissionCache = Caffeine.newBuilder()
|
||||
private final LoadingCache<ImmutableContextSet, NodeTree> permissionCache = Caffeine.newBuilder()
|
||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||
.build(contexts -> {
|
||||
// TODO move this away from NodeTree
|
||||
@ -94,21 +97,21 @@ public class SpongeGroup extends Group {
|
||||
return NodeTree.of(permissions);
|
||||
});
|
||||
|
||||
private final LoadingCache<ContextSet, Set<SubjectReference>> parentCache = Caffeine.newBuilder()
|
||||
private final LoadingCache<ImmutableContextSet, ImmutableList<SubjectReference>> parentCache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(10, TimeUnit.MINUTES)
|
||||
.build(contexts -> {
|
||||
Set<SubjectReference> subjects = getParent().getAllNodes(ExtractedContexts.generate(getPlugin().getService().calculateContexts(contexts))).stream()
|
||||
.map(LocalizedNode::getNode)
|
||||
.filter(Node::isGroupNode)
|
||||
.map(Node::getGroupName)
|
||||
.map(s -> getPlugin().getService().getGroupSubjects().get(s))
|
||||
.map(s -> getPlugin().getService().getGroupSubjects().loadSubject(s).join())
|
||||
.map(LPSubject::toReference)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
subjects.addAll(getPlugin().getService().getGroupSubjects().getDefaultSubject().resolve(getService()).getParents(contexts));
|
||||
subjects.addAll(getPlugin().getService().getGroupSubjects().getDefaults().getParents(contexts));
|
||||
subjects.addAll(getPlugin().getService().getDefaults().getParents(contexts));
|
||||
|
||||
return ImmutableSet.copyOf(subjects);
|
||||
return getService().sortSubjects(subjects);
|
||||
});
|
||||
|
||||
private GroupSubject(LPSpongePlugin plugin, SpongeGroup parent) {
|
||||
@ -147,8 +150,8 @@ public class SpongeGroup extends Group {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectCollectionReference getParentCollection() {
|
||||
return plugin.getService().getGroupSubjects().toReference();
|
||||
public LPSubjectCollection getParentCollection() {
|
||||
return plugin.getService().getGroupSubjects();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -157,15 +160,15 @@ public class SpongeGroup extends Group {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(ContextSet contexts, String permission) {
|
||||
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 = Util.convertTristate(nt.get(permission));
|
||||
Tristate t = CompatibilityUtil.convertTristate(nt.get(permission));
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
|
||||
t = plugin.getService().getGroupSubjects().getDefaultSubject().resolve(getService()).getPermissionValue(contexts, permission);
|
||||
t = plugin.getService().getGroupSubjects().getDefaults().getPermissionValue(contexts, permission);
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
@ -176,21 +179,21 @@ public class SpongeGroup extends Group {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(ContextSet contexts, SubjectReference parent) {
|
||||
public boolean isChildOf(ImmutableContextSet contexts, SubjectReference parent) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_IS_CHILD_OF)) {
|
||||
return parent.getCollection().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SubjectReference> getParents(ContextSet contexts) {
|
||||
public ImmutableList<SubjectReference> getParents(ImmutableContextSet contexts) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_PARENTS)) {
|
||||
return parentCache.get(contexts);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(ContextSet contexts, String s) {
|
||||
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")) {
|
||||
@ -207,7 +210,7 @@ public class SpongeGroup extends Group {
|
||||
return option;
|
||||
}
|
||||
|
||||
option = plugin.getService().getGroupSubjects().getDefaultSubject().resolve(getService()).getOption(contexts, s);
|
||||
option = plugin.getService().getGroupSubjects().getDefaults().getOption(contexts, s);
|
||||
if (option.isPresent()) {
|
||||
return option;
|
||||
}
|
||||
@ -217,13 +220,13 @@ public class SpongeGroup extends Group {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextSet getActiveContextSet() {
|
||||
public ImmutableContextSet getActiveContextSet() {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_ACTIVE_CONTEXTS)) {
|
||||
return plugin.getContextManager().getApplicableContext(this);
|
||||
return plugin.getContextManager().getApplicableContext(this.sponge()).makeImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<String> getChatMeta(ContextSet contexts, boolean prefix) {
|
||||
private Optional<String> getChatMeta(ImmutableContextSet contexts, boolean prefix) {
|
||||
MetaAccumulator metaAccumulator = parent.accumulateMeta(null, null, ExtractedContexts.generate(plugin.getService().calculateContexts(contexts)));
|
||||
if (prefix) {
|
||||
return Optional.ofNullable(metaAccumulator.getPrefixStack().toFormattedString());
|
||||
@ -232,7 +235,7 @@ public class SpongeGroup extends Group {
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<String> getMeta(ContextSet contexts, String key) {
|
||||
private Optional<String> getMeta(ImmutableContextSet contexts, String key) {
|
||||
MetaAccumulator metaAccumulator = parent.accumulateMeta(null, null, ExtractedContexts.generate(plugin.getService().calculateContexts(contexts)));
|
||||
Map<String, String> meta = metaAccumulator.getMeta();
|
||||
return Optional.ofNullable(meta.get(key));
|
||||
|
@ -27,17 +27,18 @@ package me.lucko.luckperms.sponge.model;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.caching.MetaData;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
@ -49,12 +50,10 @@ import org.spongepowered.api.service.permission.PermissionService;
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SpongeUser extends User {
|
||||
|
||||
@Getter
|
||||
private final UserSubject spongeData;
|
||||
|
||||
public SpongeUser(UUID uuid, LPSpongePlugin plugin) {
|
||||
@ -67,6 +66,10 @@ public class SpongeUser extends User {
|
||||
this.spongeData = new UserSubject(plugin, this);
|
||||
}
|
||||
|
||||
public UserSubject sponge() {
|
||||
return this.spongeData;
|
||||
}
|
||||
|
||||
public static class UserSubject implements LPSubject {
|
||||
private final SpongeUser parent;
|
||||
private final LPSpongePlugin plugin;
|
||||
@ -77,8 +80,6 @@ public class SpongeUser extends User {
|
||||
@Getter
|
||||
private final LuckPermsSubjectData transientSubjectData;
|
||||
|
||||
private long lastUse = System.currentTimeMillis();
|
||||
|
||||
private UserSubject(LPSpongePlugin plugin, SpongeUser parent) {
|
||||
this.parent = parent;
|
||||
this.plugin = plugin;
|
||||
@ -86,16 +87,6 @@ public class SpongeUser extends User {
|
||||
this.transientSubjectData = new LuckPermsSubjectData(false, plugin.getService(), parent, this);
|
||||
}
|
||||
|
||||
private void logUsage() {
|
||||
lastUse = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean shouldCleanup() {
|
||||
long now = System.currentTimeMillis();
|
||||
// Expire after 10 minutes of idle
|
||||
return (now - lastUse) > 600000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return plugin.getUuidCache().getExternalUUID(parent.getUuid()).toString();
|
||||
@ -114,8 +105,8 @@ public class SpongeUser extends User {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectCollectionReference getParentCollection() {
|
||||
return plugin.getService().getUserSubjects().toReference();
|
||||
public LPSubjectCollection getParentCollection() {
|
||||
return plugin.getService().getUserSubjects();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -124,24 +115,21 @@ public class SpongeUser extends User {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(ContextSet contexts, String permission) {
|
||||
logUsage();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(ContextSet contexts, SubjectReference parent) {
|
||||
logUsage();
|
||||
public boolean isChildOf(ImmutableContextSet contexts, SubjectReference parent) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_IS_CHILD_OF)) {
|
||||
return parent.getCollection().equals(PermissionService.SUBJECTS_GROUP) && getPermissionValue(contexts, "group." + parent.getIdentifier()).asBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SubjectReference> getParents(ContextSet contexts) {
|
||||
logUsage();
|
||||
public ImmutableList<SubjectReference> getParents(ImmutableContextSet contexts) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_PARENTS)) {
|
||||
ImmutableSet.Builder<SubjectReference> subjects = ImmutableSet.builder();
|
||||
|
||||
@ -152,20 +140,19 @@ public class SpongeUser extends User {
|
||||
|
||||
String groupName = perm.substring("group.".length());
|
||||
if (plugin.getGroupManager().isLoaded(groupName)) {
|
||||
subjects.add(plugin.getService().getGroupSubjects().get(groupName).toReference());
|
||||
subjects.add(plugin.getService().getGroupSubjects().loadSubject(groupName).join().toReference());
|
||||
}
|
||||
}
|
||||
|
||||
subjects.addAll(plugin.getService().getUserSubjects().getDefaultSubject().resolve(getService()).getParents(contexts));
|
||||
subjects.addAll(plugin.getService().getUserSubjects().getDefaults().getParents(contexts));
|
||||
subjects.addAll(plugin.getService().getDefaults().getParents(contexts));
|
||||
|
||||
return subjects.build();
|
||||
return getService().sortSubjects(subjects.build());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(ContextSet contexts, String s) {
|
||||
logUsage();
|
||||
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")) {
|
||||
@ -184,7 +171,7 @@ public class SpongeUser extends User {
|
||||
return Optional.of(data.getMeta().get(s));
|
||||
}
|
||||
|
||||
Optional<String> v = plugin.getService().getUserSubjects().getDefaultSubject().resolve(getService()).getOption(contexts, s);
|
||||
Optional<String> v = plugin.getService().getUserSubjects().getDefaults().getOption(contexts, s);
|
||||
if (v.isPresent()) {
|
||||
return v;
|
||||
}
|
||||
@ -194,10 +181,9 @@ public class SpongeUser extends User {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextSet getActiveContextSet() {
|
||||
logUsage();
|
||||
public ImmutableContextSet getActiveContextSet() {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.USER_GET_ACTIVE_CONTEXTS)) {
|
||||
return plugin.getContextManager().getApplicableContext(this);
|
||||
return plugin.getContextManager().getApplicableContext(this.sponge()).makeImmutable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,12 +26,8 @@
|
||||
package me.lucko.luckperms.sponge.service;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
@ -43,37 +39,35 @@ import com.google.common.collect.MapMaker;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ContextCalculator;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.caching.UserCache;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
import me.lucko.luckperms.sponge.contexts.SpongeCalculatorLink;
|
||||
import me.lucko.luckperms.sponge.managers.SpongeGroupManager;
|
||||
import me.lucko.luckperms.sponge.managers.SpongeUserManager;
|
||||
import me.lucko.luckperms.sponge.model.SpongeGroup;
|
||||
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.calculated.OptionLookup;
|
||||
import me.lucko.luckperms.sponge.service.calculated.PermissionLookup;
|
||||
import me.lucko.luckperms.sponge.service.description.SimpleDescriptionBuilder;
|
||||
import me.lucko.luckperms.sponge.service.legacystorage.LegacyDataMigrator;
|
||||
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.persisted.PersistedCollection;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.proxy.PermissionServiceProxy;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
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.context.ContextCalculator;
|
||||
import org.spongepowered.api.service.permission.PermissionDescription;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
import org.spongepowered.api.text.Text;
|
||||
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
@ -81,31 +75,32 @@ import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* The LuckPerms implementation of the Sponge Permission Service
|
||||
*/
|
||||
@Getter
|
||||
public class LuckPermsService implements PermissionService {
|
||||
public class LuckPermsService implements LPPermissionService {
|
||||
public static final String SERVER_CONTEXT = "server";
|
||||
|
||||
private final LPSpongePlugin plugin;
|
||||
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final PermissionServiceProxy spongeProxy;
|
||||
|
||||
private final SubjectStorage storage;
|
||||
private final SpongeUserManager userSubjects;
|
||||
private final PersistedCollection fallbackUserSubjects;
|
||||
private final SpongeGroupManager groupSubjects;
|
||||
private final PersistedCollection fallbackGroupSubjects;
|
||||
private final PersistedCollection defaultSubjects;
|
||||
private final Set<PermissionDescription> descriptionSet;
|
||||
|
||||
private final Set<LoadingCache<PermissionLookup, Tristate>> localPermissionCaches;
|
||||
private final Set<LoadingCache<ImmutableContextSet, Set<SubjectReference>>> localParentCaches;
|
||||
private final Set<LoadingCache<ImmutableContextSet, ImmutableList<SubjectReference>>> localParentCaches;
|
||||
private final Set<LoadingCache<OptionLookup, Optional<String>>> localOptionCaches;
|
||||
private final Set<CalculatedSubjectData> localDataCaches;
|
||||
|
||||
@ -114,7 +109,7 @@ public class LuckPermsService implements PermissionService {
|
||||
.build(new CacheLoader<String, LPSubjectCollection>() {
|
||||
@Override
|
||||
public LPSubjectCollection load(String s) {
|
||||
return new PersistedCollection(LuckPermsService.this, s, true);
|
||||
return new PersistedCollection(LuckPermsService.this, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -125,26 +120,23 @@ public class LuckPermsService implements PermissionService {
|
||||
|
||||
public LuckPermsService(LPSpongePlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.spongeProxy = new PermissionServiceProxy(this);
|
||||
|
||||
localPermissionCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
||||
localParentCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
||||
localOptionCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
||||
localDataCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
||||
|
||||
storage = new SubjectStorage(new File(plugin.getDataDirectory(), "sponge-data"));
|
||||
storage = new SubjectStorage(this, new File(plugin.getDataDirectory(), "sponge-data"));
|
||||
new LegacyDataMigrator(plugin, new File(plugin.getDataDirectory(), "local"), storage).run();
|
||||
|
||||
userSubjects = plugin.getUserManager();
|
||||
fallbackUserSubjects = new PersistedCollection(this, "fallback-users", true);
|
||||
groupSubjects = plugin.getGroupManager();
|
||||
fallbackGroupSubjects = new PersistedCollection(this, "fallback-groups", true);
|
||||
defaultSubjects = new PersistedCollection(this, "defaults", false);
|
||||
defaultSubjects = new PersistedCollection(this, "defaults");
|
||||
defaultSubjects.loadAll();
|
||||
|
||||
collections.put(PermissionService.SUBJECTS_USER, userSubjects);
|
||||
collections.put("fallback-users", fallbackUserSubjects);
|
||||
collections.put(PermissionService.SUBJECTS_GROUP, groupSubjects);
|
||||
collections.put("fallback-groups", fallbackGroupSubjects);
|
||||
collections.put("defaults", defaultSubjects);
|
||||
|
||||
for (String collection : storage.getSavedCollections()) {
|
||||
@ -152,7 +144,7 @@ public class LuckPermsService implements PermissionService {
|
||||
continue;
|
||||
}
|
||||
|
||||
PersistedCollection c = new PersistedCollection(this, collection.toLowerCase(), true);
|
||||
PersistedCollection c = new PersistedCollection(this, collection.toLowerCase());
|
||||
c.loadAll();
|
||||
collections.put(c.getIdentifier(), c);
|
||||
}
|
||||
@ -160,40 +152,46 @@ public class LuckPermsService implements PermissionService {
|
||||
descriptionSet = ConcurrentHashMap.newKeySet();
|
||||
}
|
||||
|
||||
public LPSubjectData getDefaultData() {
|
||||
return getDefaults().getSubjectData();
|
||||
@Override
|
||||
public PermissionService sponge() {
|
||||
return spongeProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPSubject getDefaults() {
|
||||
return getDefaultSubjects().get("default");
|
||||
return getDefaultSubjects().loadSubject("default").join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPSubjectCollection getSubjects(String s) {
|
||||
public Predicate<String> getIdentifierValidityPredicate() {
|
||||
return Predicates.alwaysTrue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPSubjectCollection getCollection(String s) {
|
||||
try (Timing ignored = plugin.getTimings().time(LPTiming.GET_SUBJECTS)) {
|
||||
return collections.get(s.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, LPSubjectCollection> getCollections() {
|
||||
@Override
|
||||
public ImmutableMap<String, LPSubjectCollection> getLoadedCollections() {
|
||||
return ImmutableMap.copyOf(collections.asMap());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public Map<String, SubjectCollection> getKnownSubjects() {
|
||||
return getCollections().entrySet().stream().collect(ImmutableCollectors.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
public SubjectReference newSubjectReference(String collectionIdentifier, String subjectIdentifier) {
|
||||
return SubjectReference.of(this, collectionIdentifier, subjectIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PermissionDescription.Builder> newDescriptionBuilder(@NonNull Object o) {
|
||||
public PermissionDescription.Builder newDescriptionBuilder(@NonNull Object o) {
|
||||
Optional<PluginContainer> container = plugin.getGame().getPluginManager().fromInstance(o);
|
||||
if (!container.isPresent()) {
|
||||
throw new IllegalArgumentException("Couldn't find a plugin container for " + o.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
return Optional.of(new DescriptionBuilder(this, container.get()));
|
||||
return new SimpleDescriptionBuilder(this, container.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -208,24 +206,25 @@ public class LuckPermsService implements PermissionService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PermissionDescription> getDescriptions() {
|
||||
public ImmutableSet<PermissionDescription> getDescriptions() {
|
||||
return ImmutableSet.copyOf(descriptionSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerContextCalculator(@NonNull ContextCalculator<Subject> contextCalculator) {
|
||||
plugin.getContextManager().registerCalculator(new SpongeCalculatorLink(contextCalculator));
|
||||
plugin.getContextManager().registerCalculator(contextCalculator);
|
||||
}
|
||||
|
||||
public List<Subject> sortSubjects(List<Subject> s) {
|
||||
List<Subject> ret = new ArrayList<>(s);
|
||||
@Override
|
||||
public ImmutableList<SubjectReference> sortSubjects(Collection<SubjectReference> s) {
|
||||
List<SubjectReference> ret = new ArrayList<>(s);
|
||||
ret.sort(Collections.reverseOrder((o1, o2) -> {
|
||||
if (o1.equals(o2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean o1isGroup = o1.getContainingCollection().getIdentifier().equals(PermissionService.SUBJECTS_GROUP);
|
||||
boolean o2isGroup = o2.getContainingCollection().getIdentifier().equals(PermissionService.SUBJECTS_GROUP);
|
||||
boolean o1isGroup = o1.getCollection().equals(PermissionService.SUBJECTS_GROUP);
|
||||
boolean o2isGroup = o2.getCollection().equals(PermissionService.SUBJECTS_GROUP);
|
||||
|
||||
if (o1isGroup != o2isGroup) {
|
||||
return o1isGroup ? 1 : -1;
|
||||
@ -256,7 +255,8 @@ public class LuckPermsService implements PermissionService {
|
||||
return ImmutableList.copyOf(ret);
|
||||
}
|
||||
|
||||
public Contexts calculateContexts(ContextSet contextSet) {
|
||||
@Override
|
||||
public Contexts calculateContexts(ImmutableContextSet contextSet) {
|
||||
return new Contexts(
|
||||
contextSet,
|
||||
plugin.getConfiguration().get(ConfigKeys.INCLUDING_GLOBAL_PERMS),
|
||||
@ -268,6 +268,7 @@ public class LuckPermsService implements PermissionService {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidatePermissionCaches() {
|
||||
for (LoadingCache<PermissionLookup, Tristate> c : localPermissionCaches) {
|
||||
c.invalidateAll();
|
||||
@ -284,18 +285,20 @@ public class LuckPermsService implements PermissionService {
|
||||
}
|
||||
|
||||
for (SpongeGroup group : plugin.getGroupManager().getAll().values()) {
|
||||
group.getSpongeData().invalidateCaches();
|
||||
group.sponge().invalidateCaches();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateParentCaches() {
|
||||
for (LoadingCache<ImmutableContextSet, Set<SubjectReference>> c : localParentCaches) {
|
||||
for (LoadingCache<ImmutableContextSet, ImmutableList<SubjectReference>> c : localParentCaches) {
|
||||
c.invalidateAll();
|
||||
}
|
||||
invalidateOptionCaches();
|
||||
invalidatePermissionCaches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateOptionCaches() {
|
||||
for (LoadingCache<OptionLookup, Optional<String>> c : localOptionCaches) {
|
||||
c.invalidateAll();
|
||||
@ -306,74 +309,4 @@ public class LuckPermsService implements PermissionService {
|
||||
userCache.invalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
@ToString
|
||||
public static final class DescriptionBuilder implements PermissionDescription.Builder {
|
||||
private final LuckPermsService service;
|
||||
private final PluginContainer container;
|
||||
private final Map<String, Tristate> roles = new HashMap<>();
|
||||
private String id = null;
|
||||
private Text description = null;
|
||||
|
||||
@Override
|
||||
public PermissionDescription.Builder id(@NonNull String s) {
|
||||
id = s;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionDescription.Builder description(@NonNull Text text) {
|
||||
description = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionDescription.Builder assign(@NonNull String s, boolean b) {
|
||||
roles.put(s, Tristate.fromBoolean(b));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionDescription register() throws IllegalStateException {
|
||||
if (id == null) {
|
||||
throw new IllegalStateException("id cannot be null");
|
||||
}
|
||||
if (description == null) {
|
||||
throw new IllegalStateException("description cannot be null");
|
||||
}
|
||||
|
||||
Description d = new Description(service, container, id, description);
|
||||
service.getDescriptionSet().add(d);
|
||||
|
||||
// Set role-templates
|
||||
LPSubjectCollection subjects = service.getSubjects(PermissionService.SUBJECTS_ROLE_TEMPLATE);
|
||||
for (Map.Entry<String, Tristate> assignment : roles.entrySet()) {
|
||||
LPSubject subject = subjects.get(assignment.getKey());
|
||||
subject.getTransientSubjectData().setPermission(ContextSet.empty(), id, assignment.getValue());
|
||||
}
|
||||
|
||||
service.getPlugin().getPermissionVault().offer(id);
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
@ToString
|
||||
public static final class Description implements PermissionDescription {
|
||||
private final LuckPermsService service;
|
||||
private final PluginContainer owner;
|
||||
private final String id;
|
||||
private final Text description;
|
||||
|
||||
@Override
|
||||
public Map<Subject, Boolean> getAssignedSubjects(String id) {
|
||||
SubjectCollection subjects = service.getSubjects(id);
|
||||
return subjects.getAllWithPermission(this.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,13 +29,12 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import me.lucko.luckperms.api.DataMutateResult;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.caching.MetaAccumulator;
|
||||
import me.lucko.luckperms.common.core.NodeFactory;
|
||||
@ -43,8 +42,8 @@ import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.core.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.common.utils.ExtractedContexts;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
|
||||
@ -56,7 +55,7 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@ -74,7 +73,7 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
LPSubject parentSubject;
|
||||
|
||||
@Override
|
||||
public Map<ImmutableContextSet, Map<String, Boolean>> getPermissions() {
|
||||
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<>();
|
||||
|
||||
@ -86,7 +85,7 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
perms.put(e.getKey(), results);
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, Map<String, Boolean>> map = ImmutableMap.builder();
|
||||
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());
|
||||
}
|
||||
@ -95,7 +94,7 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPermission(@NonNull ContextSet contexts, @NonNull String permission, @NonNull Tristate tristate) {
|
||||
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
|
||||
@ -107,8 +106,7 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
holder.unsetTransientPermission(node);
|
||||
}
|
||||
|
||||
objectSave(holder);
|
||||
return true;
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
|
||||
Node node = NodeFactory.newBuilder(permission).setValue(tristate.asBoolean()).withExtraContext(contexts).build();
|
||||
@ -126,13 +124,12 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
holder.setTransientPermission(node);
|
||||
}
|
||||
|
||||
objectSave(holder);
|
||||
return true;
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearPermissions() {
|
||||
public CompletableFuture<Boolean> clearPermissions() {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PERMISSIONS)) {
|
||||
boolean ret;
|
||||
if (enduring) {
|
||||
@ -142,20 +139,19 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
if (holder instanceof User) {
|
||||
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
|
||||
}
|
||||
|
||||
objectSave(holder);
|
||||
return true;
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearPermissions(@NonNull ContextSet set) {
|
||||
public CompletableFuture<Boolean> clearPermissions(@NonNull ImmutableContextSet set) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PERMISSIONS)) {
|
||||
boolean ret;
|
||||
|
||||
@ -171,35 +167,34 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
if (holder instanceof User) {
|
||||
service.getPlugin().getUserManager().giveDefaultIfNeeded(((User) holder), false);
|
||||
}
|
||||
|
||||
objectSave(holder);
|
||||
return true;
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ImmutableContextSet, Set<SubjectReference>> getParents() {
|
||||
public ImmutableMap<ImmutableContextSet, ImmutableList<SubjectReference>> getAllParents() {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_GET_PARENTS)) {
|
||||
Map<ImmutableContextSet, ImmutableSet.Builder<SubjectReference>> parents = new HashMap<>();
|
||||
Map<ImmutableContextSet, ImmutableList.Builder<SubjectReference>> parents = new HashMap<>();
|
||||
|
||||
for (Map.Entry<ImmutableContextSet, Collection<Node>> e : (enduring ? holder.getNodes() : holder.getTransientNodes()).asMap().entrySet()) {
|
||||
ImmutableSet.Builder<SubjectReference> results = ImmutableSet.builder();
|
||||
ImmutableList.Builder<SubjectReference> results = ImmutableList.builder();
|
||||
for (Node n : e.getValue()) {
|
||||
if (n.isGroupNode()) {
|
||||
results.add(service.getGroupSubjects().get(n.getGroupName()).toReference());
|
||||
results.add(service.getGroupSubjects().loadSubject(n.getGroupName()).join().toReference());
|
||||
}
|
||||
}
|
||||
parents.put(e.getKey(), results);
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, Set<SubjectReference>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, ImmutableSet.Builder<SubjectReference>> e : parents.entrySet()) {
|
||||
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();
|
||||
@ -207,63 +202,63 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addParent(@NonNull ContextSet contexts, @NonNull SubjectReference subject) {
|
||||
public CompletableFuture<Boolean> addParent(@NonNull ImmutableContextSet contexts, @NonNull SubjectReference subject) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_ADD_PARENT)) {
|
||||
if (subject.getCollection().equals(PermissionService.SUBJECTS_GROUP)) {
|
||||
LPSubject permsSubject = subject.resolve(service);
|
||||
DataMutateResult result;
|
||||
return subject.resolve().thenCompose(sub -> {
|
||||
DataMutateResult result;
|
||||
|
||||
if (enduring) {
|
||||
result = holder.setPermission(NodeFactory.newBuilder("group." + permsSubject.getIdentifier())
|
||||
.withExtraContext(contexts)
|
||||
.build());
|
||||
} else {
|
||||
result = holder.setTransientPermission(NodeFactory.newBuilder("group." + permsSubject.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 false;
|
||||
}
|
||||
if (!result.asBoolean()) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
objectSave(holder);
|
||||
return true;
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
});
|
||||
}
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeParent(@NonNull ContextSet contexts, @NonNull SubjectReference subject) {
|
||||
public CompletableFuture<Boolean> removeParent(@NonNull ImmutableContextSet contexts, @NonNull SubjectReference subject) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_REMOVE_PARENT)) {
|
||||
if (subject.getCollection().equals(PermissionService.SUBJECTS_GROUP)) {
|
||||
LPSubject permsSubject = subject.resolve(service);
|
||||
DataMutateResult result;
|
||||
subject.resolve().thenCompose(sub -> {
|
||||
DataMutateResult result;
|
||||
|
||||
if (enduring) {
|
||||
result = holder.unsetPermission(NodeFactory.newBuilder("group." + permsSubject.getIdentifier())
|
||||
.withExtraContext(contexts)
|
||||
.build());
|
||||
} else {
|
||||
result = holder.unsetTransientPermission(NodeFactory.newBuilder("group." + permsSubject.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 false;
|
||||
}
|
||||
if (!result.asBoolean()) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
objectSave(holder);
|
||||
return true;
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
});
|
||||
}
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearParents() {
|
||||
public CompletableFuture<Boolean> clearParents() {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PARENTS)) {
|
||||
boolean ret;
|
||||
|
||||
@ -283,16 +278,15 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
objectSave(holder);
|
||||
return true;
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearParents(@NonNull ContextSet set) {
|
||||
public CompletableFuture<Boolean> clearParents(@NonNull ImmutableContextSet set) {
|
||||
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_CLEAR_PARENTS)) {
|
||||
boolean ret;
|
||||
if (enduring) {
|
||||
@ -312,16 +306,15 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
objectSave(holder);
|
||||
return true;
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ImmutableContextSet, Map<String, String>> getOptions() {
|
||||
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<>();
|
||||
@ -363,7 +356,7 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
}
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, Map<String, String>> map = ImmutableMap.builder();
|
||||
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()));
|
||||
}
|
||||
@ -372,7 +365,7 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setOption(@NonNull ContextSet context, @NonNull String key, @NonNull String value) {
|
||||
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.
|
||||
@ -414,13 +407,12 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
}
|
||||
}
|
||||
|
||||
objectSave(holder);
|
||||
return true;
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unsetOption(ContextSet set, String key) {
|
||||
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 -> {
|
||||
@ -437,13 +429,12 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
objectSave(holder);
|
||||
return true;
|
||||
return objectSave(holder).thenApply(v -> true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOptions(@NonNull ContextSet set) {
|
||||
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())
|
||||
@ -452,13 +443,12 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
objectSave(holder);
|
||||
return !toRemove.isEmpty();
|
||||
return objectSave(holder).thenApply(v -> !toRemove.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOptions() {
|
||||
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())
|
||||
@ -466,8 +456,7 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
|
||||
toRemove.forEach(makeUnsetConsumer(enduring));
|
||||
|
||||
objectSave(holder);
|
||||
return !toRemove.isEmpty();
|
||||
return objectSave(holder).thenApply(v -> !toRemove.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@ -485,21 +474,22 @@ public class LuckPermsSubjectData implements LPSubjectData {
|
||||
};
|
||||
}
|
||||
|
||||
private void objectSave(PermissionHolder t) {
|
||||
private CompletableFuture<Void> objectSave(PermissionHolder t) {
|
||||
if (!enduring) {
|
||||
// don't bother saving to primary storage. just refresh
|
||||
if (t instanceof User) {
|
||||
((User) t).getRefreshBuffer().request();
|
||||
User user = ((User) t);
|
||||
return user.getRefreshBuffer().request();
|
||||
} else {
|
||||
service.getPlugin().getUpdateTaskBuffer().request();
|
||||
return service.getPlugin().getUpdateTaskBuffer().request();
|
||||
}
|
||||
} else {
|
||||
if (t instanceof User) {
|
||||
service.getPlugin().getStorage().saveUser(((User) t))
|
||||
.thenRunAsync(() -> ((User) t).getRefreshBuffer().request(), service.getPlugin().getScheduler().getAsyncExecutor());
|
||||
User user = ((User) t);
|
||||
return service.getPlugin().getStorage().saveUser(user).thenCombineAsync(user.getRefreshBuffer().request(), (b, v) -> v, service.getPlugin().getScheduler().getAsyncExecutor());
|
||||
} else {
|
||||
service.getPlugin().getStorage().saveGroup((Group) t)
|
||||
.thenRunAsync(() -> service.getPlugin().getUpdateTaskBuffer().request(), service.getPlugin().getScheduler().getAsyncExecutor());
|
||||
Group group = ((Group) t);
|
||||
return service.getPlugin().getStorage().saveGroup(group).thenCombineAsync(service.getPlugin().getUpdateTaskBuffer().request(), (b, v) -> v, service.getPlugin().getScheduler().getAsyncExecutor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,8 @@ package me.lucko.luckperms.sponge.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ServiceCacheHousekeepingTask implements Runnable {
|
||||
@ -36,8 +36,8 @@ public class ServiceCacheHousekeepingTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (LPSubjectCollection collection : service.getCollections().values()) {
|
||||
for (LPSubject subject : collection.getSubjects()) {
|
||||
for (LPSubjectCollection collection : service.getLoadedCollections().values()) {
|
||||
for (LPSubject subject : collection.getLoadedSubjects()) {
|
||||
subject.performCleanup();
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
@ -43,9 +42,9 @@ import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||
import me.lucko.luckperms.common.calculators.PermissionProcessor;
|
||||
import me.lucko.luckperms.common.calculators.processors.MapProcessor;
|
||||
import me.lucko.luckperms.sponge.calculators.SpongeWildcardProcessor;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import java.util.Comparator;
|
||||
@ -55,9 +54,13 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* In-memory implementation of {@link LPSubjectData}.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class CalculatedSubjectData implements LPSubjectData {
|
||||
private static final ContextComparator CONTEXT_COMPARATOR = new ContextComparator();
|
||||
@ -65,10 +68,13 @@ public class CalculatedSubjectData implements LPSubjectData {
|
||||
@Getter
|
||||
private final LPSubject parentSubject;
|
||||
|
||||
private final LuckPermsService service;
|
||||
private final LPPermissionService service;
|
||||
private final String calculatorDisplayName;
|
||||
|
||||
private final Map<ContextSet, Map<String, Boolean>> permissions = new ConcurrentHashMap<>();
|
||||
private final Map<ImmutableContextSet, Map<String, Boolean>> permissions = new ConcurrentHashMap<>();
|
||||
private final Map<ImmutableContextSet, Set<SubjectReference>> parents = new ConcurrentHashMap<>();
|
||||
private final Map<ImmutableContextSet, Map<String, String>> options = new ConcurrentHashMap<>();
|
||||
|
||||
private final LoadingCache<ContextSet, CalculatorHolder> permissionCache = Caffeine.newBuilder()
|
||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||
.build(new CacheLoader<ContextSet, CalculatorHolder>() {
|
||||
@ -85,9 +91,6 @@ public class CalculatedSubjectData implements LPSubjectData {
|
||||
}
|
||||
});
|
||||
|
||||
private final Map<ContextSet, Set<SubjectReference>> parents = new ConcurrentHashMap<>();
|
||||
private final Map<ContextSet, Map<String, String>> options = new ConcurrentHashMap<>();
|
||||
|
||||
public void cleanup() {
|
||||
permissionCache.cleanUp();
|
||||
}
|
||||
@ -128,210 +131,185 @@ public class CalculatedSubjectData implements LPSubjectData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ImmutableContextSet, Map<String, Boolean>> getPermissions() {
|
||||
ImmutableMap.Builder<ImmutableContextSet, Map<String, Boolean>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ContextSet, Map<String, Boolean>> e : permissions.entrySet()) {
|
||||
map.put(e.getKey().makeImmutable(), ImmutableMap.copyOf(e.getValue()));
|
||||
public ImmutableMap<ImmutableContextSet, ImmutableMap<String, Boolean>> getAllPermissions() {
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableMap<String, Boolean>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, Map<String, Boolean>> e : permissions.entrySet()) {
|
||||
map.put(e.getKey(), ImmutableMap.copyOf(e.getValue()));
|
||||
}
|
||||
return map.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getPermissions(ContextSet contexts) {
|
||||
return ImmutableMap.copyOf(permissions.getOrDefault(contexts, ImmutableMap.of()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPermission(ContextSet contexts, String permission, Tristate value) {
|
||||
public CompletableFuture<Boolean> setPermission(ImmutableContextSet contexts, String permission, Tristate value) {
|
||||
boolean b;
|
||||
if (value == Tristate.UNDEFINED) {
|
||||
Map<String, Boolean> perms = permissions.get(contexts);
|
||||
b = perms != null && perms.remove(permission.toLowerCase()) != null;
|
||||
} else {
|
||||
Map<String, Boolean> perms = permissions.computeIfAbsent(contexts.makeImmutable(), c -> new ConcurrentHashMap<>());
|
||||
Map<String, Boolean> perms = permissions.computeIfAbsent(contexts, c -> new ConcurrentHashMap<>());
|
||||
b = !Objects.equals(perms.put(permission.toLowerCase(), value.asBoolean()), value.asBoolean());
|
||||
}
|
||||
if (b) {
|
||||
permissionCache.invalidateAll();
|
||||
service.invalidatePermissionCaches();
|
||||
}
|
||||
return b;
|
||||
return CompletableFuture.completedFuture(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearPermissions() {
|
||||
public CompletableFuture<Boolean> clearPermissions() {
|
||||
if (permissions.isEmpty()) {
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
} else {
|
||||
permissions.clear();
|
||||
permissionCache.invalidateAll();
|
||||
service.invalidatePermissionCaches();
|
||||
return true;
|
||||
return CompletableFuture.completedFuture(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearPermissions(ContextSet contexts) {
|
||||
public CompletableFuture<Boolean> clearPermissions(ImmutableContextSet contexts) {
|
||||
Map<String, Boolean> perms = permissions.get(contexts);
|
||||
if (perms == null) {
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
permissions.remove(contexts);
|
||||
if (!perms.isEmpty()) {
|
||||
permissionCache.invalidateAll();
|
||||
service.invalidatePermissionCaches();
|
||||
return true;
|
||||
return CompletableFuture.completedFuture(true);
|
||||
}
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ImmutableContextSet, Set<SubjectReference>> getParents() {
|
||||
ImmutableMap.Builder<ImmutableContextSet, Set<SubjectReference>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ContextSet, Set<SubjectReference>> e : parents.entrySet()) {
|
||||
map.put(e.getKey().makeImmutable(), ImmutableSet.copyOf(e.getValue()));
|
||||
}
|
||||
return map.build();
|
||||
}
|
||||
|
||||
public Map<ImmutableContextSet, List<SubjectReference>> getParentsAsList() {
|
||||
ImmutableMap.Builder<ImmutableContextSet, List<SubjectReference>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ContextSet, Set<SubjectReference>> e : parents.entrySet()) {
|
||||
map.put(e.getKey().makeImmutable(), ImmutableList.copyOf(e.getValue()));
|
||||
public ImmutableMap<ImmutableContextSet, ImmutableList<SubjectReference>> getAllParents() {
|
||||
ImmutableMap.Builder<ImmutableContextSet, ImmutableList<SubjectReference>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, Set<SubjectReference>> e : parents.entrySet()) {
|
||||
map.put(e.getKey(), service.sortSubjects(e.getValue()));
|
||||
}
|
||||
return map.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SubjectReference> getParents(ContextSet contexts) {
|
||||
return ImmutableSet.copyOf(parents.getOrDefault(contexts, ImmutableSet.of()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addParent(ContextSet contexts, SubjectReference parent) {
|
||||
Set<SubjectReference> set = parents.computeIfAbsent(contexts.makeImmutable(), c -> ConcurrentHashMap.newKeySet());
|
||||
public CompletableFuture<Boolean> addParent(ImmutableContextSet contexts, SubjectReference parent) {
|
||||
Set<SubjectReference> set = parents.computeIfAbsent(contexts, c -> ConcurrentHashMap.newKeySet());
|
||||
boolean b = set.add(parent);
|
||||
if (b) {
|
||||
service.invalidateParentCaches();
|
||||
}
|
||||
return b;
|
||||
return CompletableFuture.completedFuture(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeParent(ContextSet contexts, SubjectReference parent) {
|
||||
public CompletableFuture<Boolean> removeParent(ImmutableContextSet contexts, SubjectReference parent) {
|
||||
Set<SubjectReference> set = parents.get(contexts);
|
||||
boolean b = set != null && set.remove(parent);
|
||||
if (b) {
|
||||
service.invalidateParentCaches();
|
||||
}
|
||||
return b;
|
||||
return CompletableFuture.completedFuture(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearParents() {
|
||||
public CompletableFuture<Boolean> clearParents() {
|
||||
if (parents.isEmpty()) {
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
} else {
|
||||
parents.clear();
|
||||
service.invalidateOptionCaches();
|
||||
return true;
|
||||
return CompletableFuture.completedFuture(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearParents(ContextSet contexts) {
|
||||
public CompletableFuture<Boolean> clearParents(ImmutableContextSet contexts) {
|
||||
Set<SubjectReference> set = parents.get(contexts);
|
||||
if (set == null) {
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
parents.remove(contexts);
|
||||
service.invalidateParentCaches();
|
||||
return !set.isEmpty();
|
||||
return CompletableFuture.completedFuture(!set.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ImmutableContextSet, Map<String, String>> getOptions() {
|
||||
ImmutableMap.Builder<ImmutableContextSet, Map<String, String>> map = ImmutableMap.builder();
|
||||
for (Map.Entry<ContextSet, Map<String, String>> e : options.entrySet()) {
|
||||
map.put(e.getKey().makeImmutable(), ImmutableMap.copyOf(e.getValue()));
|
||||
public ImmutableMap<ImmutableContextSet, ImmutableMap<String, String>> getAllOptions() {
|
||||
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 Map<String, String> getOptions(ContextSet contexts) {
|
||||
return ImmutableMap.copyOf(options.getOrDefault(contexts, ImmutableMap.of()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setOption(ContextSet contexts, String key, String value) {
|
||||
Map<String, String> options = this.options.computeIfAbsent(contexts.makeImmutable(), c -> new ConcurrentHashMap<>());
|
||||
public CompletableFuture<Boolean> setOption(ImmutableContextSet contexts, String key, String value) {
|
||||
Map<String, String> options = this.options.computeIfAbsent(contexts, c -> new ConcurrentHashMap<>());
|
||||
boolean b = !stringEquals(options.put(key.toLowerCase(), value), value);
|
||||
if (b) {
|
||||
service.invalidateOptionCaches();
|
||||
}
|
||||
return b;
|
||||
return CompletableFuture.completedFuture(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unsetOption(ContextSet contexts, String key) {
|
||||
public CompletableFuture<Boolean> unsetOption(ImmutableContextSet contexts, String key) {
|
||||
Map<String, String> options = this.options.get(contexts);
|
||||
boolean b = options != null && options.remove(key.toLowerCase()) != null;
|
||||
if (b) {
|
||||
service.invalidateOptionCaches();
|
||||
}
|
||||
return b;
|
||||
return CompletableFuture.completedFuture(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOptions() {
|
||||
public CompletableFuture<Boolean> clearOptions() {
|
||||
if (options.isEmpty()) {
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
} else {
|
||||
options.clear();
|
||||
service.invalidateOptionCaches();
|
||||
return true;
|
||||
return CompletableFuture.completedFuture(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOptions(ContextSet contexts) {
|
||||
public CompletableFuture<Boolean> clearOptions(ImmutableContextSet contexts) {
|
||||
Map<String, String> map = options.get(contexts);
|
||||
if (map == null) {
|
||||
return false;
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
options.remove(contexts);
|
||||
service.invalidateOptionCaches();
|
||||
return !map.isEmpty();
|
||||
return CompletableFuture.completedFuture(!map.isEmpty());
|
||||
}
|
||||
|
||||
private static <V> Map<String, V> flattenMap(ContextSet contexts, Map<ContextSet, Map<String, V>> source) {
|
||||
private static <V> Map<String, V> flattenMap(ContextSet contexts, Map<ImmutableContextSet, Map<String, V>> source) {
|
||||
Map<String, V> map = new HashMap<>();
|
||||
|
||||
SortedMap<ContextSet, Map<String, V>> ret = getRelevantEntries(contexts, source);
|
||||
SortedMap<ImmutableContextSet, Map<String, V>> ret = getRelevantEntries(contexts, source);
|
||||
for (Map<String, V> m : ret.values()) {
|
||||
for (Map.Entry<String, V> e : m.entrySet()) {
|
||||
if (!map.containsKey(e.getKey())) {
|
||||
map.put(e.getKey(), e.getValue());
|
||||
}
|
||||
map.putIfAbsent(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return ImmutableMap.copyOf(map);
|
||||
}
|
||||
|
||||
private static <K, V> SortedMap<ContextSet, Map<K, V>> getRelevantEntries(ContextSet set, Map<ContextSet, Map<K, V>> map) {
|
||||
ImmutableSortedMap.Builder<ContextSet, Map<K, V>> perms = ImmutableSortedMap.orderedBy(CONTEXT_COMPARATOR);
|
||||
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);
|
||||
|
||||
for (Map.Entry<ContextSet, Map<K, V>> e : map.entrySet()) {
|
||||
for (Map.Entry<ImmutableContextSet, Map<K, V>> e : map.entrySet()) {
|
||||
if (!e.getKey().isSatisfiedBy(set)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
perms.put(e.getKey().makeImmutable(), ImmutableMap.copyOf(e.getValue()));
|
||||
perms.put(e.getKey(), ImmutableMap.copyOf(e.getValue()));
|
||||
}
|
||||
|
||||
return perms.build();
|
||||
@ -341,10 +319,10 @@ public class CalculatedSubjectData implements LPSubjectData {
|
||||
return a == null && b == null || a != null && b != null && a.equalsIgnoreCase(b);
|
||||
}
|
||||
|
||||
private static class ContextComparator implements Comparator<ContextSet> {
|
||||
private static class ContextComparator implements Comparator<ImmutableContextSet> {
|
||||
|
||||
@Override
|
||||
public int compare(ContextSet o1, ContextSet o2) {
|
||||
public int compare(ImmutableContextSet o1, ImmutableContextSet o2) {
|
||||
int i = Integer.compare(o1.size(), o2.size());
|
||||
return i == 0 ? 1 : i;
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.description;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.proxy.SubjectProxy;
|
||||
|
||||
import org.spongepowered.api.plugin.PluginContainer;
|
||||
import org.spongepowered.api.service.permission.PermissionDescription;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.text.Text;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(of = {"owner", "id", "description"})
|
||||
@ToString(of = {"owner", "id", "description"})
|
||||
public final class SimpleDescription implements PermissionDescription {
|
||||
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final LPPermissionService service;
|
||||
private final PluginContainer owner;
|
||||
private final String id;
|
||||
private final Text description;
|
||||
|
||||
@Override
|
||||
public Map<Subject, Boolean> getAssignedSubjects(String id) {
|
||||
LPSubjectCollection subjects = service.getCollection(id);
|
||||
return (Map) subjects.getAllWithPermission(this.id)
|
||||
.thenApply(map -> map.entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(
|
||||
e -> new SubjectProxy(service, e.getKey()),
|
||||
Map.Entry::getValue)
|
||||
)
|
||||
).join();
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.description;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
|
||||
import org.spongepowered.api.plugin.PluginContainer;
|
||||
import org.spongepowered.api.service.permission.PermissionDescription;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.text.Text;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ToString(of = {"container", "roles", "id", "description"})
|
||||
@EqualsAndHashCode(of = {"container", "roles", "id", "description"})
|
||||
@RequiredArgsConstructor
|
||||
public final class SimpleDescriptionBuilder implements PermissionDescription.Builder {
|
||||
private final LuckPermsService service;
|
||||
private final PluginContainer container;
|
||||
private final Map<String, Tristate> roles = new HashMap<>();
|
||||
private String id = null;
|
||||
private Text description = null;
|
||||
|
||||
@Override
|
||||
public PermissionDescription.Builder id(@NonNull String s) {
|
||||
id = s;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionDescription.Builder description(@NonNull Text text) {
|
||||
description = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionDescription.Builder assign(@NonNull String s, boolean b) {
|
||||
roles.put(s, Tristate.fromBoolean(b));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionDescription register() throws IllegalStateException {
|
||||
if (id == null) {
|
||||
throw new IllegalStateException("id cannot be null");
|
||||
}
|
||||
if (description == null) {
|
||||
throw new IllegalStateException("description cannot be null");
|
||||
}
|
||||
|
||||
SimpleDescription d = new SimpleDescription(service, container, id, description);
|
||||
service.getDescriptionSet().add(d);
|
||||
|
||||
// Set role-templates
|
||||
LPSubjectCollection subjects = service.getCollection(PermissionService.SUBJECTS_ROLE_TEMPLATE);
|
||||
for (Map.Entry<String, Tristate> assignment : roles.entrySet()) {
|
||||
LPSubject subject = subjects.loadSubject(assignment.getKey()).join();
|
||||
subject.getTransientSubjectData().setPermission(ContextSet.empty(), id, assignment.getValue());
|
||||
}
|
||||
|
||||
service.getPlugin().getPermissionVault().offer(id);
|
||||
|
||||
// null stuff so this instance can be reused
|
||||
roles.clear();
|
||||
id = null;
|
||||
description = null;
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ package me.lucko.luckperms.sponge.service.legacystorage;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
import me.lucko.luckperms.sponge.service.storage.SubjectStorage;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@ -39,7 +39,7 @@ import java.nio.file.Files;
|
||||
@SuppressWarnings("deprecation")
|
||||
@RequiredArgsConstructor
|
||||
public class LegacyDataMigrator implements Runnable {
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final LPSpongePlugin plugin;
|
||||
|
||||
private final File oldDirectory;
|
||||
private final SubjectStorage storage;
|
||||
@ -69,7 +69,7 @@ public class LegacyDataMigrator implements Runnable {
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(subjectFile.toPath(), StandardCharsets.UTF_8)) {
|
||||
SubjectDataHolder holder = storage.getGson().fromJson(reader, SubjectDataHolder.class);
|
||||
storage.saveToFile(holder.asSubjectModel(), storage.resolveFile(collectionDir.getName(), subjectName));
|
||||
storage.saveToFile(holder.asSubjectModel(plugin.getService()), storage.resolveFile(collectionDir.getName(), subjectName));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -27,7 +27,8 @@ package me.lucko.luckperms.sponge.service.legacystorage;
|
||||
|
||||
import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel;
|
||||
|
||||
@ -50,22 +51,22 @@ public class SubjectDataHolder {
|
||||
// For gson
|
||||
}
|
||||
|
||||
public SubjectStorageModel asSubjectModel() {
|
||||
return new SubjectStorageModel(
|
||||
public SubjectStorageModel asSubjectModel(LPPermissionService service) {
|
||||
return new SubjectStorageModel(service,
|
||||
permissions.entrySet().stream()
|
||||
.collect(Collectors.toMap(
|
||||
k -> ContextSet.fromMap(k.getKey()),
|
||||
k -> ImmutableContextSet.fromMap(k.getKey()),
|
||||
Map.Entry::getValue
|
||||
)),
|
||||
options.entrySet().stream()
|
||||
.collect(Collectors.toMap(
|
||||
k -> ContextSet.fromMap(k.getKey()),
|
||||
k -> ImmutableContextSet.fromMap(k.getKey()),
|
||||
Map.Entry::getValue
|
||||
)),
|
||||
parents.entrySet().stream()
|
||||
.collect(Collectors.toMap(
|
||||
k -> ContextSet.fromMap(k.getKey()),
|
||||
v -> v.getValue().stream().map(SubjectReference::deserialize).collect(Collectors.toList())
|
||||
k -> ImmutableContextSet.fromMap(k.getKey()),
|
||||
v -> v.getValue().stream().map(s -> SubjectReference.deserialize(service, s)).collect(Collectors.toList())
|
||||
))
|
||||
);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.sponge.service.proxy;
|
||||
package me.lucko.luckperms.sponge.service.model;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.experimental.UtilityClass;
|
||||
@ -41,19 +41,22 @@ import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utility class for converting between Sponge and LuckPerms context and tristate classes
|
||||
*/
|
||||
@UtilityClass
|
||||
public class Util {
|
||||
public class CompatibilityUtil {
|
||||
private static final LoadingCache<Set<Context>, ImmutableContextSet> SPONGE_TO_LP_CACHE = Caffeine.newBuilder()
|
||||
.build(ImmutableContextSet::fromEntries);
|
||||
|
||||
private static final LoadingCache<ImmutableContextSet, Set<Context>> LP_TO_SPONGE_CACHE = Caffeine.newBuilder()
|
||||
private static final LoadingCache<ImmutableContextSet, ImmutableSet<Context>> LP_TO_SPONGE_CACHE = Caffeine.newBuilder()
|
||||
.build(set -> set.toSet().stream().map(e -> new Context(e.getKey(), e.getValue())).collect(ImmutableCollectors.toImmutableSet()));
|
||||
|
||||
public static ContextSet convertContexts(@NonNull Set<Context> contexts) {
|
||||
public static ImmutableContextSet convertContexts(@NonNull Set<Context> contexts) {
|
||||
return SPONGE_TO_LP_CACHE.get(ImmutableSet.copyOf(contexts));
|
||||
}
|
||||
|
||||
public static Set<Context> convertContexts(@NonNull ContextSet contexts) {
|
||||
public static ImmutableSet<Context> convertContexts(@NonNull ContextSet contexts) {
|
||||
return LP_TO_SPONGE_CACHE.get(contexts.makeImmutable());
|
||||
}
|
||||
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.context.ContextCalculator;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.sponge.LPSpongePlugin;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import org.spongepowered.api.service.permission.PermissionDescription;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* LuckPerms model for the Sponge {@link org.spongepowered.api.service.permission.PermissionService}
|
||||
*/
|
||||
public interface LPPermissionService {
|
||||
|
||||
LPSpongePlugin getPlugin();
|
||||
|
||||
PermissionService sponge();
|
||||
|
||||
LPSubjectCollection getUserSubjects();
|
||||
|
||||
LPSubjectCollection getGroupSubjects();
|
||||
|
||||
default LPSubjectData getDefaultData() {
|
||||
return getDefaults().getSubjectData();
|
||||
}
|
||||
|
||||
LPSubject getDefaults();
|
||||
|
||||
Predicate<String> getIdentifierValidityPredicate();
|
||||
|
||||
LPSubjectCollection getCollection(String identifier);
|
||||
|
||||
ImmutableMap<String, LPSubjectCollection> getLoadedCollections();
|
||||
|
||||
SubjectReference newSubjectReference(String collectionIdentifier, String subjectIdentifier);
|
||||
|
||||
PermissionDescription.Builder newDescriptionBuilder(Object plugin);
|
||||
|
||||
Optional<PermissionDescription> getDescription(String permission);
|
||||
|
||||
ImmutableCollection<PermissionDescription> getDescriptions();
|
||||
|
||||
void registerContextCalculator(ContextCalculator<Subject> calculator);
|
||||
|
||||
// utils
|
||||
ImmutableList<SubjectReference> sortSubjects(Collection<SubjectReference> s);
|
||||
|
||||
Contexts calculateContexts(ImmutableContextSet contextSet);
|
||||
|
||||
void invalidatePermissionCaches();
|
||||
|
||||
void invalidateParentCaches();
|
||||
|
||||
void invalidateOptionCaches();
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.proxy.SubjectProxy;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* LuckPerms model for the Sponge {@link org.spongepowered.api.service.permission.Subject}
|
||||
*/
|
||||
public interface LPSubject {
|
||||
|
||||
default Subject sponge() {
|
||||
return new SubjectProxy(getService(), toReference());
|
||||
}
|
||||
|
||||
LuckPermsService getService();
|
||||
|
||||
String getIdentifier();
|
||||
|
||||
default SubjectReference toReference() {
|
||||
return getService().newSubjectReference(getParentCollection().getIdentifier(), getIdentifier());
|
||||
}
|
||||
|
||||
default LPSubjectData getDefaultData() {
|
||||
return getDefaults().getSubjectData();
|
||||
}
|
||||
|
||||
default LPSubject getDefaults() {
|
||||
return getService().getDefaultSubjects().loadSubject(getIdentifier()).join();
|
||||
}
|
||||
|
||||
default Optional<String> getFriendlyIdentifier() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
default Optional<CommandSource> getCommandSource() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
LPSubjectCollection getParentCollection();
|
||||
|
||||
LPSubjectData getSubjectData();
|
||||
|
||||
LPSubjectData getTransientSubjectData();
|
||||
|
||||
Tristate getPermissionValue(ImmutableContextSet contexts, String permission);
|
||||
|
||||
boolean isChildOf(ImmutableContextSet contexts, SubjectReference parent);
|
||||
|
||||
ImmutableList<SubjectReference> getParents(ImmutableContextSet contexts);
|
||||
|
||||
Optional<String> getOption(ImmutableContextSet contexts, String key);
|
||||
|
||||
ImmutableContextSet getActiveContextSet();
|
||||
|
||||
default void performCleanup() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* LuckPerms model for the Sponge {@link org.spongepowered.api.service.permission.SubjectCollection}
|
||||
*/
|
||||
public interface LPSubjectCollection {
|
||||
|
||||
SubjectCollection sponge();
|
||||
|
||||
LuckPermsService getService();
|
||||
|
||||
String getIdentifier();
|
||||
|
||||
default SubjectReference newSubjectReference(String identifier) {
|
||||
return getService().newSubjectReference(getIdentifier(), identifier);
|
||||
}
|
||||
|
||||
Predicate<String> getIdentifierValidityPredicate();
|
||||
|
||||
CompletableFuture<LPSubject> loadSubject(String identifier);
|
||||
|
||||
Optional<LPSubject> getSubject(String identifier);
|
||||
|
||||
CompletableFuture<Boolean> hasRegistered(String identifier);
|
||||
|
||||
CompletableFuture<ImmutableCollection<LPSubject>> loadSubjects(Set<String> identifiers);
|
||||
|
||||
ImmutableCollection<LPSubject> getLoadedSubjects();
|
||||
|
||||
CompletableFuture<ImmutableSet<String>> getAllIdentifiers();
|
||||
|
||||
CompletableFuture<ImmutableMap<SubjectReference, Boolean>> getAllWithPermission(String permission);
|
||||
|
||||
CompletableFuture<ImmutableMap<SubjectReference, Boolean>> getAllWithPermission(ImmutableContextSet contexts, String permission);
|
||||
|
||||
ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(String permission);
|
||||
|
||||
ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(ImmutableContextSet contexts, String permission);
|
||||
|
||||
LPSubject getDefaults();
|
||||
|
||||
void suggestUnload(String identifier);
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* LuckPerms model for the Sponge {@link org.spongepowered.api.service.permission.SubjectData}
|
||||
*/
|
||||
public interface LPSubjectData {
|
||||
|
||||
LPSubject getParentSubject();
|
||||
|
||||
/* permissions */
|
||||
|
||||
ImmutableMap<ImmutableContextSet, ImmutableMap<String, Boolean>> getAllPermissions();
|
||||
|
||||
default ImmutableMap<String, Boolean> getPermissions(ImmutableContextSet contexts) {
|
||||
return ImmutableMap.copyOf(getAllPermissions().getOrDefault(contexts, ImmutableMap.of()));
|
||||
}
|
||||
|
||||
CompletableFuture<Boolean> setPermission(ImmutableContextSet contexts, String permission, Tristate value);
|
||||
|
||||
CompletableFuture<Boolean> clearPermissions();
|
||||
|
||||
CompletableFuture<Boolean> clearPermissions(ImmutableContextSet contexts);
|
||||
|
||||
/* parents */
|
||||
|
||||
ImmutableMap<ImmutableContextSet, ImmutableList<SubjectReference>> getAllParents();
|
||||
|
||||
default ImmutableList<SubjectReference> getParents(ImmutableContextSet contexts) {
|
||||
return ImmutableList.copyOf(getAllParents().getOrDefault(contexts, ImmutableList.of()));
|
||||
}
|
||||
|
||||
CompletableFuture<Boolean> addParent(ImmutableContextSet contexts, SubjectReference parent);
|
||||
|
||||
CompletableFuture<Boolean> removeParent(ImmutableContextSet contexts, SubjectReference parent);
|
||||
|
||||
CompletableFuture<Boolean> clearParents();
|
||||
|
||||
CompletableFuture<Boolean> clearParents(ImmutableContextSet contexts);
|
||||
|
||||
/* options */
|
||||
|
||||
ImmutableMap<ImmutableContextSet, ImmutableMap<String, String>> getAllOptions();
|
||||
|
||||
default ImmutableMap<String, String> getOptions(ImmutableContextSet contexts) {
|
||||
return ImmutableMap.copyOf(getAllOptions().getOrDefault(contexts, ImmutableMap.of()));
|
||||
}
|
||||
|
||||
CompletableFuture<Boolean> setOption(ImmutableContextSet contexts, String key, String value);
|
||||
|
||||
CompletableFuture<Boolean> unsetOption(ImmutableContextSet contexts, String key);
|
||||
|
||||
CompletableFuture<Boolean> clearOptions();
|
||||
|
||||
CompletableFuture<Boolean> clearOptions(ImmutableContextSet contexts);
|
||||
|
||||
}
|
@ -27,67 +27,123 @@ package me.lucko.luckperms.sponge.service.persisted;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
import me.lucko.luckperms.sponge.service.proxy.SubjectCollectionProxy;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A simple persistable subject collection
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class PersistedCollection implements LPSubjectCollection {
|
||||
private final LuckPermsService service;
|
||||
private final String identifier;
|
||||
private final boolean transientHasPriority;
|
||||
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final SubjectCollectionProxy spongeProxy;
|
||||
|
||||
@Getter(AccessLevel.NONE)
|
||||
private final LoadingCache<String, PersistedSubject> subjects = Caffeine.newBuilder()
|
||||
.build(s -> new PersistedSubject(s, getService(), PersistedCollection.this));
|
||||
|
||||
public PersistedCollection(LuckPermsService service, String identifier) {
|
||||
this.service = service;
|
||||
this.identifier = identifier;
|
||||
this.spongeProxy = new SubjectCollectionProxy(service, this);
|
||||
}
|
||||
|
||||
public void loadAll() {
|
||||
Map<String, SubjectStorageModel> holders = service.getStorage().loadAllFromFile(identifier);
|
||||
for (Map.Entry<String, SubjectStorageModel> e : holders.entrySet()) {
|
||||
PersistedSubject subject = get(e.getKey());
|
||||
PersistedSubject subject = subjects.get(e.getKey().toLowerCase());
|
||||
subject.loadData(e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistedSubject get(@NonNull String id) {
|
||||
return subjects.get(id.toLowerCase());
|
||||
public SubjectCollection sponge() {
|
||||
return spongeProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRegistered(@NonNull String id) {
|
||||
return subjects.asMap().containsKey(id.toLowerCase());
|
||||
public Predicate<String> getIdentifierValidityPredicate() {
|
||||
return Predicates.alwaysTrue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<LPSubject> getSubjects() {
|
||||
return subjects.asMap().values().stream().map(s -> (LPSubject) s).collect(ImmutableCollectors.toImmutableList());
|
||||
public CompletableFuture<LPSubject> loadSubject(String identifier) {
|
||||
return CompletableFuture.completedFuture(subjects.get(identifier.toLowerCase()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<LPSubject, Boolean> getWithPermission(@NonNull ContextSet contexts, @NonNull String node) {
|
||||
public Optional<LPSubject> getSubject(String identifier) {
|
||||
return Optional.of(subjects.get(identifier.toLowerCase()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> hasRegistered(String identifier) {
|
||||
return CompletableFuture.completedFuture(subjects.asMap().containsKey(identifier.toLowerCase()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ImmutableCollection<LPSubject>> loadSubjects(Set<String> identifiers) {
|
||||
ImmutableSet.Builder<LPSubject> ret = ImmutableSet.builder();
|
||||
for (String id : identifiers) {
|
||||
ret.add(subjects.get(id.toLowerCase()));
|
||||
}
|
||||
return CompletableFuture.completedFuture(ret.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableCollection<LPSubject> getLoadedSubjects() {
|
||||
return ImmutableList.copyOf(subjects.asMap().values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ImmutableSet<String>> getAllIdentifiers() {
|
||||
return CompletableFuture.completedFuture(ImmutableSet.copyOf(subjects.asMap().keySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ImmutableMap<SubjectReference, Boolean>> getAllWithPermission(String permission) {
|
||||
return CompletableFuture.completedFuture(getLoadedWithPermission(permission).entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(e -> e.getKey().toReference(), Map.Entry::getValue)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ImmutableMap<SubjectReference, Boolean>> getAllWithPermission(ImmutableContextSet contexts, String permission) {
|
||||
return CompletableFuture.completedFuture(getLoadedWithPermission(contexts, permission).entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(e -> e.getKey().toReference(), Map.Entry::getValue)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(String permission) {
|
||||
ImmutableMap.Builder<LPSubject, Boolean> m = ImmutableMap.builder();
|
||||
for (LPSubject subject : subjects.asMap().values()) {
|
||||
Tristate ts = subject.getPermissionValue(contexts, node);
|
||||
Tristate ts = subject.getPermissionValue(ImmutableContextSet.empty(), permission);
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
m.put(subject, ts.asBoolean());
|
||||
}
|
||||
@ -97,12 +153,25 @@ public class PersistedCollection implements LPSubjectCollection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectReference getDefaultSubject() {
|
||||
return SubjectReference.of("defaults", identifier);
|
||||
public ImmutableMap<LPSubject, Boolean> getLoadedWithPermission(ImmutableContextSet contexts, String permission) {
|
||||
ImmutableMap.Builder<LPSubject, Boolean> m = ImmutableMap.builder();
|
||||
for (LPSubject subject : subjects.asMap().values()) {
|
||||
Tristate ts = subject.getPermissionValue(contexts, permission);
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
m.put(subject, ts.asBoolean());
|
||||
}
|
||||
|
||||
}
|
||||
return m.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTransientHasPriority() {
|
||||
return transientHasPriority;
|
||||
public LPSubject getDefaults() {
|
||||
return service.getDefaultSubjects().loadSubject(getIdentifier()).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestUnload(String identifier) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
@ -30,18 +30,16 @@ import lombok.NonNull;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.calculated.OptionLookup;
|
||||
import me.lucko.luckperms.sponge.service.calculated.PermissionLookup;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel;
|
||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||
@ -51,9 +49,9 @@ import org.spongepowered.api.command.CommandSource;
|
||||
import co.aikar.timings.Timing;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -63,9 +61,9 @@ import java.util.concurrent.TimeUnit;
|
||||
public class PersistedSubject implements LPSubject {
|
||||
private final String identifier;
|
||||
|
||||
@Getter
|
||||
private final LuckPermsService service;
|
||||
private final SubjectCollectionReference parentCollection;
|
||||
private final PersistedCollection parentCollection;
|
||||
|
||||
private final PersistedSubjectData subjectData;
|
||||
private final CalculatedSubjectData transientSubjectData;
|
||||
|
||||
@ -73,7 +71,7 @@ public class PersistedSubject implements LPSubject {
|
||||
.expireAfterAccess(20, TimeUnit.MINUTES)
|
||||
.build(lookup -> lookupPermissionValue(lookup.getContexts(), lookup.getNode()));
|
||||
|
||||
private final LoadingCache<ImmutableContextSet, Set<SubjectReference>> parentLookupCache = Caffeine.newBuilder()
|
||||
private final LoadingCache<ImmutableContextSet, ImmutableList<SubjectReference>> parentLookupCache = Caffeine.newBuilder()
|
||||
.expireAfterAccess(20, TimeUnit.MINUTES)
|
||||
.build(this::lookupParents);
|
||||
|
||||
@ -95,13 +93,13 @@ public class PersistedSubject implements LPSubject {
|
||||
}
|
||||
};
|
||||
|
||||
public PersistedSubject(String identifier, LuckPermsService service, PersistedCollection containingCollection) {
|
||||
public PersistedSubject(String identifier, LuckPermsService service, PersistedCollection parentCollection) {
|
||||
this.identifier = identifier;
|
||||
this.service = service;
|
||||
this.parentCollection = containingCollection.toReference();
|
||||
this.parentCollection = parentCollection;
|
||||
|
||||
this.subjectData = new PersistedSubjectData(service, "local:" + containingCollection.getIdentifier() + "/" + identifier + "(p)", this);
|
||||
this.transientSubjectData = new CalculatedSubjectData(this, service, "local:" + containingCollection.getIdentifier() + "/" + identifier + "(t)");
|
||||
this.subjectData = new PersistedSubjectData(service, "local:" + parentCollection.getIdentifier() + "/" + identifier + "(p)", this);
|
||||
this.transientSubjectData = new CalculatedSubjectData(this, service, "local:" + parentCollection.getIdentifier() + "/" + identifier + "(t)");
|
||||
|
||||
service.getLocalDataCaches().add(subjectData);
|
||||
service.getLocalDataCaches().add(transientSubjectData);
|
||||
@ -134,10 +132,11 @@ public class PersistedSubject implements LPSubject {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Tristate lookupPermissionValue(ContextSet contexts, String node) {
|
||||
private Tristate lookupPermissionValue(ImmutableContextSet contexts, String node) {
|
||||
Tristate res;
|
||||
|
||||
if (parentCollection.resolve(service).getTransientHasPriority()) {
|
||||
// if transient has priority
|
||||
if (!parentCollection.getIdentifier().equals("defaults")) {
|
||||
res = transientSubjectData.getPermissionValue(contexts, node);
|
||||
if (res != Tristate.UNDEFINED) {
|
||||
return res;
|
||||
@ -160,17 +159,17 @@ public class PersistedSubject implements LPSubject {
|
||||
}
|
||||
|
||||
for (SubjectReference parent : getParents(contexts)) {
|
||||
res = parent.resolve(service).getPermissionValue(contexts, node);
|
||||
res = parent.resolve().join().getPermissionValue(contexts, node);
|
||||
if (res != Tristate.UNDEFINED) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")) {
|
||||
if (getParentCollection().getIdentifier().equalsIgnoreCase("defaults")) {
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
|
||||
res = getParentCollection().resolve(service).getDefaultSubject().resolve(service).getPermissionValue(contexts, node);
|
||||
res = getParentCollection().getDefaults().getPermissionValue(contexts, node);
|
||||
if (res != Tristate.UNDEFINED) {
|
||||
return res;
|
||||
}
|
||||
@ -179,23 +178,24 @@ public class PersistedSubject implements LPSubject {
|
||||
return res;
|
||||
}
|
||||
|
||||
private Set<SubjectReference> lookupParents(ContextSet contexts) {
|
||||
Set<SubjectReference> s = new HashSet<>();
|
||||
private ImmutableList<SubjectReference> lookupParents(ImmutableContextSet contexts) {
|
||||
List<SubjectReference> s = new ArrayList<>();
|
||||
s.addAll(subjectData.getParents(contexts));
|
||||
s.addAll(transientSubjectData.getParents(contexts));
|
||||
|
||||
if (!getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")) {
|
||||
s.addAll(getParentCollection().resolve(service).getDefaultSubject().resolve(service).getParents(contexts));
|
||||
if (!getParentCollection().getIdentifier().equalsIgnoreCase("defaults")) {
|
||||
s.addAll(getParentCollection().getDefaults().getParents(contexts));
|
||||
s.addAll(service.getDefaults().getParents(contexts));
|
||||
}
|
||||
|
||||
return ImmutableSet.copyOf(s);
|
||||
return service.sortSubjects(s);
|
||||
}
|
||||
|
||||
private Optional<String> lookupOptionValue(ContextSet contexts, String key) {
|
||||
private Optional<String> lookupOptionValue(ImmutableContextSet contexts, String key) {
|
||||
Optional<String> res;
|
||||
|
||||
if (getParentCollection().resolve(service).getTransientHasPriority()) {
|
||||
// if transient has priority
|
||||
if (!parentCollection.getIdentifier().equals("defaults")) {
|
||||
res = Optional.ofNullable(transientSubjectData.getOptions(contexts).get(key));
|
||||
if (res.isPresent()) {
|
||||
return res;
|
||||
@ -218,17 +218,17 @@ public class PersistedSubject implements LPSubject {
|
||||
}
|
||||
|
||||
for (SubjectReference parent : getParents(contexts)) {
|
||||
res = parent.resolve(service).getOption(contexts, key);
|
||||
res = parent.resolve().join().getOption(contexts, key);
|
||||
if (res.isPresent()) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")) {
|
||||
if (getParentCollection().getIdentifier().equalsIgnoreCase("defaults")) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
res = getParentCollection().resolve(service).getDefaultSubject().resolve(service).getOption(contexts, key);
|
||||
res = getParentCollection().getDefaults().getOption(contexts, key);
|
||||
if (res.isPresent()) {
|
||||
return res;
|
||||
}
|
||||
@ -237,47 +237,47 @@ public class PersistedSubject implements LPSubject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(@NonNull ContextSet contexts, @NonNull String node) {
|
||||
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.makeImmutable()));
|
||||
service.getPlugin().getVerboseHandler().offer("local:" + getParentCollection().getCollection() + "/" + identifier, node, t);
|
||||
Tristate t = permissionLookupCache.get(PermissionLookup.of(node, contexts));
|
||||
service.getPlugin().getVerboseHandler().offer("local:" + getParentCollection().getIdentifier() + "/" + identifier, node, t);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(@NonNull ContextSet contexts, @NonNull SubjectReference subject) {
|
||||
public boolean isChildOf(@NonNull ImmutableContextSet contexts, @NonNull SubjectReference subject) {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_IS_CHILD_OF)) {
|
||||
if (getParentCollection().resolve(service).getIdentifier().equalsIgnoreCase("defaults")) {
|
||||
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().resolve(service).getDefaultSubject().resolve(service).getParents(contexts).contains(subject) ||
|
||||
getParentCollection().getDefaults().getParents(contexts).contains(subject) ||
|
||||
service.getDefaults().getParents(contexts).contains(subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SubjectReference> getParents(@NonNull ContextSet contexts) {
|
||||
public ImmutableList<SubjectReference> getParents(@NonNull ImmutableContextSet contexts) {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_PARENTS)) {
|
||||
return parentLookupCache.get(contexts.makeImmutable());
|
||||
return parentLookupCache.get(contexts);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(ContextSet contexts, String key) {
|
||||
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.makeImmutable()));
|
||||
return optionLookupCache.get(OptionLookup.of(key, contexts));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextSet getActiveContextSet() {
|
||||
public ImmutableContextSet getActiveContextSet() {
|
||||
try (Timing ignored = service.getPlugin().getTimings().time(LPTiming.INTERNAL_SUBJECT_GET_ACTIVE_CONTEXTS)) {
|
||||
return service.getPlugin().getContextManager().getApplicableContext(this);
|
||||
return service.getPlugin().getContextManager().getApplicableContext(sponge()).makeImmutable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,15 +28,19 @@ package me.lucko.luckperms.sponge.service.persisted;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Extension of MemorySubjectData which persists data when modified
|
||||
*/
|
||||
public class PersistedSubjectData extends CalculatedSubjectData {
|
||||
public class PersistedSubjectData extends CalculatedSubjectData implements Function<Boolean, Boolean> {
|
||||
private final PersistedSubject subject;
|
||||
|
||||
@Getter
|
||||
@ -59,79 +63,63 @@ public class PersistedSubjectData extends CalculatedSubjectData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPermission(ContextSet contexts, String permission, me.lucko.luckperms.api.Tristate value) {
|
||||
boolean r = super.setPermission(contexts, permission, value);
|
||||
public Boolean apply(Boolean b) {
|
||||
save();
|
||||
return r;
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearPermissions() {
|
||||
boolean r = super.clearPermissions();
|
||||
save();
|
||||
return r;
|
||||
public CompletableFuture<Boolean> setPermission(ImmutableContextSet contexts, String permission, Tristate value) {
|
||||
return super.setPermission(contexts, permission, value).thenApply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearPermissions(ContextSet contexts) {
|
||||
boolean r = super.clearPermissions(contexts);
|
||||
save();
|
||||
return r;
|
||||
public CompletableFuture<Boolean> clearPermissions() {
|
||||
return super.clearPermissions().thenApply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addParent(ContextSet contexts, SubjectReference parent) {
|
||||
boolean r = super.addParent(contexts, parent);
|
||||
save();
|
||||
return r;
|
||||
public CompletableFuture<Boolean> clearPermissions(ImmutableContextSet contexts) {
|
||||
return super.clearPermissions(contexts).thenApply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeParent(ContextSet contexts, SubjectReference parent) {
|
||||
boolean r = super.removeParent(contexts, parent);
|
||||
save();
|
||||
return r;
|
||||
public CompletableFuture<Boolean> addParent(ImmutableContextSet contexts, SubjectReference parent) {
|
||||
return super.addParent(contexts, parent).thenApply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearParents() {
|
||||
boolean r = super.clearParents();
|
||||
save();
|
||||
return r;
|
||||
public CompletableFuture<Boolean> removeParent(ImmutableContextSet contexts, SubjectReference parent) {
|
||||
return super.removeParent(contexts, parent).thenApply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearParents(ContextSet contexts) {
|
||||
boolean r = super.clearParents(contexts);
|
||||
save();
|
||||
return r;
|
||||
public CompletableFuture<Boolean> clearParents() {
|
||||
return super.clearParents().thenApply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setOption(ContextSet contexts, String key, String value) {
|
||||
boolean r = super.setOption(contexts, key, value);
|
||||
save();
|
||||
return r;
|
||||
public CompletableFuture<Boolean> clearParents(ImmutableContextSet contexts) {
|
||||
return super.clearParents(contexts).thenApply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unsetOption(ContextSet contexts, String key) {
|
||||
boolean r = super.unsetOption(contexts, key);
|
||||
save();
|
||||
return r;
|
||||
public CompletableFuture<Boolean> setOption(ImmutableContextSet contexts, String key, String value) {
|
||||
return super.setOption(contexts, key, value).thenApply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOptions(ContextSet contexts) {
|
||||
boolean r = super.clearOptions(contexts);
|
||||
save();
|
||||
return r;
|
||||
public CompletableFuture<Boolean> unsetOption(ImmutableContextSet contexts, String key) {
|
||||
return super.unsetOption(contexts, key).thenApply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOptions() {
|
||||
boolean r = super.clearOptions();
|
||||
save();
|
||||
return r;
|
||||
public CompletableFuture<Boolean> clearOptions() {
|
||||
return super.clearOptions().thenApply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> clearOptions(ImmutableContextSet contexts) {
|
||||
return super.clearOptions(contexts).thenApply(this);
|
||||
}
|
||||
}
|
||||
|
@ -1,159 +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.proxy;
|
||||
|
||||
import lombok.NonNull;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static me.lucko.luckperms.sponge.service.proxy.Util.convertContexts;
|
||||
import static me.lucko.luckperms.sponge.service.proxy.Util.convertTristate;
|
||||
|
||||
public interface LPSubject extends Subject {
|
||||
|
||||
@Override
|
||||
String getIdentifier();
|
||||
|
||||
default Optional<String> getFriendlyIdentifier() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
default Optional<CommandSource> getCommandSource() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
SubjectCollectionReference getParentCollection();
|
||||
|
||||
LuckPermsService getService();
|
||||
|
||||
default void performCleanup() {
|
||||
|
||||
}
|
||||
|
||||
default SubjectReference toReference() {
|
||||
return SubjectReference.of(getParentCollection().getCollection(), getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
LPSubjectData getSubjectData();
|
||||
|
||||
@Override
|
||||
LPSubjectData getTransientSubjectData();
|
||||
|
||||
me.lucko.luckperms.api.Tristate getPermissionValue(ContextSet contexts, String permission);
|
||||
|
||||
boolean isChildOf(ContextSet contexts, SubjectReference parent);
|
||||
|
||||
Set<SubjectReference> getParents(ContextSet contexts);
|
||||
|
||||
Optional<String> getOption(ContextSet contexts, String key);
|
||||
|
||||
ContextSet getActiveContextSet();
|
||||
|
||||
|
||||
/* Compat */
|
||||
|
||||
@Override
|
||||
default LPSubjectCollection getContainingCollection() {
|
||||
return getParentCollection().resolve(getService());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean hasPermission(@NonNull Set<Context> contexts, @NonNull String permission) {
|
||||
return getPermissionValue(convertContexts(contexts), permission).asBoolean();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean hasPermission(@NonNull String permission) {
|
||||
return getPermissionValue(getActiveContextSet(), permission).asBoolean();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Tristate getPermissionValue(@NonNull Set<Context> contexts, @NonNull String permission) {
|
||||
return convertTristate(getPermissionValue(convertContexts(contexts), permission));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean isChildOf(@NonNull Subject parent) {
|
||||
return isChildOf(getActiveContextSet(), SubjectReference.of(parent));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean isChildOf(@NonNull Set<Context> contexts, @NonNull Subject parent) {
|
||||
return isChildOf(convertContexts(contexts), SubjectReference.of(parent));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default List<Subject> getParents() {
|
||||
List<Subject> ret = getParents(getActiveContextSet()).stream().map(s -> s.resolve(getService())).collect(ImmutableCollectors.toImmutableList());
|
||||
return getService().sortSubjects(ret);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default List<Subject> getParents(@NonNull Set<Context> contexts) {
|
||||
List<Subject> ret = getParents(convertContexts(contexts)).stream().map(s -> s.resolve(getService())).collect(ImmutableCollectors.toImmutableList());
|
||||
return getService().sortSubjects(ret);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Optional<String> getOption(@NonNull String key) {
|
||||
return getOption(getActiveContextSet(), key);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Optional<String> getOption(@NonNull Set<Context> contexts, @NonNull String key) {
|
||||
return getOption(convertContexts(contexts), key);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Set<Context> getActiveContexts() {
|
||||
return convertContexts(getActiveContextSet());
|
||||
}
|
||||
}
|
@ -1,99 +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.proxy;
|
||||
|
||||
import lombok.NonNull;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static me.lucko.luckperms.sponge.service.proxy.Util.convertContexts;
|
||||
|
||||
public interface LPSubjectCollection extends SubjectCollection {
|
||||
|
||||
@Override
|
||||
String getIdentifier();
|
||||
|
||||
LuckPermsService getService();
|
||||
|
||||
default SubjectCollectionReference toReference() {
|
||||
return SubjectCollectionReference.of(getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
LPSubject get(String identifier);
|
||||
|
||||
@Override
|
||||
boolean hasRegistered(String identifier);
|
||||
|
||||
Collection<LPSubject> getSubjects();
|
||||
|
||||
default Map<LPSubject, Boolean> getWithPermission(String permission) {
|
||||
return getWithPermission(ContextSet.empty(), permission);
|
||||
}
|
||||
|
||||
Map<LPSubject, Boolean> getWithPermission(ContextSet contexts, String permission);
|
||||
|
||||
SubjectReference getDefaultSubject();
|
||||
|
||||
boolean getTransientHasPriority();
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Subject getDefaults() {
|
||||
return getDefaultSubject().resolve(getService());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Iterable<Subject> getAllSubjects() {
|
||||
return getSubjects().stream().collect(ImmutableCollectors.toImmutableList());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Map<Subject, Boolean> getAllWithPermission(@NonNull String permission) {
|
||||
return getWithPermission(permission).entrySet().stream().collect(ImmutableCollectors.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Map<Subject, Boolean> getAllWithPermission(@NonNull Set<Context> contexts, @NonNull String permission) {
|
||||
return getWithPermission(convertContexts(contexts), permission).entrySet().stream().collect(ImmutableCollectors.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
}
|
@ -1,194 +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.proxy;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectData;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static me.lucko.luckperms.sponge.service.proxy.Util.convertContexts;
|
||||
import static me.lucko.luckperms.sponge.service.proxy.Util.convertTristate;
|
||||
|
||||
public interface LPSubjectData extends SubjectData {
|
||||
|
||||
LPSubject getParentSubject();
|
||||
|
||||
Map<ImmutableContextSet, Map<String, Boolean>> getPermissions();
|
||||
|
||||
default Map<String, Boolean> getPermissions(ContextSet contexts) {
|
||||
return ImmutableMap.copyOf(getPermissions().getOrDefault(contexts, ImmutableMap.of()));
|
||||
}
|
||||
|
||||
boolean setPermission(ContextSet contexts, String permission, me.lucko.luckperms.api.Tristate value);
|
||||
|
||||
@Override
|
||||
boolean clearPermissions();
|
||||
|
||||
boolean clearPermissions(ContextSet contexts);
|
||||
|
||||
Map<ImmutableContextSet, Set<SubjectReference>> getParents();
|
||||
|
||||
default Set<SubjectReference> getParents(ContextSet contexts) {
|
||||
return ImmutableSet.copyOf(getParents().getOrDefault(contexts, ImmutableSet.of()));
|
||||
}
|
||||
|
||||
boolean addParent(ContextSet contexts, SubjectReference parent);
|
||||
|
||||
boolean removeParent(ContextSet contexts, SubjectReference parent);
|
||||
|
||||
@Override
|
||||
boolean clearParents();
|
||||
|
||||
boolean clearParents(ContextSet contexts);
|
||||
|
||||
Map<ImmutableContextSet, Map<String, String>> getOptions();
|
||||
|
||||
default Map<String, String> getOptions(ContextSet contexts) {
|
||||
return ImmutableMap.copyOf(getOptions().getOrDefault(contexts, ImmutableMap.of()));
|
||||
}
|
||||
|
||||
boolean setOption(ContextSet contexts, String key, String value);
|
||||
|
||||
boolean unsetOption(ContextSet contexts, String key);
|
||||
|
||||
boolean clearOptions(ContextSet contexts);
|
||||
|
||||
@Override
|
||||
boolean clearOptions();
|
||||
|
||||
|
||||
|
||||
/* Compat */
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Map<Set<Context>, Map<String, Boolean>> getAllPermissions() {
|
||||
return getPermissions().entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(
|
||||
e -> convertContexts(e.getKey()),
|
||||
e -> ImmutableMap.copyOf(e.getValue()))
|
||||
);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Map<String, Boolean> getPermissions(Set<Context> contexts) {
|
||||
return ImmutableMap.copyOf(getPermissions(convertContexts(contexts)));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean setPermission(Set<Context> contexts, String permission, Tristate value) {
|
||||
return setPermission(convertContexts(contexts), permission, convertTristate(value));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean clearPermissions(Set<Context> contexts) {
|
||||
return clearPermissions(convertContexts(contexts));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Map<Set<Context>, List<Subject>> getAllParents() {
|
||||
return getParents().entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(
|
||||
e -> convertContexts(e.getKey()),
|
||||
e -> e.getValue().stream()
|
||||
.map(s -> s.resolve(getParentSubject().getService()))
|
||||
.collect(ImmutableCollectors.toImmutableList())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default List<Subject> getParents(Set<Context> contexts) {
|
||||
return getParents(convertContexts(contexts)).stream().map(s -> s.resolve(getParentSubject().getService())).collect(ImmutableCollectors.toImmutableList());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean addParent(Set<Context> contexts, Subject parent) {
|
||||
return addParent(convertContexts(contexts), SubjectReference.of(parent));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean removeParent(Set<Context> contexts, Subject parent) {
|
||||
return removeParent(convertContexts(contexts), SubjectReference.of(parent));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean clearParents(Set<Context> contexts) {
|
||||
return clearParents(convertContexts(contexts));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Map<Set<Context>, Map<String, String>> getAllOptions() {
|
||||
return getOptions().entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(
|
||||
e -> convertContexts(e.getKey()),
|
||||
e -> ImmutableMap.copyOf(e.getValue()))
|
||||
);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default Map<String, String> getOptions(Set<Context> contexts) {
|
||||
return ImmutableMap.copyOf(getOptions(convertContexts(contexts)));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean setOption(Set<Context> contexts, String key, @Nullable String value) {
|
||||
return value == null ? unsetOption(convertContexts(contexts), key) : setOption(convertContexts(contexts), key, value);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default boolean clearOptions(Set<Context> contexts) {
|
||||
return clearOptions(convertContexts(contexts));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.sponge.contexts.SpongeCalculatorLink;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
|
||||
import org.spongepowered.api.service.context.ContextCalculator;
|
||||
import org.spongepowered.api.service.permission.PermissionDescription;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class PermissionServiceProxy implements PermissionService {
|
||||
private final LPPermissionService handle;
|
||||
|
||||
@Override
|
||||
public SubjectCollection getUserSubjects() {
|
||||
return handle.getUserSubjects().sponge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectCollection getGroupSubjects() {
|
||||
return handle.getGroupSubjects().sponge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return handle.getDefaults().sponge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectCollection getSubjects(String s) {
|
||||
return handle.getCollection(s).sponge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, SubjectCollection> getKnownSubjects() {
|
||||
return handle.getLoadedCollections().entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(
|
||||
Map.Entry::getKey,
|
||||
e -> e.getValue().sponge()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PermissionDescription.Builder> newDescriptionBuilder(Object o) {
|
||||
return Optional.of(handle.newDescriptionBuilder(o));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PermissionDescription> getDescription(String s) {
|
||||
return handle.getDescription(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PermissionDescription> getDescriptions() {
|
||||
return handle.getDescriptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerContextCalculator(ContextCalculator<Subject> contextCalculator) {
|
||||
handle.registerContextCalculator(new SpongeCalculatorLink(contextCalculator));
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.sponge.service.model.CompatibilityUtil;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectCollection;
|
||||
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@RequiredArgsConstructor
|
||||
public class SubjectCollectionProxy implements SubjectCollection {
|
||||
private final LPPermissionService service;
|
||||
private final LPSubjectCollection handle;
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return handle.getIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subject get(String s) {
|
||||
// force load the subject.
|
||||
// after this call, users will expect that the subject is loaded in memory.
|
||||
return handle.loadSubject(s).thenApply(LPSubject::sponge).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRegistered(String s) {
|
||||
return handle.hasRegistered(s).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Subject> getAllSubjects() {
|
||||
// this will lazily load all subjects. it will initially just get the identifiers of each subject, and will initialize dummy
|
||||
// providers for those identifiers. when any methods against the dummy are called, the actual data will be loaded.
|
||||
// this behaviour should be replaced when CompletableFutures are added to Sponge
|
||||
return (List) handle.getAllIdentifiers()
|
||||
.thenApply(ids -> ids.stream()
|
||||
.map(s -> new SubjectProxy(service, service.newSubjectReference(getIdentifier(), s)))
|
||||
.collect(ImmutableCollectors.toImmutableList())
|
||||
).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Subject, Boolean> getAllWithPermission(String s) {
|
||||
// again, these methods will lazily load subjects.
|
||||
return (Map) handle.getAllWithPermission(s).thenApply(map -> {
|
||||
return map.entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(
|
||||
e -> new SubjectProxy(service, e.getKey()),
|
||||
Map.Entry::getValue
|
||||
));
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Subject, Boolean> getAllWithPermission(Set<Context> set, String s) {
|
||||
return (Map) handle.getAllWithPermission(CompatibilityUtil.convertContexts(set), s)
|
||||
.thenApply(map -> map.entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(
|
||||
e -> new SubjectProxy(service, e.getKey()),
|
||||
Map.Entry::getValue
|
||||
))
|
||||
).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return handle.getDefaults().sponge();
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.sponge.service.model.CompatibilityUtil;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectData;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Proxies a LuckPerms Subject to implement {@link SubjectData}.
|
||||
*
|
||||
* All methods which return "boolean" will return instantly, and the change will be applied in the background.
|
||||
* This will be changed as soon as Sponge implements futures into its API.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@RequiredArgsConstructor
|
||||
public class SubjectDataProxy implements SubjectData {
|
||||
private final LPPermissionService service;
|
||||
private final SubjectReference ref;
|
||||
private final boolean enduring;
|
||||
|
||||
private CompletableFuture<LPSubjectData> getHandle() {
|
||||
return enduring ? ref.resolve().thenApply(LPSubject::getSubjectData) : ref.resolve().thenApply(LPSubject::getTransientSubjectData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Set<Context>, Map<String, Boolean>> getAllPermissions() {
|
||||
return (Map) getHandle().thenApply(handle -> {
|
||||
return handle.getAllPermissions().entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(
|
||||
e -> CompatibilityUtil.convertContexts(e.getKey()),
|
||||
Map.Entry::getValue
|
||||
));
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getPermissions(Set<Context> contexts) {
|
||||
return getHandle().thenApply(handle -> handle.getPermissions(CompatibilityUtil.convertContexts(contexts))).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPermission(Set<Context> contexts, String permission, Tristate value) {
|
||||
getHandle().thenCompose(handle -> {
|
||||
return handle.setPermission(
|
||||
CompatibilityUtil.convertContexts(contexts),
|
||||
permission,
|
||||
CompatibilityUtil.convertTristate(value)
|
||||
);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearPermissions() {
|
||||
getHandle().thenCompose(LPSubjectData::clearPermissions);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearPermissions(Set<Context> contexts) {
|
||||
getHandle().thenCompose(handle -> handle.clearPermissions(CompatibilityUtil.convertContexts(contexts)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Set<Context>, List<Subject>> getAllParents() {
|
||||
return (Map) getHandle().thenApply(handle -> {
|
||||
return handle.getAllParents().entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(
|
||||
e -> CompatibilityUtil.convertContexts(e.getKey()),
|
||||
e -> e.getValue().stream()
|
||||
.map(s -> new SubjectProxy(service, s))
|
||||
.collect(ImmutableCollectors.toImmutableList())
|
||||
)
|
||||
);
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Subject> getParents(Set<Context> contexts) {
|
||||
return (List) getHandle().thenApply(handle -> {
|
||||
return handle.getParents(CompatibilityUtil.convertContexts(contexts)).stream()
|
||||
.map(s -> new SubjectProxy(service, s))
|
||||
.collect(ImmutableCollectors.toImmutableList());
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addParent(Set<Context> contexts, Subject parent) {
|
||||
getHandle().thenCompose(handle -> {
|
||||
return handle.addParent(
|
||||
CompatibilityUtil.convertContexts(contexts),
|
||||
service.newSubjectReference(
|
||||
parent.getContainingCollection().getIdentifier(),
|
||||
parent.getIdentifier()
|
||||
)
|
||||
);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeParent(Set<Context> contexts, Subject parent) {
|
||||
getHandle().thenCompose(handle -> {
|
||||
return handle.removeParent(
|
||||
CompatibilityUtil.convertContexts(contexts),
|
||||
service.newSubjectReference(
|
||||
parent.getContainingCollection().getIdentifier(),
|
||||
parent.getIdentifier()
|
||||
)
|
||||
);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearParents() {
|
||||
getHandle().thenCompose(LPSubjectData::clearParents);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearParents(Set<Context> contexts) {
|
||||
getHandle().thenCompose(handle -> handle.clearParents(CompatibilityUtil.convertContexts(contexts)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Set<Context>, Map<String, String>> getAllOptions() {
|
||||
return (Map) getHandle().thenApply(handle -> {
|
||||
return handle.getAllOptions().entrySet().stream()
|
||||
.collect(ImmutableCollectors.toImmutableMap(
|
||||
e -> CompatibilityUtil.convertContexts(e.getKey()),
|
||||
Map.Entry::getValue
|
||||
));
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getOptions(Set<Context> contexts) {
|
||||
return getHandle().thenApply(handle -> handle.getOptions(CompatibilityUtil.convertContexts(contexts))).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setOption(Set<Context> contexts, String key, String value) {
|
||||
if (value == null) {
|
||||
getHandle().thenCompose(handle -> handle.unsetOption(CompatibilityUtil.convertContexts(contexts), key));
|
||||
return true;
|
||||
} else {
|
||||
getHandle().thenCompose(handle -> handle.setOption(CompatibilityUtil.convertContexts(contexts), key, value));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOptions(Set<Context> contexts) {
|
||||
getHandle().thenCompose(handle -> handle.clearOptions(CompatibilityUtil.convertContexts(contexts)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOptions() {
|
||||
getHandle().thenCompose(LPSubjectData::clearOptions);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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.proxy;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.common.utils.ImmutableCollectors;
|
||||
import me.lucko.luckperms.sponge.service.model.CompatibilityUtil;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
import org.spongepowered.api.service.permission.SubjectData;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@RequiredArgsConstructor
|
||||
public class SubjectProxy implements Subject {
|
||||
private final LPPermissionService service;
|
||||
private final SubjectReference ref;
|
||||
|
||||
private CompletableFuture<LPSubject> getHandle() {
|
||||
return ref.resolve();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CommandSource> getCommandSource() {
|
||||
return getHandle().thenApply(LPSubject::getCommandSource).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectCollection getContainingCollection() {
|
||||
return service.getCollection(ref.getCollection()).sponge();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectData getSubjectData() {
|
||||
return new SubjectDataProxy(service, ref, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectData getTransientSubjectData() {
|
||||
return new SubjectDataProxy(service, ref, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Set<Context> contexts, String permission) {
|
||||
return getHandle().thenApply(handle -> {
|
||||
return handle.getPermissionValue(CompatibilityUtil.convertContexts(contexts), permission).asBoolean();
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return getHandle().thenApply(handle -> {
|
||||
return handle.getPermissionValue(ImmutableContextSet.empty(), permission).asBoolean();
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(Set<Context> contexts, String permission) {
|
||||
return getHandle().thenApply(handle -> {
|
||||
return CompatibilityUtil.convertTristate(handle.getPermissionValue(CompatibilityUtil.convertContexts(contexts), permission));
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(Subject parent) {
|
||||
return getHandle().thenApply(handle -> {
|
||||
return handle.isChildOf(
|
||||
ImmutableContextSet.empty(),
|
||||
service.newSubjectReference(
|
||||
parent.getContainingCollection().getIdentifier(),
|
||||
parent.getIdentifier()
|
||||
)
|
||||
);
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(Set<Context> contexts, Subject parent) {
|
||||
return getHandle().thenApply(handle -> {
|
||||
return handle.isChildOf(
|
||||
CompatibilityUtil.convertContexts(contexts),
|
||||
service.newSubjectReference(
|
||||
parent.getContainingCollection().getIdentifier(),
|
||||
parent.getIdentifier()
|
||||
)
|
||||
);
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Subject> getParents() {
|
||||
return (List) getHandle().thenApply(handle -> {
|
||||
return handle.getParents(ImmutableContextSet.empty()).stream()
|
||||
.map(s -> new SubjectProxy(service, s))
|
||||
.collect(ImmutableCollectors.toImmutableList());
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Subject> getParents(Set<Context> contexts) {
|
||||
return (List) getHandle().thenApply(handle -> {
|
||||
return handle.getParents(CompatibilityUtil.convertContexts(contexts)).stream()
|
||||
.map(s -> new SubjectProxy(service, s))
|
||||
.collect(ImmutableCollectors.toImmutableList());
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(Set<Context> contexts, String key) {
|
||||
return getHandle().thenApply(handle -> {
|
||||
return handle.getOption(CompatibilityUtil.convertContexts(contexts), key);
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(String key) {
|
||||
return getHandle().thenApply(handle -> {
|
||||
return handle.getOption(ImmutableContextSet.empty(), key);
|
||||
}).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return ref.getIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Context> getActiveContexts() {
|
||||
return getHandle().thenApply(handle -> CompatibilityUtil.convertContexts(handle.getActiveContextSet())).join();
|
||||
}
|
||||
}
|
@ -1,60 +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.references;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@ToString(of = "collection")
|
||||
@EqualsAndHashCode(of = "collection")
|
||||
@RequiredArgsConstructor(staticName = "of")
|
||||
public final class SubjectCollectionReference {
|
||||
|
||||
@Getter
|
||||
private final String collection;
|
||||
|
||||
private WeakReference<LPSubjectCollection> ref = null;
|
||||
|
||||
public synchronized LPSubjectCollection resolve(LuckPermsService service) {
|
||||
if (ref != null) {
|
||||
LPSubjectCollection sc = ref.get();
|
||||
if (sc != null) {
|
||||
return sc;
|
||||
}
|
||||
}
|
||||
|
||||
LPSubjectCollection sc = service.getSubjects(collection);
|
||||
ref = new WeakReference<>(sc);
|
||||
return sc;
|
||||
}
|
||||
}
|
@ -32,46 +32,75 @@ import lombok.ToString;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
|
||||
import me.lucko.luckperms.sponge.service.LuckPermsService;
|
||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.model.LPSubject;
|
||||
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ToString(of = {"collection", "identifier"})
|
||||
@EqualsAndHashCode(of = {"collection", "identifier"})
|
||||
@RequiredArgsConstructor(staticName = "of")
|
||||
public final class SubjectReference {
|
||||
public static SubjectReference deserialize(String s) {
|
||||
|
||||
@Deprecated
|
||||
public static SubjectReference deserialize(LPPermissionService service, String s) {
|
||||
List<String> parts = Splitter.on('/').limit(2).splitToList(s);
|
||||
return of(parts.get(0), parts.get(1));
|
||||
return of(service, parts.get(0), parts.get(1));
|
||||
}
|
||||
|
||||
public static SubjectReference of(Subject subject) {
|
||||
return of(subject.getContainingCollection().getIdentifier(), subject.getIdentifier());
|
||||
public static SubjectReference of(LPPermissionService service, Subject subject) {
|
||||
return of(service, subject.getContainingCollection().getIdentifier(), subject.getIdentifier());
|
||||
}
|
||||
|
||||
private final LPPermissionService service;
|
||||
|
||||
@Getter
|
||||
private final String collection;
|
||||
|
||||
@Getter
|
||||
private final String identifier;
|
||||
|
||||
private WeakReference<LPSubject> ref = null;
|
||||
private long lastLookup = 0L;
|
||||
private WeakReference<LPSubject> cache = null;
|
||||
|
||||
public synchronized LPSubject resolve(LuckPermsService service) {
|
||||
if (ref != null) {
|
||||
LPSubject s = ref.get();
|
||||
if (s != null) {
|
||||
return s;
|
||||
private synchronized LPSubject resolveDirectly() {
|
||||
long sinceLast = System.currentTimeMillis() - lastLookup;
|
||||
|
||||
// try the cache
|
||||
if (sinceLast < TimeUnit.SECONDS.toMillis(10)) {
|
||||
if (cache != null) {
|
||||
LPSubject s = cache.get();
|
||||
if (s != null) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LPSubject s = service.getSubjects(collection).get(identifier);
|
||||
ref = new WeakReference<>(s);
|
||||
LPSubject s = service.getCollection(collection).loadSubject(identifier).join();
|
||||
lastLookup = System.currentTimeMillis();
|
||||
cache = new WeakReference<>(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
public CompletableFuture<LPSubject> resolve() {
|
||||
long sinceLast = System.currentTimeMillis() - lastLookup;
|
||||
|
||||
// try the cache
|
||||
if (sinceLast < TimeUnit.SECONDS.toMillis(10)) {
|
||||
if (cache != null) {
|
||||
LPSubject s = cache.get();
|
||||
if (s != null) {
|
||||
return CompletableFuture.completedFuture(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CompletableFuture.supplyAsync(this::resolveDirectly);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.persisted.PersistedSubject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@ -52,12 +53,15 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class SubjectStorage {
|
||||
|
||||
private final LPPermissionService service;
|
||||
|
||||
@Getter
|
||||
private final Gson gson;
|
||||
|
||||
private final File container;
|
||||
|
||||
public SubjectStorage(File container) {
|
||||
public SubjectStorage(LPPermissionService service, File container) {
|
||||
this.service = service;
|
||||
this.gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
this.container = container;
|
||||
checkContainer();
|
||||
@ -89,7 +93,7 @@ public class SubjectStorage {
|
||||
}
|
||||
|
||||
public void saveToFile(PersistedSubject subject) throws IOException {
|
||||
File subjectFile = resolveFile(subject.getContainingCollection().getIdentifier(), subject.getIdentifier());
|
||||
File subjectFile = resolveFile(subject.getParentCollection().getIdentifier(), subject.getIdentifier());
|
||||
saveToFile(new SubjectStorageModel(subject.getSubjectData()), subjectFile);
|
||||
}
|
||||
|
||||
@ -153,7 +157,7 @@ public class SubjectStorage {
|
||||
|
||||
try (BufferedReader reader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
|
||||
JsonObject data = gson.fromJson(reader, JsonObject.class);
|
||||
SubjectStorageModel model = new SubjectStorageModel(data);
|
||||
SubjectStorageModel model = new SubjectStorageModel(service, data);
|
||||
return Maps.immutableEntry(subjectName, model);
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ import me.lucko.luckperms.common.core.ContextSetComparator;
|
||||
import me.lucko.luckperms.common.core.NodeModel;
|
||||
import me.lucko.luckperms.common.core.PriorityComparator;
|
||||
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
||||
import me.lucko.luckperms.sponge.service.model.LPPermissionService;
|
||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -50,35 +51,40 @@ import java.util.Map;
|
||||
*/
|
||||
@Getter
|
||||
public class SubjectStorageModel {
|
||||
private final LPPermissionService service;
|
||||
private final Map<ImmutableContextSet, Map<String, Boolean>> permissions;
|
||||
private final Map<ImmutableContextSet, Map<String, String>> options;
|
||||
private final Map<ImmutableContextSet, List<SubjectReference>> parents;
|
||||
|
||||
public SubjectStorageModel(Map<ImmutableContextSet, Map<String, Boolean>> permissions, Map<ImmutableContextSet, Map<String, String>> options, Map<ImmutableContextSet, List<SubjectReference>> parents) {
|
||||
public SubjectStorageModel(LPPermissionService service, Map<ImmutableContextSet, ? extends Map<String, Boolean>> permissions, Map<ImmutableContextSet, ? extends Map<String, String>> options, Map<ImmutableContextSet, ? extends List<SubjectReference>> parents) {
|
||||
this.service = service;
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, Map<String, Boolean>> permissionsBuilder = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, 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()));
|
||||
}
|
||||
this.permissions = permissionsBuilder.build();
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, Map<String, String>> optionsBuilder = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, Map<String, String>> e : options.entrySet()) {
|
||||
for (Map.Entry<ImmutableContextSet, ? extends Map<String, String>> e : options.entrySet()) {
|
||||
optionsBuilder.put(e.getKey(), ImmutableMap.copyOf(e.getValue()));
|
||||
}
|
||||
this.options = optionsBuilder.build();
|
||||
|
||||
ImmutableMap.Builder<ImmutableContextSet, List<SubjectReference>> parentsBuilder = ImmutableMap.builder();
|
||||
for (Map.Entry<ImmutableContextSet, List<SubjectReference>> e : parents.entrySet()) {
|
||||
for (Map.Entry<ImmutableContextSet, ? extends List<SubjectReference>> e : parents.entrySet()) {
|
||||
parentsBuilder.put(e.getKey(), ImmutableList.copyOf(e.getValue()));
|
||||
}
|
||||
this.parents = parentsBuilder.build();
|
||||
}
|
||||
|
||||
public SubjectStorageModel(CalculatedSubjectData data) {
|
||||
this(data.getPermissions(), data.getOptions(), data.getParentsAsList());
|
||||
this(data.getParentSubject().getService(), data.getAllPermissions(), data.getAllOptions(), data.getAllParents());
|
||||
}
|
||||
|
||||
public SubjectStorageModel(JsonObject root) {
|
||||
public SubjectStorageModel(LPPermissionService service, JsonObject root) {
|
||||
this.service = service;
|
||||
|
||||
Preconditions.checkArgument(root.get("permissions").isJsonArray());
|
||||
Preconditions.checkArgument(root.get("options").isJsonArray());
|
||||
Preconditions.checkArgument(root.get("parents").isJsonArray());
|
||||
@ -158,7 +164,7 @@ public class SubjectStorageModel {
|
||||
String collection = parent.get("collection").getAsString();
|
||||
String subject = parent.get("subject").getAsString();
|
||||
|
||||
pars.add(SubjectReference.of(collection, subject));
|
||||
pars.add(SubjectReference.of(service, collection, subject));
|
||||
}
|
||||
|
||||
parentsBuilder.put(contextSet, pars.build());
|
||||
|
Loading…
Reference in New Issue
Block a user