mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-09-09 20:38:07 +02:00
Add node equality predicates, and provide way to determine hasPermission behaviour using them (#782)
This commit is contained in:
parent
b1fa4263ed
commit
736105cc12
@ -318,39 +318,81 @@ public interface Node extends Map.Entry<String, Boolean> {
|
||||
Map.Entry<Integer, String> getSuffix() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Checks if this Node is equal to another node
|
||||
* Returns if this Node is equal to another node
|
||||
*
|
||||
* @param obj the other node
|
||||
* @return true if this node is equal to the other provided
|
||||
* @see #equalsIgnoringValue(Node) for a less strict implementation of this method
|
||||
* @see StandardNodeEquality#EXACT
|
||||
*/
|
||||
@Override
|
||||
boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the value
|
||||
* Returns if this Node is equal to another node as defined by the given
|
||||
* {@link StandardNodeEquality} predicate.
|
||||
*
|
||||
* @param other the other node
|
||||
* @param equalityPredicate the predicate
|
||||
* @return true if this node is considered equal
|
||||
* @since 4.1
|
||||
*/
|
||||
boolean standardEquals(Node other, StandardNodeEquality equalityPredicate);
|
||||
|
||||
/**
|
||||
* Returns if this Node is equal to another node as defined by the given
|
||||
* {@link NodeEqualityPredicate}.
|
||||
*
|
||||
* @param other the other node
|
||||
* @param equalityPredicate the predicate
|
||||
* @return true if this node is considered equal
|
||||
* @since 4.1
|
||||
*/
|
||||
default boolean equals(Node other, NodeEqualityPredicate equalityPredicate) {
|
||||
return equalityPredicate.areEqual(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the
|
||||
* value.
|
||||
*
|
||||
* @param other the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
* @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)}
|
||||
* @see StandardNodeEquality#IGNORE_VALUE
|
||||
*/
|
||||
boolean equalsIgnoringValue(@Nonnull Node other);
|
||||
@Deprecated
|
||||
default boolean equalsIgnoringValue(@Nonnull Node other) {
|
||||
return equals(other, StandardNodeEquality.IGNORE_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the expiry time or value
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the
|
||||
* expiry time or value.
|
||||
*
|
||||
* @param other the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
* @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)}
|
||||
* @see StandardNodeEquality#IGNORE_EXPIRY_TIME_AND_VALUE
|
||||
*/
|
||||
boolean almostEquals(@Nonnull Node other);
|
||||
@Deprecated
|
||||
default boolean almostEquals(@Nonnull Node other) {
|
||||
return equals(other, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the value or if the node is temporary
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the
|
||||
* value or if the node is temporary.
|
||||
*
|
||||
* @param other the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
* @since 2.8
|
||||
* @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)}
|
||||
* @see StandardNodeEquality#IGNORE_VALUE_OR_IF_TEMPORARY
|
||||
*/
|
||||
boolean equalsIgnoringValueOrTemp(@Nonnull Node other);
|
||||
@Deprecated
|
||||
default boolean equalsIgnoringValueOrTemp(@Nonnull Node other) {
|
||||
return equals(other, StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Node instance
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A rule for determining if two nodes are equal.
|
||||
*
|
||||
* <p>Generally, individual instances of this interface should fulfil the same
|
||||
* requirements as the {@link Object#equals(Object)} contract.</p>
|
||||
*
|
||||
* <p>Some standard implementations are provided by
|
||||
* {@link StandardNodeEquality}.</p>
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface NodeEqualityPredicate {
|
||||
|
||||
/**
|
||||
* Returns if the two nodes are equal
|
||||
*
|
||||
* @param o1 the first node
|
||||
* @param o2 the second node
|
||||
* @return true if equal
|
||||
*/
|
||||
boolean areEqual(@Nonnull Node o1, @Nonnull Node o2);
|
||||
|
||||
}
|
@ -271,6 +271,42 @@ public interface PermissionHolder {
|
||||
*/
|
||||
void auditTemporaryPermissions();
|
||||
|
||||
/**
|
||||
* Checks to see if the object has a certain permission
|
||||
*
|
||||
* @param node the node to check for
|
||||
* @param equalityPredicate how to determine if a node matches
|
||||
* @return a Tristate for the holders permission status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 4.1
|
||||
*/
|
||||
@Nonnull
|
||||
Tristate hasPermission(@Nonnull Node node, @Nonnull NodeEqualityPredicate equalityPredicate);
|
||||
|
||||
/**
|
||||
* Checks to see if the object has a certain permission
|
||||
*
|
||||
* @param node the node to check for
|
||||
* @param equalityPredicate how to determine if a node matches
|
||||
* @return a Tristate for the holders permission status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 4.1
|
||||
*/
|
||||
@Nonnull
|
||||
Tristate hasTransientPermission(@Nonnull Node node, @Nonnull NodeEqualityPredicate equalityPredicate);
|
||||
|
||||
/**
|
||||
* Checks to see if the object inherits a certain permission
|
||||
*
|
||||
* @param node the node to check for
|
||||
* @param equalityPredicate how to determine if a node matches
|
||||
* @return a Tristate for the holders inheritance status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 4.1
|
||||
*/
|
||||
@Nonnull
|
||||
Tristate inheritsPermission(@Nonnull Node node, @Nonnull NodeEqualityPredicate equalityPredicate);
|
||||
|
||||
/**
|
||||
* Checks to see if the object has a certain permission
|
||||
*
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Standard {@link NodeEqualityPredicate}s.
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
public enum StandardNodeEquality implements NodeEqualityPredicate {
|
||||
|
||||
/**
|
||||
* Represents an exact match.
|
||||
*
|
||||
* <p>All attributes of the nodes must match for them to be considered
|
||||
* equal.</p>
|
||||
*/
|
||||
EXACT,
|
||||
|
||||
/**
|
||||
* All attributes must match, except for
|
||||
* {@link Node#getValuePrimitive() value}, which is ignored.
|
||||
*/
|
||||
IGNORE_VALUE,
|
||||
|
||||
/**
|
||||
* All attributes must match, except for the
|
||||
* {@link Node#getExpiry() expiry time}, which is ignored.
|
||||
*
|
||||
* <p>Note that with this setting, whether a node is temporary or not is
|
||||
* still considered.</p>
|
||||
*/
|
||||
IGNORE_EXPIRY_TIME,
|
||||
|
||||
/**
|
||||
* All attributes must match, except for
|
||||
* {@link Node#getValuePrimitive() value} and the
|
||||
* {@link Node#getExpiry() expiry time}, which are ignored.
|
||||
*/
|
||||
IGNORE_EXPIRY_TIME_AND_VALUE,
|
||||
|
||||
/**
|
||||
* All attributes must match, except for
|
||||
* {@link Node#getValuePrimitive() value} and the if the node is
|
||||
* {@link Node#isTemporary() temporary}, which are ignored.
|
||||
*/
|
||||
IGNORE_VALUE_OR_IF_TEMPORARY;
|
||||
|
||||
@Override
|
||||
public boolean areEqual(@Nonnull Node o1, @Nonnull Node o2) {
|
||||
return o1.standardEquals(o2, this);
|
||||
}
|
||||
}
|
@ -35,6 +35,7 @@ import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.DataMutateResult;
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.NodeEqualityPredicate;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.caching.CachedData;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
@ -158,18 +159,42 @@ public class ApiPermissionHolder implements me.lucko.luckperms.api.PermissionHol
|
||||
return ImmutableMap.copyOf(this.handle.exportNodesAndShorthand(contexts, lowerCase));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Tristate hasPermission(@Nonnull Node node, @Nonnull NodeEqualityPredicate equalityPredicate) {
|
||||
Objects.requireNonNull(node, "node");
|
||||
Objects.requireNonNull(equalityPredicate, "equalityPredicate");
|
||||
return this.handle.hasPermission(NodeMapType.ENDURING, node, equalityPredicate);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Tristate hasTransientPermission(@Nonnull Node node, @Nonnull NodeEqualityPredicate equalityPredicate) {
|
||||
Objects.requireNonNull(node, "node");
|
||||
Objects.requireNonNull(equalityPredicate, "equalityPredicate");
|
||||
return this.handle.hasPermission(NodeMapType.TRANSIENT, node, equalityPredicate);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Tristate inheritsPermission(@Nonnull Node node, @Nonnull NodeEqualityPredicate equalityPredicate) {
|
||||
Objects.requireNonNull(node, "node");
|
||||
Objects.requireNonNull(equalityPredicate, "equalityPredicate");
|
||||
return this.handle.inheritsPermission(node, equalityPredicate);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Tristate hasPermission(@Nonnull Node node) {
|
||||
Objects.requireNonNull(node, "node");
|
||||
return this.handle.hasPermission(node, NodeMapType.ENDURING);
|
||||
return this.handle.hasPermission(NodeMapType.ENDURING, node);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Tristate hasTransientPermission(@Nonnull Node node) {
|
||||
Objects.requireNonNull(node, "node");
|
||||
return this.handle.hasPermission(node, NodeMapType.TRANSIENT);
|
||||
return this.handle.hasPermission(NodeMapType.TRANSIENT, node);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.impl.generic.permission;
|
||||
|
||||
import me.lucko.luckperms.api.StandardNodeEquality;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.ArgumentPermissions;
|
||||
@ -62,7 +63,7 @@ public class PermissionCheck extends SharedSubCommand {
|
||||
String node = ArgumentUtils.handleString(0, args);
|
||||
MutableContextSet context = ArgumentUtils.handleContext(1, args, plugin);
|
||||
|
||||
Tristate result = holder.hasPermission(NodeFactory.builder(node).withExtraContext(context).build());
|
||||
Tristate result = holder.hasPermission(NodeFactory.builder(node).withExtraContext(context).build(), StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY);
|
||||
String s = CommandUtils.formatTristate(result);
|
||||
|
||||
Message.CHECK_PERMISSION.send(sender, holder.getFriendlyName(), node, s, CommandUtils.contextSetToString(context));
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.impl.generic.permission;
|
||||
|
||||
import me.lucko.luckperms.api.StandardNodeEquality;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.common.commands.ArgumentPermissions;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
@ -62,7 +63,7 @@ public class PermissionCheckInherits extends SharedSubCommand {
|
||||
String node = ArgumentUtils.handleString(0, args);
|
||||
MutableContextSet context = ArgumentUtils.handleContext(1, args, plugin);
|
||||
|
||||
InheritanceInfo result = holder.inheritsPermissionInfo(NodeFactory.builder(node).withExtraContext(context).build());
|
||||
InheritanceInfo result = holder.searchForInheritedMatch(NodeFactory.builder(node).withExtraContext(context).build(), StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY);
|
||||
|
||||
String location = result.getLocation().orElse(null);
|
||||
if (location == null || location.equalsIgnoreCase(holder.getObjectName())) {
|
||||
|
@ -35,6 +35,8 @@ import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.DataMutateResult;
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.NodeEqualityPredicate;
|
||||
import me.lucko.luckperms.api.StandardNodeEquality;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
@ -578,44 +580,53 @@ public abstract class PermissionHolder {
|
||||
return transientWork || enduringWork;
|
||||
}
|
||||
|
||||
private Optional<Node> getAlmostEquals(Node node, NodeMapType type) {
|
||||
private Optional<Node> searchForMatch(NodeMapType type, Node node, NodeEqualityPredicate equalityPredicate) {
|
||||
for (Node n : getData(type).immutable().values()) {
|
||||
if (n.almostEquals(node)) {
|
||||
if (n.equals(node, equalityPredicate)) {
|
||||
return Optional.of(n);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the holder has a permission node
|
||||
*
|
||||
* @param node the node to check
|
||||
* @param type which backing map to check
|
||||
* @return a tristate
|
||||
* @param node the node to check
|
||||
* @param equalityPredicate how to match
|
||||
* @return a tristate, returns undefined if no match
|
||||
*/
|
||||
public Tristate hasPermission(Node node, NodeMapType type) {
|
||||
public Tristate hasPermission(NodeMapType type, Node node, NodeEqualityPredicate equalityPredicate) {
|
||||
if (this.getType().isGroup() && node.isGroupNode() && node.getGroupName().equalsIgnoreCase(getObjectName())) {
|
||||
return Tristate.TRUE;
|
||||
}
|
||||
|
||||
return getAlmostEquals(node, type).map(Node::getTristate).orElse(Tristate.UNDEFINED);
|
||||
return searchForMatch(type, node, equalityPredicate).map(Node::getTristate).orElse(Tristate.UNDEFINED);
|
||||
}
|
||||
|
||||
public Tristate hasPermission(NodeMapType type, Node node) {
|
||||
return hasPermission(type, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
|
||||
}
|
||||
|
||||
public Tristate hasPermission(Node node, NodeEqualityPredicate equalityPredicate) {
|
||||
return hasPermission(NodeMapType.ENDURING, node, equalityPredicate);
|
||||
}
|
||||
|
||||
public Tristate hasPermission(Node node) {
|
||||
return hasPermission(node, NodeMapType.ENDURING);
|
||||
return hasPermission(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the holder inherits a node
|
||||
*
|
||||
* @param node the node to check
|
||||
* @param equalityPredicate how to match
|
||||
* @return the result of the lookup
|
||||
*/
|
||||
public InheritanceInfo inheritsPermissionInfo(Node node) {
|
||||
public InheritanceInfo searchForInheritedMatch(Node node, NodeEqualityPredicate equalityPredicate) {
|
||||
for (LocalizedNode n : resolveInheritances()) {
|
||||
if (n.getNode().almostEquals(node)) {
|
||||
if (n.getNode().equals(node, equalityPredicate)) {
|
||||
return InheritanceInfo.of(n);
|
||||
}
|
||||
}
|
||||
@ -627,10 +638,15 @@ public abstract class PermissionHolder {
|
||||
* Check if the holder inherits a node
|
||||
*
|
||||
* @param node the node to check
|
||||
* @param equalityPredicate how to match
|
||||
* @return the Tristate result
|
||||
*/
|
||||
public Tristate inheritsPermission(Node node, NodeEqualityPredicate equalityPredicate) {
|
||||
return searchForInheritedMatch(node, equalityPredicate).getResult();
|
||||
}
|
||||
|
||||
public Tristate inheritsPermission(Node node) {
|
||||
return inheritsPermissionInfo(node).getResult();
|
||||
return inheritsPermission(node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -639,7 +655,7 @@ public abstract class PermissionHolder {
|
||||
* @param node the node to set
|
||||
*/
|
||||
public DataMutateResult setPermission(Node node) {
|
||||
if (hasPermission(node, NodeMapType.ENDURING) != Tristate.UNDEFINED) {
|
||||
if (hasPermission(NodeMapType.ENDURING, node) != Tristate.UNDEFINED) {
|
||||
return DataMutateResult.ALREADY_HAS;
|
||||
}
|
||||
|
||||
@ -663,7 +679,7 @@ public abstract class PermissionHolder {
|
||||
if (node.isTemporary()) {
|
||||
if (modifier == TemporaryModifier.ACCUMULATE) {
|
||||
// Try to accumulate with an existing node
|
||||
Optional<Node> existing = getAlmostEquals(node, NodeMapType.ENDURING);
|
||||
Optional<Node> existing = searchForMatch(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
|
||||
|
||||
// An existing node was found
|
||||
if (existing.isPresent()) {
|
||||
@ -684,7 +700,7 @@ public abstract class PermissionHolder {
|
||||
|
||||
} else if (modifier == TemporaryModifier.REPLACE) {
|
||||
// Try to replace an existing node
|
||||
Optional<Node> existing = getAlmostEquals(node, NodeMapType.ENDURING);
|
||||
Optional<Node> existing = searchForMatch(NodeMapType.ENDURING, node, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
|
||||
|
||||
// An existing node was found
|
||||
if (existing.isPresent()) {
|
||||
@ -717,7 +733,7 @@ public abstract class PermissionHolder {
|
||||
* @param node the node to set
|
||||
*/
|
||||
public DataMutateResult setTransientPermission(Node node) {
|
||||
if (hasPermission(node, NodeMapType.TRANSIENT) != Tristate.UNDEFINED) {
|
||||
if (hasPermission(NodeMapType.TRANSIENT, node) != Tristate.UNDEFINED) {
|
||||
return DataMutateResult.ALREADY_HAS;
|
||||
}
|
||||
|
||||
@ -732,7 +748,7 @@ public abstract class PermissionHolder {
|
||||
* @param node the node to unset
|
||||
*/
|
||||
public DataMutateResult unsetPermission(Node node) {
|
||||
if (hasPermission(node, NodeMapType.ENDURING) == Tristate.UNDEFINED) {
|
||||
if (hasPermission(NodeMapType.ENDURING, node) == Tristate.UNDEFINED) {
|
||||
return DataMutateResult.LACKS;
|
||||
}
|
||||
|
||||
@ -751,7 +767,7 @@ public abstract class PermissionHolder {
|
||||
* @param node the node to unset
|
||||
*/
|
||||
public DataMutateResult unsetTransientPermission(Node node) {
|
||||
if (hasPermission(node, NodeMapType.TRANSIENT) == Tristate.UNDEFINED) {
|
||||
if (hasPermission(NodeMapType.TRANSIENT, node) == Tristate.UNDEFINED) {
|
||||
return DataMutateResult.LACKS;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
package me.lucko.luckperms.common.node;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.StandardNodeEquality;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
|
||||
@ -224,18 +225,8 @@ public abstract class ForwardingNode implements Node {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsIgnoringValue(@Nonnull Node other) {
|
||||
return delegate().equalsIgnoringValue(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean almostEquals(@Nonnull Node other) {
|
||||
return delegate().almostEquals(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsIgnoringValueOrTemp(@Nonnull Node other) {
|
||||
return delegate().equalsIgnoringValueOrTemp(other);
|
||||
public boolean standardEquals(Node other, StandardNodeEquality equalityPredicate) {
|
||||
return delegate().standardEquals(other, equalityPredicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableList;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.StandardNodeEquality;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
@ -320,27 +321,41 @@ public final class ImmutableNode implements Node {
|
||||
return this.resolvedShorthand;
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringEquality")
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof Node)) return false;
|
||||
final Node other = (Node) o;
|
||||
|
||||
if (this.permission != other.getPermission()) return false;
|
||||
if (this.value != other.getValuePrimitive()) return false;
|
||||
if (this.override != other.isOverride()) return false;
|
||||
Node other = (Node) o;
|
||||
while (other instanceof ForwardingNode) {
|
||||
other = ((ForwardingNode) other).delegate();
|
||||
}
|
||||
return other instanceof ImmutableNode && Equality.EXACT.areEqual(this, (ImmutableNode) other);
|
||||
}
|
||||
|
||||
final String thisServer = this.server;
|
||||
final String otherServer = other.getServer().orElse(null);
|
||||
if (thisServer == null ? otherServer != null : !thisServer.equals(otherServer)) return false;
|
||||
|
||||
final String thisWorld = this.world;
|
||||
final String otherWorld = other.getWorld().orElse(null);
|
||||
if (thisWorld == null ? otherWorld != null : !thisWorld.equals(otherWorld)) return false;
|
||||
|
||||
final long otherExpireAt = other.isTemporary() ? other.getExpiryUnixTime() : 0L;
|
||||
return this.expireAt == otherExpireAt && this.getContexts().equals(other.getContexts());
|
||||
@Override
|
||||
public boolean standardEquals(Node o, StandardNodeEquality equalityPredicate) {
|
||||
while (o instanceof ForwardingNode) {
|
||||
o = ((ForwardingNode) o).delegate();
|
||||
}
|
||||
if (!(o instanceof ImmutableNode)) {
|
||||
return false;
|
||||
}
|
||||
ImmutableNode other = (ImmutableNode) o;
|
||||
switch (equalityPredicate) {
|
||||
case EXACT:
|
||||
return Equality.EXACT.areEqual(this, other);
|
||||
case IGNORE_VALUE:
|
||||
return Equality.IGNORE_VALUE.areEqual(this, other);
|
||||
case IGNORE_EXPIRY_TIME:
|
||||
return Equality.IGNORE_EXPIRY_TIME.areEqual(this, other);
|
||||
case IGNORE_EXPIRY_TIME_AND_VALUE:
|
||||
return Equality.IGNORE_EXPIRY_TIME_AND_VALUE.areEqual(this, other);
|
||||
case IGNORE_VALUE_OR_IF_TEMPORARY:
|
||||
return Equality.IGNORE_VALUE_OR_IF_TEMPORARY.areEqual(this, other);
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -362,57 +377,70 @@ public final class ImmutableNode implements Node {
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringEquality")
|
||||
@Override
|
||||
public boolean equalsIgnoringValue(@Nonnull Node other) {
|
||||
if (this.permission != other.getPermission()) return false;
|
||||
if (this.override != other.isOverride()) return false;
|
||||
private enum Equality {
|
||||
EXACT {
|
||||
@Override
|
||||
public boolean areEqual(@Nonnull ImmutableNode o1, @Nonnull ImmutableNode o2) {
|
||||
return o1 == o2 ||
|
||||
o1.permission == o2.permission &&
|
||||
o1.value == o2.value &&
|
||||
o1.override == o2.override &&
|
||||
(o1.server == null ? o2.server == null : o1.server.equals(o2.server)) &&
|
||||
(o1.world == null ? o2.world == null : o1.world.equals(o2.world)) &&
|
||||
o1.expireAt == o2.expireAt &&
|
||||
o1.getContexts().equals(o2.getContexts());
|
||||
}
|
||||
},
|
||||
IGNORE_VALUE {
|
||||
@Override
|
||||
public boolean areEqual(@Nonnull ImmutableNode o1, @Nonnull ImmutableNode o2) {
|
||||
return o1 == o2 ||
|
||||
o1.permission == o2.permission &&
|
||||
o1.override == o2.override &&
|
||||
(o1.server == null ? o2.server == null : o1.server.equals(o2.server)) &&
|
||||
(o1.world == null ? o2.world == null : o1.world.equals(o2.world)) &&
|
||||
o1.expireAt == o2.expireAt &&
|
||||
o1.getContexts().equals(o2.getContexts());
|
||||
}
|
||||
},
|
||||
IGNORE_EXPIRY_TIME {
|
||||
@Override
|
||||
public boolean areEqual(@Nonnull ImmutableNode o1, @Nonnull ImmutableNode o2) {
|
||||
return o1 == o2 ||
|
||||
o1.permission == o2.permission &&
|
||||
o1.value == o2.value &&
|
||||
o1.override == o2.override &&
|
||||
(o1.server == null ? o2.server == null : o1.server.equals(o2.server)) &&
|
||||
(o1.world == null ? o2.world == null : o1.world.equals(o2.world)) &&
|
||||
o1.isTemporary() == o2.isTemporary() &&
|
||||
o1.getContexts().equals(o2.getContexts());
|
||||
}
|
||||
},
|
||||
IGNORE_EXPIRY_TIME_AND_VALUE {
|
||||
@Override
|
||||
public boolean areEqual(@Nonnull ImmutableNode o1, @Nonnull ImmutableNode o2) {
|
||||
return o1 == o2 ||
|
||||
o1.permission == o2.permission &&
|
||||
o1.override == o2.override &&
|
||||
(o1.server == null ? o2.server == null : o1.server.equals(o2.server)) &&
|
||||
(o1.world == null ? o2.world == null : o1.world.equals(o2.world)) &&
|
||||
o1.isTemporary() == o2.isTemporary() &&
|
||||
o1.getContexts().equals(o2.getContexts());
|
||||
}
|
||||
},
|
||||
IGNORE_VALUE_OR_IF_TEMPORARY {
|
||||
@Override
|
||||
public boolean areEqual(@Nonnull ImmutableNode o1, @Nonnull ImmutableNode o2) {
|
||||
return o1 == o2 ||
|
||||
o1.permission == o2.permission &&
|
||||
o1.override == o2.override &&
|
||||
(o1.server == null ? o2.server == null : o1.server.equals(o2.server)) &&
|
||||
(o1.world == null ? o2.world == null : o1.world.equals(o2.world)) &&
|
||||
o1.getContexts().equals(o2.getContexts());
|
||||
}
|
||||
};
|
||||
|
||||
final String thisServer = this.server;
|
||||
final String otherServer = other.getServer().orElse(null);
|
||||
if (thisServer == null ? otherServer != null : !thisServer.equals(otherServer)) return false;
|
||||
|
||||
final String thisWorld = this.world;
|
||||
final String otherWorld = other.getWorld().orElse(null);
|
||||
if (thisWorld == null ? otherWorld != null : !thisWorld.equals(otherWorld)) return false;
|
||||
|
||||
final long otherExpireAt = other.isTemporary() ? other.getExpiryUnixTime() : 0L;
|
||||
return this.expireAt == otherExpireAt && this.getContexts().equals(other.getContexts());
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringEquality")
|
||||
@Override
|
||||
public boolean almostEquals(@Nonnull Node other) {
|
||||
if (this.permission != other.getPermission()) return false;
|
||||
if (this.override != other.isOverride()) return false;
|
||||
|
||||
final String thisServer = this.server;
|
||||
final String otherServer = other.getServer().orElse(null);
|
||||
if (thisServer == null ? otherServer != null : !thisServer.equals(otherServer))
|
||||
return false;
|
||||
|
||||
final String thisWorld = this.world;
|
||||
final String otherWorld = other.getWorld().orElse(null);
|
||||
return (thisWorld == null ? otherWorld == null : thisWorld.equals(otherWorld)) &&
|
||||
this.isTemporary() == other.isTemporary() &&
|
||||
this.getContexts().equals(other.getContexts());
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringEquality")
|
||||
@Override
|
||||
public boolean equalsIgnoringValueOrTemp(@Nonnull Node other) {
|
||||
if (this.permission != other.getPermission()) return false;
|
||||
if (this.override != other.isOverride()) return false;
|
||||
|
||||
final String thisServer = this.server;
|
||||
final String otherServer = other.getServer().orElse(null);
|
||||
if (thisServer == null ? otherServer != null : !thisServer.equals(otherServer))
|
||||
return false;
|
||||
|
||||
final String thisWorld = this.world;
|
||||
final String otherWorld = other.getWorld().orElse(null);
|
||||
return (thisWorld == null ? otherWorld == null : thisWorld.equals(otherWorld)) &&
|
||||
this.getContexts().equals(other.getContexts());
|
||||
public abstract boolean areEqual(@Nonnull ImmutableNode o1, @Nonnull ImmutableNode o2);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -443,6 +471,13 @@ public final class ImmutableNode implements Node {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ImmutableNode(permission=" + this.permission + ", value=" + this.value + ", override=" + this.override + ", server=" + this.getServer() + ", world=" + this.getWorld() + ", expireAt=" + this.expireAt + ", contexts=" + this.contexts + ")";
|
||||
return "ImmutableNode(" +
|
||||
"permission=" + this.permission + ", " +
|
||||
"value=" + this.value + ", " +
|
||||
"override=" + this.override + ", " +
|
||||
"server=" + this.getServer() + ", " +
|
||||
"world=" + this.getWorld() + ", " +
|
||||
"expireAt=" + this.expireAt + ", " +
|
||||
"contexts=" + this.contexts + ")";
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user