From 9c505e440274582b77a541348d74c28fd50fe7c6 Mon Sep 17 00:00:00 2001 From: Luck Date: Thu, 12 Oct 2017 19:43:42 +0100 Subject: [PATCH] Move Track methods away from checked exceptions, refactor ContextManager & primary group holders --- .../bukkit/contexts/BukkitContextManager.java | 7 +- .../bungee/contexts/BungeeContextManager.java | 7 +- .../common/api/delegates/GroupDelegate.java | 4 +- .../delegates/PermissionHolderDelegate.java | 4 +- .../common/api/delegates/TrackDelegate.java | 24 ++++-- .../common/api/delegates/UserDelegate.java | 4 +- .../caching/handlers/StateListener.java | 37 +++++++++ .../commands/impl/track/TrackAppend.java | 9 +- .../commands/impl/track/TrackInsert.java | 30 ++++--- .../commands/impl/track/TrackRemove.java | 9 +- .../common/commands/impl/user/UserDemote.java | 7 +- .../commands/impl/user/UserPromote.java | 4 +- .../contexts/AbstractContextManager.java | 43 +++++++--- .../common/contexts/ContextManager.java | 33 ++++++-- .../common/model/PermissionHolder.java | 7 +- .../lucko/luckperms/common/model/Track.java | 83 ++++++++++--------- .../AllParentsByWeightHolder.java | 36 ++------ .../CachedPrimaryGroupHolder.java | 63 ++++++++++++++ .../primarygroup/ParentsByWeightHolder.java | 34 +++----- .../common/primarygroup/StoredHolder.java | 10 ++- .../luckperms/common/utils/UuidCache.java | 14 ++-- .../sponge/contexts/SpongeContextManager.java | 7 +- .../migration/MigrationPermissionsEx.java | 5 +- 23 files changed, 301 insertions(+), 180 deletions(-) create mode 100644 common/src/main/java/me/lucko/luckperms/common/caching/handlers/StateListener.java create mode 100644 common/src/main/java/me/lucko/luckperms/common/primarygroup/CachedPrimaryGroupHolder.java diff --git a/bukkit/src/main/java/me/lucko/luckperms/bukkit/contexts/BukkitContextManager.java b/bukkit/src/main/java/me/lucko/luckperms/bukkit/contexts/BukkitContextManager.java index f620c3dba..55643a6b3 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/bukkit/contexts/BukkitContextManager.java +++ b/bukkit/src/main/java/me/lucko/luckperms/bukkit/contexts/BukkitContextManager.java @@ -25,8 +25,6 @@ package me.lucko.luckperms.bukkit.contexts; -import lombok.RequiredArgsConstructor; - import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.bukkit.LPBukkitPlugin; @@ -35,9 +33,10 @@ import me.lucko.luckperms.common.contexts.AbstractContextManager; import org.bukkit.entity.Player; -@RequiredArgsConstructor public class BukkitContextManager extends AbstractContextManager { - private final LPBukkitPlugin plugin; + public BukkitContextManager(LPBukkitPlugin plugin) { + super(plugin); + } @Override public Contexts formContexts(Player subject, ImmutableContextSet contextSet) { diff --git a/bungee/src/main/java/me/lucko/luckperms/bungee/contexts/BungeeContextManager.java b/bungee/src/main/java/me/lucko/luckperms/bungee/contexts/BungeeContextManager.java index 784a5bbdf..ddae1afdc 100644 --- a/bungee/src/main/java/me/lucko/luckperms/bungee/contexts/BungeeContextManager.java +++ b/bungee/src/main/java/me/lucko/luckperms/bungee/contexts/BungeeContextManager.java @@ -25,8 +25,6 @@ package me.lucko.luckperms.bungee.contexts; -import lombok.RequiredArgsConstructor; - import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.bungee.LPBungeePlugin; @@ -35,9 +33,10 @@ import me.lucko.luckperms.common.contexts.AbstractContextManager; import net.md_5.bungee.api.connection.ProxiedPlayer; -@RequiredArgsConstructor public class BungeeContextManager extends AbstractContextManager { - private final LPBungeePlugin plugin; + public BungeeContextManager(LPBungeePlugin plugin) { + super(plugin); + } @Override public Contexts formContexts(ProxiedPlayer subject, ImmutableContextSet contextSet) { diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/GroupDelegate.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/GroupDelegate.java index d342d3b8c..fec94069b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/GroupDelegate.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/GroupDelegate.java @@ -188,10 +188,10 @@ public final class GroupDelegate extends PermissionHolderDelegate implements Gro if (!(o instanceof GroupDelegate)) return false; GroupDelegate other = (GroupDelegate) o; - return this.getName().equals(other.getName()); + return handle.equals(other.handle); } public int hashCode() { - return this.getName().hashCode(); + return handle.hashCode(); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/PermissionHolderDelegate.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/PermissionHolderDelegate.java index 9c0a159ef..fa3abc03b 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/PermissionHolderDelegate.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/PermissionHolderDelegate.java @@ -438,12 +438,12 @@ public class PermissionHolderDelegate implements PermissionHolder { @Override public List resolveInheritances(Contexts contexts) { - return null; + return handle.resolveInheritances(ExtractedContexts.generate(contexts)); } @Override public List resolveInheritances() { - return null; + return handle.resolveInheritances(); } @Override diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/TrackDelegate.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/TrackDelegate.java index 7c3b52fcf..bc9ced92c 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/TrackDelegate.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/TrackDelegate.java @@ -69,32 +69,40 @@ public final class TrackDelegate implements Track { @Override public String getNext(@NonNull Group current) throws ObjectLacksException { - return handle.getNext(GroupDelegate.cast(current)); + try { + return handle.getNext(GroupDelegate.cast(current)); + } catch (IllegalArgumentException e) { + throw new ObjectLacksException(); + } } @Override public String getPrevious(@NonNull Group current) throws ObjectLacksException { - return handle.getPrevious(GroupDelegate.cast(current)); + try { + return handle.getPrevious(GroupDelegate.cast(current)); + } catch (IllegalArgumentException e) { + throw new ObjectLacksException(); + } } @Override public void appendGroup(@NonNull Group group) throws ObjectAlreadyHasException { - handle.appendGroup(GroupDelegate.cast(group)); + handle.appendGroup(GroupDelegate.cast(group)).throwException(); } @Override public void insertGroup(@NonNull Group group, @NonNull int position) throws ObjectAlreadyHasException, IndexOutOfBoundsException { - handle.insertGroup(GroupDelegate.cast(group), position); + handle.insertGroup(GroupDelegate.cast(group), position).throwException(); } @Override public void removeGroup(@NonNull Group group) throws ObjectLacksException { - handle.removeGroup(GroupDelegate.cast(group)); + handle.removeGroup(GroupDelegate.cast(group)).throwException(); } @Override public void removeGroup(@NonNull String group) throws ObjectLacksException { - handle.removeGroup(group); + handle.removeGroup(group).throwException(); } @Override @@ -117,10 +125,10 @@ public final class TrackDelegate implements Track { if (!(o instanceof TrackDelegate)) return false; TrackDelegate other = (TrackDelegate) o; - return this.getName().equals(other.getName()); + return handle.equals(other.handle); } public int hashCode() { - return this.getName().hashCode(); + return handle.hashCode(); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/api/delegates/UserDelegate.java b/common/src/main/java/me/lucko/luckperms/common/api/delegates/UserDelegate.java index a0450b74b..d7c4884db 100644 --- a/common/src/main/java/me/lucko/luckperms/common/api/delegates/UserDelegate.java +++ b/common/src/main/java/me/lucko/luckperms/common/api/delegates/UserDelegate.java @@ -228,10 +228,10 @@ public final class UserDelegate extends PermissionHolderDelegate implements User if (!(o instanceof UserDelegate)) return false; UserDelegate other = (UserDelegate) o; - return this.getUuid().equals(other.getUuid()); + return handle.equals(other.handle); } public int hashCode() { - return this.getUuid().hashCode(); + return handle.hashCode(); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/caching/handlers/StateListener.java b/common/src/main/java/me/lucko/luckperms/common/caching/handlers/StateListener.java new file mode 100644 index 000000000..bf233dc4f --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/caching/handlers/StateListener.java @@ -0,0 +1,37 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.common.caching.handlers; + +import me.lucko.luckperms.common.model.PermissionHolder; + +/** + * Represents an object which is notified when the state of a {@link PermissionHolder} changes. + */ +public interface StateListener { + + void onStateChange(); + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackAppend.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackAppend.java index e41efe067..f52e9b32d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackAppend.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackAppend.java @@ -25,6 +25,7 @@ package me.lucko.luckperms.common.commands.impl.track; +import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.commands.CommandException; import me.lucko.luckperms.common.commands.CommandResult; @@ -40,7 +41,6 @@ import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.utils.Predicates; -import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import java.util.List; @@ -68,8 +68,9 @@ public class TrackAppend extends SubCommand { return CommandResult.LOADING_ERROR; } - try { - track.appendGroup(group); + DataMutateResult result = track.appendGroup(group); + + if (result.asBoolean()) { Message.TRACK_APPEND_SUCCESS.send(sender, group.getName(), track.getName()); if (track.getGroups().size() > 1) { Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), group.getName())); @@ -79,7 +80,7 @@ public class TrackAppend extends SubCommand { .build().submit(plugin, sender); save(track, sender, plugin); return CommandResult.SUCCESS; - } catch (ObjectAlreadyHasException e) { + } else { Message.TRACK_ALREADY_CONTAINS.send(sender, track.getName(), group.getName()); return CommandResult.STATE_ERROR; } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackInsert.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackInsert.java index da1b449ed..941714d26 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackInsert.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackInsert.java @@ -25,6 +25,7 @@ package me.lucko.luckperms.common.commands.impl.track; +import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.commands.CommandException; import me.lucko.luckperms.common.commands.CommandResult; @@ -40,7 +41,6 @@ import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.utils.Predicates; -import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import java.util.List; @@ -77,19 +77,23 @@ public class TrackInsert extends SubCommand { } try { - track.insertGroup(group, pos - 1); - Message.TRACK_INSERT_SUCCESS.send(sender, group.getName(), track.getName(), pos); - if (track.getGroups().size() > 1) { - Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), group.getName())); + DataMutateResult result = track.insertGroup(group, pos - 1); + + if (result.asBoolean()) { + Message.TRACK_INSERT_SUCCESS.send(sender, group.getName(), track.getName(), pos); + if (track.getGroups().size() > 1) { + Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), group.getName())); + } + ExtendedLogEntry.build().actor(sender).acted(track) + .action("insert " + group.getName() + " " + pos) + .build().submit(plugin, sender); + save(track, sender, plugin); + return CommandResult.SUCCESS; + } else { + Message.TRACK_ALREADY_CONTAINS.send(sender, track.getName(), group.getName()); + return CommandResult.STATE_ERROR; } - ExtendedLogEntry.build().actor(sender).acted(track) - .action("insert " + group.getName() + " " + pos) - .build().submit(plugin, sender); - save(track, sender, plugin); - return CommandResult.SUCCESS; - } catch (ObjectAlreadyHasException e) { - Message.TRACK_ALREADY_CONTAINS.send(sender, track.getName(), group.getName()); - return CommandResult.STATE_ERROR; + } catch (IndexOutOfBoundsException e) { Message.TRACK_INSERT_ERROR_INVALID_POS.send(sender, pos); return CommandResult.INVALID_ARGS; diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackRemove.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackRemove.java index 86a7be849..c131512d8 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackRemove.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/track/TrackRemove.java @@ -25,6 +25,7 @@ package me.lucko.luckperms.common.commands.impl.track; +import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.common.actionlog.ExtendedLogEntry; import me.lucko.luckperms.common.commands.CommandException; import me.lucko.luckperms.common.commands.CommandResult; @@ -39,7 +40,6 @@ import me.lucko.luckperms.common.locale.Message; import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.utils.Predicates; -import me.lucko.luckperms.exceptions.ObjectLacksException; import java.util.List; @@ -56,8 +56,9 @@ public class TrackRemove extends SubCommand { return CommandResult.INVALID_ARGS; } - try { - track.removeGroup(groupName); + DataMutateResult result = track.removeGroup(groupName); + + if (result.asBoolean()) { Message.TRACK_REMOVE_SUCCESS.send(sender, groupName, track.getName()); if (track.getGroups().size() > 1) { Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups())); @@ -67,7 +68,7 @@ public class TrackRemove extends SubCommand { .build().submit(plugin, sender); save(track, sender, plugin); return CommandResult.SUCCESS; - } catch (ObjectLacksException e) { + } else { Message.TRACK_DOES_NOT_CONTAIN.send(sender, track.getName(), groupName); return CommandResult.STATE_ERROR; } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/user/UserDemote.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/user/UserDemote.java index fd9d504e5..11c1a4d22 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/user/UserDemote.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/user/UserDemote.java @@ -48,7 +48,6 @@ import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.NodeFactory; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.utils.Predicates; -import me.lucko.luckperms.exceptions.ObjectLacksException; import java.util.List; import java.util.Set; @@ -120,7 +119,7 @@ public class UserDemote extends SubCommand { final String previous; try { previous = track.getPrevious(old); - } catch (ObjectLacksException e) { + } catch (IllegalArgumentException e) { Message.TRACK_DOES_NOT_CONTAIN.send(sender, track.getName(), old); return CommandResult.STATE_ERROR; } @@ -131,17 +130,15 @@ public class UserDemote extends SubCommand { } if (previous == null) { - user.unsetPermission(oldNode); - Message.USER_DEMOTE_ENDOFTRACK.send(sender, track.getName(), user.getFriendlyName(), old); ExtendedLogEntry.build().actor(sender).acted(user) .action("demote " + args.stream().collect(Collectors.joining(" "))) .build().submit(plugin, sender); + save(user, sender, plugin); plugin.getApiProvider().getEventFactory().handleUserDemote(user, track, old, null); - return CommandResult.SUCCESS; } diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/user/UserPromote.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/user/UserPromote.java index 2df40a9f3..6a89e8023 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/user/UserPromote.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/user/UserPromote.java @@ -46,7 +46,6 @@ import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.node.NodeFactory; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.utils.Predicates; -import me.lucko.luckperms.exceptions.ObjectLacksException; import java.util.List; import java.util.Set; @@ -123,6 +122,7 @@ public class UserPromote extends SubCommand { ExtendedLogEntry.build().actor(sender).acted(user) .action("promote " + args.stream().collect(Collectors.joining(" "))) .build().submit(plugin, sender); + save(user, sender, plugin); plugin.getApiProvider().getEventFactory().handleUserPromote(user, track, null, first); return CommandResult.SUCCESS; @@ -138,7 +138,7 @@ public class UserPromote extends SubCommand { final String next; try { next = track.getNext(old); - } catch (ObjectLacksException e) { + } catch (IllegalArgumentException e) { Message.TRACK_DOES_NOT_CONTAIN.send(sender, track.getName(), old); return CommandResult.STATE_ERROR; } diff --git a/common/src/main/java/me/lucko/luckperms/common/contexts/AbstractContextManager.java b/common/src/main/java/me/lucko/luckperms/common/contexts/AbstractContextManager.java index 22809a2ca..bcfe2f1b0 100644 --- a/common/src/main/java/me/lucko/luckperms/common/contexts/AbstractContextManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/contexts/AbstractContextManager.java @@ -35,6 +35,8 @@ import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ContextCalculator; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet; +import me.lucko.luckperms.common.config.ConfigKeys; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -47,6 +49,7 @@ import java.util.concurrent.TimeUnit; */ public abstract class AbstractContextManager implements ContextManager { + protected final LuckPermsPlugin plugin; private final List> calculators = new CopyOnWriteArrayList<>(); private final List> staticCalculators = new CopyOnWriteArrayList<>(); @@ -56,9 +59,14 @@ public abstract class AbstractContextManager implements ContextManager { .expireAfterWrite(50L, TimeUnit.MILLISECONDS) // expire roughly every tick .build(new Loader()); + protected AbstractContextManager(LuckPermsPlugin plugin) { + this.plugin = plugin; + } + @Override public ImmutableContextSet getApplicableContext(@NonNull T subject) { // this is actually already immutable, but the Contexts method signature returns the interface. + // using the makeImmutable method is faster than casting return getApplicableContexts(subject).getContexts().makeImmutable(); } @@ -68,8 +76,30 @@ public abstract class AbstractContextManager implements ContextManager { } @Override - public void registerCalculator(ContextCalculator calculator) { - registerCalculator(calculator, false); + public ImmutableContextSet getStaticContext() { + MutableContextSet accumulator = MutableContextSet.create(); + for (ContextCalculator calculator : staticCalculators) { + calculator.giveApplicableContext(null, accumulator); + } + return accumulator.makeImmutable(); + } + + @Override + public Contexts getStaticContexts() { + return formContexts(getStaticContext()); + } + + @Override + public Contexts formContexts(ImmutableContextSet contextSet) { + return new Contexts( + contextSet, + plugin.getConfiguration().get(ConfigKeys.INCLUDING_GLOBAL_PERMS), + plugin.getConfiguration().get(ConfigKeys.INCLUDING_GLOBAL_WORLD_PERMS), + true, + plugin.getConfiguration().get(ConfigKeys.APPLYING_GLOBAL_GROUPS), + plugin.getConfiguration().get(ConfigKeys.APPLYING_GLOBAL_WORLD_GROUPS), + false + ); } @Override @@ -82,15 +112,6 @@ public abstract class AbstractContextManager implements ContextManager { } } - @Override - public ImmutableContextSet getStaticContexts() { - MutableContextSet accumulator = MutableContextSet.create(); - for (ContextCalculator calculator : staticCalculators) { - calculator.giveApplicableContext(null, accumulator); - } - return accumulator.makeImmutable(); - } - @Override public void invalidateCache(@NonNull T subject){ lookupCache.invalidate(subject); diff --git a/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java b/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java index 985beed22..8716a4b3d 100644 --- a/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java +++ b/common/src/main/java/me/lucko/luckperms/common/contexts/ContextManager.java @@ -55,6 +55,20 @@ public interface ContextManager { */ Contexts getApplicableContexts(@NonNull T subject); + /** + * Gets the contexts from the static calculators in this manager. + * + * @return the current active static contexts + */ + ImmutableContextSet getStaticContext(); + + /** + * Gets the contexts from the static calculators in this manager. + * + * @return the current active static contexts + */ + Contexts getStaticContexts(); + /** * Forms a {@link Contexts} instance from an {@link ImmutableContextSet}. * @@ -64,12 +78,22 @@ public interface ContextManager { */ Contexts formContexts(T subject, ImmutableContextSet contextSet); + /** + * Forms a {@link Contexts} instance from an {@link ImmutableContextSet}. + * + * @param contextSet the context set + * @return a contexts instance + */ + Contexts formContexts(ImmutableContextSet contextSet); + /** * Registers a context calculator with the manager. * * @param calculator the calculator */ - void registerCalculator(ContextCalculator calculator); + default void registerCalculator(ContextCalculator calculator) { + registerCalculator(calculator, false); + } /** * Registers a context calculator with the manager. @@ -79,13 +103,6 @@ public interface ContextManager { */ void registerCalculator(ContextCalculator calculator, boolean isStatic); - /** - * Gets the contexts from the static calculators in this manager. - * - * @return the current active static contexts - */ - ImmutableContextSet getStaticContexts(); - /** * Invalidates the lookup cache for a given subject * diff --git a/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java b/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java index a53340726..10c401468 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/PermissionHolder.java @@ -48,6 +48,7 @@ import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.common.api.delegates.PermissionHolderDelegate; import me.lucko.luckperms.common.buffers.Cache; import me.lucko.luckperms.common.caching.MetaAccumulator; +import me.lucko.luckperms.common.caching.handlers.StateListener; import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.contexts.ContextSetComparator; import me.lucko.luckperms.common.contexts.ExtractedContexts; @@ -208,7 +209,7 @@ public abstract class PermissionHolder { * A set of runnables which are called when this objects state changes. */ @Getter - private final Set stateListeners = ConcurrentHashMap.newKeySet(); + private final Set stateListeners = ConcurrentHashMap.newKeySet(); private void invalidateCache() { nodesCopy.invalidate(); @@ -216,9 +217,9 @@ public abstract class PermissionHolder { weightCache.invalidate(); // Invalidate listeners - for (Runnable r : stateListeners) { + for (StateListener listener : stateListeners) { try { - r.run(); + listener.onStateChange(); } catch (Exception e) { e.printStackTrace(); } diff --git a/common/src/main/java/me/lucko/luckperms/common/model/Track.java b/common/src/main/java/me/lucko/luckperms/common/model/Track.java index fa65a624f..016f70dc7 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/Track.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/Track.java @@ -32,11 +32,10 @@ import lombok.ToString; import com.google.common.collect.ImmutableList; +import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.common.api.delegates.TrackDelegate; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.references.Identifiable; -import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; -import me.lucko.luckperms.exceptions.ObjectLacksException; import java.util.ArrayList; import java.util.Collections; @@ -101,9 +100,9 @@ public class Track implements Identifiable { * * @param current the group before the group being requested * @return the group name, or null if the end of the track has been reached - * @throws ObjectLacksException if the track does not contain the group given + * @throws IllegalArgumentException if the track does not contain the group given */ - public String getNext(Group current) throws ObjectLacksException { + public String getNext(Group current) throws IllegalArgumentException { return getNext(current.getName()); } @@ -112,9 +111,9 @@ public class Track implements Identifiable { * * @param current the group after the group being requested * @return the group name, or null if the start of the track has been reached - * @throws ObjectLacksException if the track does not contain the group given + * @throws IllegalArgumentException if the track does not contain the group given */ - public String getPrevious(Group current) throws ObjectLacksException { + public String getPrevious(Group current) throws IllegalArgumentException { return getPrevious(current.getName()); } @@ -123,10 +122,12 @@ public class Track implements Identifiable { * * @param current the group before the group being requested * @return the group name, or null if the end of the track has been reached - * @throws ObjectLacksException if the track does not contain the group given + * @throws IllegalArgumentException if the track does not contain the group given */ - public String getNext(String current) throws ObjectLacksException { - assertContains(current); + public String getNext(String current) throws IllegalArgumentException { + if (!containsGroup(current)) { + throw new IllegalArgumentException(); + } if (groups.indexOf(current) == groups.size() - 1) { return null; @@ -140,10 +141,12 @@ public class Track implements Identifiable { * * @param current the group after the group being requested * @return the group name, or null if the start of the track has been reached - * @throws ObjectLacksException if the track does not contain the group given + * @throws IllegalArgumentException if the track does not contain the group given */ - public String getPrevious(String current) throws ObjectLacksException { - assertContains(current); + public String getPrevious(String current) throws IllegalArgumentException { + if (!containsGroup(current)) { + throw new IllegalArgumentException(); + } if (groups.indexOf(current) == 0) { return null; @@ -156,16 +159,19 @@ public class Track implements Identifiable { * Appends a group to the end of this track * * @param group the group to append - * @throws ObjectAlreadyHasException if the group is already on this track somewhere + * @return the result of the operation */ - public void appendGroup(Group group) throws ObjectAlreadyHasException { + public DataMutateResult appendGroup(Group group) { + if (containsGroup(group)) { + return DataMutateResult.ALREADY_HAS; + } + List before = ImmutableList.copyOf(groups); - - assertNotContains(group); groups.add(group.getName()); - List after = ImmutableList.copyOf(groups); + plugin.getApiProvider().getEventFactory().handleTrackAddGroup(this, group.getName(), before, after); + return DataMutateResult.SUCCESS; } /** @@ -173,42 +179,49 @@ public class Track implements Identifiable { * * @param group the group to be inserted * @param position the index position (a value of 0 inserts at the start) - * @throws ObjectAlreadyHasException if the group is already on this track somewhere * @throws IndexOutOfBoundsException if the position is less than 0 or greater than the size of the track + * @return the result of the operation */ - public void insertGroup(Group group, int position) throws ObjectAlreadyHasException, IndexOutOfBoundsException { - List before = ImmutableList.copyOf(groups); + public DataMutateResult insertGroup(Group group, int position) throws IndexOutOfBoundsException { + if (containsGroup(group)) { + return DataMutateResult.ALREADY_HAS; + } - assertNotContains(group); + List before = ImmutableList.copyOf(groups); groups.add(position, group.getName()); - List after = ImmutableList.copyOf(groups); + plugin.getApiProvider().getEventFactory().handleTrackAddGroup(this, group.getName(), before, after); + return DataMutateResult.SUCCESS; } /** * Removes a group from this track * * @param group the group to remove - * @throws ObjectLacksException if the group is not on this track + * @return the result of the operation */ - public void removeGroup(Group group) throws ObjectLacksException { - removeGroup(group.getName()); + public DataMutateResult removeGroup(Group group) { + return removeGroup(group.getName()); } /** * Removes a group from this track * * @param group the group to remove - * @throws ObjectLacksException if the group is not on this track + * @return the result of the operation */ - public void removeGroup(String group) throws ObjectLacksException { + public DataMutateResult removeGroup(String group) { + if (!containsGroup(group)) { + return DataMutateResult.LACKS; + } + List before = ImmutableList.copyOf(groups); - assertContains(group); groups.remove(group); - List after = ImmutableList.copyOf(groups); + plugin.getApiProvider().getEventFactory().handleTrackRemoveGroup(this, group, before, after); + return DataMutateResult.SUCCESS; } /** @@ -239,16 +252,4 @@ public class Track implements Identifiable { groups.clear(); plugin.getApiProvider().getEventFactory().handleTrackClear(this, before); } - - private void assertNotContains(Group g) throws ObjectAlreadyHasException { - if (containsGroup(g)) { - throw new ObjectAlreadyHasException(); - } - } - - private void assertContains(String g) throws ObjectLacksException { - if (!containsGroup(g)) { - throw new ObjectLacksException(); - } - } } diff --git a/common/src/main/java/me/lucko/luckperms/common/primarygroup/AllParentsByWeightHolder.java b/common/src/main/java/me/lucko/luckperms/common/primarygroup/AllParentsByWeightHolder.java index c5dbc0f19..fa6927c3a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/primarygroup/AllParentsByWeightHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/primarygroup/AllParentsByWeightHolder.java @@ -25,51 +25,31 @@ package me.lucko.luckperms.common.primarygroup; -import lombok.NonNull; - import me.lucko.luckperms.api.Contexts; -import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.contexts.ExtractedContexts; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.User; import java.util.AbstractList; import java.util.ArrayList; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; -public class AllParentsByWeightHolder extends StoredHolder { - - private String cachedValue = null; - private boolean useCached = false; - - public AllParentsByWeightHolder(@NonNull User user) { +public class AllParentsByWeightHolder extends CachedPrimaryGroupHolder { + public AllParentsByWeightHolder(User user) { super(user); - user.getStateListeners().add(() -> useCached = false); } @Override - public String getValue() { - if (useCached) { - return cachedValue; - } - + protected String calculateValue() { Contexts contexts = user.getPlugin().getContextForUser(user); if (contexts == null) { - contexts = new Contexts( - user.getPlugin().getContextManager().getStaticContexts(), - user.getPlugin().getConfiguration().get(ConfigKeys.INCLUDING_GLOBAL_PERMS), - user.getPlugin().getConfiguration().get(ConfigKeys.INCLUDING_GLOBAL_WORLD_PERMS), - true, - user.getPlugin().getConfiguration().get(ConfigKeys.APPLYING_GLOBAL_GROUPS), - user.getPlugin().getConfiguration().get(ConfigKeys.APPLYING_GLOBAL_WORLD_GROUPS), - false - ); + contexts = user.getPlugin().getContextManager().getStaticContexts(); } // hack to get a list of groups the holder is inheriting from - Set groupNames = new HashSet<>(); + Set groupNames = new LinkedHashSet<>(); user.resolveInheritances(new NoopList<>(), groupNames, ExtractedContexts.generate(contexts)); List groups = new ArrayList<>(); @@ -93,9 +73,7 @@ public class AllParentsByWeightHolder extends StoredHolder { } } - cachedValue = bestGroup == null ? null : bestGroup.getName(); - useCached = true; - return cachedValue; + return bestGroup == null ? null : bestGroup.getName(); } private static final class NoopList extends AbstractList implements List { diff --git a/common/src/main/java/me/lucko/luckperms/common/primarygroup/CachedPrimaryGroupHolder.java b/common/src/main/java/me/lucko/luckperms/common/primarygroup/CachedPrimaryGroupHolder.java new file mode 100644 index 000000000..00491b286 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/common/primarygroup/CachedPrimaryGroupHolder.java @@ -0,0 +1,63 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * 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.common.primarygroup; + +import me.lucko.luckperms.common.buffers.Cache; +import me.lucko.luckperms.common.caching.handlers.StateListener; +import me.lucko.luckperms.common.model.User; + +/** + * Abstract implementation of {@link StateListener} which caches all lookups. + */ +public abstract class CachedPrimaryGroupHolder extends StoredHolder implements StateListener { + + // cache lookups + private final Cache cache = new Cache() { + @Override + protected String supply() { + return calculateValue(); + } + }; + + public CachedPrimaryGroupHolder(User user) { + super(user); + user.getStateListeners().add(this); + } + + protected abstract String calculateValue(); + + @Override + public String getValue() { + String s = cache.get(); + return s != null ? s : getStoredValue(); + } + + @Override + public void onStateChange() { + cache.invalidate(); + } + +} diff --git a/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java b/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java index 3e95ee937..c37701369 100644 --- a/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/primarygroup/ParentsByWeightHolder.java @@ -25,38 +25,28 @@ package me.lucko.luckperms.common.primarygroup; -import lombok.NonNull; - import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.Node; -import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.common.model.Group; import me.lucko.luckperms.common.model.User; -import java.util.ArrayList; -import java.util.List; +import java.util.LinkedHashSet; +import java.util.Set; -public class ParentsByWeightHolder extends StoredHolder { - - private String cachedValue = null; - private boolean useCached = false; - - public ParentsByWeightHolder(@NonNull User user) { +public class ParentsByWeightHolder extends CachedPrimaryGroupHolder { + public ParentsByWeightHolder(User user) { super(user); - user.getStateListeners().add(() -> useCached = false); } @Override - public String getValue() { - if (useCached) { - return cachedValue; + protected String calculateValue() { + Contexts contexts = user.getPlugin().getContextForUser(user); + if (contexts == null) { + contexts = user.getPlugin().getContextManager().getStaticContexts(); } - Contexts contexts = user.getPlugin().getContextForUser(user); - ContextSet contextSet = contexts != null ? contexts.getContexts() : user.getPlugin().getContextManager().getStaticContexts(); - - List groups = new ArrayList<>(); - for (Node node : user.filterNodes(contextSet)) { + Set groups = new LinkedHashSet<>(); + for (Node node : user.filterNodes(contexts.getContexts())) { if (!node.getValuePrimitive() || !node.isGroupNode()) { continue; } @@ -80,8 +70,6 @@ public class ParentsByWeightHolder extends StoredHolder { } } - cachedValue = bestGroup == null ? null : bestGroup.getName(); - useCached = true; - return cachedValue; + return bestGroup == null ? null : bestGroup.getName(); } } diff --git a/common/src/main/java/me/lucko/luckperms/common/primarygroup/StoredHolder.java b/common/src/main/java/me/lucko/luckperms/common/primarygroup/StoredHolder.java index 8c75314e6..f6f1d3d28 100644 --- a/common/src/main/java/me/lucko/luckperms/common/primarygroup/StoredHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/primarygroup/StoredHolder.java @@ -26,12 +26,14 @@ package me.lucko.luckperms.common.primarygroup; import lombok.Getter; -import lombok.RequiredArgsConstructor; +import lombok.NonNull; import lombok.Setter; import me.lucko.luckperms.common.model.User; -@RequiredArgsConstructor +/** + * Simple implementation of {@link PrimaryGroupHolder}, which just returns the stored value. + */ public class StoredHolder implements PrimaryGroupHolder { protected final User user; @@ -40,6 +42,10 @@ public class StoredHolder implements PrimaryGroupHolder { @Setter private String storedValue = null; + public StoredHolder(@NonNull User user) { + this.user = user; + } + public String getValue() { return storedValue; } diff --git a/common/src/main/java/me/lucko/luckperms/common/utils/UuidCache.java b/common/src/main/java/me/lucko/luckperms/common/utils/UuidCache.java index 2341f8e5a..82e3aa9ec 100644 --- a/common/src/main/java/me/lucko/luckperms/common/utils/UuidCache.java +++ b/common/src/main/java/me/lucko/luckperms/common/utils/UuidCache.java @@ -52,25 +52,29 @@ public class UuidCache { private final UuidCacheDelegate delegate = new UuidCacheDelegate(this); public UUID getUUID(UUID external) { - return plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUIDS) ? external : cache.getOrDefault(external, external); + return inUse() ? external : cache.getOrDefault(external, external); } public UUID getExternalUUID(UUID internal) { - return plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUIDS) ? internal : cache.inverse().getOrDefault(internal, internal); + return inUse() ? internal : cache.inverse().getOrDefault(internal, internal); } public void addToCache(UUID external, UUID internal) { - if (plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUIDS)) return; + if (inUse()) return; cache.forcePut(external, internal); } public void clearCache(UUID external) { - if (plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUIDS)) return; + if (inUse()) return; cache.remove(external); } public int getSize() { - return plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUIDS) ? 0 : cache.size(); + return inUse() ? 0 : cache.size(); + } + + private boolean inUse() { + return plugin.getConfiguration().get(ConfigKeys.USE_SERVER_UUIDS); } } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeContextManager.java b/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeContextManager.java index d21a9ae5c..fd3500aea 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeContextManager.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/contexts/SpongeContextManager.java @@ -25,8 +25,6 @@ package me.lucko.luckperms.sponge.contexts; -import lombok.RequiredArgsConstructor; - import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.common.config.ConfigKeys; @@ -35,9 +33,10 @@ import me.lucko.luckperms.sponge.LPSpongePlugin; import org.spongepowered.api.service.permission.Subject; -@RequiredArgsConstructor public class SpongeContextManager extends AbstractContextManager { - private final LPSpongePlugin plugin; + public SpongeContextManager(LPSpongePlugin plugin) { + super(plugin); + } @Override public Contexts formContexts(Subject subject, ImmutableContextSet contextSet) { diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java index 708371c34..51307b057 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/migration/MigrationPermissionsEx.java @@ -41,7 +41,6 @@ import me.lucko.luckperms.common.model.Track; import me.lucko.luckperms.common.model.User; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.utils.Predicates; -import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.service.LuckPermsService; @@ -161,9 +160,7 @@ public class MigrationPermissionsEx extends SubCommand { for (String groupName : e.getValue().values()) { Group group = plugin.getGroupManager().getIfLoaded(groupName); if (group != null) { - try { - track.appendGroup(group); - } catch (ObjectAlreadyHasException ignored) {} + track.appendGroup(group); } } }