Expose MetaStacks in the API, general cleanup, release 3.2

This commit is contained in:
Luck 2017-05-16 21:41:20 +01:00
parent dc801464ef
commit abc1c164cf
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
56 changed files with 1094 additions and 505 deletions

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>3.1-SNAPSHOT</version> <version>3.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -49,7 +49,7 @@ public final class LuckPerms {
} }
/** /**
* Gets an instance of {@link LuckPermsApi} safely. * Gets an instance of {@link LuckPermsApi}, if it is loaded.
* *
* <p> Unlike {@link LuckPerms#getApi}, this method will not throw an {@link IllegalStateException} if the API is * <p> Unlike {@link LuckPerms#getApi}, this method will not throw an {@link IllegalStateException} if the API is
* not loaded, rather return an empty {@link Optional}. * not loaded, rather return an empty {@link Optional}.
@ -60,10 +60,12 @@ public final class LuckPerms {
return Optional.ofNullable(api); return Optional.ofNullable(api);
} }
/* method used by the implementation to set the singleton instance */
static void registerProvider(LuckPermsApi luckPermsApi) { static void registerProvider(LuckPermsApi luckPermsApi) {
api = luckPermsApi; api = luckPermsApi;
} }
/* method used by the implementation to remove any previous instance */
static void unregisterProvider() { static void unregisterProvider() {
api = null; api = null;
} }

View File

@ -23,14 +23,20 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.metastacking; package me.lucko.luckperms.api;
import me.lucko.luckperms.api.Node;
import java.util.Map; import java.util.Map;
public enum MetaType { /**
* Represents a type of chat meta
*
* @since 3.2
*/
public enum ChatMetaType {
/**
* Represents a prefix
*/
PREFIX { PREFIX {
@Override @Override
public boolean matches(Node node) { public boolean matches(Node node) {
@ -48,6 +54,9 @@ public enum MetaType {
} }
}, },
/**
* Represents a suffix
*/
SUFFIX { SUFFIX {
@Override @Override
public boolean matches(Node node) { public boolean matches(Node node) {
@ -65,10 +74,29 @@ public enum MetaType {
} }
}; };
/**
* Returns if the passed node matches the type
*
* @param node the node to test
* @return true if the node has the same type
*/
public abstract boolean matches(Node node); public abstract boolean matches(Node node);
/**
* Returns if the passed node should be ignored when searching for meta of this type
*
* @param node the node to test
* @return true if the node does not share the same type
*/
public abstract boolean shouldIgnore(Node node); public abstract boolean shouldIgnore(Node node);
/**
* Maps the corresponding entry from the given node
*
* @param node the node to retrieve the entry from
* @return the entry
* @throws IllegalStateException if the node does not share the same type
*/
public abstract Map.Entry<Integer, String> getEntry(Node node); public abstract Map.Entry<Integer, String> getEntry(Node node);
} }

View File

@ -165,6 +165,7 @@ public class Contexts {
return this.applyGlobalWorldGroups; return this.applyGlobalWorldGroups;
} }
@Override
public String toString() { public String toString() {
return "Contexts(" + return "Contexts(" +
"context=" + this.getContexts() + ", " + "context=" + this.getContexts() + ", " +
@ -181,18 +182,12 @@ public class Contexts {
* Ugly auto-generated lombok code * Ugly auto-generated lombok code
*/ */
/** @Override
* Check for equality
*
* @param o the other
* @return true if equal
* @since 2.12
*/
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (!(o instanceof Contexts)) return false; if (!(o instanceof Contexts)) return false;
final Contexts other = (Contexts) o; final Contexts other = (Contexts) o;
return (this.getContexts() == null ? other.getContexts() == null : this.getContexts().equals(other.getContexts())) && return this.getContexts().equals(other.getContexts()) &&
this.isOp() == other.isOp() && this.isOp() == other.isOp() &&
this.isIncludeGlobal() == other.isIncludeGlobal() && this.isIncludeGlobal() == other.isIncludeGlobal() &&
this.isIncludeGlobalWorld() == other.isIncludeGlobalWorld() && this.isIncludeGlobalWorld() == other.isIncludeGlobalWorld() &&
@ -201,12 +196,7 @@ public class Contexts {
this.isApplyGlobalWorldGroups() == other.isApplyGlobalWorldGroups(); this.isApplyGlobalWorldGroups() == other.isApplyGlobalWorldGroups();
} }
/** @Override
* Gets the hashcode
*
* @return the hashcode
* @since 2.12
*/
public int hashCode() { public int hashCode() {
final int PRIME = 59; final int PRIME = 59;
int result = 1; int result = 1;

View File

@ -22,6 +22,7 @@
package me.lucko.luckperms.api; package me.lucko.luckperms.api;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.exceptions.ObjectLacksException;
@ -41,7 +42,7 @@ public interface Group extends PermissionHolder {
String getName(); String getName();
/** /**
* Check to see if a group inherits a group * Check to see if a group inherits another group directly
* *
* @param group The group to check membership of * @param group The group to check membership of
* @return true if the group inherits the other group * @return true if the group inherits the other group
@ -50,6 +51,26 @@ public interface Group extends PermissionHolder {
*/ */
boolean inheritsGroup(Group group); boolean inheritsGroup(Group group);
/**
* Check to see if a group inherits another group directly
*
* @param group The group to check membership of
* @param contextSet the context set to filter by
* @return true if the group inherits the other group
* @throws NullPointerException if the group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
* @since 3.2
*/
boolean inheritsGroup(Group group, ContextSet contextSet);
/**
* Gets the weight of this group, if present.
*
* @return the group weight
* @since 2.17
*/
OptionalInt getWeight();
/** /**
* Check to see if the group inherits a group on a specific server * Check to see if the group inherits a group on a specific server
* *
@ -59,7 +80,9 @@ public interface Group extends PermissionHolder {
* @throws NullPointerException if the group or server is null * @throws NullPointerException if the group or server is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms. * @throws IllegalStateException if the group instance was not obtained from LuckPerms.
* @throws IllegalArgumentException if the server is invalid * @throws IllegalArgumentException if the server is invalid
* @deprecated in favour of {@link #inheritsGroup(Group, ContextSet)}
*/ */
@Deprecated
boolean inheritsGroup(Group group, String server); boolean inheritsGroup(Group group, String server);
/** /**
@ -72,7 +95,9 @@ public interface Group extends PermissionHolder {
* @throws NullPointerException if the group, server or world is null * @throws NullPointerException if the group, server or world is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms. * @throws IllegalStateException if the group instance was not obtained from LuckPerms.
* @throws IllegalArgumentException if the server or world is invalid * @throws IllegalArgumentException if the server or world is invalid
* @deprecated in favour of {@link #inheritsGroup(Group, ContextSet)}
*/ */
@Deprecated
boolean inheritsGroup(Group group, String server, String world); boolean inheritsGroup(Group group, String server, String world);
/** /**
@ -250,7 +275,9 @@ public interface Group extends PermissionHolder {
* Get a {@link List} of all of the groups the group inherits, on all servers * Get a {@link List} of all of the groups the group inherits, on all servers
* *
* @return a {@link List} of group names * @return a {@link List} of group names
* @deprecated in favour of just querying a users permissions
*/ */
@Deprecated
List<String> getGroupNames(); List<String> getGroupNames();
/** /**
@ -260,7 +287,9 @@ public interface Group extends PermissionHolder {
* @return a {@link List} of group names * @return a {@link List} of group names
* @throws NullPointerException if the server is null * @throws NullPointerException if the server is null
* @throws IllegalArgumentException if the server is invalid * @throws IllegalArgumentException if the server is invalid
* @deprecated in favour of just querying a users permissions
*/ */
@Deprecated
List<String> getLocalGroups(String server); List<String> getLocalGroups(String server);
@ -272,15 +301,9 @@ public interface Group extends PermissionHolder {
* @return a {@link List} of group names * @return a {@link List} of group names
* @throws NullPointerException if the server or world is null * @throws NullPointerException if the server or world is null
* @throws IllegalArgumentException if the server or world is invalid * @throws IllegalArgumentException if the server or world is invalid
* @deprecated in favour of just querying a users permissions
*/ */
@Deprecated
List<String> getLocalGroups(String server, String world); List<String> getLocalGroups(String server, String world);
/**
* Gets the weight of this group, is present.
*
* @return the group weight
* @since 2.17
*/
OptionalInt getWeight();
} }

View File

@ -23,10 +23,10 @@
package me.lucko.luckperms.api; package me.lucko.luckperms.api;
/** /**
* A wrapper interface for platform logger instances * Represents the logger instance being used by LuckPerms on the platform.
* *
* <p>Bukkit/Bungee both use java.util.logging, and Sponge uses org.slf4j. This class wraps those classes so the * <p>Messages sent using the logger are sent prefixed with the LuckPerms tag, and on some implementations will be colored
* commons module can access a logger.</p> * depending on the message type.</p>
*/ */
public interface Logger { public interface Logger {

View File

@ -25,6 +25,7 @@ package me.lucko.luckperms.api;
import me.lucko.luckperms.api.context.ContextCalculator; import me.lucko.luckperms.api.context.ContextCalculator;
import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.event.EventBus; import me.lucko.luckperms.api.event.EventBus;
import me.lucko.luckperms.api.metastacking.MetaStackFactory;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
@ -42,6 +43,7 @@ public interface LuckPermsApi {
/** /**
* Gets the API version * Gets the API version
*
* @return the version of the API running on the platform * @return the version of the API running on the platform
* @since 2.6 * @since 2.6
*/ */
@ -49,12 +51,14 @@ public interface LuckPermsApi {
/** /**
* Gets the plugin version * Gets the plugin version
*
* @return the version of the plugin running on the platform * @return the version of the plugin running on the platform
*/ */
String getVersion(); String getVersion();
/** /**
* Gets the platform LuckPerms is running on * Gets the platform LuckPerms is running on
*
* @return the platform LuckPerms is running on * @return the platform LuckPerms is running on
* @since 2.7 * @since 2.7
*/ */
@ -62,6 +66,7 @@ public interface LuckPermsApi {
/** /**
* Gets the event bus, used for subscribing to events * Gets the event bus, used for subscribing to events
*
* @return the event bus * @return the event bus
* @since 3.0 * @since 3.0
*/ */
@ -247,6 +252,14 @@ public interface LuckPermsApi {
*/ */
NodeFactory getNodeFactory(); NodeFactory getNodeFactory();
/**
* Gets the MetaStackFactory, used for creating MetaStacks.
*
* @return the meta stack factory
* @since 3.2
*/
MetaStackFactory getMetaStackFactory();
/** /**
* Returns a permission builder instance * Returns a permission builder instance
* *

View File

@ -40,12 +40,14 @@ import java.util.Set;
public interface Node extends Map.Entry<String, Boolean> { public interface Node extends Map.Entry<String, Boolean> {
/** /**
* Returns the actual permission string
*
* @return the actual permission node * @return the actual permission node
*/ */
String getPermission(); String getPermission();
/** /**
* Get what value the permission is set to. A negated node would return <code>false</code>. * Gets what value the permission is set to. A negated node would return <code>false</code>.
* *
* @return the permission's value * @return the permission's value
*/ */
@ -53,14 +55,22 @@ public interface Node extends Map.Entry<String, Boolean> {
Boolean getValue(); Boolean getValue();
/** /**
* Returns the value of this node as a tristate
*
* @return the value of this node as a Tristate * @return the value of this node as a Tristate
*/ */
Tristate getTristate(); default Tristate getTristate() {
return Tristate.fromBoolean(getValue());
}
/** /**
* Returns if the node is negated
*
* @return true if the node is negated * @return true if the node is negated
*/ */
boolean isNegated(); default boolean isNegated() {
return !getValue();
}
/** /**
* If this node is set to override explicitly. * If this node is set to override explicitly.
@ -201,28 +211,40 @@ public interface Node extends Map.Entry<String, Boolean> {
List<String> resolveShorthand(); List<String> resolveShorthand();
/** /**
* Returns if this node will expire in the future
*
* @return true if this node will expire in the future * @return true if this node will expire in the future
*/ */
boolean isTemporary(); boolean isTemporary();
/** /**
* Returns if this node will not expire
*
* @return true if this node will not expire * @return true if this node will not expire
*/ */
boolean isPermanent(); default boolean isPermanent() {
return !isTemporary();
}
/** /**
* Returns a unix timestamp in seconds when this node will expire
*
* @return the time in Unix time when this node will expire * @return the time in Unix time when this node will expire
* @throws IllegalStateException if the node is not temporary * @throws IllegalStateException if the node is not temporary
*/ */
long getExpiryUnixTime(); long getExpiryUnixTime();
/** /**
* Returns the date when this node will expire
*
* @return the {@link Date} when this node will expire * @return the {@link Date} when this node will expire
* @throws IllegalStateException if the node is not temporary * @throws IllegalStateException if the node is not temporary
*/ */
Date getExpiry(); Date getExpiry();
/** /**
* Return the number of seconds until this permission will expire
*
* @return the number of seconds until this permission will expire * @return the number of seconds until this permission will expire
* @throws IllegalStateException if the node is not temporary * @throws IllegalStateException if the node is not temporary
*/ */
@ -307,6 +329,8 @@ public interface Node extends Map.Entry<String, Boolean> {
Map.Entry<String, String> getMeta(); Map.Entry<String, String> getMeta();
/** /**
* Returns if this node is a prefix node
*
* @return true if this node is a prefix node * @return true if this node is a prefix node
*/ */
boolean isPrefix(); boolean isPrefix();
@ -320,6 +344,8 @@ public interface Node extends Map.Entry<String, Boolean> {
Map.Entry<Integer, String> getPrefix(); Map.Entry<Integer, String> getPrefix();
/** /**
* Returns if this node is a suffix node
*
* @return true if this node is a suffix node * @return true if this node is a suffix node
*/ */
boolean isSuffix(); boolean isSuffix();

View File

@ -36,7 +36,10 @@ public interface NodeFactory {
* @param value the value of the node * @param value the value of the node
* @return a node instance * @return a node instance
* @throws NullPointerException if the permission is null * @throws NullPointerException if the permission is null
* @deprecated since this format isn't used internally for permissions anymore
* @see Node#toSerializedNode()
*/ */
@Deprecated
Node fromSerialisedNode(String serialisedPermission, boolean value); Node fromSerialisedNode(String serialisedPermission, boolean value);
@ -65,7 +68,10 @@ public interface NodeFactory {
* @param value the value of the node * @param value the value of the node
* @return a node builder instance * @return a node builder instance
* @throws NullPointerException if the permission is null * @throws NullPointerException if the permission is null
* @deprecated since this format isn't used internally for permissions anymore
* @see Node#toSerializedNode()
*/ */
@Deprecated
Node.Builder newBuilderFromSerialisedNode(String serialisedPermission, boolean value); Node.Builder newBuilderFromSerialisedNode(String serialisedPermission, boolean value);
@ -90,6 +96,17 @@ public interface NodeFactory {
*/ */
Node.Builder makeMetaNode(String key, String value); Node.Builder makeMetaNode(String key, String value);
/**
* Creates a node builder for the given chat meta type
*
* @param priority the priority
* @param value the value for the prefix/suffix
* @return a node builder instance
* @throws NullPointerException if the type or value is null
* @since 3.2
*/
Node.Builder makeChatMetaNode(ChatMetaType type, int priority, String value);
/** /**
* Creates a node builder from a prefix string and priority * Creates a node builder from a prefix string and priority
* *

View File

@ -22,12 +22,14 @@
package me.lucko.luckperms.api; package me.lucko.luckperms.api;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.function.Predicate;
/** /**
* An object capable of holding permissions * An object capable of holding permissions
@ -46,6 +48,17 @@ public interface PermissionHolder {
*/ */
String getObjectName(); String getObjectName();
/**
* Gets a friendly name for this holder, to be displayed in command output, etc.
*
* <p>This will <strong>always</strong> return a value, eventually falling back to {@link #getObjectName()} if no
* other "friendlier" identifiers are present.</p>
*
* @return a friendly identifier for this holder
* @since 3.2
*/
String getFriendlyName();
/** /**
* Gets a sorted set of all held permissions. * Gets a sorted set of all held permissions.
* *
@ -57,21 +70,39 @@ public interface PermissionHolder {
/** /**
* Similar to {@link #getPermissions()}, except without transient permissions * Similar to {@link #getPermissions()}, except without transient permissions
* *
* <p>Unlike transient permissions, enduring permissions will be saved to storage, and exist after the session.</p>
*
* @return a set of nodes * @return a set of nodes
* @since 2.6 * @since 2.6
*/ */
Set<? extends Node> getEnduringPermissions(); Set<? extends Node> getEnduringPermissions();
/** /**
* Gets an immutable set of all transiently held permissions. * Similar to {@link #getPermissions()}, except without enduring permissions
* *
* <p> Transient permissions only exist for the duration of the session. * <p>Transient permissions only exist for the duration of the session.</p>
* *
* @return a set of nodes * @return a set of nodes
* @since 2.6 * @since 2.6
*/ */
Set<? extends Node> getTransientPermissions(); Set<? extends Node> getTransientPermissions();
/**
* Processes the nodes and returns the non-temporary ones.
*
* @return a set of permanent nodes
* @since 2.6
*/
Set<Node> getPermanentPermissionNodes();
/**
* Processes the nodes and returns the temporary ones.
*
* @return a set of temporary nodes
* @since 2.6
*/
Set<Node> getTemporaryPermissionNodes();
/** /**
* Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context * Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context
* *
@ -80,7 +111,7 @@ public interface PermissionHolder {
* *
* <p>Nodes are sorted into priority order.</p> * <p>Nodes are sorted into priority order.</p>
* *
* @param contexts the context for the lookup, * @param contexts the context for the lookup
* @return a mutable sorted set of permissions * @return a mutable sorted set of permissions
* @throws NullPointerException if the context is null * @throws NullPointerException if the context is null
* @since 2.11 * @since 2.11
@ -134,81 +165,6 @@ public interface PermissionHolder {
*/ */
Tristate hasTransientPermission(Node node); Tristate hasTransientPermission(Node node);
/**
* Checks to see if the object has a certain permission
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @return true if the object has the permission
* @throws NullPointerException if the node is null
* @throws IllegalArgumentException if the node is invalid
*/
boolean hasPermission(String node, boolean b);
/**
* Checks to see the the object has a permission on a certain server
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @return true if the object has the permission
* @throws NullPointerException if the node or server is null
* @throws IllegalArgumentException if the node or server is invalid
*/
boolean hasPermission(String node, boolean b, String server);
/**
* Checks to see the the object has a permission on a certain server and world
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @return true if the object has the permission
* @throws NullPointerException if the node, server or world is null
* @throws IllegalArgumentException if the node, server or world is invalid
*/
boolean hasPermission(String node, boolean b, String server, String world);
/**
* Checks to see the the object has a permission
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param temporary if the permission is temporary
* @return true if the object has the permission
* @throws NullPointerException if the node is null
* @throws IllegalArgumentException if the node is invalid
*/
boolean hasPermission(String node, boolean b, boolean temporary);
/**
* Checks to see the the object has a permission on a certain server
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server to check on
* @param temporary if the permission is temporary
* @return true if the object has the permission
* @throws NullPointerException if the node or server is null
* @throws IllegalArgumentException if the node or server is invalid
*/
boolean hasPermission(String node, boolean b, String server, boolean temporary);
/**
* Checks to see the the object has a permission on a certain server and world
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server to check on
* @param world The world to check on
* @param temporary if the permission is temporary
* @return true if the object has the permission
* @throws NullPointerException if the node, server or world is null
* @throws IllegalArgumentException if the node, server or world is invalid
*/
boolean hasPermission(String node, boolean b, String server, String world, boolean temporary);
/** /**
* Checks to see if the object inherits a certain permission * Checks to see if the object inherits a certain permission
* *
@ -219,81 +175,6 @@ public interface PermissionHolder {
*/ */
Tristate inheritsPermission(Node node); Tristate inheritsPermission(Node node);
/**
* Checks to see if the object inherits a certain permission
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @return true if the object inherits the permission
* @throws NullPointerException if the node is null
* @throws IllegalArgumentException if the node is invalid
*/
boolean inheritsPermission(String node, boolean b);
/**
* Checks to see the the object inherits a permission on a certain server
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @return true if the object inherits the permission
* @throws NullPointerException if the node or server is null
* @throws IllegalArgumentException if the node or server is invalid
*/
boolean inheritsPermission(String node, boolean b, String server);
/**
* Checks to see the the object inherits a permission on a certain server and world
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @return true if the object inherits the permission
* @throws NullPointerException if the node, server or world is null
* @throws IllegalArgumentException if the node server or world is invalid
*/
boolean inheritsPermission(String node, boolean b, String server, String world);
/**
* Checks to see if the object inherits a permission
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param temporary if the permission is temporary
* @return true if the object inherits the permission
* @throws NullPointerException if the node is null
* @throws IllegalArgumentException if the node is invalid
*/
boolean inheritsPermission(String node, boolean b, boolean temporary);
/**
* Checks to see if the object inherits a permission on a certain server
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param temporary if the permission is temporary
* @return true if the object inherits the permission
* @throws NullPointerException if the node or server is null
* @throws IllegalArgumentException if the node or server is invalid
*/
boolean inheritsPermission(String node, boolean b, String server, boolean temporary);
/**
* Checks to see if the object inherits a permission on a certain server and world
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @param temporary if the permission is temporary
* @return true if the object inherits the permission
* @throws NullPointerException if the node, server or world is null
* @throws IllegalArgumentException if the node, server or world if invalid
*/
boolean inheritsPermission(String node, boolean b, String server, String world, boolean temporary);
/** /**
* Sets a permission for the object * Sets a permission for the object
* *
@ -352,6 +233,286 @@ public interface PermissionHolder {
*/ */
DataMutateResult setTransientPermissionUnchecked(Node node); DataMutateResult setTransientPermissionUnchecked(Node node);
/**
* Unsets a permission for the object
*
* @param node The node to be unset
* @throws ObjectLacksException if the node wasn't already set
* @throws NullPointerException if the node is null
* @since 2.6
*/
void unsetPermission(Node node) throws ObjectLacksException;
/**
* Unsets a permission for the object
*
* @param node The node to be unset
* @throws NullPointerException if the node is null
* @return the result of the operation
* @since 3.1
*/
DataMutateResult unsetPermissionUnchecked(Node node);
/**
* Unsets a transient permission for the object
*
* @param node The node to be unset
* @throws ObjectLacksException if the node wasn't already set
* @throws NullPointerException if the node is null
* @since 2.6
*/
void unsetTransientPermission(Node node) throws ObjectLacksException;
/**
* Unsets a transient permission for the object
*
* @param node The node to be unset
* @throws NullPointerException if the node is null
* @return the result of the operation
* @since 3.1
*/
DataMutateResult unsetTransientPermissionUnchecked(Node node);
/**
* Clears any nodes from the holder which pass the predicate
*
* @param test the predicate to test for nodes which should be removed
* @since 3.2
*/
void clearMatching(Predicate<Node> test);
/**
* Clears any transient nodes from the holder which pass the predicate
*
* @param test the predicate to test for nodes which should be removed
* @since 3.2
*/
void clearMatchingTransient(Predicate<Node> test);
/**
* Clears all nodes held by the object
*
* @since 2.17
*/
void clearNodes();
/**
* Clears all nodes held by the object in a specific context
*
* @param contextSet the contexts to filter by
* @since 3.2
*/
void clearNodes(ContextSet contextSet);
/**
* Clears all parent groups
*
* @since 2.17
*/
void clearParents();
/**
* Clears all parent groups in a specific context
*
* @param contextSet the contexts to filter by
* @since 3.2
*/
void clearParents(ContextSet contextSet);
/**
* Clears all meta held by the object
*
* @since 2.17
*/
void clearMeta();
/**
* Clears all meta held by the object in a specific context
*
* @param contextSet the contexts to filter by
* @since 3.2
*/
void clearMeta(ContextSet contextSet);
/**
* Clears all transient permissions the holder has.
*/
void clearTransientNodes();
/**
* Checks to see if the object has a certain permission
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @return true if the object has the permission
* @throws NullPointerException if the node is null
* @throws IllegalArgumentException if the node is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean hasPermission(String node, boolean b);
/**
* Checks to see the the object has a permission on a certain server
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @return true if the object has the permission
* @throws NullPointerException if the node or server is null
* @throws IllegalArgumentException if the node or server is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean hasPermission(String node, boolean b, String server);
/**
* Checks to see the the object has a permission on a certain server and world
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @return true if the object has the permission
* @throws NullPointerException if the node, server or world is null
* @throws IllegalArgumentException if the node, server or world is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean hasPermission(String node, boolean b, String server, String world);
/**
* Checks to see the the object has a permission
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param temporary if the permission is temporary
* @return true if the object has the permission
* @throws NullPointerException if the node is null
* @throws IllegalArgumentException if the node is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean hasPermission(String node, boolean b, boolean temporary);
/**
* Checks to see the the object has a permission on a certain server
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server to check on
* @param temporary if the permission is temporary
* @return true if the object has the permission
* @throws NullPointerException if the node or server is null
* @throws IllegalArgumentException if the node or server is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean hasPermission(String node, boolean b, String server, boolean temporary);
/**
* Checks to see the the object has a permission on a certain server and world
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server to check on
* @param world The world to check on
* @param temporary if the permission is temporary
* @return true if the object has the permission
* @throws NullPointerException if the node, server or world is null
* @throws IllegalArgumentException if the node, server or world is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean hasPermission(String node, boolean b, String server, String world, boolean temporary);
/**
* Checks to see if the object inherits a certain permission
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @return true if the object inherits the permission
* @throws NullPointerException if the node is null
* @throws IllegalArgumentException if the node is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean inheritsPermission(String node, boolean b);
/**
* Checks to see the the object inherits a permission on a certain server
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @return true if the object inherits the permission
* @throws NullPointerException if the node or server is null
* @throws IllegalArgumentException if the node or server is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean inheritsPermission(String node, boolean b, String server);
/**
* Checks to see the the object inherits a permission on a certain server and world
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @return true if the object inherits the permission
* @throws NullPointerException if the node, server or world is null
* @throws IllegalArgumentException if the node server or world is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean inheritsPermission(String node, boolean b, String server, String world);
/**
* Checks to see if the object inherits a permission
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param temporary if the permission is temporary
* @return true if the object inherits the permission
* @throws NullPointerException if the node is null
* @throws IllegalArgumentException if the node is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean inheritsPermission(String node, boolean b, boolean temporary);
/**
* Checks to see if the object inherits a permission on a certain server
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param temporary if the permission is temporary
* @return true if the object inherits the permission
* @throws NullPointerException if the node or server is null
* @throws IllegalArgumentException if the node or server is invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean inheritsPermission(String node, boolean b, String server, boolean temporary);
/**
* Checks to see if the object inherits a permission on a certain server and world
*
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @param temporary if the permission is temporary
* @return true if the object inherits the permission
* @throws NullPointerException if the node, server or world is null
* @throws IllegalArgumentException if the node, server or world if invalid
* @deprecated in favour of {@link #hasPermission(Node)}
*/
@Deprecated
boolean inheritsPermission(String node, boolean b, String server, String world, boolean temporary);
/** /**
* Sets a permission for the object * Sets a permission for the object
* *
@ -439,46 +600,6 @@ public interface PermissionHolder {
@Deprecated @Deprecated
void setPermission(String node, boolean value, String server, String world, long expireAt) throws ObjectAlreadyHasException; void setPermission(String node, boolean value, String server, String world, long expireAt) throws ObjectAlreadyHasException;
/**
* Unsets a permission for the object
*
* @param node The node to be unset
* @throws ObjectLacksException if the node wasn't already set
* @throws NullPointerException if the node is null
* @since 2.6
*/
void unsetPermission(Node node) throws ObjectLacksException;
/**
* Unsets a permission for the object
*
* @param node The node to be unset
* @throws NullPointerException if the node is null
* @return the result of the operation
* @since 3.1
*/
DataMutateResult unsetPermissionUnchecked(Node node);
/**
* Unsets a transient permission for the object
*
* @param node The node to be unset
* @throws ObjectLacksException if the node wasn't already set
* @throws NullPointerException if the node is null
* @since 2.6
*/
void unsetTransientPermission(Node node) throws ObjectLacksException;
/**
* Unsets a transient permission for the object
*
* @param node The node to be unset
* @throws NullPointerException if the node is null
* @return the result of the operation
* @since 3.1
*/
DataMutateResult unsetTransientPermissionUnchecked(Node node);
/** /**
* Unsets a permission for the object * Unsets a permission for the object
* *
@ -560,19 +681,14 @@ public interface PermissionHolder {
@Deprecated @Deprecated
void unsetPermission(String node, String server, String world, boolean temporary) throws ObjectLacksException; void unsetPermission(String node, String server, String world, boolean temporary) throws ObjectLacksException;
/**
* Clears all nodes held by the object
*
* @since 2.17
*/
void clearNodes();
/** /**
* Clears all nodes held by the object on a specific server * Clears all nodes held by the object on a specific server
* *
* @param server the server to filter by, can be null * @param server the server to filter by, can be null
* @since 2.17 * @since 2.17
* @deprecated in favour of {@link #clearNodes(ContextSet)}
*/ */
@Deprecated
void clearNodes(String server); void clearNodes(String server);
/** /**
@ -581,22 +697,19 @@ public interface PermissionHolder {
* @param server the server to filter by, can be null * @param server the server to filter by, can be null
* @param world the world to filter by, can be null * @param world the world to filter by, can be null
* @since 2.17 * @since 2.17
* @deprecated in favour of {@link #clearNodes(ContextSet)}
*/ */
@Deprecated
void clearNodes(String server, String world); void clearNodes(String server, String world);
/**
* Clears all parent groups
*
* @since 2.17
*/
void clearParents();
/** /**
* Clears all parents on a specific server * Clears all parents on a specific server
* *
* @param server the server to filter by, can be null * @param server the server to filter by, can be null
* @since 2.17 * @since 2.17
* @deprecated in favour of {@link #clearParents(ContextSet)}
*/ */
@Deprecated
void clearParents(String server); void clearParents(String server);
/** /**
@ -605,22 +718,19 @@ public interface PermissionHolder {
* @param server the server to filter by, can be null * @param server the server to filter by, can be null
* @param world the world to filter by, can be null * @param world the world to filter by, can be null
* @since 2.17 * @since 2.17
* @deprecated in favour of {@link #clearParents(ContextSet)}
*/ */
@Deprecated
void clearParents(String server, String world); void clearParents(String server, String world);
/**
* Clears all meta held by the object
*
* @since 2.17
*/
void clearMeta();
/** /**
* Clears all meta held by the object on a specific server * Clears all meta held by the object on a specific server
* *
* @param server the server to filter by, can be null * @param server the server to filter by, can be null
* @since 2.17 * @since 2.17
* @deprecated in favour of {@link #clearMeta(ContextSet)}
*/ */
@Deprecated
void clearMeta(String server); void clearMeta(String server);
/** /**
@ -629,7 +739,9 @@ public interface PermissionHolder {
* @param server the server to filter by, can be null * @param server the server to filter by, can be null
* @param world the world to filter by, can be null * @param world the world to filter by, can be null
* @since 2.17 * @since 2.17
* @deprecated in favour of {@link #clearMeta(ContextSet)}
*/ */
@Deprecated
void clearMeta(String server, String world); void clearMeta(String server, String world);
/** /**
@ -639,28 +751,9 @@ public interface PermissionHolder {
* @param server the server to filter by, can be null * @param server the server to filter by, can be null
* @param world the world to filter by, can be null * @param world the world to filter by, can be null
* @param temporary whether the query is for temporary nodes or not. * @param temporary whether the query is for temporary nodes or not.
* @deprecated in favour of {@link #removeIf(Predicate)}
*/ */
@Deprecated
void clearMetaKeys(String key, String server, String world, boolean temporary); void clearMetaKeys(String key, String server, String world, boolean temporary);
/**
* Clears all transient permissions the holder has.
*/
void clearTransientNodes();
/**
* Processes the nodes and returns the non-temporary ones.
*
* @return a set of permanent nodes
* @since 2.6
*/
Set<Node> getPermanentPermissionNodes();
/**
* Processes the nodes and returns the temporary ones.
*
* @return a set of temporary nodes
* @since 2.6
*/
Set<Node> getTemporaryPermissionNodes();
} }

View File

@ -25,8 +25,8 @@ package me.lucko.luckperms.api;
/** /**
* Represents a permission setting. * Represents a permission setting.
* *
* <p>Consider a value of {@link #FALSE} to be a "negated" setting, and a value of {@link #UNDEFINED} to be a * <p>Consider a value of {@link #TRUE} to be a positive setting, {@link #FALSE} to be a "negated" setting,
* non-existent value.</p> * and a value of {@link #UNDEFINED} to be a non-existent value.</p>
*/ */
public enum Tristate { public enum Tristate {

View File

@ -23,6 +23,7 @@
package me.lucko.luckperms.api; package me.lucko.luckperms.api;
import me.lucko.luckperms.api.caching.UserData; import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.exceptions.ObjectLacksException;
@ -45,19 +46,22 @@ public interface User extends PermissionHolder {
/** /**
* Gets the users username, or null if no username is associated with this user * Gets the users username, or null if no username is associated with this user
* *
* @return the Users Username * @return the users username
*/ */
String getName(); String getName();
/** /**
* Gets the users primary group * Gets the users current primary group.
*
* <p>The result of this method depends on which method is configured for primary group calculation. It may not
* be the same as any value set through {@link #setPrimaryGroup(String)}.</p>
* *
* @return the users primary group * @return the users primary group
*/ */
String getPrimaryGroup(); String getPrimaryGroup();
/** /**
* Sets a users primary group * Sets a users primary group. This will only take effect if platform is using stored primary groups.
* *
* @param group the new primary group * @param group the new primary group
* @throws ObjectAlreadyHasException if the user already has this set as their primary group * @throws ObjectAlreadyHasException if the user already has this set as their primary group
@ -69,35 +73,59 @@ public interface User extends PermissionHolder {
/** /**
* Refresh and re-assign the users permissions. * Refresh and re-assign the users permissions.
* *
* <p>This request is not buffered, and the refresh call will be ran directly. This should ideally be called on * <p>This request is not buffered, and the refresh call will be ran directly. This should be called on an
* an asynchronous thread.</p> * asynchronous thread.</p>
*/ */
void refreshPermissions(); void refreshPermissions();
/**
* Gets the user's {@link UserData} cache.
*
* @return the users cached data.
* @since 3.2
*/
UserData getCachedData();
/**
* Check to see if the user is a direct member of a group
*
* @param group The group to check membership of
* @return true if the user is a member of the group
* @throws NullPointerException if the group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
boolean isInGroup(Group group);
/**
* Check to see if the user is a direct member of a group in a specific context
*
* @param group the group to check membership of
* @param contextSet the context set to filter by
* @return true if the user is a member of the group
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
* @since 3.2
*/
boolean isInGroup(Group group, ContextSet contextSet);
/** /**
* Gets the user's {@link UserData} cache, if they have one setup. * Gets the user's {@link UserData} cache, if they have one setup.
* *
* @return an optional, possibly containing the user's cached lookup data. * @return an optional, possibly containing the user's cached lookup data.
* @since 2.13 * @since 2.13
* @deprecated in version 3.2, as this cache is now always loaded
*/ */
@Deprecated
Optional<UserData> getUserDataCache(); Optional<UserData> getUserDataCache();
/** /**
* Sets up the users data cache, if the don't have one setup already. * Sets up the users data cache, if the don't have one setup already.
* *
* @since 2.17 * @since 2.17
* @deprecated in version 3.2, as this cache is now always loaded.
*/ */
@Deprecated
void setupDataCache(); void setupDataCache();
/**
* Check to see if the user is a member of a group
*
* @param group The group to check membership of
* @return true if the user is a member of the group
* @throws NullPointerException if the group is null
*/
boolean isInGroup(Group group);
/** /**
* Check to see if a user is a member of a group on a specific server * Check to see if a user is a member of a group on a specific server
* *
@ -106,7 +134,9 @@ public interface User extends PermissionHolder {
* @return true if the user is a member of the group * @return true if the user is a member of the group
* @throws NullPointerException if the group or server is null * @throws NullPointerException if the group or server is null
* @throws IllegalArgumentException if the server is invalid * @throws IllegalArgumentException if the server is invalid
* @deprecated in favour of {@link #isInGroup(Group, ContextSet)}
*/ */
@Deprecated
boolean isInGroup(Group group, String server); boolean isInGroup(Group group, String server);
/** /**
@ -118,7 +148,9 @@ public interface User extends PermissionHolder {
* @return true if the user is a member of the group * @return true if the user is a member of the group
* @throws NullPointerException if the group, server or world is null * @throws NullPointerException if the group, server or world is null
* @throws IllegalArgumentException if the server or world is invalid * @throws IllegalArgumentException if the server or world is invalid
* @deprecated in favour of {@link #isInGroup(Group, ContextSet)}
*/ */
@Deprecated
boolean isInGroup(Group group, String server, String world); boolean isInGroup(Group group, String server, String world);
/** /**
@ -296,7 +328,9 @@ public interface User extends PermissionHolder {
* Get a {@link List} of all of the groups the user is a member of, on all servers * Get a {@link List} of all of the groups the user is a member of, on all servers
* *
* @return a {@link List} of group names * @return a {@link List} of group names
* @deprecated in favour of just querying a users permissions
*/ */
@Deprecated
List<String> getGroupNames(); List<String> getGroupNames();
/** /**
@ -307,7 +341,9 @@ public interface User extends PermissionHolder {
* @return a {@link List} of group names * @return a {@link List} of group names
* @throws NullPointerException if the server or world is null * @throws NullPointerException if the server or world is null
* @throws IllegalArgumentException if the server or world is invalid * @throws IllegalArgumentException if the server or world is invalid
* @deprecated in favour of just querying a users permissions
*/ */
@Deprecated
List<String> getLocalGroups(String server, String world); List<String> getLocalGroups(String server, String world);
/** /**
@ -317,7 +353,9 @@ public interface User extends PermissionHolder {
* @return a {@link List} of group names * @return a {@link List} of group names
* @throws NullPointerException if the server is null * @throws NullPointerException if the server is null
* @throws IllegalArgumentException if the server is invalid * @throws IllegalArgumentException if the server is invalid
* @deprecated in favour of just querying a users permissions
*/ */
@Deprecated
List<String> getLocalGroups(String server); List<String> getLocalGroups(String server);
} }

View File

@ -30,10 +30,10 @@ import java.util.UUID;
* <p>This UuidCache is a means of allowing users to have the same internal UUID across a network of offline mode * <p>This UuidCache is a means of allowing users to have the same internal UUID across a network of offline mode
* servers or mixed offline mode and online mode servers. Platforms running in offline mode generate a UUID for a * servers or mixed offline mode and online mode servers. Platforms running in offline mode generate a UUID for a
* user when they first join the server, but this UUID will then not be consistent across the network. LuckPerms will * user when they first join the server, but this UUID will then not be consistent across the network. LuckPerms will
* instead check the datastore cache, to get a UUID for a user that is consistent across an entire network. * instead check the datastore cache, to get a UUID for a user that is consistent across an entire network.</p>
* *
* <p>If you want to get a user object from the Storage using the api on a server in offline mode, you will need to use * <p>If you want to get a user object from the Storage using the api on a server in offline mode, you will need to use
* this cache, OR use Storage#getUUID, for users that are not online. * this cache, OR use Storage#getUUID, for users that are not online.</p>
* *
* <p><strong>This is only effective for online players. Use {@link Storage#getUUID(String)} for offline players.</strong></p> * <p><strong>This is only effective for online players. Use {@link Storage#getUUID(String)} for offline players.</strong></p>
*/ */

View File

@ -0,0 +1,110 @@
/*
* 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.api.caching;
import com.google.common.base.Preconditions;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
/**
* Represents the context for a meta lookup, consisting of a standard {@link Contexts} element, plus options to define how
* the meta stack should be constructed.
*
* @since 3.2
*/
public final class MetaContexts {
/**
* Creates a new meta contexts instance
*
* @param contexts the standard contexts for the query
* @param prefixStackDefinition the prefix stack definition to be used
* @param suffixStackDefinition the suffix stack definition to be used
* @return the new instance
*/
public static MetaContexts of(Contexts contexts, MetaStackDefinition prefixStackDefinition, MetaStackDefinition suffixStackDefinition) {
return new MetaContexts(contexts, prefixStackDefinition, suffixStackDefinition);
}
private final Contexts contexts;
private final MetaStackDefinition prefixStackDefinition;
private final MetaStackDefinition suffixStackDefinition;
/**
* Creates a new meta contexts instance
*
* @param contexts the standard contexts for the query
* @param prefixStackDefinition the prefix stack definition to be used
* @param suffixStackDefinition the suffix stack definition to be used
*/
public MetaContexts(Contexts contexts, MetaStackDefinition prefixStackDefinition, MetaStackDefinition suffixStackDefinition) {
this.contexts = Preconditions.checkNotNull(contexts, "contexts");
this.prefixStackDefinition = Preconditions.checkNotNull(prefixStackDefinition, "prefixStackDefinition");
this.suffixStackDefinition = Preconditions.checkNotNull(suffixStackDefinition, "suffixStackDefinition");
}
public Contexts getContexts() {
return this.contexts;
}
public MetaStackDefinition getPrefixStackDefinition() {
return this.prefixStackDefinition;
}
public MetaStackDefinition getSuffixStackDefinition() {
return this.suffixStackDefinition;
}
@Override
public String toString() {
return "MetaContexts(" +
"contexts=" + this.getContexts() + ", " +
"prefixStackDefinition=" + this.getPrefixStackDefinition() + ", " +
"suffixStackDefinition=" + this.getSuffixStackDefinition() +
")";
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof MetaContexts)) return false;
final MetaContexts other = (MetaContexts) o;
return this.getContexts().equals(other.getContexts()) &&
this.getPrefixStackDefinition().equals(other.getPrefixStackDefinition()) &&
this.getSuffixStackDefinition().equals(other.getSuffixStackDefinition());
}
@Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.getContexts().hashCode();
result = result * PRIME + this.getPrefixStackDefinition().hashCode();
result = result * PRIME + this.getSuffixStackDefinition().hashCode();
return result;
}
}

View File

@ -22,6 +22,8 @@
package me.lucko.luckperms.api.caching; package me.lucko.luckperms.api.caching;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import java.util.Map; import java.util.Map;
import java.util.SortedMap; import java.util.SortedMap;
@ -69,4 +71,20 @@ public interface MetaData {
*/ */
String getSuffix(); String getSuffix();
/**
* Gets the definition used for the prefix stack
*
* @return the definition used for the prefix stack
* @since 3.2
*/
MetaStackDefinition getPrefixStackDefinition();
/**
* Gets the definition used for the suffix stack
*
* @return the definition used for the suffix stack
* @since 3.2
*/
MetaStackDefinition getSuffixStackDefinition();
} }

View File

@ -32,6 +32,10 @@ import java.util.Set;
* <p>Data is only likely to be available for online users. All calls will account for inheritance, as well as any * <p>Data is only likely to be available for online users. All calls will account for inheritance, as well as any
* default data provided by the platform. This calls are heavily cached and are therefore fast.</p> * default data provided by the platform. This calls are heavily cached and are therefore fast.</p>
* *
* <p>For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that
* the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the
* values from the configuration are used.</p>
*
* @since 2.13 * @since 2.13
*/ */
public interface UserData { public interface UserData {
@ -47,6 +51,18 @@ public interface UserData {
*/ */
PermissionData getPermissionData(Contexts contexts); PermissionData getPermissionData(Contexts contexts);
/**
* Gets MetaData from the cache, given a specified context.
*
* <p>If the data is not cached, it is calculated. Therefore, this call could be costly.</p>
*
* @param contexts the contexts to get the permission data in
* @return a meta data instance
* @throws NullPointerException if contexts is null
* @since 3.2
*/
MetaData getMetaData(MetaContexts contexts);
/** /**
* Gets MetaData from the cache, given a specified context. * Gets MetaData from the cache, given a specified context.
* *
@ -67,6 +83,16 @@ public interface UserData {
*/ */
PermissionData calculatePermissions(Contexts contexts); PermissionData calculatePermissions(Contexts contexts);
/**
* Calculates meta data, bypassing the cache.
*
* @param contexts the contexts to get meta data in
* @return a meta data instance
* @throws NullPointerException if contexts is null
* @since 3.2
*/
MetaData calculateMeta(MetaContexts contexts);
/** /**
* Calculates meta data, bypassing the cache. * Calculates meta data, bypassing the cache.
* *
@ -87,6 +113,18 @@ public interface UserData {
*/ */
void recalculatePermissions(Contexts contexts); void recalculatePermissions(Contexts contexts);
/**
* Calculates meta data and stores it in the cache.
*
* <p>If there is already data cached for the given contexts, and if the resultant output is different,
* the cached value is updated.</p>
*
* @param contexts the contexts to recalculate in.
* @throws NullPointerException if contexts is null
* @since 3.2
*/
void recalculateMeta(MetaContexts contexts);
/** /**
* Calculates meta data and stores it in the cache. * Calculates meta data and stores it in the cache.
* *

View File

@ -23,30 +23,49 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.metastacking.definition; package me.lucko.luckperms.api.metastacking;
import me.lucko.luckperms.common.metastacking.GenericMetaStack;
import me.lucko.luckperms.common.metastacking.MetaStack;
import me.lucko.luckperms.common.metastacking.MetaType;
import java.util.List; import java.util.List;
/**
* Represents a meta stack model, consisting of a chain of elements, separated by spacers.
*
* <p>The resultant string is constructed as:
* [start spacer] [element] [middle spacer] [element] [middle spacer] [element] [end spacer]</p>
*
* <p>Definitions can be passed to a users UserData instance using MetaContexts, and the result of this stack can be
* retrieved from the returned MetaData instance.</p>
*
* @since 2.3
*/
public interface MetaStackDefinition { public interface MetaStackDefinition {
static MetaStackDefinition create(List<MetaStackElement> elements, String startSpacer, String middleSpacer, String endSpacer) { /**
return new SimpleMetaStackDefinition(elements, startSpacer, middleSpacer, endSpacer); * Gets an immutable list of the elements in this stack definition
} *
* @return the elements in this stack
*/
List<MetaStackElement> getElements(); List<MetaStackElement> getElements();
/**
* Gets the spacer string added before any stack elements
*
* @return the start spacer
*/
String getStartSpacer(); String getStartSpacer();
/**
* Gets the spacer added between stack elements
*
* @return the middle spacer
*/
String getMiddleSpacer(); String getMiddleSpacer();
/**
* Gets the spacer added after any stack elements
*
* @return the end spacer
*/
String getEndSpacer(); String getEndSpacer();
default MetaStack newStack(MetaType type) {
return new GenericMetaStack(this, type);
}
} }

View File

@ -23,15 +23,31 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.metastacking.definition; package me.lucko.luckperms.api.metastacking;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.common.metastacking.MetaType; import me.lucko.luckperms.api.Node;
import java.util.Map; import java.util.Map;
/**
* Represents an element within a {@link MetaStackDefinition}.
*
* @since 3.2
*/
public interface MetaStackElement { public interface MetaStackElement {
boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current); /**
* Returns if the given node should be accumulated onto the stack.
*
* <p>The element being considered can be retrieved using {@link ChatMetaType#getEntry(Node)}.</p>
*
* @param node the node being considered
* @param type the type of entry being accumulated
* @param current the current value being used. If this returns true, the current value will be replaced by this entry
* @return true if the node should be accumulated into this element, replacing the current value
*/
boolean shouldAccumulate(LocalizedNode node, ChatMetaType type, Map.Entry<Integer, String> current);
} }

View File

@ -0,0 +1,67 @@
/*
* 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.api.metastacking;
import java.util.List;
import java.util.Optional;
/**
* Factory to create meta stack elements and definitions.
*
* @since 3.2
*/
public interface MetaStackFactory {
/**
* Parses a standard {@link MetaStackElement} from string, using the pre-defined elements in the plugin.
*
* @param definition the definition
* @return the parsed element, if present
*/
Optional<MetaStackElement> fromString(String definition);
/**
* Parses a list of {@link MetaStackElement}s from string, using the pre-defined elements in the plugin.
*
* <p>If an element cannot be parsed, it will not be included in the resultant list.</p>
*
* @param definitions the definition strings
* @return a list of parsed elements
*/
List<MetaStackElement> fromStrings(List<String> definitions);
/**
* Creates a new {@link MetaStackDefinition} with the given properties.
*
* @param elements the elements to be included in the stack.
* @param startSpacer the spacer to be included at the start of the stacks output
* @param middleSpacer the spacer to be included between stack elements
* @param endSpacer the spacer to be included at the end of the stacks output
* @return the new stack definition instance
*/
MetaStackDefinition createDefinition(List<MetaStackElement> elements, String startSpacer, String middleSpacer, String endSpacer);
}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>3.1-SNAPSHOT</version> <version>3.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>3.1-SNAPSHOT</version> <version>3.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -32,6 +32,7 @@ import de.bananaco.bpermissions.api.Permission;
import de.bananaco.bpermissions.api.World; import de.bananaco.bpermissions.api.World;
import de.bananaco.bpermissions.api.WorldManager; import de.bananaco.bpermissions.api.WorldManager;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.common.commands.CommandException; import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult; import me.lucko.luckperms.common.commands.CommandResult;
@ -41,7 +42,6 @@ import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.ProgressLogger; import me.lucko.luckperms.common.utils.ProgressLogger;
@ -225,7 +225,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
} }
if (meta.getKey().equalsIgnoreCase("prefix") || meta.getKey().equalsIgnoreCase("suffix")) { if (meta.getKey().equalsIgnoreCase("prefix") || meta.getKey().equalsIgnoreCase("suffix")) {
MetaType type = MetaType.valueOf(meta.getKey().toUpperCase()); ChatMetaType type = ChatMetaType.valueOf(meta.getKey().toUpperCase());
holder.setPermission(NodeFactory.makeChatMetaNode(type, c.getPriority(), meta.getValue()).setWorld(world.getName()).build()); holder.setPermission(NodeFactory.makeChatMetaNode(type, c.getPriority(), meta.getValue()).setWorld(world.getName()).build());
continue; continue;
} }

View File

@ -25,6 +25,7 @@
package me.lucko.luckperms.bukkit.migration; package me.lucko.luckperms.bukkit.migration;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.common.commands.Arg; import me.lucko.luckperms.common.commands.Arg;
@ -35,7 +36,6 @@ import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
import me.lucko.luckperms.common.commands.sender.Sender; import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Permission; import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.ProgressLogger; import me.lucko.luckperms.common.utils.ProgressLogger;
@ -173,7 +173,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
} }
if (key.equals("prefix") || key.equals("suffix")) { if (key.equals("prefix") || key.equals("suffix")) {
MetaType type = MetaType.valueOf(key.toUpperCase()); ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase());
groups.get(groupName).add(NodeFactory.makeChatMetaNode(type, 50, value).setWorld(worldMappingFunc.apply(world)).build()); groups.get(groupName).add(NodeFactory.makeChatMetaNode(type, 50, value).setWorld(worldMappingFunc.apply(world)).build());
} else { } else {
groups.get(groupName).add(NodeFactory.makeMetaNode(key, value).setWorld(worldMappingFunc.apply(world)).build()); groups.get(groupName).add(NodeFactory.makeMetaNode(key, value).setWorld(worldMappingFunc.apply(world)).build());
@ -230,7 +230,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
} }
if (key.equals("prefix") || key.equals("suffix")) { if (key.equals("prefix") || key.equals("suffix")) {
MetaType type = MetaType.valueOf(key.toUpperCase()); ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase());
users.get(uuid).add(NodeFactory.makeChatMetaNode(type, 100, value).setWorld(worldMappingFunc.apply(world)).build()); users.get(uuid).add(NodeFactory.makeChatMetaNode(type, 100, value).setWorld(worldMappingFunc.apply(world)).build());
} else { } else {
users.get(uuid).add(NodeFactory.makeMetaNode(key, value).setWorld(worldMappingFunc.apply(world)).build()); users.get(uuid).add(NodeFactory.makeMetaNode(key, value).setWorld(worldMappingFunc.apply(world)).build());

View File

@ -25,6 +25,7 @@
package me.lucko.luckperms.bukkit.migration; package me.lucko.luckperms.bukkit.migration;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.cause.CreationCause; import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.common.commands.CommandException; import me.lucko.luckperms.common.commands.CommandException;
@ -39,7 +40,6 @@ import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.core.model.Track; import me.lucko.luckperms.common.core.model.Track;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.ProgressLogger; import me.lucko.luckperms.common.utils.ProgressLogger;
@ -214,7 +214,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
String key = metadata.getName().toLowerCase(); String key = metadata.getName().toLowerCase();
if (key.equals("prefix") || key.equals("suffix")) { if (key.equals("prefix") || key.equals("suffix")) {
MetaType type = MetaType.valueOf(key.toUpperCase()); ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase());
holder.setPermission(NodeFactory.makeChatMetaNode(type, weight, metadata.getStringValue()).build()); holder.setPermission(NodeFactory.makeChatMetaNode(type, weight, metadata.getStringValue()).build());
} else { } else {
holder.setPermission(NodeFactory.makeMetaNode(key, metadata.getStringValue()).build()); holder.setPermission(NodeFactory.makeMetaNode(key, metadata.getStringValue()).build());

View File

@ -27,6 +27,7 @@ package me.lucko.luckperms.bukkit.vault;
import lombok.NonNull; import lombok.NonNull;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.caching.MetaData; import me.lucko.luckperms.api.caching.MetaData;
@ -35,7 +36,6 @@ import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.utils.ExtractedContexts; import me.lucko.luckperms.common.utils.ExtractedContexts;
import net.milkbowl.vault.chat.Chat; import net.milkbowl.vault.chat.Chat;
@ -84,7 +84,7 @@ public class VaultChatHook extends Chat {
}); });
} }
private void setChatMeta(MetaType type, PermissionHolder holder, String value, String world) { private void setChatMeta(ChatMetaType type, PermissionHolder holder, String value, String world) {
String finalWorld = perms.isIgnoreWorld() ? null : world; String finalWorld = perms.isIgnoreWorld() ? null : world;
if (holder == null) return; if (holder == null) return;
if (value.equals("")) return; if (value.equals("")) return;
@ -97,7 +97,7 @@ public class VaultChatHook extends Chat {
// find the max inherited priority & add 10 // find the max inherited priority & add 10
MetaAccumulator metaAccumulator = holder.accumulateMeta(null, null, ExtractedContexts.generate(perms.createContextForWorldSet(finalWorld))); MetaAccumulator metaAccumulator = holder.accumulateMeta(null, null, ExtractedContexts.generate(perms.createContextForWorldSet(finalWorld)));
int priority = (type == MetaType.PREFIX ? metaAccumulator.getPrefixes() : metaAccumulator.getSuffixes()).keySet().stream() int priority = (type == ChatMetaType.PREFIX ? metaAccumulator.getPrefixes() : metaAccumulator.getSuffixes()).keySet().stream()
.mapToInt(e -> e).max().orElse(0) + 10; .mapToInt(e -> e).max().orElse(0) + 10;
Node.Builder chatMetaNode = NodeFactory.makeChatMetaNode(type, priority, value); Node.Builder chatMetaNode = NodeFactory.makeChatMetaNode(type, priority, value);
@ -123,14 +123,14 @@ public class VaultChatHook extends Chat {
return ret != null ? ret : defaultValue; return ret != null ? ret : defaultValue;
} }
private String getUserChatMeta(MetaType type, User user, String world) { private String getUserChatMeta(ChatMetaType type, User user, String world) {
if (user == null) return ""; if (user == null) return "";
world = perms.isIgnoreWorld() ? null : world; world = perms.isIgnoreWorld() ? null : world;
perms.log("Getting " + type.name().toLowerCase() + " for user " + user.getFriendlyName() + " on world " + world + ", server " + perms.getServer()); perms.log("Getting " + type.name().toLowerCase() + " for user " + user.getFriendlyName() + " on world " + world + ", server " + perms.getServer());
MetaData data = user.getUserData().getMetaData(perms.createContextForWorldLookup(perms.getPlugin().getPlayer(user), world)); MetaData data = user.getUserData().getMetaData(perms.createContextForWorldLookup(perms.getPlugin().getPlayer(user), world));
String ret = type == MetaType.PREFIX ? data.getPrefix() : data.getSuffix(); String ret = type == ChatMetaType.PREFIX ? data.getPrefix() : data.getSuffix();
return ret != null ? ret : ""; return ret != null ? ret : "";
} }
@ -154,7 +154,7 @@ public class VaultChatHook extends Chat {
return defaultValue; return defaultValue;
} }
private String getGroupChatMeta(MetaType type, Group group, String world) { private String getGroupChatMeta(ChatMetaType type, Group group, String world) {
world = perms.isIgnoreWorld() ? null : world; world = perms.isIgnoreWorld() ? null : world;
if (group == null) return ""; if (group == null) return "";
@ -182,49 +182,49 @@ public class VaultChatHook extends Chat {
@Override @Override
public String getPlayerPrefix(String world, @NonNull String player) { public String getPlayerPrefix(String world, @NonNull String player) {
final User user = perms.getPlugin().getUserManager().getByUsername(player); final User user = perms.getPlugin().getUserManager().getByUsername(player);
return getUserChatMeta(MetaType.PREFIX, user, world); return getUserChatMeta(ChatMetaType.PREFIX, user, world);
} }
@Override @Override
public void setPlayerPrefix(String world, @NonNull String player, @NonNull String prefix) { public void setPlayerPrefix(String world, @NonNull String player, @NonNull String prefix) {
final User user = perms.getPlugin().getUserManager().getByUsername(player); final User user = perms.getPlugin().getUserManager().getByUsername(player);
setChatMeta(MetaType.PREFIX, user, prefix, world); setChatMeta(ChatMetaType.PREFIX, user, prefix, world);
} }
@Override @Override
public String getPlayerSuffix(String world, @NonNull String player) { public String getPlayerSuffix(String world, @NonNull String player) {
final User user = perms.getPlugin().getUserManager().getByUsername(player); final User user = perms.getPlugin().getUserManager().getByUsername(player);
return getUserChatMeta(MetaType.SUFFIX, user, world); return getUserChatMeta(ChatMetaType.SUFFIX, user, world);
} }
@Override @Override
public void setPlayerSuffix(String world, @NonNull String player, @NonNull String suffix) { public void setPlayerSuffix(String world, @NonNull String player, @NonNull String suffix) {
final User user = perms.getPlugin().getUserManager().getByUsername(player); final User user = perms.getPlugin().getUserManager().getByUsername(player);
setChatMeta(MetaType.SUFFIX, user, suffix, world); setChatMeta(ChatMetaType.SUFFIX, user, suffix, world);
} }
@Override @Override
public String getGroupPrefix(String world, @NonNull String group) { public String getGroupPrefix(String world, @NonNull String group) {
final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group); final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group);
return getGroupChatMeta(MetaType.PREFIX, g, world); return getGroupChatMeta(ChatMetaType.PREFIX, g, world);
} }
@Override @Override
public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) { public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) {
final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group); final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group);
setChatMeta(MetaType.PREFIX, g, prefix, world); setChatMeta(ChatMetaType.PREFIX, g, prefix, world);
} }
@Override @Override
public String getGroupSuffix(String world, @NonNull String group) { public String getGroupSuffix(String world, @NonNull String group) {
final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group); final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group);
return getGroupChatMeta(MetaType.SUFFIX, g, world); return getGroupChatMeta(ChatMetaType.SUFFIX, g, world);
} }
@Override @Override
public void setGroupSuffix(String world, @NonNull String group, @NonNull String suffix) { public void setGroupSuffix(String world, @NonNull String group, @NonNull String suffix) {
final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group); final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group);
setChatMeta(MetaType.SUFFIX, g, suffix, world); setChatMeta(ChatMetaType.SUFFIX, g, suffix, world);
} }
@Override @Override

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>3.1-SNAPSHOT</version> <version>3.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>3.1-SNAPSHOT</version> <version>3.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -43,6 +43,7 @@ import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.UuidCache; import me.lucko.luckperms.api.UuidCache;
import me.lucko.luckperms.api.context.ContextCalculator; import me.lucko.luckperms.api.context.ContextCalculator;
import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.api.delegates.MetaStackFactoryDelegate;
import me.lucko.luckperms.common.api.delegates.NodeFactoryDelegate; import me.lucko.luckperms.common.api.delegates.NodeFactoryDelegate;
import me.lucko.luckperms.common.api.delegates.UserDelegate; import me.lucko.luckperms.common.api.delegates.UserDelegate;
import me.lucko.luckperms.common.core.UserIdentifier; import me.lucko.luckperms.common.core.UserIdentifier;
@ -69,10 +70,14 @@ public class ApiProvider implements LuckPermsApi {
@Getter @Getter
private final EventFactory eventFactory; private final EventFactory eventFactory;
@Getter
private final MetaStackFactoryDelegate metaStackFactory;
public ApiProvider(LuckPermsPlugin plugin) { public ApiProvider(LuckPermsPlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
this.eventBus = new LuckPermsEventBus(plugin); this.eventBus = new LuckPermsEventBus(plugin);
this.eventFactory = new EventFactory(eventBus); this.eventFactory = new EventFactory(eventBus);
this.metaStackFactory = new MetaStackFactoryDelegate(plugin);
} }
@Override @Override
@ -82,7 +87,7 @@ public class ApiProvider implements LuckPermsApi {
@Override @Override
public double getApiVersion() { public double getApiVersion() {
return 3.1; return 3.2;
} }
@Override @Override

View File

@ -33,6 +33,7 @@ import com.google.common.base.Preconditions;
import me.lucko.luckperms.api.Group; import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.exceptions.ObjectLacksException;
@ -70,9 +71,14 @@ public final class GroupDelegate extends PermissionHolderDelegate implements Gro
return handle.inheritsGroup(cast(group)); return handle.inheritsGroup(cast(group));
} }
@Override
public boolean inheritsGroup(@NonNull Group group, @NonNull ContextSet contextSet) {
return handle.inheritsGroup(cast(group), contextSet);
}
@Override @Override
public boolean inheritsGroup(@NonNull Group group, @NonNull String server) { public boolean inheritsGroup(@NonNull Group group, @NonNull String server) {
return handle.inheritsGroup(((GroupDelegate) group).getHandle(), server); return handle.inheritsGroup(cast(group), server);
} }
@Override @Override

View File

@ -0,0 +1,64 @@
/*
* 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.common.api.delegates;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.api.metastacking.MetaStackElement;
import me.lucko.luckperms.api.metastacking.MetaStackFactory;
import me.lucko.luckperms.common.metastacking.definition.SimpleMetaStackDefinition;
import me.lucko.luckperms.common.metastacking.definition.StandardStackElements;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import java.util.List;
import java.util.Optional;
@AllArgsConstructor
public class MetaStackFactoryDelegate implements MetaStackFactory {
public final LuckPermsPlugin plugin;
@Override
public Optional<MetaStackElement> fromString(@NonNull String definition) {
return StandardStackElements.parseFromString(plugin, definition);
}
@Override
public List<MetaStackElement> fromStrings(@NonNull List<String> definitions) {
if (definitions.isEmpty()) {
return ImmutableList.of();
}
return StandardStackElements.parseList(plugin, definitions);
}
@Override
public MetaStackDefinition createDefinition(List<MetaStackElement> elements, String startSpacer, String middleSpacer, String endSpacer) {
return new SimpleMetaStackDefinition(elements, startSpacer, middleSpacer, endSpacer);
}
}

View File

@ -27,6 +27,7 @@ package me.lucko.luckperms.common.api.delegates;
import lombok.NonNull; import lombok.NonNull;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.Group; import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
@ -64,6 +65,11 @@ public class NodeFactoryDelegate implements me.lucko.luckperms.api.NodeFactory {
return NodeFactory.makeMetaNode(key, value); return NodeFactory.makeMetaNode(key, value);
} }
@Override
public Node.Builder makeChatMetaNode(@NonNull ChatMetaType type, int priority, @NonNull String value) {
return NodeFactory.makeChatMetaNode(type, priority, value);
}
@Override @Override
public Node.Builder makePrefixNode(int priority, @NonNull String prefix) { public Node.Builder makePrefixNode(int priority, @NonNull String prefix) {
return NodeFactory.makePrefixNode(priority, prefix); return NodeFactory.makePrefixNode(priority, prefix);

View File

@ -37,8 +37,10 @@ import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.PermissionHolder; import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.MutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.utils.ExtractedContexts; import me.lucko.luckperms.common.utils.ExtractedContexts;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.exceptions.ObjectLacksException;
@ -49,6 +51,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.function.Predicate;
import static me.lucko.luckperms.common.api.ApiUtils.checkTime; import static me.lucko.luckperms.common.api.ApiUtils.checkTime;
@ -64,6 +67,11 @@ public class PermissionHolderDelegate implements PermissionHolder {
return handle.getObjectName(); return handle.getObjectName();
} }
@Override
public String getFriendlyName() {
return handle.getFriendlyName();
}
@Override @Override
public SortedSet<? extends Node> getPermissions() { public SortedSet<? extends Node> getPermissions() {
return ImmutableSortedSet.copyOfSorted(handle.mergePermissionsToSortedSet()); return ImmutableSortedSet.copyOfSorted(handle.mergePermissionsToSortedSet());
@ -239,6 +247,19 @@ public class PermissionHolderDelegate implements PermissionHolder {
return handle.unsetTransientPermission(node); return handle.unsetTransientPermission(node);
} }
@Override
public void clearMatching(Predicate<Node> test) {
handle.removeIf(test);
if (handle instanceof User) {
handle.getPlugin().getUserManager().giveDefaultIfNeeded((User) handle, false);
}
}
@Override
public void clearMatchingTransient(Predicate<Node> test) {
handle.removeIfTransient(test);
}
@Override @Override
public void unsetPermission(@NonNull String node, @NonNull boolean temporary) throws ObjectLacksException { public void unsetPermission(@NonNull String node, @NonNull boolean temporary) throws ObjectLacksException {
handle.unsetPermission(NodeFactory.make(node, temporary)).throwException(); handle.unsetPermission(NodeFactory.make(node, temporary)).throwException();
@ -274,6 +295,11 @@ public class PermissionHolderDelegate implements PermissionHolder {
handle.clearNodes(); handle.clearNodes();
} }
@Override
public void clearNodes(@NonNull ContextSet contextSet) {
handle.clearNodes(contextSet);
}
@Override @Override
public void clearNodes(String server) { public void clearNodes(String server) {
MutableContextSet set = new MutableContextSet(); MutableContextSet set = new MutableContextSet();
@ -302,6 +328,11 @@ public class PermissionHolderDelegate implements PermissionHolder {
handle.clearParents(true); handle.clearParents(true);
} }
@Override
public void clearParents(@NonNull ContextSet contextSet) {
handle.clearParents(contextSet, true);
}
@Override @Override
public void clearParents(String server) { public void clearParents(String server) {
MutableContextSet set = new MutableContextSet(); MutableContextSet set = new MutableContextSet();
@ -330,6 +361,11 @@ public class PermissionHolderDelegate implements PermissionHolder {
handle.clearMeta(); handle.clearMeta();
} }
@Override
public void clearMeta(@NonNull ContextSet contextSet) {
handle.clearMeta(contextSet);
}
@Override @Override
public void clearMeta(String server) { public void clearMeta(String server) {
MutableContextSet set = new MutableContextSet(); MutableContextSet set = new MutableContextSet();

View File

@ -34,6 +34,7 @@ import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.User; import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.caching.UserData; import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.exceptions.ObjectLacksException;
@ -95,9 +96,13 @@ public final class UserDelegate extends PermissionHolderDelegate implements User
handle.getRefreshBuffer().requestDirectly(); handle.getRefreshBuffer().requestDirectly();
} }
@Override
public UserData getCachedData() {
return handle.getUserData();
}
@Override @Override
public Optional<UserData> getUserDataCache() { public Optional<UserData> getUserDataCache() {
// TODO Deprecate this and return a nonnull instance
return Optional.of(handle.getUserData()); return Optional.of(handle.getUserData());
} }
@ -111,14 +116,19 @@ public final class UserDelegate extends PermissionHolderDelegate implements User
return handle.inheritsGroup(GroupDelegate.cast(group)); return handle.inheritsGroup(GroupDelegate.cast(group));
} }
@Override
public boolean isInGroup(@NonNull Group group, @NonNull ContextSet contextSet) {
return handle.inheritsGroup(GroupDelegate.cast(group), contextSet);
}
@Override @Override
public boolean isInGroup(@NonNull Group group, @NonNull String server) { public boolean isInGroup(@NonNull Group group, @NonNull String server) {
return handle.inheritsGroup(((GroupDelegate) group).getHandle(), server); return handle.inheritsGroup(GroupDelegate.cast(group), server);
} }
@Override @Override
public boolean isInGroup(@NonNull Group group, @NonNull String server, @NonNull String world) { public boolean isInGroup(@NonNull Group group, @NonNull String server, @NonNull String world) {
return handle.inheritsGroup(((GroupDelegate) group).getHandle(), server, world); return handle.inheritsGroup(GroupDelegate.cast(group), server, world);
} }
@Override @Override

View File

@ -30,10 +30,11 @@ import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.ToString; import lombok.ToString;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.metastacking.GenericMetaStack;
import me.lucko.luckperms.common.metastacking.MetaStack; import me.lucko.luckperms.common.metastacking.MetaStack;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import java.util.Comparator; import java.util.Comparator;
@ -50,8 +51,8 @@ import java.util.TreeMap;
public class MetaAccumulator { public class MetaAccumulator {
public static MetaAccumulator makeFromConfig(LuckPermsPlugin plugin) { public static MetaAccumulator makeFromConfig(LuckPermsPlugin plugin) {
return new MetaAccumulator( return new MetaAccumulator(
plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS).newStack(MetaType.PREFIX), new GenericMetaStack(plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS), ChatMetaType.PREFIX),
plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS).newStack(MetaType.SUFFIX) new GenericMetaStack(plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS), ChatMetaType.SUFFIX)
); );
} }
@ -113,12 +114,12 @@ public class MetaAccumulator {
return this.meta; return this.meta;
} }
public Map<Integer, String> getChatMeta(MetaType type) { public Map<Integer, String> getChatMeta(ChatMetaType type) {
return type == MetaType.PREFIX ? prefixes : suffixes; return type == ChatMetaType.PREFIX ? prefixes : suffixes;
} }
public MetaStack getStack(MetaType type) { public MetaStack getStack(ChatMetaType type) {
return type == MetaType.PREFIX ? prefixStack : suffixStack; return type == ChatMetaType.PREFIX ? prefixStack : suffixStack;
} }
} }

View File

@ -32,6 +32,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedMap;
import me.lucko.luckperms.api.caching.MetaData; import me.lucko.luckperms.api.caching.MetaData;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.common.metastacking.MetaStack; import me.lucko.luckperms.common.metastacking.MetaStack;
import java.util.Map; import java.util.Map;
@ -94,4 +95,14 @@ public class MetaCache implements MetaData {
} }
} }
@Override
public MetaStackDefinition getPrefixStackDefinition() {
return prefixStack.getDefinition();
}
@Override
public MetaStackDefinition getSuffixStackDefinition() {
return suffixStack.getDefinition();
}
} }

View File

@ -1,67 +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.common.caching;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.metastacking.definition.MetaStackDefinition;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
@Getter
@ToString
@EqualsAndHashCode
public final class MetaContexts {
public static MetaContexts makeFromConfig(Contexts contexts, LuckPermsPlugin plugin) {
return new MetaContexts(
contexts,
plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS),
plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS)
);
}
private final Contexts contexts;
private final MetaStackDefinition prefixStackDefinition;
private final MetaStackDefinition suffixStackDefinition;
public MetaContexts(@NonNull Contexts contexts, @NonNull MetaStackDefinition prefixStackDefinition, @NonNull MetaStackDefinition suffixStackDefinition) {
this.contexts = contexts;
this.prefixStackDefinition = prefixStackDefinition;
this.suffixStackDefinition = suffixStackDefinition;
}
public MetaAccumulator newAccumulator() {
return new MetaAccumulator(
prefixStackDefinition.newStack(MetaType.PREFIX),
suffixStackDefinition.newStack(MetaType.SUFFIX)
);
}
}

View File

@ -33,11 +33,16 @@ import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache; import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.caching.MetaContexts;
import me.lucko.luckperms.api.caching.MetaData; import me.lucko.luckperms.api.caching.MetaData;
import me.lucko.luckperms.api.caching.PermissionData; import me.lucko.luckperms.api.caching.PermissionData;
import me.lucko.luckperms.api.caching.UserData; import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.metastacking.GenericMetaStack;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.ExtractedContexts; import me.lucko.luckperms.common.utils.ExtractedContexts;
import java.util.Set; import java.util.Set;
@ -79,7 +84,7 @@ public class UserCache implements UserData {
@Override @Override
public MetaCache reload(MetaContexts contexts, MetaCache oldData) { public MetaCache reload(MetaContexts contexts, MetaCache oldData) {
oldData.loadMeta(user.accumulateMeta(contexts.newAccumulator(), null, ExtractedContexts.generate(contexts.getContexts()))); oldData.loadMeta(user.accumulateMeta(newAccumulator(contexts), null, ExtractedContexts.generate(contexts.getContexts())));
return oldData; return oldData;
} }
}); });
@ -90,15 +95,16 @@ public class UserCache implements UserData {
} }
@Override @Override
public MetaData getMetaData(@NonNull Contexts contexts) {
// just create a MetaContexts instance using the values in the config
return getMetaData(MetaContexts.makeFromConfig(contexts, user.getPlugin()));
}
public MetaData getMetaData(@NonNull MetaContexts contexts) { public MetaData getMetaData(@NonNull MetaContexts contexts) {
return meta.get(contexts); return meta.get(contexts);
} }
@Override
public MetaData getMetaData(@NonNull Contexts contexts) {
// just create a MetaContexts instance using the values in the config
return getMetaData(makeFromMetaContextsConfig(contexts, user.getPlugin()));
}
@Override @Override
public PermissionCache calculatePermissions(@NonNull Contexts contexts) { public PermissionCache calculatePermissions(@NonNull Contexts contexts) {
PermissionCache data = new PermissionCache(contexts, user, user.getPlugin().getCalculatorFactory()); PermissionCache data = new PermissionCache(contexts, user, user.getPlugin().getCalculatorFactory());
@ -107,31 +113,33 @@ public class UserCache implements UserData {
} }
@Override @Override
public MetaCache calculateMeta(@NonNull Contexts contexts) {
// just create a MetaContexts instance using the values in the config
return calculateMeta(MetaContexts.makeFromConfig(contexts, user.getPlugin()));
}
public MetaCache calculateMeta(@NonNull MetaContexts contexts) { public MetaCache calculateMeta(@NonNull MetaContexts contexts) {
MetaCache data = new MetaCache(); MetaCache data = new MetaCache();
data.loadMeta(user.accumulateMeta(contexts.newAccumulator(), null, ExtractedContexts.generate(contexts.getContexts()))); data.loadMeta(user.accumulateMeta(newAccumulator(contexts), null, ExtractedContexts.generate(contexts.getContexts())));
return data; return data;
} }
@Override
public MetaCache calculateMeta(@NonNull Contexts contexts) {
// just create a MetaContexts instance using the values in the config
return calculateMeta(makeFromMetaContextsConfig(contexts, user.getPlugin()));
}
@Override @Override
public void recalculatePermissions(@NonNull Contexts contexts) { public void recalculatePermissions(@NonNull Contexts contexts) {
permission.refresh(contexts); permission.refresh(contexts);
} }
@Override @Override
public void recalculateMeta(@NonNull Contexts contexts) {
recalculateMeta(MetaContexts.makeFromConfig(contexts, user.getPlugin()));
}
public void recalculateMeta(@NonNull MetaContexts contexts) { public void recalculateMeta(@NonNull MetaContexts contexts) {
meta.refresh(contexts); meta.refresh(contexts);
} }
@Override
public void recalculateMeta(@NonNull Contexts contexts) {
recalculateMeta(makeFromMetaContextsConfig(contexts, user.getPlugin()));
}
@Override @Override
public void recalculatePermissions() { public void recalculatePermissions() {
Set<Contexts> keys = ImmutableSet.copyOf(permission.asMap().keySet()); Set<Contexts> keys = ImmutableSet.copyOf(permission.asMap().keySet());
@ -152,7 +160,7 @@ public class UserCache implements UserData {
@Override @Override
public void preCalculate(@NonNull Contexts contexts) { public void preCalculate(@NonNull Contexts contexts) {
permission.get(contexts); permission.get(contexts);
meta.get(MetaContexts.makeFromConfig(contexts, user.getPlugin())); meta.get(makeFromMetaContextsConfig(contexts, user.getPlugin()));
} }
public void invalidateCache() { public void invalidateCache() {
@ -175,4 +183,19 @@ public class UserCache implements UserData {
meta.invalidateAll(); meta.invalidateAll();
} }
private static MetaContexts makeFromMetaContextsConfig(Contexts contexts, LuckPermsPlugin plugin) {
return new MetaContexts(
contexts,
plugin.getConfiguration().get(ConfigKeys.PREFIX_FORMATTING_OPTIONS),
plugin.getConfiguration().get(ConfigKeys.SUFFIX_FORMATTING_OPTIONS)
);
}
private static MetaAccumulator newAccumulator(MetaContexts contexts) {
return new MetaAccumulator(
new GenericMetaStack(contexts.getPrefixStackDefinition(), ChatMetaType.PREFIX),
new GenericMetaStack(contexts.getSuffixStackDefinition(), ChatMetaType.SUFFIX)
);
}
} }

View File

@ -27,10 +27,10 @@ package me.lucko.luckperms.common.commands.impl.generic.meta;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.common.commands.abstraction.SharedMainCommand; import me.lucko.luckperms.common.commands.abstraction.SharedMainCommand;
import me.lucko.luckperms.common.commands.abstraction.SharedSubCommand; import me.lucko.luckperms.common.commands.abstraction.SharedSubCommand;
import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.metastacking.MetaType;
public class CommandMeta<T extends PermissionHolder> extends SharedMainCommand<T> { public class CommandMeta<T extends PermissionHolder> extends SharedMainCommand<T> {
public CommandMeta(boolean user) { public CommandMeta(boolean user) {
@ -40,14 +40,14 @@ public class CommandMeta<T extends PermissionHolder> extends SharedMainCommand<T
.add(new MetaUnset()) .add(new MetaUnset())
.add(new MetaSetTemp()) .add(new MetaSetTemp())
.add(new MetaUnsetTemp()) .add(new MetaUnsetTemp())
.add(new MetaAddChatMeta(MetaType.PREFIX)) .add(new MetaAddChatMeta(ChatMetaType.PREFIX))
.add(new MetaAddChatMeta(MetaType.SUFFIX)) .add(new MetaAddChatMeta(ChatMetaType.SUFFIX))
.add(new MetaRemoveChatMeta(MetaType.PREFIX)) .add(new MetaRemoveChatMeta(ChatMetaType.PREFIX))
.add(new MetaRemoveChatMeta(MetaType.SUFFIX)) .add(new MetaRemoveChatMeta(ChatMetaType.SUFFIX))
.add(new MetaAddTempChatMeta(MetaType.PREFIX)) .add(new MetaAddTempChatMeta(ChatMetaType.PREFIX))
.add(new MetaAddTempChatMeta(MetaType.SUFFIX)) .add(new MetaAddTempChatMeta(ChatMetaType.SUFFIX))
.add(new MetaRemoveTempChatMeta(MetaType.PREFIX)) .add(new MetaRemoveTempChatMeta(ChatMetaType.PREFIX))
.add(new MetaRemoveTempChatMeta(MetaType.SUFFIX)) .add(new MetaRemoveTempChatMeta(ChatMetaType.SUFFIX))
.add(new MetaClear()) .add(new MetaClear())
.build()); .build());
} }

View File

@ -25,6 +25,7 @@
package me.lucko.luckperms.common.commands.impl.generic.meta; package me.lucko.luckperms.common.commands.impl.generic.meta;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.DataMutateResult;
import me.lucko.luckperms.api.context.MutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.commands.Arg; import me.lucko.luckperms.common.commands.Arg;
@ -39,7 +40,6 @@ import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry; import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
@ -47,13 +47,13 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class MetaAddChatMeta extends SharedSubCommand { public class MetaAddChatMeta extends SharedSubCommand {
private final MetaType type; private final ChatMetaType type;
public MetaAddChatMeta(MetaType type) { public MetaAddChatMeta(ChatMetaType type) {
super("add" + type.name().toLowerCase(), super("add" + type.name().toLowerCase(),
"Adds a " + type.name().toLowerCase(), "Adds a " + type.name().toLowerCase(),
type == MetaType.PREFIX ? Permission.USER_META_ADDPREFIX : Permission.USER_META_ADDSUFFIX, type == ChatMetaType.PREFIX ? Permission.USER_META_ADDPREFIX : Permission.USER_META_ADDSUFFIX,
type == MetaType.PREFIX ? Permission.GROUP_META_ADDPREFIX : Permission.GROUP_META_ADDSUFFIX, type == ChatMetaType.PREFIX ? Permission.GROUP_META_ADDPREFIX : Permission.GROUP_META_ADDSUFFIX,
Predicates.inRange(0, 1), Predicates.inRange(0, 1),
Arg.list( Arg.list(
Arg.create("priority", true, "the priority to add the " + type.name().toLowerCase() + " at"), Arg.create("priority", true, "the priority to add the " + type.name().toLowerCase() + " at"),

View File

@ -25,6 +25,7 @@
package me.lucko.luckperms.common.commands.impl.generic.meta; package me.lucko.luckperms.common.commands.impl.generic.meta;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.DataMutateResult;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.context.MutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet;
@ -42,7 +43,6 @@ import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.TemporaryModifier; import me.lucko.luckperms.common.core.TemporaryModifier;
import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry; import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.DateUtil; import me.lucko.luckperms.common.utils.DateUtil;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
@ -52,13 +52,13 @@ import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class MetaAddTempChatMeta extends SharedSubCommand { public class MetaAddTempChatMeta extends SharedSubCommand {
private final MetaType type; private final ChatMetaType type;
public MetaAddTempChatMeta(MetaType type) { public MetaAddTempChatMeta(ChatMetaType type) {
super("addtemp" + type.name().toLowerCase(), super("addtemp" + type.name().toLowerCase(),
"Adds a " + type.name().toLowerCase() + " temporarily", "Adds a " + type.name().toLowerCase() + " temporarily",
type == MetaType.PREFIX ? Permission.USER_META_ADDTEMP_PREFIX : Permission.USER_META_ADDTEMP_SUFFIX, type == ChatMetaType.PREFIX ? Permission.USER_META_ADDTEMP_PREFIX : Permission.USER_META_ADDTEMP_SUFFIX,
type == MetaType.PREFIX ? Permission.GROUP_META_ADDTEMP_PREFIX : Permission.GROUP_META_ADDTEMP_SUFFIX, type == ChatMetaType.PREFIX ? Permission.GROUP_META_ADDTEMP_PREFIX : Permission.GROUP_META_ADDTEMP_SUFFIX,
Predicates.inRange(0, 2), Predicates.inRange(0, 2),
Arg.list( Arg.list(
Arg.create("priority", true, "the priority to add the " + type.name().toLowerCase() + " at"), Arg.create("priority", true, "the priority to add the " + type.name().toLowerCase() + " at"),

View File

@ -25,6 +25,7 @@
package me.lucko.luckperms.common.commands.impl.generic.meta; package me.lucko.luckperms.common.commands.impl.generic.meta;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.DataMutateResult;
import me.lucko.luckperms.api.context.MutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.commands.Arg; import me.lucko.luckperms.common.commands.Arg;
@ -39,7 +40,6 @@ import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry; import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
@ -47,13 +47,13 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class MetaRemoveChatMeta extends SharedSubCommand { public class MetaRemoveChatMeta extends SharedSubCommand {
private final MetaType type; private final ChatMetaType type;
public MetaRemoveChatMeta(MetaType type) { public MetaRemoveChatMeta(ChatMetaType type) {
super("remove" + type.name().toLowerCase(), super("remove" + type.name().toLowerCase(),
"Removes a " + type.name().toLowerCase(), "Removes a " + type.name().toLowerCase(),
type == MetaType.PREFIX ? Permission.USER_META_REMOVEPREFIX : Permission.USER_META_REMOVESUFFIX, type == ChatMetaType.PREFIX ? Permission.USER_META_REMOVEPREFIX : Permission.USER_META_REMOVESUFFIX,
type == MetaType.PREFIX ? Permission.GROUP_META_REMOVEPREFIX : Permission.GROUP_META_REMOVESUFFIX, type == ChatMetaType.PREFIX ? Permission.GROUP_META_REMOVEPREFIX : Permission.GROUP_META_REMOVESUFFIX,
Predicates.is(0), Predicates.is(0),
Arg.list( Arg.list(
Arg.create("priority", true, "the priority to remove the " + type.name().toLowerCase() + " at"), Arg.create("priority", true, "the priority to remove the " + type.name().toLowerCase() + " at"),

View File

@ -25,6 +25,7 @@
package me.lucko.luckperms.common.commands.impl.generic.meta; package me.lucko.luckperms.common.commands.impl.generic.meta;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.DataMutateResult;
import me.lucko.luckperms.api.context.MutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.commands.Arg; import me.lucko.luckperms.common.commands.Arg;
@ -39,7 +40,6 @@ import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry; import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
@ -47,13 +47,13 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class MetaRemoveTempChatMeta extends SharedSubCommand { public class MetaRemoveTempChatMeta extends SharedSubCommand {
private final MetaType type; private final ChatMetaType type;
public MetaRemoveTempChatMeta(MetaType type) { public MetaRemoveTempChatMeta(ChatMetaType type) {
super("removetemp" +type.name().toLowerCase(), super("removetemp" +type.name().toLowerCase(),
"Removes a temporary " + type.name().toLowerCase(), "Removes a temporary " + type.name().toLowerCase(),
type == MetaType.PREFIX ? Permission.USER_META_REMOVETEMP_PREFIX : Permission.USER_META_REMOVETEMP_SUFFIX, type == ChatMetaType.PREFIX ? Permission.USER_META_REMOVETEMP_PREFIX : Permission.USER_META_REMOVETEMP_SUFFIX,
type == MetaType.PREFIX ? Permission.GROUP_META_REMOVETEMP_PREFIX : Permission.GROUP_META_REMOVETEMP_SUFFIX, type == ChatMetaType.PREFIX ? Permission.GROUP_META_REMOVETEMP_PREFIX : Permission.GROUP_META_REMOVETEMP_SUFFIX,
Predicates.is(0), Predicates.is(0),
Arg.list( Arg.list(
Arg.create("priority", true, "the priority to remove the " + type.name().toLowerCase() + " at"), Arg.create("priority", true, "the priority to remove the " + type.name().toLowerCase() + " at"),

View File

@ -30,6 +30,7 @@ import lombok.experimental.UtilityClass;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.common.config.keys.AbstractKey; import me.lucko.luckperms.common.config.keys.AbstractKey;
import me.lucko.luckperms.common.config.keys.BooleanKey; import me.lucko.luckperms.common.config.keys.BooleanKey;
import me.lucko.luckperms.common.config.keys.EnduringKey; import me.lucko.luckperms.common.config.keys.EnduringKey;
@ -41,7 +42,7 @@ import me.lucko.luckperms.common.config.keys.StringKey;
import me.lucko.luckperms.common.core.TemporaryModifier; import me.lucko.luckperms.common.core.TemporaryModifier;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.defaults.Rule; import me.lucko.luckperms.common.defaults.Rule;
import me.lucko.luckperms.common.metastacking.definition.MetaStackDefinition; import me.lucko.luckperms.common.metastacking.definition.SimpleMetaStackDefinition;
import me.lucko.luckperms.common.metastacking.definition.StandardStackElements; import me.lucko.luckperms.common.metastacking.definition.StandardStackElements;
import me.lucko.luckperms.common.primarygroup.AllParentsByWeightHolder; import me.lucko.luckperms.common.primarygroup.AllParentsByWeightHolder;
import me.lucko.luckperms.common.primarygroup.ParentsByWeightHolder; import me.lucko.luckperms.common.primarygroup.ParentsByWeightHolder;
@ -227,7 +228,7 @@ public class ConfigKeys {
String middleSpacer = l.getString("meta-formatting.prefix.middle-spacer", " "); String middleSpacer = l.getString("meta-formatting.prefix.middle-spacer", " ");
String endSpacer = l.getString("meta-formatting.prefix.end-spacer", ""); String endSpacer = l.getString("meta-formatting.prefix.end-spacer", "");
return MetaStackDefinition.create(StandardStackElements.parseList(l.getPlugin(), format), startSpacer, middleSpacer, endSpacer); return new SimpleMetaStackDefinition(StandardStackElements.parseList(l.getPlugin(), format), startSpacer, middleSpacer, endSpacer);
}); });
/** /**
@ -242,7 +243,7 @@ public class ConfigKeys {
String middleSpacer = l.getString("meta-formatting.suffix.middle-spacer", " "); String middleSpacer = l.getString("meta-formatting.suffix.middle-spacer", " ");
String endSpacer = l.getString("meta-formatting.suffix.end-spacer", ""); String endSpacer = l.getString("meta-formatting.suffix.end-spacer", "");
return MetaStackDefinition.create(StandardStackElements.parseList(l.getPlugin(), format), startSpacer, middleSpacer, endSpacer); return new SimpleMetaStackDefinition(StandardStackElements.parseList(l.getPlugin(), format), startSpacer, middleSpacer, endSpacer);
}); });
/** /**

View File

@ -31,11 +31,11 @@ import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache; import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.MetaUtils; import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.context.ContextSet; import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.utils.PatternCache; import me.lucko.luckperms.common.utils.PatternCache;
import java.util.List; import java.util.List;
@ -123,8 +123,8 @@ public class NodeFactory {
return new NodeBuilder("meta." + MetaUtils.escapeCharacters(key) + "." + MetaUtils.escapeCharacters(value)); return new NodeBuilder("meta." + MetaUtils.escapeCharacters(key) + "." + MetaUtils.escapeCharacters(value));
} }
public static Node.Builder makeChatMetaNode(MetaType type, int priority, String s) { public static Node.Builder makeChatMetaNode(ChatMetaType type, int priority, String s) {
return type == MetaType.PREFIX ? makePrefixNode(priority, s) : makeSuffixNode(priority, s); return type == ChatMetaType.PREFIX ? makePrefixNode(priority, s) : makeSuffixNode(priority, s);
} }
public static Node.Builder makePrefixNode(int priority, String prefix) { public static Node.Builder makePrefixNode(int priority, String prefix) {

View File

@ -36,7 +36,6 @@ import com.google.common.collect.Maps;
import me.lucko.luckperms.api.MetaUtils; import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.Node; 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.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.api.context.MutableContextSet; import me.lucko.luckperms.api.context.MutableContextSet;
@ -265,16 +264,6 @@ public final class ImmutableNode implements Node {
this.optWorld = Optional.ofNullable(this.world); this.optWorld = Optional.ofNullable(this.world);
} }
@Override
public Tristate getTristate() {
return Tristate.fromBoolean(value);
}
@Override
public boolean isNegated() {
return !value;
}
@Override @Override
public Optional<String> getServer() { public Optional<String> getServer() {
return optServer; return optServer;
@ -310,11 +299,6 @@ public final class ImmutableNode implements Node {
return expireAt != 0L; return expireAt != 0L;
} }
@Override
public boolean isPermanent() {
return !isTemporary();
}
@Override @Override
public long getExpiryUnixTime() { public long getExpiryUnixTime() {
Preconditions.checkState(isTemporary(), "Node does not have an expiry time."); Preconditions.checkState(isTemporary(), "Node does not have an expiry time.");

View File

@ -1062,6 +1062,10 @@ public abstract class PermissionHolder {
return group.getName().equalsIgnoreCase(this.getObjectName()) || hasPermission("group." + group.getName(), true); return group.getName().equalsIgnoreCase(this.getObjectName()) || hasPermission("group." + group.getName(), true);
} }
public boolean inheritsGroup(Group group, ContextSet contextSet) {
return group.getName().equalsIgnoreCase(this.getObjectName()) || hasPermission(NodeFactory.newBuilder("group." + group.getName()).withExtraContext(contextSet).build()).asBoolean();
}
public boolean inheritsGroup(Group group, String server) { public boolean inheritsGroup(Group group, String server) {
return group.getName().equalsIgnoreCase(this.getObjectName()) || hasPermission("group." + group.getName(), true, server); return group.getName().equalsIgnoreCase(this.getObjectName()) || hasPermission("group." + group.getName(), true, server);
} }

View File

@ -28,8 +28,9 @@ package me.lucko.luckperms.common.metastacking;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.common.metastacking.definition.MetaStackDefinition; import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.common.utils.ImmutableCollectors;
import java.util.ArrayList; import java.util.ArrayList;
@ -39,12 +40,12 @@ import java.util.List;
public class GenericMetaStack implements MetaStack { public class GenericMetaStack implements MetaStack {
private final MetaStackDefinition definition; private final MetaStackDefinition definition;
private final MetaType targetType; private final ChatMetaType targetType;
@Getter(AccessLevel.NONE) @Getter(AccessLevel.NONE)
private final List<MetaStackEntry> entries; private final List<MetaStackEntry> entries;
public GenericMetaStack(MetaStackDefinition definition, MetaType targetType) { public GenericMetaStack(MetaStackDefinition definition, ChatMetaType targetType) {
this.definition = definition; this.definition = definition;
this.targetType = targetType; this.targetType = targetType;
this.entries = definition.getElements().stream() this.entries = definition.getElements().stream()

View File

@ -25,14 +25,15 @@
package me.lucko.luckperms.common.metastacking; package me.lucko.luckperms.common.metastacking;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.common.metastacking.definition.MetaStackDefinition; import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
public interface MetaStack { public interface MetaStack {
MetaStackDefinition getDefinition(); MetaStackDefinition getDefinition();
MetaType getTargetType(); ChatMetaType getTargetType();
String toFormattedString(); String toFormattedString();

View File

@ -26,7 +26,7 @@
package me.lucko.luckperms.common.metastacking; package me.lucko.luckperms.common.metastacking;
import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.common.metastacking.definition.MetaStackElement; import me.lucko.luckperms.api.metastacking.MetaStackElement;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;

View File

@ -29,19 +29,20 @@ import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.common.metastacking.definition.MetaStackElement; import me.lucko.luckperms.api.metastacking.MetaStackElement;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@Getter @Getter
@RequiredArgsConstructor @RequiredArgsConstructor
public class SimpleMetaStackEntry implements MetaStackEntry { class SimpleMetaStackEntry implements MetaStackEntry {
private final MetaStack parentStack; private final MetaStack parentStack;
private final MetaStackElement element; private final MetaStackElement element;
private final MetaType type; private final ChatMetaType type;
@Getter(AccessLevel.NONE) @Getter(AccessLevel.NONE)
private Map.Entry<Integer, String> current = null; private Map.Entry<Integer, String> current = null;

View File

@ -32,12 +32,15 @@ import lombok.ToString;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.api.metastacking.MetaStackElement;
import java.util.List; import java.util.List;
@Getter @Getter
@EqualsAndHashCode @EqualsAndHashCode
@ToString @ToString
final class SimpleMetaStackDefinition implements MetaStackDefinition { public final class SimpleMetaStackDefinition implements MetaStackDefinition {
private final List<MetaStackElement> elements; private final List<MetaStackElement> elements;
private final String startSpacer; private final String startSpacer;

View File

@ -30,9 +30,10 @@ import lombok.RequiredArgsConstructor;
import lombok.ToString; import lombok.ToString;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.metastacking.MetaStackElement;
import me.lucko.luckperms.common.core.model.Track; import me.lucko.luckperms.common.core.model.Track;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.ImmutableCollectors; import me.lucko.luckperms.common.utils.ImmutableCollectors;
@ -167,7 +168,7 @@ public class StandardStackElements {
@ToString @ToString
private static final class HighestPriority implements MetaStackElement { private static final class HighestPriority implements MetaStackElement {
@Override @Override
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) { public boolean shouldAccumulate(LocalizedNode node, ChatMetaType type, Map.Entry<Integer, String> current) {
if (type.shouldIgnore(node)) { if (type.shouldIgnore(node)) {
return false; return false;
} }
@ -180,7 +181,7 @@ public class StandardStackElements {
@ToString @ToString
private static final class HighestPriorityOwn implements MetaStackElement { private static final class HighestPriorityOwn implements MetaStackElement {
@Override @Override
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) { public boolean shouldAccumulate(LocalizedNode node, ChatMetaType type, Map.Entry<Integer, String> current) {
if (type.shouldIgnore(node)) { if (type.shouldIgnore(node)) {
return false; return false;
} }
@ -202,7 +203,7 @@ public class StandardStackElements {
private final String trackName; private final String trackName;
@Override @Override
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) { public boolean shouldAccumulate(LocalizedNode node, ChatMetaType type, Map.Entry<Integer, String> current) {
if (type.shouldIgnore(node)) { if (type.shouldIgnore(node)) {
return false; return false;
} }
@ -220,7 +221,7 @@ public class StandardStackElements {
private final String trackName; private final String trackName;
@Override @Override
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) { public boolean shouldAccumulate(LocalizedNode node, ChatMetaType type, Map.Entry<Integer, String> current) {
if (type.shouldIgnore(node)) { if (type.shouldIgnore(node)) {
return false; return false;
} }
@ -233,7 +234,7 @@ public class StandardStackElements {
@ToString @ToString
private static final class LowestPriority implements MetaStackElement { private static final class LowestPriority implements MetaStackElement {
@Override @Override
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) { public boolean shouldAccumulate(LocalizedNode node, ChatMetaType type, Map.Entry<Integer, String> current) {
if (type.shouldIgnore(node)) { if (type.shouldIgnore(node)) {
return false; return false;
} }
@ -246,7 +247,7 @@ public class StandardStackElements {
@ToString @ToString
private static final class LowestPriorityOwn implements MetaStackElement { private static final class LowestPriorityOwn implements MetaStackElement {
@Override @Override
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) { public boolean shouldAccumulate(LocalizedNode node, ChatMetaType type, Map.Entry<Integer, String> current) {
if (type.shouldIgnore(node)) { if (type.shouldIgnore(node)) {
return false; return false;
} }
@ -268,7 +269,7 @@ public class StandardStackElements {
private final String trackName; private final String trackName;
@Override @Override
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) { public boolean shouldAccumulate(LocalizedNode node, ChatMetaType type, Map.Entry<Integer, String> current) {
if (type.shouldIgnore(node)) { if (type.shouldIgnore(node)) {
return false; return false;
} }
@ -286,7 +287,7 @@ public class StandardStackElements {
private final String trackName; private final String trackName;
@Override @Override
public boolean shouldAccumulate(LocalizedNode node, MetaType type, Map.Entry<Integer, String> current) { public boolean shouldAccumulate(LocalizedNode node, ChatMetaType type, Map.Entry<Integer, String> current) {
if (type.shouldIgnore(node)) { if (type.shouldIgnore(node)) {
return false; return false;
} }

View File

@ -6,7 +6,7 @@
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<version>3.1-SNAPSHOT</version> <version>3.2-SNAPSHOT</version>
<modules> <modules>
<module>api</module> <module>api</module>
@ -44,7 +44,7 @@
<maven.test.skip>true</maven.test.skip> <maven.test.skip>true</maven.test.skip>
<!-- Manually entered release version --> <!-- Manually entered release version -->
<release.version>3.1</release.version> <release.version>3.2</release.version>
<!-- Get how many commits have been made since the last tag (the previous release) --> <!-- Get how many commits have been made since the last tag (the previous release) -->
<patch.version>${git.closest.tag.commit.count}</patch.version> <patch.version>${git.closest.tag.commit.count}</patch.version>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>3.1-SNAPSHOT</version> <version>3.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -31,13 +31,13 @@ import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache; import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.LocalizedNode; import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ImmutableContextSet; import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.common.caching.MetaAccumulator; import me.lucko.luckperms.common.caching.MetaAccumulator;
import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.utils.ExtractedContexts; import me.lucko.luckperms.common.utils.ExtractedContexts;
import me.lucko.luckperms.sponge.LPSpongePlugin; import me.lucko.luckperms.sponge.LPSpongePlugin;
import me.lucko.luckperms.sponge.service.LuckPermsService; import me.lucko.luckperms.sponge.service.LuckPermsService;
@ -198,10 +198,10 @@ public class SpongeGroup extends Group {
try (Timing ignored = plugin.getService().getPlugin().getTimings().time(LPTiming.GROUP_GET_OPTION)) { try (Timing ignored = plugin.getService().getPlugin().getTimings().time(LPTiming.GROUP_GET_OPTION)) {
Optional<String> option; Optional<String> option;
if (s.equalsIgnoreCase("prefix")) { if (s.equalsIgnoreCase("prefix")) {
option = getChatMeta(contexts, MetaType.PREFIX); option = getChatMeta(contexts, ChatMetaType.PREFIX);
} else if (s.equalsIgnoreCase("suffix")) { } else if (s.equalsIgnoreCase("suffix")) {
option = getChatMeta(contexts, MetaType.SUFFIX); option = getChatMeta(contexts, ChatMetaType.SUFFIX);
} else { } else {
option = getMeta(contexts, s); option = getMeta(contexts, s);
@ -227,7 +227,7 @@ public class SpongeGroup extends Group {
} }
} }
private Optional<String> getChatMeta(ImmutableContextSet contexts, MetaType type) { private Optional<String> getChatMeta(ImmutableContextSet contexts, ChatMetaType type) {
MetaAccumulator metaAccumulator = parent.accumulateMeta(null, null, ExtractedContexts.generate(plugin.getService().calculateContexts(contexts))); MetaAccumulator metaAccumulator = parent.accumulateMeta(null, null, ExtractedContexts.generate(plugin.getService().calculateContexts(contexts)));
return Optional.ofNullable(metaAccumulator.getStack(type).toFormattedString()); return Optional.ofNullable(metaAccumulator.getStack(type).toFormattedString());
} }

View File

@ -32,6 +32,7 @@ import lombok.NonNull;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.DataMutateResult; import me.lucko.luckperms.api.DataMutateResult;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.Tristate; import me.lucko.luckperms.api.Tristate;
@ -41,7 +42,6 @@ import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.metastacking.MetaType;
import me.lucko.luckperms.common.utils.ExtractedContexts; import me.lucko.luckperms.common.utils.ExtractedContexts;
import me.lucko.luckperms.sponge.service.model.LPSubject; import me.lucko.luckperms.sponge.service.model.LPSubject;
import me.lucko.luckperms.sponge.service.model.LPSubjectData; import me.lucko.luckperms.sponge.service.model.LPSubjectData;
@ -370,7 +370,7 @@ public class LuckPermsSubjectData implements LPSubjectData {
try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_OPTION)) { try (Timing i = service.getPlugin().getTimings().time(LPTiming.LP_SUBJECT_SET_OPTION)) {
if (key.equalsIgnoreCase("prefix") || key.equalsIgnoreCase("suffix")) { if (key.equalsIgnoreCase("prefix") || key.equalsIgnoreCase("suffix")) {
// special handling. // special handling.
MetaType type = MetaType.valueOf(key.toUpperCase()); ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase());
// remove all prefixes/suffixes from the user // remove all prefixes/suffixes from the user
List<Node> toRemove = streamNodes(enduring) List<Node> toRemove = streamNodes(enduring)