diff --git a/api/src/main/java/me/lucko/luckperms/api/Contexts.java b/api/src/main/java/me/lucko/luckperms/api/Contexts.java index 9cfb4b744..c3b603499 100644 --- a/api/src/main/java/me/lucko/luckperms/api/Contexts.java +++ b/api/src/main/java/me/lucko/luckperms/api/Contexts.java @@ -25,14 +25,11 @@ package me.lucko.luckperms.api; -import com.google.common.collect.ImmutableSet; - import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.EnumSet; import java.util.Objects; import java.util.Set; @@ -57,9 +54,9 @@ public class Contexts { public static final String WORLD_KEY = "world"; /** - * The default {@link LookupSetting}s. + * The default {@link LookupSetting}s as a flag. */ - private static final EnumSet DEFAULT_SETTINGS = EnumSet.of( + private static final byte DEFAULT_SETTINGS_FLAG = LookupSetting.createFlag( LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER, LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD, LookupSetting.RESOLVE_INHERITANCE, @@ -73,7 +70,7 @@ public class Contexts { *

Formed of an empty {@link ContextSet} and all inclusion and * inheritance {@link LookupSetting}s applied.

*/ - private static final Contexts GLOBAL = new Contexts(ImmutableContextSet.empty(), ImmutableSet.copyOf(DEFAULT_SETTINGS)); + private static final Contexts GLOBAL = new Contexts(ImmutableContextSet.empty(), DEFAULT_SETTINGS_FLAG); /** * Gets the {@link FullySatisfiedContexts} instance. @@ -111,7 +108,7 @@ public class Contexts { */ public static @NonNull Contexts of(@NonNull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) { Objects.requireNonNull(contextSet, "contextSet"); - EnumSet settings = formSettings( + byte settingsFlag = LookupSetting.createFlag( includeNodesSetWithoutServer, includeNodesSetWithoutWorld, resolveInheritance, @@ -119,18 +116,10 @@ public class Contexts { applyParentsWithoutWorld, isOp ); - if (contextSet.isEmpty() && DEFAULT_SETTINGS.equals(settings)) { + if (contextSet.isEmpty() && DEFAULT_SETTINGS_FLAG == settingsFlag) { return GLOBAL; } - return new Contexts(contextSet.makeImmutable(), ImmutableSet.copyOf(settings)); - } - - private static EnumSet asEnumSet(Set settings) { - if (settings instanceof EnumSet) { - return ((EnumSet) settings); - } else { - return EnumSet.copyOf(settings); - } + return new Contexts(contextSet.makeImmutable(), settingsFlag); } /** @@ -144,12 +133,12 @@ public class Contexts { Objects.requireNonNull(contextSet, "contextSet"); Objects.requireNonNull(settings, "settings"); - EnumSet settingsCopy = asEnumSet(settings); - if (contextSet.isEmpty() && DEFAULT_SETTINGS.equals(settingsCopy)) { + byte settingsFlag = LookupSetting.createFlag(settings); + if (contextSet.isEmpty() && DEFAULT_SETTINGS_FLAG == settingsFlag) { return GLOBAL; } - return new Contexts(contextSet.makeImmutable(), ImmutableSet.copyOf(settingsCopy)); + return new Contexts(contextSet.makeImmutable(), settingsFlag); } /** @@ -160,7 +149,7 @@ public class Contexts { /** * The settings for this lookup */ - private final ImmutableSet settings; + private final byte settingsFlag; // cache hashcode - this class is immutable, and is used as an index in the permission cache. private final int hashCode; @@ -180,20 +169,20 @@ public class Contexts { @Deprecated public Contexts(@NonNull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) { this.contextSet = Objects.requireNonNull(contextSet, "contextSet").makeImmutable(); - this.settings = ImmutableSet.copyOf(formSettings( + this.settingsFlag = LookupSetting.createFlag( includeNodesSetWithoutServer, includeNodesSetWithoutWorld, resolveInheritance, applyParentsWithoutServer, applyParentsWithoutWorld, isOp - )); + ); this.hashCode = calculateHashCode(); } - protected Contexts(@NonNull ImmutableContextSet contextSet, @NonNull ImmutableSet settings) { + protected Contexts(@NonNull ImmutableContextSet contextSet, byte settingsFlag) { this.contextSet = contextSet; - this.settings = settings; + this.settingsFlag = settingsFlag; this.hashCode = calculateHashCode(); } @@ -214,7 +203,7 @@ public class Contexts { * @since 4.2 */ public @NonNull Set getSettings() { - return this.settings; + return LookupSetting.createSetFromFlag(this.settingsFlag); } /** @@ -225,7 +214,7 @@ public class Contexts { * @since 4.2 */ public boolean hasSetting(@NonNull LookupSetting setting) { - return this.settings.contains(setting); + return LookupSetting.isSet(this.settingsFlag, setting); } /** @@ -302,7 +291,7 @@ public class Contexts { @Override public @NonNull String toString() { - return "Contexts(contextSet=" + this.contextSet + ", settings=" + this.settings + ")"; + return "Contexts(contextSet=" + this.contextSet + ", settings=" + LookupSetting.createSetFromFlag(this.settingsFlag) + ")"; } @Override @@ -311,14 +300,14 @@ public class Contexts { if (o == allowAll()) return false; if (!(o instanceof Contexts)) return false; final Contexts that = (Contexts) o; - return this.contextSet.equals(that.contextSet) && this.settings.equals(that.settings); + return this.contextSet.equals(that.contextSet) && this.settingsFlag == that.settingsFlag; } private int calculateHashCode() { final int PRIME = 59; int result = 1; result = result * PRIME + this.contextSet.hashCode(); - result = result * PRIME + this.settings.hashCode(); + result = result * PRIME + this.settingsFlag; return result; } @@ -327,27 +316,4 @@ public class Contexts { return this.hashCode; } - private static EnumSet formSettings(boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) { - EnumSet settings = EnumSet.noneOf(LookupSetting.class); - if (includeNodesSetWithoutServer) { - settings.add(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER); - } - if (includeNodesSetWithoutWorld) { - settings.add(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD); - } - if (resolveInheritance) { - settings.add(LookupSetting.RESOLVE_INHERITANCE); - } - if (applyParentsWithoutServer) { - settings.add(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER); - } - if (applyParentsWithoutWorld) { - settings.add(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD); - } - if (isOp) { - settings.add(LookupSetting.IS_OP); - } - return settings; - } - } diff --git a/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java b/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java index d332feeae..d7e897fb7 100644 --- a/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java +++ b/api/src/main/java/me/lucko/luckperms/api/FullySatisfiedContexts.java @@ -25,8 +25,6 @@ package me.lucko.luckperms.api; -import com.google.common.collect.ImmutableSet; - import me.lucko.luckperms.api.caching.CachedData; import me.lucko.luckperms.api.caching.MetaContexts; import me.lucko.luckperms.api.context.ImmutableContextSet; @@ -59,7 +57,7 @@ public final class FullySatisfiedContexts extends Contexts { } private FullySatisfiedContexts() { - super(ImmutableContextSet.empty(), ImmutableSet.copyOf(Contexts.global().getSettings())); + super(ImmutableContextSet.empty(), LookupSetting.createFlag(Contexts.global().getSettings())); } @Override diff --git a/api/src/main/java/me/lucko/luckperms/api/LookupSetting.java b/api/src/main/java/me/lucko/luckperms/api/LookupSetting.java index 726c95e6b..740a72d91 100644 --- a/api/src/main/java/me/lucko/luckperms/api/LookupSetting.java +++ b/api/src/main/java/me/lucko/luckperms/api/LookupSetting.java @@ -25,6 +25,9 @@ package me.lucko.luckperms.api; +import java.util.EnumSet; +import java.util.Set; + /** * The various lookup setting flags for {@link Contexts}. * @@ -60,5 +63,62 @@ public enum LookupSetting { /** * If global or non-world-specific group memberships should be applied */ - APPLY_PARENTS_SET_WITHOUT_WORLD + APPLY_PARENTS_SET_WITHOUT_WORLD; + + + + /* bitwise utility methods */ + + static boolean isSet(byte b, LookupSetting setting) { + return ((b >> setting.ordinal()) & 1) == 1; + } + + static byte createFlag(LookupSetting... settings) { + byte b = 0; + for (LookupSetting setting : settings) { + b |= (1 << setting.ordinal()); + } + return b; + } + + static byte createFlag(Set settings) { + byte b = 0; + for (LookupSetting setting : settings) { + b |= (1 << setting.ordinal()); + } + return b; + } + + static Set createSetFromFlag(byte b) { + EnumSet settings = EnumSet.noneOf(LookupSetting.class); + for (LookupSetting setting : LookupSetting.values()) { + if (((b >> setting.ordinal()) & 1) == 1) { + settings.add(setting); + } + } + return settings; + } + + static byte createFlag(boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) { + byte b = 0; + if (includeNodesSetWithoutServer) { + b |= (1 << LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER.ordinal()); + } + if (includeNodesSetWithoutWorld) { + b |= (1 << LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD.ordinal()); + } + if (resolveInheritance) { + b |= (1 << LookupSetting.RESOLVE_INHERITANCE.ordinal()); + } + if (applyParentsWithoutServer) { + b |= (1 << LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER.ordinal()); + } + if (applyParentsWithoutWorld) { + b |= (1 << LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD.ordinal()); + } + if (isOp) { + b |= (1 << LookupSetting.IS_OP.ordinal()); + } + return b; + } }