diff --git a/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java b/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java index c450914ed..bf7e4d904 100644 --- a/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java +++ b/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java @@ -100,7 +100,7 @@ public class LPSpongePlugin implements LuckPermsPlugin { private ConsecutiveExecutor consecutiveExecutor; private LuckPermsService service; private LocaleManager localeManager; - private ContextManager contextManager; + private ContextManager contextManager; // TODO convert this to use Subject instead of Player @Listener public void onEnable(GamePreInitializationEvent event) { diff --git a/sponge/src/main/java/me/lucko/luckperms/SpongeListener.java b/sponge/src/main/java/me/lucko/luckperms/SpongeListener.java index 7d5043da2..ca36dd8b7 100644 --- a/sponge/src/main/java/me/lucko/luckperms/SpongeListener.java +++ b/sponge/src/main/java/me/lucko/luckperms/SpongeListener.java @@ -48,7 +48,8 @@ public class SpongeListener extends AbstractListener { } final GameProfile p = e.getProfile(); - onAsyncLogin(p.getUniqueId(), p.getName().get()); + onAsyncLogin(p.getUniqueId(), p.getName().get()); // Load the user into LuckPerms + plugin.getService().getUserSubjects().load(p.getUniqueId()); // Load the user into the PermissionService } @SuppressWarnings("deprecation") @@ -57,12 +58,14 @@ public class SpongeListener extends AbstractListener { final GameProfile player = e.getProfile(); final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId())); + // Check if the user was loaded successfully. if (user == null) { e.setCancelled(true); e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(Message.LOADING_ERROR.toString())); return; } + // Refresh permissions again user.refreshPermissions(); } diff --git a/sponge/src/main/java/me/lucko/luckperms/api/sponge/collections/UserCollection.java b/sponge/src/main/java/me/lucko/luckperms/api/sponge/collections/UserCollection.java index 8fa442487..7a14f3563 100644 --- a/sponge/src/main/java/me/lucko/luckperms/api/sponge/collections/UserCollection.java +++ b/sponge/src/main/java/me/lucko/luckperms/api/sponge/collections/UserCollection.java @@ -27,6 +27,7 @@ import lombok.NonNull; import me.lucko.luckperms.api.sponge.LuckPermsService; import me.lucko.luckperms.api.sponge.LuckPermsUserSubject; import me.lucko.luckperms.api.sponge.simple.SimpleCollection; +import me.lucko.luckperms.commands.Util; import me.lucko.luckperms.users.User; import me.lucko.luckperms.users.UserIdentifier; import me.lucko.luckperms.users.UserManager; @@ -42,6 +43,10 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +/** + * Manages low level Subject instances for the PermissionService. + * Most calls are cached. + */ public class UserCollection implements SubjectCollection { private final LuckPermsService service; private final UserManager manager; @@ -61,34 +66,45 @@ public class UserCollection implements SubjectCollection { return PermissionService.SUBJECTS_USER; } - private void load(UUID uuid) { + /** + * Load a user into this manager + * @param uuid the external uuid of the user + */ + public synchronized void load(UUID uuid) { UUID internal = service.getPlugin().getUuidCache().getUUID(uuid); - if (!manager.isLoaded(UserIdentifier.of(uuid, null))) { - return; + if (!manager.isLoaded(UserIdentifier.of(internal, null))) { + return; // Not loaded at a higher level + } + + if (users.containsKey(internal)) { + return; // Already loaded } User user = manager.get(internal); - users.put(internal, LuckPermsUserSubject.wrapUser(user, service)); + LuckPermsUserSubject subject = LuckPermsUserSubject.wrapUser(user, service); + subject.calculateActivePermissions(true); // Pre-process some of their permissions + + users.put(internal, subject); } + /** + * Unload a user from this manager + * @param uuid the internal uuid of the user + */ public void unload(UUID uuid) { - users.remove(service.getPlugin().getUuidCache().getUUID(uuid)); + users.remove(uuid); } @Override - public synchronized Subject get(@NonNull String id) { - try { - UUID u = service.getPlugin().getUuidCache().getUUID(UUID.fromString(id)); - if (users.containsKey(u)) { - return users.get(u); + public Subject get(@NonNull String id) { + final UUID uuid = Util.parseUuid(id); + if (uuid != null) { + UUID internal = service.getPlugin().getUuidCache().getUUID(uuid); + if (users.containsKey(internal)) { + return users.get(internal); } - if (manager.isLoaded(UserIdentifier.of(u, null))) { - load(u); - return users.get(u); - } - - } catch (IllegalArgumentException e) { + } else { for (LuckPermsUserSubject subject : users.values()) { if (subject.getUser().getName().equals(id)) { return subject; @@ -100,20 +116,28 @@ public class UserCollection implements SubjectCollection { service.getPlugin().getLog().warn("Couldn't get user subject for: " + id); } - // What am I meant to do here? What if no user is loaded? Load it? Create it? - // If I do load/create it, this method should always be called async??.... errr. + // Fallback to the other collection. This Subject instance will never be persisted. return fallback.get(id); } @Override public boolean hasRegistered(@NonNull String id) { - try { - UUID u = UUID.fromString(id); - return manager.isLoaded(UserIdentifier.of(service.getPlugin().getUuidCache().getUUID(u), null)); - } catch (IllegalArgumentException e) { - User user = manager.get(id); - return user != null; + final UUID uuid = Util.parseUuid(id); + if (uuid != null) { + UUID internal = service.getPlugin().getUuidCache().getUUID(uuid); + if (users.containsKey(internal)) { + return true; + } + + } else { + for (LuckPermsUserSubject subject : users.values()) { + if (subject.getUser().getName().equals(id)) { + return true; + } + } } + + return false; } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/users/SpongeUserManager.java b/sponge/src/main/java/me/lucko/luckperms/users/SpongeUserManager.java index 8b425e748..524dcd4a7 100644 --- a/sponge/src/main/java/me/lucko/luckperms/users/SpongeUserManager.java +++ b/sponge/src/main/java/me/lucko/luckperms/users/SpongeUserManager.java @@ -27,7 +27,6 @@ import me.lucko.luckperms.api.context.ContextListener; import org.spongepowered.api.entity.living.player.Player; import java.util.Map; -import java.util.UUID; public class SpongeUserManager extends UserManager implements ContextListener { private final LPSpongePlugin plugin; @@ -67,11 +66,6 @@ public class SpongeUserManager extends UserManager implements ContextListener before, Map.Entry current) throws Exception { - UUID internal = plugin.getUuidCache().getUUID(subject.getUniqueId()); - - User user = get(internal); - if (user != null) { - plugin.doAsync(user::refreshPermissions); - } + // Not needed on Sponge. The context is accumulated on each permission check. } }