Release 2.8

This commit is contained in:
Luck
2016-09-07 20:53:33 +01:00
Unverified
parent d84767af68
commit ea07f05097
28 changed files with 366 additions and 318 deletions
@@ -67,7 +67,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public double getApiVersion() {
return 2.7;
return 2.8;
}
@Override
@@ -86,6 +86,16 @@ public class LPConfigurationLink implements LPConfiguration {
return master.getLogNotify();
}
@Override
public boolean getEnableOps() {
return master.getEnableOps();
}
@Override
public boolean getCommandsAllowOp() {
return master.getCommandsAllowOp();
}
@Override
public String getVaultServer() {
return master.getVaultServer();
@@ -52,7 +52,7 @@ public class PermissionHolderLink implements PermissionHolder {
@Override
public SortedSet<Node> getPermissions() {
return Collections.unmodifiableSortedSet(master.getPermissions());
return Collections.unmodifiableSortedSet(master.getPermissions(false));
}
@Override
@@ -24,6 +24,7 @@ package me.lucko.luckperms.commands;
import com.google.common.collect.ImmutableMap;
import lombok.Getter;
import me.lucko.luckperms.constants.Constants;
import me.lucko.luckperms.constants.Permission;
import java.lang.ref.WeakReference;
@@ -46,39 +47,7 @@ public abstract class SenderFactory<T> implements Runnable {
protected abstract boolean hasPermission(T t, String node);
public final Sender wrap(T t) {
return new Sender() {
final WeakReference<T> tRef = new WeakReference<>(t);
// Cache these permissions, so they can be accessed async
final Map<Permission, Boolean> perms = ImmutableMap.copyOf(Arrays.stream(Permission.values())
.collect(Collectors.toMap(p -> p, p -> factory.hasPermission(t, p.getNode()))));
@Getter
final String name = factory.getName(t);
@Getter
final UUID uuid = factory.getUuid(t);
@Override
public void sendMessage(String s) {
final T t = tRef.get();
if (t != null) {
synchronized (messages) {
if (!messages.containsKey(t)) {
messages.put(t, new ArrayList<>());
}
messages.get(t).add(s);
}
shouldSend.set(true);
}
}
@Override
public boolean hasPermission(Permission permission) {
return perms.get(permission);
}
};
return new SenderImp(t);
}
@Override
@@ -97,4 +66,51 @@ public abstract class SenderFactory<T> implements Runnable {
messages.clear();
}
}
private class SenderImp implements Sender {
private final WeakReference<T> tRef;
// Cache these permissions, so they can be accessed async
private Map<Permission, Boolean> perms;
@Getter
private final String name;
@Getter
private final UUID uuid;
private final boolean console;
private SenderImp(T t) {
this.tRef = new WeakReference<>(t);
this.name = factory.getName(t);
this.uuid = factory.getUuid(t);
this.console = this.uuid.equals(Constants.getConsoleUUID()) || this.uuid.equals(Constants.getImporterUUID());
if (!this.console) {
this.perms = ImmutableMap.copyOf(Arrays.stream(Permission.values())
.collect(Collectors.toMap(p -> p, p -> factory.hasPermission(t, p.getNode()))));
}
}
@Override
public void sendMessage(String s) {
final T t = tRef.get();
if (t != null) {
synchronized (messages) {
if (!messages.containsKey(t)) {
messages.put(t, new ArrayList<>());
}
messages.get(t).add(s);
}
shouldSend.set(true);
}
}
@Override
public boolean hasPermission(Permission permission) {
return console || perms.get(permission);
}
}
}
@@ -38,8 +38,8 @@ public class GroupListNodes extends SubCommand<Group> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
Message.LISTNODES.send(sender, group.getName(), Util.permNodesToString(group.getPermissions()));
Message.LISTNODES_TEMP.send(sender, group.getName(), Util.tempNodesToString(group.getPermissions()));
Message.LISTNODES.send(sender, group.getName(), Util.permNodesToString(group.getPermissions(false)));
Message.LISTNODES_TEMP.send(sender, group.getName(), Util.tempNodesToString(group.getPermissions(false)));
return CommandResult.SUCCESS;
}
}
@@ -38,8 +38,8 @@ public class UserListNodes extends SubCommand<User> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
Message.LISTNODES.send(sender, user.getName(), Util.permNodesToString(user.getPermissions()));
Message.LISTNODES_TEMP.send(sender, user.getName(), Util.tempNodesToString(user.getPermissions()));
Message.LISTNODES.send(sender, user.getName(), Util.permNodesToString(user.getPermissions(false)));
Message.LISTNODES_TEMP.send(sender, user.getName(), Util.tempNodesToString(user.getPermissions(false)));
return CommandResult.SUCCESS;
}
}
@@ -40,6 +40,7 @@ public enum Message {
PLAYER_ONLINE("&aOnline", false),
PLAYER_OFFLINE("&cOffline", false),
LOADING_ERROR("Permissions data could not be loaded. Please contact an administrator.", true),
OP_DISABLED("&eThe vanilla OP system is disabled on this server.", false),
LOG("&3LOG &3&l> %s", true),
COMMAND_NOT_RECOGNISED("Command not recognised.", true),
@@ -23,9 +23,11 @@
package me.lucko.luckperms.constants;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.commands.Sender;
@SuppressWarnings("SpellCheckingInspection")
@Getter
@AllArgsConstructor
public enum Permission {
@@ -113,15 +115,15 @@ public enum Permission {
MIGRATION("migration", null);
private String node;
private String tag;
private String group;
public String getNode() {
if (group != null) {
return "luckperms." + group + "." + node;
return "luckperms." + group + "." + tag;
}
return "luckperms." + node;
return "luckperms." + tag;
}
public boolean isAuthorized(Sender sender) {
@@ -111,6 +111,14 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
return getBoolean("log-notify", true);
}
public boolean getEnableOps() {
return getBoolean("enable-ops", true);
}
public boolean getCommandsAllowOp() {
return getBoolean("commands-allow-op", true);
}
public String getVaultServer() {
return getString("vault-server", "global");
}
@@ -77,20 +77,26 @@ public abstract class PermissionHolder {
* Returns a Set of nodes in priority order
* @return the holders transient and permanent nodes
*/
public SortedSet<Node> getPermissions() {
public SortedSet<Node> getPermissions(boolean mergeTemp) {
// Returns no duplicate nodes. as in, nodes with the same value.
TreeSet<Node> combined = new TreeSet<>(PRIORITY_COMPARATOR);
TreeSet<Node> combined = new TreeSet<>(PriorityComparator.reverse());
combined.addAll(nodes);
combined.addAll(transientNodes);
TreeSet<Node> permissions = new TreeSet<>(PRIORITY_COMPARATOR);
TreeSet<Node> permissions = new TreeSet<>(PriorityComparator.reverse());
combined:
for (Node node : combined) {
for (Node other : permissions) {
if (node.equalsIgnoringValue(other)) {
continue combined;
if (mergeTemp) {
if (node.equalsIgnoringValueOrTemp(other)) {
continue combined;
}
} else {
if (node.almostEquals(other)) {
continue combined;
}
}
}
@@ -138,7 +144,7 @@ public abstract class PermissionHolder {
* @return a set of nodes
*/
public SortedSet<Node> getAllNodes(List<String> excludedGroups) {
SortedSet<Node> all = getPermissions();
SortedSet<Node> all = getPermissions(true);
if (excludedGroups == null) {
excludedGroups = new ArrayList<>();
@@ -146,7 +152,7 @@ public abstract class PermissionHolder {
excludedGroups.add(getObjectName().toLowerCase());
Set<String> parents = getPermissions().stream()
Set<String> parents = getPermissions(true).stream()
.filter(Node::isGroupNode)
.map(Node::getGroupName)
.collect(Collectors.toSet());
@@ -190,11 +196,12 @@ public abstract class PermissionHolder {
SortedSet<Node> allNodes;
if (applyGroups) {
allNodes = sort(getAllNodes(null), true);
allNodes = getAllNodes(null);
} else {
allNodes = sort(getPermissions(), true);
allNodes = getPermissions(true);
}
all:
for (Node node : allNodes) {
if (!node.shouldApplyOnServer(server, includeGlobal, plugin.getConfiguration().getApplyRegex())) {
continue;
@@ -208,6 +215,13 @@ public abstract class PermissionHolder {
continue;
}
// Force higher priority nodes to override
for (Node alreadyIn : perms) {
if (node.getPermission().equals(alreadyIn.getPermission())) {
continue all;
}
}
perms.add(node);
}
@@ -502,7 +516,7 @@ public abstract class PermissionHolder {
* @return The temporary nodes held by the holder
*/
public Set<Node> getTemporaryNodes() {
return getPermissions().stream().filter(Node::isTemporary).collect(Collectors.toSet());
return getPermissions(false).stream().filter(Node::isTemporary).collect(Collectors.toSet());
}
@Deprecated
@@ -520,7 +534,7 @@ public abstract class PermissionHolder {
* @return The permanent nodes held by the holder
*/
public Set<Node> getPermanentNodes() {
return getPermissions().stream().filter(Node::isPermanent).collect(Collectors.toSet());
return getPermissions(false).stream().filter(Node::isPermanent).collect(Collectors.toSet());
}
/*
@@ -541,51 +555,4 @@ public abstract class PermissionHolder {
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups) {
return getLocalPermissions(server, null, excludedGroups, null);
}
public static SortedSet<Node> sort(Set<Node> toSort, boolean reversed) {
TreeSet<Node> set = new TreeSet<>(reversed ? PRIORITY_COMPARATOR.reversed() : PRIORITY_COMPARATOR);
set.addAll(toSort);
return set;
}
private static final PriorityComparator PRIORITY_COMPARATOR = new PriorityComparator();
private static class PriorityComparator implements Comparator<Node> {
@Override
public int compare(Node o1, Node o2) {
if (o1.equals(o2)) {
return 0;
}
if (o1.isOverride() != o2.isOverride()) {
return o1.isOverride() ? 1 : -1;
}
if (o1.isServerSpecific() != o2.isServerSpecific()) {
return o1.isServerSpecific() ? 1 : -1;
}
if (o1.isWorldSpecific() != o2.isWorldSpecific()) {
return o1.isWorldSpecific() ? 1 : -1;
}
if (o1.isTemporary() != o2.isTemporary()) {
return o1.isTemporary() ? 1 : -1;
}
if (o1.isWildcard() != o2.isWildcard()) {
return o1.isWildcard() ? 1 : -1;
}
if (o1.isTemporary()) {
return o1.getSecondsTilExpiry() < o2.getSecondsTilExpiry() ? 1 : -1;
}
if (o1.isWildcard()) {
return o1.getWildcardLevel() > o2.getWildcardLevel() ? 1 : -1;
}
return 1;
}
}
}
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* 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.core;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import me.lucko.luckperms.api.Node;
import java.util.Comparator;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PriorityComparator implements Comparator<Node> {
private static final PriorityComparator instance = new PriorityComparator();
public static Comparator<Node> get() {
return instance;
}
public static Comparator<Node> reverse() {
return instance.reversed();
}
@Override
public int compare(Node o1, Node o2) {
if (o1.equals(o2)) {
return 0;
}
if (o1.isOverride() != o2.isOverride()) {
return o1.isOverride() ? 1 : -1;
}
if (o1.isServerSpecific() != o2.isServerSpecific()) {
return o1.isServerSpecific() ? 1 : -1;
}
if (o1.isWorldSpecific() != o2.isWorldSpecific()) {
return o1.isWorldSpecific() ? 1 : -1;
}
if (o1.isTemporary() != o2.isTemporary()) {
return o1.isTemporary() ? 1 : -1;
}
if (o1.isWildcard() != o2.isWildcard()) {
return o1.isWildcard() ? 1 : -1;
}
if (o1.isTemporary()) {
return o1.getSecondsTilExpiry() < o2.getSecondsTilExpiry() ? 1 : -1;
}
if (o1.isWildcard()) {
return o1.getWildcardLevel() > o2.getWildcardLevel() ? 1 : -1;
}
return 1;
}
}
@@ -74,7 +74,7 @@ public abstract class UserManager extends AbstractManager<UUID, User> {
*/
public void giveDefaultIfNeeded(User user, boolean save) {
boolean hasGroup = false;
for (Node node : user.getPermissions()) {
for (Node node : user.getPermissions(false)) {
if (node.isGroupNode()) {
hasGroup = true;
break;
@@ -156,7 +156,7 @@ public class Node implements me.lucko.luckperms.api.Node {
}
public boolean isServerSpecific() {
return getServer().isPresent();
return getServer().isPresent() && !getServer().get().equalsIgnoreCase("global");
}
public boolean isWorldSpecific() {
@@ -170,28 +170,7 @@ public class Node implements me.lucko.luckperms.api.Node {
}
if (isServerSpecific()) {
if (server.toLowerCase().startsWith("r=") && applyRegex) {
Pattern p = Patterns.compile(server.substring(2));
if (p == null) {
return false;
}
return p.matcher(this.server).matches();
}
if (server.startsWith("(") && server.endsWith(")") && server.contains("|")) {
final String bits = server.substring(1, server.length() - 1);
String[] parts = Patterns.VERTICAL_BAR.split(bits);
for (String s : parts) {
if (s.equalsIgnoreCase(this.server)) {
return true;
}
}
return false;
}
return this.server.equalsIgnoreCase(server);
return shouldApply(server, applyRegex, this.server);
} else {
return includeGlobal;
}
@@ -204,33 +183,37 @@ public class Node implements me.lucko.luckperms.api.Node {
}
if (isWorldSpecific()) {
if (world.toLowerCase().startsWith("r=") && applyRegex) {
Pattern p = Patterns.compile(world.substring(2));
if (p == null) {
return false;
}
return p.matcher(this.world).matches();
}
if (world.startsWith("(") && world.endsWith(")") && world.contains("|")) {
final String bits = world.substring(1, world.length() - 1);
String[] parts = Patterns.VERTICAL_BAR.split(bits);
for (String s : parts) {
if (s.equalsIgnoreCase(this.world)) {
return true;
}
}
return false;
}
return this.world.equalsIgnoreCase(world);
return shouldApply(world, applyRegex, this.world);
} else {
return includeGlobal;
}
}
private static boolean shouldApply(String world, boolean applyRegex, String thisWorld) {
if (world.toLowerCase().startsWith("r=") && applyRegex) {
Pattern p = Patterns.compile(world.substring(2));
if (p == null) {
return false;
}
return p.matcher(thisWorld).matches();
}
if (world.startsWith("(") && world.endsWith(")") && world.contains("|")) {
final String bits = world.substring(1, world.length() - 1);
String[] parts = Patterns.VERTICAL_BAR.split(bits);
for (String s : parts) {
if (s.equalsIgnoreCase(thisWorld)) {
return true;
}
}
return false;
}
return thisWorld.equalsIgnoreCase(world);
}
@Override
public boolean shouldApplyWithContext(Map<String, String> context) {
if (context == null || context.isEmpty()) {
@@ -530,6 +513,8 @@ public class Node implements me.lucko.luckperms.api.Node {
return false;
}
}
} else {
return false;
}
if (other.getWorld().isPresent() == this.getWorld().isPresent()) {
@@ -538,6 +523,8 @@ public class Node implements me.lucko.luckperms.api.Node {
return false;
}
}
} else {
return false;
}
if (!other.getExtraContexts().equals(this.getExtraContexts())) {
@@ -563,6 +550,8 @@ public class Node implements me.lucko.luckperms.api.Node {
return false;
}
}
} else {
return false;
}
if (other.getWorld().isPresent() == this.getWorld().isPresent()) {
@@ -571,6 +560,41 @@ public class Node implements me.lucko.luckperms.api.Node {
return false;
}
}
} else {
return false;
}
if (!other.getExtraContexts().equals(this.getExtraContexts())) {
return false;
}
return true;
}
@Override
public boolean equalsIgnoringValueOrTemp(me.lucko.luckperms.api.Node other) {
if (!other.getPermission().equalsIgnoreCase(this.getPermission())) {
return false;
}
if (other.getServer().isPresent() == this.getServer().isPresent()) {
if (other.getServer().isPresent()) {
if (!other.getServer().get().equalsIgnoreCase(this.getServer().get())) {
return false;
}
}
} else {
return false;
}
if (other.getWorld().isPresent() == this.getWorld().isPresent()) {
if (other.getWorld().isPresent()) {
if (!other.getWorld().get().equalsIgnoreCase(this.getWorld().get())) {
return false;
}
}
} else {
return false;
}
if (!other.getExtraContexts().equals(this.getExtraContexts())) {