Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea07f05097 | ||
|
|
d84767af68 | ||
|
|
aab73a8d81 | ||
|
|
995fc2ccd8 | ||
|
|
60bcd5f643 | ||
|
|
ba04fb320b | ||
|
|
770b7dc282 | ||
|
|
ed85eee36c | ||
|
|
23df8a2df8 | ||
|
|
36cd388607 | ||
|
|
4d48ef1939 | ||
|
|
7970e2a1c6 | ||
|
|
cee96d7daa | ||
|
|
861c1ddd69 | ||
|
|
5dec5a54cb | ||
|
|
5c760aabd4 | ||
|
|
1a2fa5d8c3 | ||
|
|
ef0c53da82 | ||
|
|
3fd62a80e2 | ||
|
|
5c19dd8b15 | ||
|
|
1fc88e147f | ||
|
|
9b4bbe0500 | ||
|
|
b37fdd3619 | ||
|
|
ab00c41452 | ||
|
|
c15727377b | ||
|
|
1e6f32bdc4 | ||
|
|
42e69c98a7 | ||
|
|
a217727bb4 | ||
|
|
ba10b1c06e | ||
|
|
075ba33e8b | ||
|
|
19dbc7d90a | ||
|
|
ade70bb7ba | ||
|
|
4b67913eee | ||
|
|
75858c1555 | ||
|
|
659baaf5fb | ||
|
|
3c83c578eb | ||
|
|
3ddbf1da87 | ||
|
|
35cb5b81dc | ||
|
|
02d9b996a7 | ||
|
|
d4cf6a5ad7 | ||
|
|
9fdb4fa25f | ||
|
|
d5bc1cdf5d | ||
|
|
f5995c0afa | ||
|
|
2cc65160b4 |
No files matched your search
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Wrapper interface for the internal Datastore instance
|
||||
* Interface for the internal Datastore instance
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Datastore {
|
||||
@@ -55,7 +55,7 @@ public interface Datastore {
|
||||
Async async();
|
||||
|
||||
/**
|
||||
* Gets the {@link Future} interface
|
||||
* Gets the {@link Future} interface.
|
||||
*
|
||||
* All operations through this interface are called in a new, separate asynchronous thread, similar to {@link Async}.
|
||||
* The only difference is that instead of providing a callback, a {@link java.util.concurrent.Future} is returned.
|
||||
@@ -112,7 +112,7 @@ public interface Datastore {
|
||||
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
|
||||
* @return if the operation was performed successfully
|
||||
* @throws NullPointerException if uuid or username is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
boolean loadUser(UUID uuid, String username);
|
||||
|
||||
@@ -128,14 +128,14 @@ public interface Datastore {
|
||||
/**
|
||||
* Removes users from the datastore who are "default". This is called every time the plugin loads.
|
||||
* @return true if the operation completed successfully
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
boolean cleanupUsers();
|
||||
|
||||
/**
|
||||
* Gets a set all user's UUIDs who are "unique", and aren't just a member of the "default" group.
|
||||
* @return a set of uuids, or null if the operation failed.
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<UUID> getUniqueUsers();
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal Group instances
|
||||
* Interface for internal Group instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Group extends PermissionHolder {
|
||||
|
||||
@@ -25,6 +25,8 @@ package me.lucko.luckperms.api;
|
||||
import me.lucko.luckperms.api.data.DatastoreConfiguration;
|
||||
import me.lucko.luckperms.api.data.MySQLConfiguration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A wrapper interface for the internal LuckPerms configuration, providing read only access.
|
||||
*/
|
||||
@@ -43,14 +45,14 @@ public interface LPConfiguration {
|
||||
|
||||
/**
|
||||
* @return the default group, in a node representation
|
||||
* @deprecated as of 1.6, the default group is always "default"
|
||||
* @deprecated as of 2.6, the default group is always "default"
|
||||
*/
|
||||
@Deprecated
|
||||
String getDefaultGroupNode();
|
||||
|
||||
/**
|
||||
* @return the name of the default group
|
||||
* @deprecated as of 1.6, the default group is always "default"
|
||||
* @deprecated as of 2.6, the default group is always "default"
|
||||
*/
|
||||
@Deprecated
|
||||
String getDefaultGroupName();
|
||||
@@ -80,6 +82,36 @@ public interface LPConfiguration {
|
||||
*/
|
||||
boolean getApplyShorthand();
|
||||
|
||||
/**
|
||||
* @return if LuckPerms will send notifications to users when permissions are modified
|
||||
* @since 2.7
|
||||
*/
|
||||
boolean getLogNotify();
|
||||
|
||||
/**
|
||||
* @return true if the vanilla op system is enabled
|
||||
* @since 2.8
|
||||
*/
|
||||
boolean getEnableOps();
|
||||
|
||||
/**
|
||||
* @return true if opped players are allowed to use LuckPerms commands
|
||||
* @since 2.8
|
||||
*/
|
||||
boolean getCommandsAllowOp();
|
||||
|
||||
/**
|
||||
* @return the name of the server used within Vault operations
|
||||
* @since 2.7
|
||||
*/
|
||||
String getVaultServer();
|
||||
|
||||
/**
|
||||
* @return true if global permissions should be considered when retrieving meta or player groups
|
||||
* @since 2.7
|
||||
*/
|
||||
boolean getVaultIncludeGlobal();
|
||||
|
||||
/**
|
||||
* @return the database values set in the configuration
|
||||
* @deprecated use {@link #getDatastoreConfig()}
|
||||
@@ -98,4 +130,17 @@ public interface LPConfiguration {
|
||||
*/
|
||||
String getStorageMethod();
|
||||
|
||||
/**
|
||||
* @return true if split storage is enabled
|
||||
* @since 2.7
|
||||
*/
|
||||
boolean getSplitStorage();
|
||||
|
||||
/**
|
||||
* @return a map of split storage options, where the key is the storage section, and the value is the storage method.
|
||||
* For example: key = user, value = json
|
||||
* @since 2.7
|
||||
*/
|
||||
Map<String, String> getSplitStorageOptions();
|
||||
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import java.util.UUID;
|
||||
/**
|
||||
* Represents a single entry in a log
|
||||
*/
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
public class LogEntry implements Comparable<LogEntry> {
|
||||
public static LogEntryBuilder builder() {
|
||||
return new LogEntryBuilder();
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
/**
|
||||
* A wrapper class for platform logger instances.
|
||||
* A wrapper interface for platform logger instances.
|
||||
*
|
||||
* <p> Bukkit/Bungee both use java.util.logging, and Sponge uses org.slf4j. This class wraps those classes so the commons
|
||||
* module can access a logger.
|
||||
|
||||
@@ -41,7 +41,7 @@ public interface LuckPermsApi {
|
||||
|
||||
/**
|
||||
* @return the version of the API running on the platform
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
double getApiVersion();
|
||||
|
||||
@@ -50,6 +50,12 @@ public interface LuckPermsApi {
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* @return the platform LuckPerms is running on
|
||||
* @since 2.7
|
||||
*/
|
||||
PlatformType getPlatformType();
|
||||
|
||||
/**
|
||||
* Registers a listener to be sent LuckPerms events
|
||||
* @param listener the listener instance
|
||||
@@ -138,7 +144,7 @@ public interface LuckPermsApi {
|
||||
* Unload a user from the internal storage, if they're not currently online.
|
||||
* @param user the user to unload
|
||||
* @throws NullPointerException if the user is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
void cleanupUser(User user);
|
||||
|
||||
@@ -208,7 +214,7 @@ public interface LuckPermsApi {
|
||||
* @return a {@link Node.Builder} instance
|
||||
* @throws IllegalArgumentException if the permission is invalid
|
||||
* @throws NullPointerException if the permission is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Node.Builder buildNode(String permission) throws IllegalArgumentException;
|
||||
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import me.lucko.luckperms.LuckPerms;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A collection of utilities to help retrieve meta values for {@link PermissionHolder}s
|
||||
* @since 2.7
|
||||
*/
|
||||
public class MetaUtils {
|
||||
|
||||
private MetaUtils(){}
|
||||
|
||||
/**
|
||||
* Escapes special characters used within LuckPerms, so the string can be saved without issues
|
||||
* @param s the string to escape
|
||||
* @return an escaped string
|
||||
* @throws NullPointerException if the string is null
|
||||
*/
|
||||
public static String escapeCharacters(String s) {
|
||||
if (s == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
s = s.replace(".", "{SEP}");
|
||||
s = s.replace("/", "{FSEP}");
|
||||
s = s.replace("$", "{DSEP}");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescapes special characters used within LuckPerms, the inverse of {@link #escapeCharacters(String)}
|
||||
* @param s the string to unescape
|
||||
* @return an unescaped string
|
||||
* @throws NullPointerException if the string is null
|
||||
*/
|
||||
public static String unescapeCharacters(String s) {
|
||||
if (s == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
s = s.replace("{SEP}", ".");
|
||||
s = s.replace("{FSEP}", "/");
|
||||
s = s.replace("{DSEP}", "$");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a meta value on a holder
|
||||
* @param holder the holder to apply the meta node to
|
||||
* @param server the server to apply the meta on, can be null
|
||||
* @param world the world to apply the meta on, can be null
|
||||
* @param node the meta node
|
||||
* @param value the meta value
|
||||
* @throws NullPointerException if the holder, node or value is null
|
||||
* @throws IllegalArgumentException if the node or value is empty
|
||||
*/
|
||||
public static void setMeta(PermissionHolder holder, String server, String world, String node, String value) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
|
||||
if (node == null) {
|
||||
throw new NullPointerException("node");
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
if (node.equals("")) {
|
||||
throw new IllegalArgumentException("node is empty");
|
||||
}
|
||||
|
||||
if (value.equals("")) {
|
||||
throw new IllegalArgumentException("value is empty");
|
||||
}
|
||||
|
||||
if (server == null || server.equals("")) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
node = escapeCharacters(node);
|
||||
value = escapeCharacters(value);
|
||||
|
||||
Set<Node> toRemove = new HashSet<>();
|
||||
for (Node n : holder.getEnduringPermissions()) {
|
||||
if (n.isMeta() && n.getMeta().getKey().equals(node)) {
|
||||
toRemove.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
for (Node n : toRemove) {
|
||||
try {
|
||||
holder.unsetPermission(n);
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
}
|
||||
|
||||
Node.Builder metaNode = LuckPerms.getApi().buildNode("meta." + node + "." + value).setValue(true);
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
metaNode.setServer(server);
|
||||
}
|
||||
if (world != null && !world.equals("")) {
|
||||
metaNode.setServer(server).setWorld(world);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(metaNode.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a meta value for the holder
|
||||
* @param holder the holder to get the meta from
|
||||
* @param server the server to retrieve the meta on, can be null
|
||||
* @param world the world to retrieve the meta on, can be null
|
||||
* @param node the node to get
|
||||
* @param defaultValue the default value to return if the node is not set
|
||||
* @param includeGlobal if global nodes should be considered when retrieving the meta
|
||||
* @return a meta string, or the default value if the user does not have the meta node
|
||||
* @throws NullPointerException if the holder or node is null
|
||||
* @throws IllegalArgumentException if the node is empty
|
||||
*/
|
||||
public static String getMeta(PermissionHolder holder, String server, String world, String node, String defaultValue, boolean includeGlobal) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
|
||||
if (server == null || server.equals("")) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
if (node == null) {
|
||||
throw new NullPointerException("node");
|
||||
}
|
||||
|
||||
if (node.equals("")) {
|
||||
throw new IllegalArgumentException("node is empty");
|
||||
}
|
||||
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
if (!n.shouldApplyOnServer(server, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
return unescapeCharacters(meta.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static void setChatMeta(boolean prefix, PermissionHolder holder, String value, int priority, String server, String world) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
|
||||
if (value == null || value.equals("")) {
|
||||
throw new IllegalArgumentException("value is null/empty");
|
||||
}
|
||||
|
||||
Node.Builder node = LuckPerms.getApi().buildNode(prefix ? "prefix" : "suffix" + "." + priority + "." + escapeCharacters(value));
|
||||
node.setValue(true);
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
node.setServer(server);
|
||||
}
|
||||
if (world != null && !world.equals("")) {
|
||||
node.setServer(server).setWorld(world);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(node.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a prefix to a holder on a specific server and world
|
||||
* @param holder the holder to set the prefix for
|
||||
* @param prefix the prefix value
|
||||
* @param priority the priority to set the prefix at
|
||||
* @param server the server to set the prefix on, can be null
|
||||
* @param world the world to set the prefix on, can be null
|
||||
* @throws NullPointerException if the holder is null
|
||||
* @throws IllegalArgumentException if the prefix is null or empty
|
||||
*/
|
||||
public static void setPrefix(PermissionHolder holder, String prefix, int priority, String server, String world) {
|
||||
setChatMeta(true, holder, prefix, priority, server, world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a suffix to a holder on a specific server and world
|
||||
* @param holder the holder to set the suffix for
|
||||
* @param suffix the suffix value
|
||||
* @param priority the priority to set the suffix at
|
||||
* @param server the server to set the suffix on, can be null
|
||||
* @param world the world to set the suffix on, can be null
|
||||
* @throws NullPointerException if the holder is null
|
||||
* @throws IllegalArgumentException if the suffix is null or empty
|
||||
*/
|
||||
public static void setSuffix(PermissionHolder holder, String suffix, int priority, String server, String world) {
|
||||
setChatMeta(false, holder, suffix, priority, server, world);
|
||||
}
|
||||
|
||||
private static String getChatMeta(boolean prefix, PermissionHolder holder, String server, String world, boolean includeGlobal) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
if (server == null) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
int priority = Integer.MIN_VALUE;
|
||||
String meta = null;
|
||||
for (Node n : holder.getAllNodes()) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
if (!n.shouldApplyOnServer(server, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix ? !n.isPrefix() : !n.isSuffix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> value = prefix ? n.getPrefix() : n.getSuffix();
|
||||
if (value.getKey() > priority) {
|
||||
meta = value.getValue();
|
||||
priority = value.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return meta == null ? "" : unescapeCharacters(meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a holders highest priority prefix, if they have one
|
||||
* @param holder the holder
|
||||
* @param server the server to retrieve the prefix on
|
||||
* @param world the world to retrieve the prefix on
|
||||
* @param includeGlobal if global nodes should be considered when retrieving the prefix
|
||||
* @return a prefix string, if the holder has one, or an empty string if not.
|
||||
* @throws NullPointerException if the holder is null
|
||||
*/
|
||||
public static String getPrefix(PermissionHolder holder, String server, String world, boolean includeGlobal) {
|
||||
return getChatMeta(true, holder, server, world, includeGlobal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a holders highest priority suffix, if they have one
|
||||
* @param holder the holder
|
||||
* @param server the server to retrieve the suffix on
|
||||
* @param world the world to retrieve the suffix on
|
||||
* @param includeGlobal if global nodes should be considered when retrieving the suffix
|
||||
* @return a suffix string, if the holder has one, or an empty string if not.
|
||||
* @throws NullPointerException if the holder is null
|
||||
*/
|
||||
public static String getSuffix(PermissionHolder holder, String server, String world, boolean includeGlobal) {
|
||||
return getChatMeta(false, holder, server, world, includeGlobal);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,8 +30,9 @@ import java.util.Optional;
|
||||
/**
|
||||
* Represents an immutable node object
|
||||
* <p> Use {@link LuckPermsApi#buildNode(String)} to get an instance.
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Node extends Map.Entry<String, Boolean> {
|
||||
|
||||
/**
|
||||
@@ -246,19 +247,38 @@ public interface Node extends Map.Entry<String, Boolean> {
|
||||
Map.Entry<Integer, String> getSuffix();
|
||||
|
||||
/**
|
||||
* Similar to {@link #equals(Object)}, except doesn't take note of the value
|
||||
* @param node the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
* Checks 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
|
||||
*/
|
||||
boolean equalsIgnoringValue(Node node);
|
||||
boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* Similar to {@link #equals(Object)}, except doesn't take note of the expiry time or value
|
||||
* @param node the other node
|
||||
* 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
|
||||
*/
|
||||
boolean almostEquals(Node node);
|
||||
boolean equalsIgnoringValue(Node other);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
boolean almostEquals(Node other);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
boolean equalsIgnoringValueOrTemp(Node other);
|
||||
|
||||
/**
|
||||
* Builds a Node instance
|
||||
*/
|
||||
interface Builder {
|
||||
Builder setNegated(boolean negated);
|
||||
Builder setValue(boolean value);
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal PermissionHolder (user/group) instances
|
||||
* Interface for internal PermissionHolder (user/group) instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface PermissionHolder {
|
||||
@@ -45,21 +45,21 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Gets an immutable Set of the objects permission nodes
|
||||
* @return an immutable set of permissions in priority order
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
SortedSet<Node> getPermissions();
|
||||
|
||||
/**
|
||||
* Similar to {@link #getPermissions()}, except excluding transient permissions
|
||||
* @return a set of nodes
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getEnduringPermissions();
|
||||
|
||||
/**
|
||||
* Similar to {@link #getPermissions()}, except excluding non-transient permissions
|
||||
* @return a set of nodes
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getTransientPermissions();
|
||||
|
||||
@@ -67,7 +67,7 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Gets an immutable set of the nodes that this object has and inherits
|
||||
* @return an immutable set of permissions
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getAllNodes();
|
||||
|
||||
@@ -84,7 +84,7 @@ public interface PermissionHolder {
|
||||
* @param node the node to check for
|
||||
* @return a Tristate for the holders permission status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Tristate hasPermission(Node node);
|
||||
|
||||
@@ -93,7 +93,7 @@ public interface PermissionHolder {
|
||||
* @param node the node to check for
|
||||
* @return a Tristate for the holders permission status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Tristate hasTransientPermission(Node node);
|
||||
|
||||
@@ -171,7 +171,7 @@ public interface PermissionHolder {
|
||||
* @param node the node to check for
|
||||
* @return a Tristate for the holders inheritance status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Tristate inheritsPermission(Node node);
|
||||
|
||||
@@ -249,7 +249,7 @@ public interface PermissionHolder {
|
||||
* @param node The node to be set
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
void setPermission(Node node) throws ObjectAlreadyHasException;
|
||||
|
||||
@@ -267,7 +267,7 @@ public interface PermissionHolder {
|
||||
* @param node The node to be set
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
void setTransientPermission(Node node) throws ObjectAlreadyHasException;
|
||||
|
||||
@@ -357,7 +357,7 @@ public interface PermissionHolder {
|
||||
* @param node The node to be unset
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
void unsetPermission(Node node) throws ObjectLacksException;
|
||||
|
||||
@@ -366,7 +366,7 @@ public interface PermissionHolder {
|
||||
* @param node The node to be unset
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
void unsetTransientPermission(Node node) throws ObjectLacksException;
|
||||
|
||||
@@ -498,7 +498,7 @@ public interface PermissionHolder {
|
||||
* @param possibleNodes a list of possible permissions for resolving wildcards
|
||||
* @param applyGroups if inherited group permissions should be included
|
||||
* @return a map of permissions
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Map<String, Boolean> getPermissions(String server, String world, Map<String, String> extraContext, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups);
|
||||
|
||||
@@ -513,7 +513,7 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Processes the nodes and returns the temporary ones.
|
||||
* @return a set of temporary nodes
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getTemporaryPermissionNodes();
|
||||
|
||||
@@ -528,7 +528,7 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Processes the nodes and returns the non-temporary ones.
|
||||
* @return a set of permanent nodes
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getPermanentPermissionNodes();
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
/**
|
||||
* Represents the platform type that LuckPerms is running on
|
||||
* @since 2.7
|
||||
*/
|
||||
public enum PlatformType {
|
||||
|
||||
BUKKIT("Bukkit"),
|
||||
BUNGEE("Bungee"),
|
||||
SPONGE("Sponge");
|
||||
|
||||
private final String friendlyName;
|
||||
|
||||
PlatformType(String friendlyName) {
|
||||
this.friendlyName = friendlyName;
|
||||
}
|
||||
|
||||
public String getFriendlyName() {
|
||||
return friendlyName;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal Track instances
|
||||
* Interface for internal Track instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Track {
|
||||
|
||||
@@ -29,7 +29,7 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal User instances
|
||||
* Interface for internal User instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface User extends PermissionHolder {
|
||||
|
||||
@@ -25,7 +25,9 @@ package me.lucko.luckperms.api;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This UuidCache is a means of allowing users to have the same internal UUID across a network of offline mode servers
|
||||
* A UUID cache for online users, between external Mojang UUIDs, and internal LuckPerms UUIDs.
|
||||
*
|
||||
* <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 random UUID for a 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.
|
||||
@@ -35,6 +37,7 @@ import java.util.UUID;
|
||||
*
|
||||
* <p> WARNING: THIS IS ONLY EFFECTIVE FOR ONLINE PLAYERS. USE THE DATASTORE METHODS FOR OFFLINE PLAYERS.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface UuidCache {
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,7 +26,7 @@ import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
|
||||
/**
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
public class AbstractPermissionEvent extends TargetedEvent<PermissionHolder> {
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ import me.lucko.luckperms.api.event.AbstractPermissionEvent;
|
||||
|
||||
/**
|
||||
* Called when a temporary permission node expires
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
public class PermissionNodeExpireEvent extends AbstractPermissionEvent {
|
||||
public PermissionNodeExpireEvent(PermissionHolder target, Node node) {
|
||||
|
||||
@@ -28,7 +28,7 @@ import me.lucko.luckperms.api.event.AbstractPermissionEvent;
|
||||
|
||||
/**
|
||||
* Called when a permission node is set on a holder
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
public class PermissionNodeSetEvent extends AbstractPermissionEvent {
|
||||
public PermissionNodeSetEvent(PermissionHolder target, Node node) {
|
||||
|
||||
@@ -28,7 +28,7 @@ import me.lucko.luckperms.api.event.AbstractPermissionEvent;
|
||||
|
||||
/**
|
||||
* Called when a permission node is unset from a holder
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
public class PermissionNodeUnsetEvent extends AbstractPermissionEvent {
|
||||
public PermissionNodeUnsetEvent(PermissionHolder target, Node node) {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package me.lucko.luckperms.exceptions;
|
||||
|
||||
/**
|
||||
* Thrown when a permission holding object doesn't / already has a permission or isn't / is already is a member of a group
|
||||
* @since 2.7
|
||||
*/
|
||||
public abstract class MembershipException extends Exception {
|
||||
}
|
||||
@@ -26,5 +26,5 @@ package me.lucko.luckperms.exceptions;
|
||||
* Thrown when a permission holding object already has a permission, is already a member of a group, or when a track
|
||||
* already contains a group.
|
||||
*/
|
||||
public class ObjectAlreadyHasException extends Exception {
|
||||
public class ObjectAlreadyHasException extends MembershipException {
|
||||
}
|
||||
@@ -26,5 +26,5 @@ package me.lucko.luckperms.exceptions;
|
||||
* Thrown when a permission holding object does not already have a permission, is not already a member of a group,
|
||||
* or when a track doesn't contain a group.
|
||||
*/
|
||||
public class ObjectLacksException extends Exception {
|
||||
public class ObjectLacksException extends MembershipException {
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>2.5</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- BukkitAPI -->
|
||||
|
||||
+1
-2
@@ -51,7 +51,6 @@ import java.util.regex.Pattern;
|
||||
* - suffix
|
||||
* - meta_<node>
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
private static final String IDENTIFIER = "luckperms";
|
||||
private static final String PLUGIN_NAME = "LuckPerms";
|
||||
@@ -76,7 +75,7 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return api == null ? "null" : api.getVersion();
|
||||
return "2.5";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.*;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
class BukkitListener extends AbstractListener implements Listener {
|
||||
@@ -45,7 +46,7 @@ class BukkitListener extends AbstractListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
|
||||
if (!plugin.getDatastore().isAcceptingLogins()) {
|
||||
// Datastore is disabled, prevent players from joining the server
|
||||
// The datastore is disabled, prevent players from joining the server
|
||||
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||
return;
|
||||
}
|
||||
@@ -67,13 +68,19 @@ class BukkitListener extends AbstractListener implements Listener {
|
||||
BukkitUser u = (BukkitUser) user;
|
||||
|
||||
PermissionAttachment attachment = player.addAttachment(plugin);
|
||||
Map<String, Boolean> newPermMap = new ConcurrentHashMap<>();
|
||||
try {
|
||||
BukkitUser.getPermissionsField().set(attachment, new ConcurrentHashMap<>());
|
||||
/* Replace the standard LinkedHashMap in the attachment with a ConcurrentHashMap.
|
||||
This means that we can iterate over and change the permissions within our attachment asynchronously,
|
||||
without worrying about thread safety. The Bukkit side of things should still operate normally. Internal
|
||||
permission stuff should work the same. This is by far the most easy and efficient way to do things, without
|
||||
having to do tons of reflection. */
|
||||
BukkitUser.getPermissionsField().set(attachment, newPermMap);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
||||
u.setAttachment(attachment);
|
||||
u.setAttachment(new BukkitUser.PermissionAttachmentHolder(attachment, newPermMap));
|
||||
}
|
||||
|
||||
plugin.doAsync(user::refreshPermissions);
|
||||
@@ -98,4 +105,22 @@ class BukkitListener extends AbstractListener implements Listener {
|
||||
plugin.getUserManager().getWorldCache().remove(e.getPlayer().getUniqueId());
|
||||
onLeave(e.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerCommand(PlayerCommandPreprocessEvent e) {
|
||||
if (plugin.getConfiguration().getEnableOps()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String s = e.getMessage()
|
||||
.replace("/", "")
|
||||
.replace("bukkit:", "")
|
||||
.replace("spigot:", "")
|
||||
.replace("minecraft:", "");
|
||||
|
||||
if (s.startsWith("op") || s.startsWith("deop")) {
|
||||
e.setCancelled(true);
|
||||
e.getPlayer().sendMessage(Message.OP_DISABLED.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ package me.lucko.luckperms;
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.LuckPermsApi;
|
||||
import me.lucko.luckperms.api.PlatformType;
|
||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||
import me.lucko.luckperms.api.vault.VaultHook;
|
||||
import me.lucko.luckperms.commands.ConsecutiveExecutor;
|
||||
@@ -43,6 +44,8 @@ import me.lucko.luckperms.users.BukkitUserManager;
|
||||
import me.lucko.luckperms.utils.LogFactory;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
@@ -132,6 +135,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
registerPermissions(getConfiguration().getCommandsAllowOp() ? PermissionDefault.OP : PermissionDefault.FALSE);
|
||||
if (!getConfiguration().getEnableOps()) {
|
||||
getServer().getOperators().forEach(o -> o.setOp(false));
|
||||
}
|
||||
|
||||
getLog().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
@@ -161,8 +169,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.BUKKIT;
|
||||
public PlatformType getType() {
|
||||
return PlatformType.BUKKIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -217,6 +225,16 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
return getServer().getServicesManager().load(clazz);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public UUID getUUID(String playerName) {
|
||||
try {
|
||||
return getServer().getOfflinePlayer(playerName).getUniqueId();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginLoaded(String name) {
|
||||
return getServer().getPluginManager().isPluginEnabled(name);
|
||||
@@ -226,4 +244,34 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
public void runUpdateTask() {
|
||||
getServer().getScheduler().runTaskAsynchronously(this, new UpdateTask(this));
|
||||
}
|
||||
|
||||
private void registerPermissions(PermissionDefault def) {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
|
||||
Map<String, List<String>> wildcards = new HashMap<>();
|
||||
List<String> all = new ArrayList<>();
|
||||
for (me.lucko.luckperms.constants.Permission p : me.lucko.luckperms.constants.Permission.values()) {
|
||||
pm.addPermission(new Permission(p.getNode(), def));
|
||||
if (p.getGroup() != null) {
|
||||
if (!wildcards.containsKey(p.getGroup())) {
|
||||
wildcards.put(p.getGroup(), new ArrayList<>());
|
||||
}
|
||||
wildcards.get(p.getGroup()).add(p.getTag());
|
||||
}
|
||||
|
||||
all.add(p.getNode());
|
||||
}
|
||||
|
||||
for (Map.Entry<String, List<String>> e : wildcards.entrySet()) {
|
||||
pm.addPermission(new Permission(
|
||||
"luckperms." + e.getKey() + ".*", def,
|
||||
e.getValue().stream()
|
||||
.map(tag -> "luckperms." + e.getKey() + "." + tag)
|
||||
.collect(Collectors.toMap(s -> s, s -> false))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
pm.addPermission(new Permission("luckperms.*", def, all.stream().collect(Collectors.toMap(s -> s, s -> false))));
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import static me.lucko.luckperms.utils.ArgumentChecker.escapeCharacters;
|
||||
@@ -80,113 +81,35 @@ public class VaultChatHook extends Chat {
|
||||
node = escapeCharacters(node);
|
||||
value = escapeCharacters(value);
|
||||
|
||||
if (world == null || world.equals("")) {
|
||||
try {
|
||||
holder.setPermission("meta." + node + "." + value, true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
} else {
|
||||
try {
|
||||
holder.setPermission("meta." + node + "." + value, true, "global", world);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
Iterator<Node> nodes = holder.getNodes().iterator();
|
||||
while (nodes.hasNext()) {
|
||||
Node n = nodes.next();
|
||||
if (n.isMeta() && n.getMeta().getKey().equals(node)) {
|
||||
nodes.remove();
|
||||
}
|
||||
}
|
||||
|
||||
Node.Builder metaNode = new me.lucko.luckperms.utils.Node.Builder("meta." + node + "." + value).setValue(true);
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
metaNode.setServer(perms.getServer());
|
||||
}
|
||||
if (world != null && !world.equals("")) {
|
||||
metaNode.setServer(perms.getServer()).setWorld(world);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(metaNode.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(holder);
|
||||
}
|
||||
|
||||
private static int getMeta(PermissionHolder holder, String world, String node, int defaultValue) {
|
||||
private String getMeta(PermissionHolder holder, String world, String node, String defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, true, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
|
||||
try {
|
||||
return Integer.parseInt(unescapeCharacters(meta.getValue()));
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static double getMeta(PermissionHolder holder, String world, String node, double defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, true, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
|
||||
try {
|
||||
return Double.parseDouble(unescapeCharacters(meta.getValue()));
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static boolean getMeta(PermissionHolder holder, String world, String node, boolean defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, true, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
|
||||
try {
|
||||
return Boolean.parseBoolean(unescapeCharacters(meta.getValue()));
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static String getMeta(PermissionHolder holder, String world, String node, String defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
for (Node n : holder.getPermissions(true)) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
@@ -195,29 +118,50 @@ public class VaultChatHook extends Chat {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, true, false)) {
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
if (!n.shouldApplyOnServer(perms.getServer(), perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
|
||||
try {
|
||||
return unescapeCharacters(meta.getValue());
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return unescapeCharacters(meta.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static String getChatMeta(boolean prefix, PermissionHolder holder, String world) {
|
||||
private void setChatMeta(boolean prefix, PermissionHolder holder, String value, String world) {
|
||||
if (holder == null) return;
|
||||
if (value.equals("")) return;
|
||||
|
||||
Node.Builder node = new me.lucko.luckperms.utils.Node.Builder(prefix ? "prefix" : "suffix" + ".1000." + escapeCharacters(value));
|
||||
node.setValue(true);
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
node.setServer(perms.getServer());
|
||||
}
|
||||
|
||||
if (world != null && !world.equals("")) {
|
||||
node.setServer(perms.getServer()).setWorld(world);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(node.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(holder);
|
||||
}
|
||||
|
||||
private String getChatMeta(boolean prefix, PermissionHolder holder, String world) {
|
||||
if (holder == null) return "";
|
||||
|
||||
int priority = -1000;
|
||||
int priority = Integer.MIN_VALUE;
|
||||
String meta = null;
|
||||
|
||||
for (Node n : holder.getAllNodes(null)) {
|
||||
@@ -225,30 +169,24 @@ public class VaultChatHook extends Chat {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, true, false)) {
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
if (!n.shouldApplyOnServer(perms.getServer(), perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
if (!n.isPrefix()) {
|
||||
continue;
|
||||
}
|
||||
if (prefix ? !n.isPrefix() : !n.isSuffix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> prefixValue = n.getPrefix();
|
||||
if (prefixValue.getKey() > priority) {
|
||||
meta = prefixValue.getValue();
|
||||
priority = prefixValue.getKey();
|
||||
}
|
||||
} else {
|
||||
if (!n.isSuffix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> suffixValue = n.getSuffix();
|
||||
if (suffixValue.getKey() > priority) {
|
||||
meta = suffixValue.getValue();
|
||||
priority = suffixValue.getKey();
|
||||
}
|
||||
Map.Entry<Integer, String> value = prefix ? n.getPrefix() : n.getSuffix();
|
||||
if (value.getKey() > priority) {
|
||||
meta = value.getValue();
|
||||
priority = value.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,15 +200,7 @@ public class VaultChatHook extends Chat {
|
||||
|
||||
public void setPlayerPrefix(String world, @NonNull String player, @NonNull String prefix) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return;
|
||||
|
||||
if (prefix.equals("")) return;
|
||||
|
||||
try {
|
||||
user.setPermission("prefix.1000." + escapeCharacters(prefix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(user);
|
||||
setChatMeta(true, user, prefix, world);
|
||||
}
|
||||
|
||||
public String getPlayerSuffix(String world, @NonNull String player) {
|
||||
@@ -280,15 +210,7 @@ public class VaultChatHook extends Chat {
|
||||
|
||||
public void setPlayerSuffix(String world, @NonNull String player, @NonNull String suffix) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return;
|
||||
|
||||
if (suffix.equals("")) return;
|
||||
|
||||
try {
|
||||
user.setPermission("suffix.1000." + escapeCharacters(suffix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(user);
|
||||
setChatMeta(false, user, suffix, world);
|
||||
}
|
||||
|
||||
public String getGroupPrefix(String world, @NonNull String group) {
|
||||
@@ -298,15 +220,7 @@ public class VaultChatHook extends Chat {
|
||||
|
||||
public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
if (g == null) return;
|
||||
|
||||
if (prefix.equals("")) return;
|
||||
|
||||
try {
|
||||
g.setPermission("prefix.1000." + escapeCharacters(prefix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(g);
|
||||
setChatMeta(true, g, prefix, world);
|
||||
}
|
||||
|
||||
public String getGroupSuffix(String world, @NonNull String group) {
|
||||
@@ -316,20 +230,16 @@ public class VaultChatHook extends Chat {
|
||||
|
||||
public void setGroupSuffix(String world, @NonNull String group, @NonNull String suffix) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
if (g == null) return;
|
||||
|
||||
if (suffix.equals("")) return;
|
||||
|
||||
try {
|
||||
g.setPermission("suffix.1000." + escapeCharacters(suffix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(g);
|
||||
setChatMeta(false, g, suffix, world);
|
||||
}
|
||||
|
||||
public int getPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int defaultValue) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
try {
|
||||
return Integer.parseInt(getMeta(user, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int value) {
|
||||
@@ -339,7 +249,11 @@ public class VaultChatHook extends Chat {
|
||||
|
||||
public int getGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int defaultValue) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
try {
|
||||
return Integer.parseInt(getMeta(g, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int value) {
|
||||
@@ -349,7 +263,11 @@ public class VaultChatHook extends Chat {
|
||||
|
||||
public double getPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double defaultValue) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
try {
|
||||
return Double.parseDouble(getMeta(user, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double value) {
|
||||
@@ -359,7 +277,11 @@ public class VaultChatHook extends Chat {
|
||||
|
||||
public double getGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double defaultValue) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
try {
|
||||
return Double.parseDouble(getMeta(g, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double value) {
|
||||
@@ -369,7 +291,11 @@ public class VaultChatHook extends Chat {
|
||||
|
||||
public boolean getPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean defaultValue) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
String s = getMeta(user, world, node, String.valueOf(defaultValue));
|
||||
if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Boolean.parseBoolean(s);
|
||||
}
|
||||
|
||||
public void setPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean value) {
|
||||
@@ -379,7 +305,11 @@ public class VaultChatHook extends Chat {
|
||||
|
||||
public boolean getGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean defaultValue) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
String s = getMeta(g, world, node, String.valueOf(defaultValue));
|
||||
if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Boolean.parseBoolean(s);
|
||||
}
|
||||
|
||||
public void setGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean value) {
|
||||
|
||||
@@ -39,6 +39,8 @@ public class VaultHook {
|
||||
permissionHook = new VaultPermissionHook();
|
||||
}
|
||||
permissionHook.setPlugin(plugin);
|
||||
permissionHook.setServer(plugin.getConfiguration().getVaultServer());
|
||||
permissionHook.setIncludeGlobal(plugin.getConfiguration().getVaultIncludeGlobal());
|
||||
|
||||
if (chatHook == null) {
|
||||
chatHook = new VaultChatHook(permissionHook);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
package me.lucko.luckperms.api.vault;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
@@ -38,6 +39,14 @@ public class VaultPermissionHook extends Permission {
|
||||
@Setter
|
||||
private LPBukkitPlugin plugin;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String server = "global";
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean includeGlobal = true;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "LuckPerms";
|
||||
@@ -57,9 +66,9 @@ public class VaultPermissionHook extends Permission {
|
||||
if (object == null) return false;
|
||||
|
||||
if (world != null && !world.equals("")) {
|
||||
return object.hasPermission(permission, true, "global", world);
|
||||
return object.hasPermission(permission, true, server, world);
|
||||
} else {
|
||||
return object.hasPermission(permission, true);
|
||||
return object.hasPermission(permission, true, server);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,9 +77,9 @@ public class VaultPermissionHook extends Permission {
|
||||
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
object.setPermission(permission, true, "global", world);
|
||||
object.setPermission(permission, true, server, world);
|
||||
} else {
|
||||
object.setPermission(permission, true);
|
||||
object.setPermission(permission, true, server);
|
||||
}
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
@@ -83,9 +92,9 @@ public class VaultPermissionHook extends Permission {
|
||||
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
object.unsetPermission(permission, "global", world);
|
||||
object.unsetPermission(permission, server, world);
|
||||
} else {
|
||||
object.unsetPermission(permission);
|
||||
object.unsetPermission(permission, server);
|
||||
}
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
|
||||
@@ -147,7 +156,7 @@ public class VaultPermissionHook extends Permission {
|
||||
if (group1 == null) return false;
|
||||
|
||||
if (world != null && !world.equals("")) {
|
||||
return user.isInGroup(group1, "global", world);
|
||||
return user.isInGroup(group1, server, world);
|
||||
} else {
|
||||
return user.isInGroup(group1);
|
||||
}
|
||||
@@ -163,7 +172,7 @@ public class VaultPermissionHook extends Permission {
|
||||
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
user.addGroup(group, "global", world);
|
||||
user.addGroup(group, server, world);
|
||||
} else {
|
||||
user.addGroup(group);
|
||||
}
|
||||
@@ -182,7 +191,7 @@ public class VaultPermissionHook extends Permission {
|
||||
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
user.removeGroup(group, "global", world);
|
||||
user.removeGroup(group, server, world);
|
||||
} else {
|
||||
user.removeGroup(group);
|
||||
}
|
||||
@@ -195,7 +204,7 @@ public class VaultPermissionHook extends Permission {
|
||||
public String[] getPlayerGroups(String world, @NonNull String player) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return (user == null) ? new String[0] :
|
||||
world != null && !world.equals("") ? user.getLocalGroups("global", world).toArray(new String[0]) :
|
||||
world != null && !world.equals("") ? user.getGroups(server, world, includeGlobal).toArray(new String[0]) :
|
||||
user.getGroupNames().toArray(new String[0]);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
package me.lucko.luckperms.users;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
@@ -52,7 +54,7 @@ public class BukkitUser extends User {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private PermissionAttachment attachment = null;
|
||||
private PermissionAttachmentHolder attachment = null;
|
||||
|
||||
BukkitUser(UUID uuid, LPBukkitPlugin plugin) {
|
||||
super(uuid, plugin);
|
||||
@@ -72,11 +74,18 @@ public class BukkitUser extends User {
|
||||
}
|
||||
|
||||
// Calculate the permissions that should be applied. This is done async, who cares about how long it takes or how often it's done.
|
||||
Map<String, Boolean> toApply = getLocalPermissions(getPlugin().getConfiguration().getServer(), plugin.getUserManager().getWorldCache().get(getUuid()), null);
|
||||
Map<String, Boolean> toApply = exportNodes(
|
||||
getPlugin().getConfiguration().getServer(),
|
||||
plugin.getUserManager().getWorldCache().get(getUuid()),
|
||||
null,
|
||||
plugin.getConfiguration().getIncludeGlobalPerms(),
|
||||
true,
|
||||
plugin.getPossiblePermissions()
|
||||
);
|
||||
|
||||
try {
|
||||
// The map in the LP PermissionAttachment is a ConcurrentHashMap. We can modify it's contents async.
|
||||
Map<String, Boolean> existing = (Map<String, Boolean>) getPermissionsField().get(attachment);
|
||||
// The map in the LP PermissionAttachment is a ConcurrentHashMap. We can modify and iterate over its contents async.
|
||||
Map<String, Boolean> existing = attachment.getPermissions();
|
||||
|
||||
boolean different = false;
|
||||
if (toApply.size() != existing.size()) {
|
||||
@@ -99,12 +108,21 @@ public class BukkitUser extends User {
|
||||
/* Must be called sync, as #recalculatePermissions is an unmodified Bukkit API call that is absolutely not thread safe.
|
||||
Shouldn't be too taxing on the server. This only gets called when permissions have actually changed,
|
||||
which is like once per user per login, assuming their permissions don't get modified. */
|
||||
plugin.doSync(() -> attachment.getPermissible().recalculatePermissions());
|
||||
plugin.doSync(() -> {
|
||||
attachment.getAttachment().getPermissible().recalculatePermissions();
|
||||
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@AllArgsConstructor
|
||||
public static class PermissionAttachmentHolder {
|
||||
private final PermissionAttachment attachment;
|
||||
private final Map<String, Boolean> permissions;
|
||||
}
|
||||
}
|
||||
@@ -44,23 +44,18 @@ public class BukkitUserManager extends UserManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(User user) {
|
||||
if (user != null) {
|
||||
public void preUnload(User user) {
|
||||
if (user instanceof BukkitUser) {
|
||||
BukkitUser u = (BukkitUser) user;
|
||||
|
||||
if (user instanceof BukkitUser) {
|
||||
BukkitUser u = (BukkitUser) user;
|
||||
if (u.getAttachment() != null) {
|
||||
Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid()));
|
||||
|
||||
if (u.getAttachment() != null) {
|
||||
Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid()));
|
||||
|
||||
if (player != null) {
|
||||
player.removeAttachment(u.getAttachment());
|
||||
}
|
||||
u.setAttachment(null);
|
||||
if (player != null) {
|
||||
player.removeAttachment(u.getAttachment().getAttachment());
|
||||
}
|
||||
u.setAttachment(null);
|
||||
}
|
||||
|
||||
getAll().remove(user.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ include-global: true
|
||||
|
||||
# 2. You are only running one server instance using LuckPerms, (not a network)
|
||||
# In this case, set online-mode to true no matter what is set in server.properties. (we can just fallback to the servers uuid cache)
|
||||
|
||||
# 3. If your proxy is running in offline mode, and you are using PaperSpigot (https://ci.destroystokyo.com/job/PaperSpigot/),
|
||||
# you should set "bungee-online-mode" to false in the paper.yml, and set "online-mode" to true in all LuckPerms configs.
|
||||
# This approach is thoroughly recommended for offline mode networks.
|
||||
online-mode: true
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
@@ -39,11 +43,39 @@ apply-regex: true
|
||||
# If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||
apply-shorthand: true
|
||||
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
log-notify: true
|
||||
|
||||
# If the vanilla OP system is enabled. If set to false, all users will be de-opped, and the op/deop commands will be disabled.
|
||||
enable-ops: true
|
||||
|
||||
# If opped players should be allowed to use LuckPerms commands. Set to false to only allow users with the permission access
|
||||
commands-allow-op: true
|
||||
|
||||
# The name of the server used within Vault operations. If you don't want Vault operations to be server specific, set this
|
||||
# to "global".
|
||||
vault-server: global
|
||||
|
||||
# If global permissions should be considered when retrieving meta or player groups
|
||||
vault-include-global: true
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
||||
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
|
||||
# Fill out connection info below if you're using MySQL or MongoDB
|
||||
storage-method: h2
|
||||
|
||||
# This block enables support for split datastores.
|
||||
# Only touch this if you're sure that you know what you're doing.
|
||||
# I (the author) do not endorse nor recommend the use of this feature.
|
||||
split-storage:
|
||||
enabled: false
|
||||
methods:
|
||||
user: h2
|
||||
group: h2
|
||||
track: h2
|
||||
uuid: h2
|
||||
log: h2
|
||||
|
||||
data:
|
||||
address: localhost:3306
|
||||
database: minecraft
|
||||
|
||||
@@ -1,130 +1,16 @@
|
||||
name: LuckPerms
|
||||
author: Luck
|
||||
version: ${release.version}.${git.closest.tag.commit.count}
|
||||
main: me.lucko.luckperms.LPBukkitPlugin
|
||||
softdepend: [Vault, PermissionsEx, GroupManager, PowerfulPerms, zPermissions] # For migration
|
||||
description: A permissions plugin
|
||||
author: Luck
|
||||
website: https://github.com/lucko/LuckPerms
|
||||
|
||||
main: me.lucko.luckperms.LPBukkitPlugin
|
||||
softdepend: [Vault, PermissionsEx, GroupManager, PowerfulPerms, zPermissions, bPermissions] # For migration
|
||||
|
||||
commands:
|
||||
luckperms:
|
||||
description: Manage permissions
|
||||
aliases: [perms, permissions, lp, p, perm]
|
||||
permissions:
|
||||
luckperms.*:
|
||||
description: Gives access to all LuckPerms commands
|
||||
children:
|
||||
luckperms.sync: true
|
||||
luckperms.info: true
|
||||
luckperms.debug: true
|
||||
luckperms.import: true
|
||||
luckperms.creategroup: true
|
||||
luckperms.deletegroup: true
|
||||
luckperms.listgroups: true
|
||||
luckperms.createtrack: true
|
||||
luckperms.deletetrack: true
|
||||
luckperms.listtracks: true
|
||||
luckperms.user.info: true
|
||||
luckperms.user.getuuid: true
|
||||
luckperms.user.listnodes: true
|
||||
luckperms.user.haspermission: true
|
||||
luckperms.user.inheritspermission: true
|
||||
luckperms.user.setpermission: true
|
||||
luckperms.user.unsetpermission: true
|
||||
luckperms.user.addgroup: true
|
||||
luckperms.user.removegroup: true
|
||||
luckperms.user.settemppermission: true
|
||||
luckperms.user.unsettemppermission: true
|
||||
luckperms.user.addtempgroup: true
|
||||
luckperms.user.removetempgroup: true
|
||||
luckperms.user.setprimarygroup: true
|
||||
luckperms.user.showtracks: true
|
||||
luckperms.user.promote: true
|
||||
luckperms.user.demote: true
|
||||
luckperms.user.showpos: true
|
||||
luckperms.user.clear: true
|
||||
luckperms.group.info: true
|
||||
luckperms.group.listnodes: true
|
||||
luckperms.group.haspermission: true
|
||||
luckperms.group.inheritspermission: true
|
||||
luckperms.group.setpermission: true
|
||||
luckperms.group.unsetpermission: true
|
||||
luckperms.group.setinherit: true
|
||||
luckperms.group.unsetinherit: true
|
||||
luckperms.group.settemppermission: true
|
||||
luckperms.group.unsettemppermission: true
|
||||
luckperms.group.settempinherit: true
|
||||
luckperms.group.unsettempinherit: true
|
||||
luckperms.group.showtracks: true
|
||||
luckperms.group.clear: true
|
||||
luckperms.group.rename: true
|
||||
luckperms.track.info: true
|
||||
luckperms.track.append: true
|
||||
luckperms.track.insert: true
|
||||
luckperms.track.remove: true
|
||||
luckperms.track.clear: true
|
||||
luckperms.track.rename: true
|
||||
luckperms.log.export: true
|
||||
luckperms.log.userhistory: true
|
||||
luckperms.log.grouphistory: true
|
||||
luckperms.log.trackhistory: true
|
||||
luckperms.log.notify: true
|
||||
luckperms.log.recent: true
|
||||
luckperms.log.search: true
|
||||
luckperms.user.*:
|
||||
description: Gives access to all LuckPerms user commands
|
||||
children:
|
||||
luckperms.user.info: true
|
||||
luckperms.user.getuuid: true
|
||||
luckperms.user.listnodes: true
|
||||
luckperms.user.haspermission: true
|
||||
luckperms.user.inheritspermission: true
|
||||
luckperms.user.setpermission: true
|
||||
luckperms.user.unsetpermission: true
|
||||
luckperms.user.addgroup: true
|
||||
luckperms.user.removegroup: true
|
||||
luckperms.user.settemppermission: true
|
||||
luckperms.user.unsettemppermission: true
|
||||
luckperms.user.addtempgroup: true
|
||||
luckperms.user.removetempgroup: true
|
||||
luckperms.user.setprimarygroup: true
|
||||
luckperms.user.showtracks: true
|
||||
luckperms.user.promote: true
|
||||
luckperms.user.demote: true
|
||||
luckperms.user.showpos: true
|
||||
luckperms.user.clear: true
|
||||
luckperms.group.*:
|
||||
description: Gives access to all LuckPerms group commands
|
||||
children:
|
||||
luckperms.group.info: true
|
||||
luckperms.group.listnodes: true
|
||||
luckperms.group.haspermission: true
|
||||
luckperms.group.inheritspermission: true
|
||||
luckperms.group.setpermission: true
|
||||
luckperms.group.unsetpermission: true
|
||||
luckperms.group.setinherit: true
|
||||
luckperms.group.unsetinherit: true
|
||||
luckperms.group.settemppermission: true
|
||||
luckperms.group.unsettemppermission: true
|
||||
luckperms.group.settempinherit: true
|
||||
luckperms.group.unsettempinherit: true
|
||||
luckperms.group.showtracks: true
|
||||
luckperms.group.clear: true
|
||||
luckperms.group.rename: true
|
||||
luckperms.track.*:
|
||||
description: Gives access to all LuckPerms track commands
|
||||
children:
|
||||
luckperms.track.info: true
|
||||
luckperms.track.append: true
|
||||
luckperms.track.insert: true
|
||||
luckperms.track.remove: true
|
||||
luckperms.track.clear: true
|
||||
luckperms.track.rename: true
|
||||
luckperms.log.*:
|
||||
description: Gives access to all LuckPerms log commands
|
||||
children:
|
||||
luckperms.log.export: true
|
||||
luckperms.log.userhistory: true
|
||||
luckperms.log.grouphistory: true
|
||||
luckperms.log.trackhistory: true
|
||||
luckperms.log.notify: true
|
||||
luckperms.log.recent: true
|
||||
luckperms.log.search: true
|
||||
|
||||
|
||||
# Permissions are registered programmatically instead of here.
|
||||
+5
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -65,6 +65,10 @@
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.sqlite</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.sqlite</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
@@ -33,7 +33,6 @@ import net.md_5.bungee.api.event.*;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@@ -109,16 +108,10 @@ public class BungeeListener extends AbstractListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerPostLogin(PostLoginEvent e) {
|
||||
final ProxiedPlayer player = e.getPlayer();
|
||||
final WeakReference<ProxiedPlayer> p = new WeakReference<>(player);
|
||||
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
|
||||
|
||||
if (user == null) {
|
||||
plugin.getProxy().getScheduler().schedule(plugin, () -> {
|
||||
final ProxiedPlayer pl = p.get();
|
||||
if (pl != null) {
|
||||
pl.sendMessage(WARN_MESSAGE);
|
||||
}
|
||||
}, 3, TimeUnit.SECONDS);
|
||||
plugin.getProxy().getScheduler().schedule(plugin, () -> player.sendMessage(WARN_MESSAGE), 3, TimeUnit.SECONDS);
|
||||
} else {
|
||||
user.refreshPermissions();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ package me.lucko.luckperms;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.PlatformType;
|
||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.commands.ConsecutiveExecutor;
|
||||
@@ -135,8 +136,8 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.BUNGEE;
|
||||
public PlatformType getType() {
|
||||
return PlatformType.BUNGEE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -185,6 +186,11 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String playerName) {
|
||||
return null; // Not needed on Bungee
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginLoaded(String name) {
|
||||
return getProxy().getPluginManager().getPlugins().stream()
|
||||
|
||||
@@ -34,15 +34,6 @@ public class BungeeUserManager extends UserManager {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(User user) {
|
||||
if (user != null) {
|
||||
// Cannot clear the ProxiedPlayer's permission map, they're leaving so that will get GCed anyway
|
||||
// Calling getPermissions.clear() throws an UnsupportedOperationException
|
||||
getAll().remove(user.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup(User user) {
|
||||
if (plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) {
|
||||
|
||||
@@ -22,6 +22,10 @@ include-global: false
|
||||
|
||||
# 2. You are only running one server instance using LuckPerms, (not a network)
|
||||
# In this case, set online-mode to true no matter what is set in server.properties. (we can just fallback to the servers uuid cache)
|
||||
|
||||
# 3. If your proxy is running in offline mode, and you are using PaperSpigot (https://ci.destroystokyo.com/job/PaperSpigot/),
|
||||
# you should set "bungee-online-mode" to false in the paper.yml, and set "online-mode" to true in all LuckPerms configs.
|
||||
# This approach is thoroughly recommended for offline mode networks.
|
||||
online-mode: true
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
@@ -39,11 +43,26 @@ apply-regex: true
|
||||
# If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||
apply-shorthand: true
|
||||
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
log-notify: true
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
||||
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
|
||||
# Fill out connection info below if you're using MySQL or MongoDB
|
||||
storage-method: h2
|
||||
|
||||
# This block enables support for split datastores.
|
||||
# Only touch this if you're sure that you know what you're doing.
|
||||
# I (the author) do not endorse nor recommend the use of this feature.
|
||||
split-storage:
|
||||
enabled: false
|
||||
methods:
|
||||
user: h2
|
||||
group: h2
|
||||
track: h2
|
||||
uuid: h2
|
||||
log: h2
|
||||
|
||||
data:
|
||||
address: localhost:3306
|
||||
database: minecraft
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: LuckPerms
|
||||
author: Luck
|
||||
version: ${release.version}.${git.closest.tag.commit.count}
|
||||
main: me.lucko.luckperms.LPBungeePlugin
|
||||
softdepend: [PowerfulPerms] # For migration
|
||||
description: A permissions plugin
|
||||
author: Luck
|
||||
main: me.lucko.luckperms.LPBungeePlugin
|
||||
softdepends: [PowerfulPerms] # For migration
|
||||
+18
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -67,6 +67,13 @@
|
||||
<version>1.7.9</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- SnakeYAML -->
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.14</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- gson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
@@ -105,6 +112,10 @@
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.gravitydevelopment.updater</groupId>
|
||||
<artifactId>updater</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -125,6 +136,12 @@
|
||||
<version>3.0-dev-52</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.bananaco</groupId>
|
||||
<artifactId>bpermissions-api</artifactId>
|
||||
<version>2.12</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -23,6 +23,7 @@
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.PlatformType;
|
||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||
import me.lucko.luckperms.commands.ConsecutiveExecutor;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
@@ -65,11 +66,10 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
|
||||
/**
|
||||
* @return the platform type
|
||||
*/
|
||||
Type getType();
|
||||
PlatformType getType();
|
||||
|
||||
/**
|
||||
* @return the main plugin directory
|
||||
@@ -136,6 +136,13 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
Object getService(Class clazz);
|
||||
|
||||
/**
|
||||
* Used as a backup for migration
|
||||
* @param playerName the players name
|
||||
* @return a uuid if found, or null if not
|
||||
*/
|
||||
UUID getUUID(String playerName);
|
||||
|
||||
/**
|
||||
* Checks if a plugin is loaded on the platform
|
||||
* @param name the name of the plugin
|
||||
@@ -160,8 +167,4 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
void doSync(Runnable r);
|
||||
|
||||
|
||||
enum Type {
|
||||
BUKKIT, BUNGEE, SPONGE;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ import java.util.stream.Collectors;
|
||||
import static me.lucko.luckperms.api.implementation.internal.Utils.checkNode;
|
||||
|
||||
/**
|
||||
* Provides static access to LuckPerms
|
||||
* Implements the LuckPerms API using the plugin instance
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class ApiProvider implements LuckPermsApi {
|
||||
@@ -67,7 +67,7 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public double getApiVersion() {
|
||||
return 1.6;
|
||||
return 2.8;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,6 +75,11 @@ public class ApiProvider implements LuckPermsApi {
|
||||
return plugin.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformType getPlatformType() {
|
||||
return plugin.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerListener(@NonNull LPListener listener) {
|
||||
eventBus.register(listener);
|
||||
|
||||
+38
@@ -27,6 +27,8 @@ import me.lucko.luckperms.api.LPConfiguration;
|
||||
import me.lucko.luckperms.api.data.DatastoreConfiguration;
|
||||
import me.lucko.luckperms.api.data.MySQLConfiguration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provides a link between {@link LPConfiguration} and {@link me.lucko.luckperms.core.LPConfiguration}
|
||||
*/
|
||||
@@ -79,6 +81,31 @@ public class LPConfigurationLink implements LPConfiguration {
|
||||
return master.getApplyShorthand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getLogNotify() {
|
||||
return master.getLogNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getEnableOps() {
|
||||
return master.getEnableOps();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCommandsAllowOp() {
|
||||
return master.getCommandsAllowOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVaultServer() {
|
||||
return master.getVaultServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVaultIncludeGlobal() {
|
||||
return master.getVaultIncludeGlobal();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public MySQLConfiguration getDatabaseValues() {
|
||||
@@ -94,4 +121,15 @@ public class LPConfigurationLink implements LPConfiguration {
|
||||
public String getStorageMethod() {
|
||||
return master.getStorageMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getSplitStorage() {
|
||||
return master.getSplitStorage();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, String> getSplitStorageOptions() {
|
||||
return master.getSplitStorageOptions();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -22,11 +22,14 @@
|
||||
|
||||
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;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -35,7 +38,7 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public abstract class SenderFactory<T> implements Runnable {
|
||||
private final Map<T, List<String>> messages = new HashMap<>();
|
||||
//private final List<Map.Entry<T, String>> messages = new ArrayList<>();
|
||||
private final AtomicBoolean shouldSend = new AtomicBoolean(false);
|
||||
private final SenderFactory<T> factory = this;
|
||||
|
||||
protected abstract String getName(T t);
|
||||
@@ -44,50 +47,70 @@ 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 = Arrays.stream(Permission.values())
|
||||
.map(p -> new AbstractMap.SimpleEntry<>(p, factory.hasPermission(t, p.getNode())))
|
||||
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Permission permission) {
|
||||
synchronized (perms) {
|
||||
return perms.get(permission);
|
||||
}
|
||||
}
|
||||
};
|
||||
return new SenderImp(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
if (!shouldSend.getAndSet(false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (messages) {
|
||||
if (!messages.isEmpty()) {
|
||||
messages.entrySet().forEach(e -> e.getValue().forEach(s -> factory.sendMessage(e.getKey(), s)));
|
||||
messages.clear();
|
||||
for (Map.Entry<T, List<String>> e : messages.entrySet()) {
|
||||
for (String s : e.getValue()) {
|
||||
factory.sendMessage(e.getKey(), s);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,10 +110,11 @@ public abstract class SubCommand<T> {
|
||||
return permission.isAuthorized(sender);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------------------
|
||||
Utility methods used by #onTabComplete and #execute implementations in sub classes
|
||||
----------------------------------------------------------------------------------
|
||||
* ----------------------------------------------------------------------------------
|
||||
* Utility methods used by #onTabComplete and #execute implementations in sub classes
|
||||
* ----------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
protected static List<String> getGroupTabComplete(List<String> args, LuckPermsPlugin plugin) {
|
||||
|
||||
@@ -23,13 +23,12 @@
|
||||
package me.lucko.luckperms.commands;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.utils.DateUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
@UtilityClass
|
||||
public class Util {
|
||||
@@ -114,35 +113,53 @@ public class Util {
|
||||
return sb.delete(sb.length() - 6, sb.length()).toString();
|
||||
}
|
||||
|
||||
public static String permNodesToString(Map<String, Boolean> nodes) {
|
||||
if (nodes.isEmpty()) return "&6None";
|
||||
|
||||
public static String permNodesToString(SortedSet<Node> nodes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
|
||||
if (e.getValue()) {
|
||||
sb.append("&a").append(e.getKey()).append("&7, ");
|
||||
} else {
|
||||
sb.append("&c").append(e.getKey()).append("&7, ");
|
||||
for (Node node : nodes) {
|
||||
if (node.isTemporary()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sb.append("&6-> ").append(node.getValue() ? "&a" : "&c");
|
||||
sb.append(node.getPermission());
|
||||
if (node.isServerSpecific()) {
|
||||
sb.append(" &7(&f").append(node.getServer().get()).append("&7)");
|
||||
}
|
||||
if (node.isWorldSpecific()) {
|
||||
sb.append(" &7(&f").append(node.getWorld().get()).append("&7)");
|
||||
}
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
return sb.delete(sb.length() - 2, sb.length()).toString();
|
||||
if (sb.length() == 0) {
|
||||
return "&6None";
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String tempNodesToString(Map<Map.Entry<String, Boolean>, Long> nodes) {
|
||||
if (nodes.isEmpty()) return "&6None";
|
||||
|
||||
public static String tempNodesToString(SortedSet<Node> nodes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (Map.Entry<Map.Entry<String, Boolean>, Long> e : nodes.entrySet()) {
|
||||
if (e.getKey().getValue()) {
|
||||
sb.append("&a").append(e.getKey().getKey()).append("&6 - expires in ")
|
||||
.append(DateUtil.formatDateDiff(e.getValue())).append("\n");
|
||||
} else {
|
||||
sb.append("&c").append(e.getKey().getKey()).append("&6 - expires in ")
|
||||
.append(DateUtil.formatDateDiff(e.getValue())).append("\n");
|
||||
for (Node node : nodes) {
|
||||
if (!node.isTemporary()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sb.append("&6-> ").append(node.getValue() ? "&a" : "&c");
|
||||
sb.append(node.getPermission());
|
||||
if (node.isServerSpecific()) {
|
||||
sb.append(" &7(&f").append(node.getServer().get()).append("&7)");
|
||||
}
|
||||
if (node.isWorldSpecific()) {
|
||||
sb.append(" &7(&f").append(node.getWorld().get()).append("&7)");
|
||||
}
|
||||
|
||||
sb.append("&6 - expires in ").append(DateUtil.formatDateDiff(node.getExpiryUnixTime())).append("\n");
|
||||
}
|
||||
|
||||
if (sb.length() == 0) {
|
||||
return "&6None";
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
@@ -161,4 +178,25 @@ public class Util {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized MetaComparator getMetaComparator() {
|
||||
if (metaComparator == null) {
|
||||
metaComparator = new MetaComparator();
|
||||
}
|
||||
return metaComparator;
|
||||
}
|
||||
|
||||
|
||||
private static MetaComparator metaComparator = null;
|
||||
public class MetaComparator implements Comparator<Map.Entry<Integer, String>> {
|
||||
|
||||
@Override
|
||||
public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) {
|
||||
int result = Integer.compare(o1.getKey(), o2.getKey());
|
||||
if (result == 0) {
|
||||
result = o1.getValue().compareTo(o2.getValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,15 @@ public class GroupMainCommand extends MainCommand<Group> {
|
||||
.add(new GroupSetTempInherit())
|
||||
.add(new GroupUnsetTempInherit())
|
||||
.add(new GroupShowTracks())
|
||||
.add(new GroupChatMeta())
|
||||
.add(new GroupAddPrefix())
|
||||
.add(new GroupAddSuffix())
|
||||
.add(new GroupRemovePrefix())
|
||||
.add(new GroupRemoveSuffix())
|
||||
.add(new GroupAddTempPrefix())
|
||||
.add(new GroupAddTempSuffix())
|
||||
.add(new GroupRemoveTempPrefix())
|
||||
.add(new GroupRemoveTempSuffix())
|
||||
.add(new GroupClear())
|
||||
.add(new GroupRename())
|
||||
.build()
|
||||
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupAddPrefix extends SubCommand<Group> {
|
||||
public GroupAddPrefix() {
|
||||
super("addprefix", "Adds a prefix to the group", "/%s group <group> addprefix <priority> <prefix> [server] [world]",
|
||||
Permission.GROUP_ADDPREFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
final String prefix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
group.setPermission(node, true, server);
|
||||
Message.ADDPREFIX_SERVER_SUCCESS.send(sender, group.getName(), prefix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addprefix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
group.setPermission(node, true, server, world);
|
||||
Message.ADDPREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), prefix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addprefix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.setPermission(node, true);
|
||||
Message.ADDPREFIX_SUCCESS.send(sender, group.getName(), prefix, priority);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addprefix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.ALREADY_HAS_PREFIX.send(sender, group.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupAddSuffix extends SubCommand<Group> {
|
||||
public GroupAddSuffix() {
|
||||
super("addsuffix", "Adds a suffix to the group", "/%s group <group> addsuffix <priority> <suffix> [server] [world]",
|
||||
Permission.GROUP_ADDSUFFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
final String suffix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
group.setPermission(node, true, server);
|
||||
Message.ADDSUFFIX_SERVER_SUCCESS.send(sender, group.getName(), suffix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addsuffix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
group.setPermission(node, true, server, world);
|
||||
Message.ADDSUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), suffix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addsuffix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.setPermission(node, true);
|
||||
Message.ADDSUFFIX_SUCCESS.send(sender, group.getName(), suffix, priority);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addsuffix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.ALREADY_HAS_SUFFIX.send(sender, group.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
import me.lucko.luckperms.utils.DateUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupAddTempPrefix extends SubCommand<Group> {
|
||||
public GroupAddTempPrefix() {
|
||||
super("addtempprefix", "Adds a prefix to the group temporarily", "/%s group <group> addtempprefix <priority> <prefix> <duration> [server] [world]",
|
||||
Permission.GROUP_ADD_TEMP_PREFIX, Predicate.notInRange(3, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
final String prefix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
long duration;
|
||||
try {
|
||||
duration = Long.parseLong(args.get(2));
|
||||
} catch (NumberFormatException e) {
|
||||
try {
|
||||
duration = DateUtil.parseDateDiff(args.get(2), true);
|
||||
} catch (DateUtil.IllegalDateException e1) {
|
||||
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
if (DateUtil.shouldExpire(duration)) {
|
||||
Message.PAST_DATE_ERROR.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 4) {
|
||||
final String server = args.get(3).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 4) {
|
||||
group.setPermission(node, true, server, duration);
|
||||
Message.ADD_TEMP_PREFIX_SERVER_SUCCESS.send(sender, group.getName(), prefix, priority, server, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(4).toLowerCase();
|
||||
group.setPermission(node, true, server, world, duration);
|
||||
Message.ADD_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), prefix, priority, server, world, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.setPermission(node, true, duration);
|
||||
Message.ADD_TEMP_PREFIX_SUCCESS.send(sender, group.getName(), prefix, priority, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.ALREADY_HAS_PREFIX.send(sender, group.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
import me.lucko.luckperms.utils.DateUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupAddTempSuffix extends SubCommand<Group> {
|
||||
public GroupAddTempSuffix() {
|
||||
super("addtempsuffix", "Adds a suffix to the group temporarily", "/%s group <group> addtempsuffix <priority> <suffix> <duration> [server] [world]",
|
||||
Permission.GROUP_ADD_TEMP_SUFFIX, Predicate.notInRange(3, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
final String suffix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
long duration;
|
||||
try {
|
||||
duration = Long.parseLong(args.get(2));
|
||||
} catch (NumberFormatException e) {
|
||||
try {
|
||||
duration = DateUtil.parseDateDiff(args.get(2), true);
|
||||
} catch (DateUtil.IllegalDateException e1) {
|
||||
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
if (DateUtil.shouldExpire(duration)) {
|
||||
Message.PAST_DATE_ERROR.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 4) {
|
||||
final String server = args.get(3).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 4) {
|
||||
group.setPermission(node, true, server, duration);
|
||||
Message.ADD_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, group.getName(), suffix, priority, server, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(4).toLowerCase();
|
||||
group.setPermission(node, true, server, world, duration);
|
||||
Message.ADD_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), suffix, priority, server, world, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.setPermission(node, true, duration);
|
||||
Message.ADD_TEMP_SUFFIX_SUCCESS.send(sender, group.getName(), suffix, priority, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.ALREADY_HAS_SUFFIX.send(sender, group.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.commands.*;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class GroupChatMeta extends SubCommand<Group> {
|
||||
public GroupChatMeta() {
|
||||
super("chatmeta", "Displays a groups chat meta", "/%s group <group> chatmeta", Permission.GROUP_CHATMETA,
|
||||
Predicate.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
SortedSet<Map.Entry<Integer, String>> prefixes = new TreeSet<>(Util.getMetaComparator().reversed());
|
||||
SortedSet<Map.Entry<Integer, String>> suffixes = new TreeSet<>(Util.getMetaComparator().reversed());
|
||||
|
||||
for (Node node : group.getAllNodes(null)) {
|
||||
if (!node.isSuffix() && !node.isPrefix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (node.isServerSpecific()) {
|
||||
if (node.isWorldSpecific()) {
|
||||
sb.append("&6W=").append(node.getWorld().get()).append(" ");
|
||||
}
|
||||
sb.append("&6S=").append(node.getServer().get()).append(" ");
|
||||
}
|
||||
|
||||
if (node.isPrefix()) {
|
||||
sb.append(node.getPrefix().getValue());
|
||||
prefixes.add(new AbstractMap.SimpleEntry<>(node.getPrefix().getKey(), sb.toString()));
|
||||
}
|
||||
|
||||
if (node.isSuffix()) {
|
||||
sb.append(node.getSuffix().getValue());
|
||||
suffixes.add(new AbstractMap.SimpleEntry<>(node.getSuffix().getKey(), sb.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (prefixes.isEmpty()) {
|
||||
Message.CHAT_META_PREFIX_NONE.send(sender, group.getName());
|
||||
} else {
|
||||
Message.CHAT_META_PREFIX_HEADER.send(sender, group.getName());
|
||||
for (Map.Entry<Integer, String> e : prefixes) {
|
||||
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (suffixes.isEmpty()) {
|
||||
Message.CHAT_META_SUFFIX_NONE.send(sender, group.getName());
|
||||
} else {
|
||||
Message.CHAT_META_SUFFIX_HEADER.send(sender, group.getName());
|
||||
for (Map.Entry<Integer, String> e : suffixes) {
|
||||
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -30,8 +30,6 @@ import me.lucko.luckperms.groups.Group;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
public class GroupListNodes extends SubCommand<Group> {
|
||||
public GroupListNodes() {
|
||||
super("listnodes", "Lists the permission nodes the group has", "/%s group <group> listnodes",
|
||||
@@ -40,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(exportToLegacy(group.getPermanentNodes())));
|
||||
Message.LISTNODES_TEMP.send(sender, group.getName(), Util.tempNodesToString(group.getTemporaryNodesLegacy()));
|
||||
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;
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupRemovePrefix extends SubCommand<Group> {
|
||||
public GroupRemovePrefix() {
|
||||
super("removeprefix", "Removes a prefix from a group", "/%s group <group> removeprefix <priority> <prefix> [server] [world]",
|
||||
Permission.GROUP_REMOVEPREFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
final String prefix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
group.unsetPermission(node, server);
|
||||
Message.REMOVEPREFIX_SERVER_SUCCESS.send(sender, group.getName(), prefix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removeprefix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
group.unsetPermission(node, server, world);
|
||||
Message.REMOVEPREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), prefix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removeprefix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.unsetPermission(node);
|
||||
Message.REMOVEPREFIX_SUCCESS.send(sender, group.getName(), prefix, priority);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removeprefix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.DOES_NOT_HAVE_PREFIX.send(sender, group.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupRemoveSuffix extends SubCommand<Group> {
|
||||
public GroupRemoveSuffix() {
|
||||
super("removesuffix", "Removes a suffix from a group", "/%s group <group> removesuffix <priority> <suffix> [server] [world]",
|
||||
Permission.GROUP_REMOVESUFFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
final String suffix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
group.unsetPermission(node, server);
|
||||
Message.REMOVESUFFIX_SERVER_SUCCESS.send(sender, group.getName(), suffix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removesuffix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
group.unsetPermission(node, server, world);
|
||||
Message.REMOVESUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), suffix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removesuffix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.unsetPermission(node);
|
||||
Message.REMOVESUFFIX_SUCCESS.send(sender, group.getName(), suffix, priority);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removesuffix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.DOES_NOT_HAVE_SUFFIX.send(sender, group.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupRemoveTempPrefix extends SubCommand<Group> {
|
||||
public GroupRemoveTempPrefix() {
|
||||
super("removetempprefix", "Removes a temporary prefix from a group", "/%s group <group> removetempprefix <priority> <prefix> [server] [world]",
|
||||
Permission.GROUP_REMOVE_TEMP_PREFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
final String prefix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
group.unsetPermission(node, server, true);
|
||||
Message.REMOVE_TEMP_PREFIX_SERVER_SUCCESS.send(sender, group.getName(), prefix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removetempprefix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
group.unsetPermission(node, server, world, true);
|
||||
Message.REMOVE_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), prefix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removetempprefix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.unsetPermission(node, true);
|
||||
Message.REMOVE_TEMP_PREFIX_SUCCESS.send(sender, group.getName(), prefix, priority);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removetempprefix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.DOES_NOT_HAVE_PREFIX.send(sender, group.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupRemoveTempSuffix extends SubCommand<Group> {
|
||||
public GroupRemoveTempSuffix() {
|
||||
super("removetempsuffix", "Removes a temporary suffix from a group", "/%s group <group> removetempsuffix <priority> <suffix> [server] [world]",
|
||||
Permission.GROUP_REMOVE_TEMP_SUFFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
final String suffix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
group.unsetPermission(node, server, true);
|
||||
Message.REMOVE_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, group.getName(), suffix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removetempsuffix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
group.unsetPermission(node, server, world, true);
|
||||
Message.REMOVE_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), suffix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removetempsuffix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.unsetPermission(node, true);
|
||||
Message.REMOVE_TEMP_SUFFIX_SUCCESS.send(sender, group.getName(), suffix, priority);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("removetempsuffix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.DOES_NOT_HAVE_SUFFIX.send(sender, group.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public class LogExport extends SubCommand<Log> {
|
||||
break track;
|
||||
}
|
||||
|
||||
b.append("track ").append(e.getActedName()).append(" ").append(e.getAction());;
|
||||
b.append("track ").append(e.getActedName()).append(" ").append(e.getAction());
|
||||
}
|
||||
|
||||
data.add(b.toString());
|
||||
|
||||
@@ -66,6 +66,11 @@ public class MigrationMainCommand extends MainCommand<Object> {
|
||||
subCommands.add(new MigrationBungeePerms());
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
try {
|
||||
Class.forName("de.bananaco.bpermissions.api.WorldManager");
|
||||
subCommands.add(new MigrationBPermissions());
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
package me.lucko.luckperms.commands.migration.subcommands;
|
||||
|
||||
import de.bananaco.bpermissions.api.*;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
import static me.lucko.luckperms.constants.Permission.MIGRATION;
|
||||
|
||||
public class MigrationBPermissions extends SubCommand<Object> {
|
||||
private static Field uConfigField;
|
||||
private static Method getConfigurationSectionMethod = null;
|
||||
private static Method getKeysMethod = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
uConfigField = Class.forName("de.bananaco.bpermissions.imp.YamlWorld").getDeclaredField("uconfig");
|
||||
uConfigField.setAccessible(true);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Set<String> getUsers(World world) {
|
||||
try {
|
||||
Object yamlWorldUsers = uConfigField.get(world);
|
||||
if (getConfigurationSectionMethod == null) {
|
||||
getConfigurationSectionMethod = yamlWorldUsers.getClass().getMethod("getConfigurationSection", String.class);
|
||||
getConfigurationSectionMethod.setAccessible(true);
|
||||
}
|
||||
|
||||
Object configSection = getConfigurationSectionMethod.invoke(yamlWorldUsers, "users");
|
||||
if (configSection == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
if (getKeysMethod == null) {
|
||||
getKeysMethod = configSection.getClass().getMethod("getKeys", boolean.class);
|
||||
getKeysMethod.setAccessible(true);
|
||||
}
|
||||
|
||||
return (Set<String>) getKeysMethod.invoke(configSection, false);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public MigrationBPermissions() {
|
||||
super("bpermissions", "Migration from bPermissions", "/%s migration bpermissions", MIGRATION, Predicate.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
|
||||
final Logger log = plugin.getLog();
|
||||
|
||||
WorldManager worldManager = WorldManager.getInstance();
|
||||
if (worldManager == null) {
|
||||
log.severe("bPermissions Migration: Error -> bPermissions is not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
log.info("bPermissions Migration: Forcing the plugin to load all data. This could take a while.");
|
||||
for (World world : worldManager.getAllWorlds()) {
|
||||
Set<String> users = getUsers(world);
|
||||
if (users == null) {
|
||||
log.severe("bPermissions Migration: Couldn't get a list of users.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
users.forEach(s -> world.loadOne(s, CalculableType.USER));
|
||||
}
|
||||
|
||||
// Migrate one world at a time.
|
||||
log.info("bPermissions Migration: Starting world migration.");
|
||||
for (World world : worldManager.getAllWorlds()) {
|
||||
log.info("bPermissions Migration: Migrating world: " + world.getName());
|
||||
|
||||
// Migrate all groups
|
||||
log.info("bPermissions Migration: Starting group migration in world " + world.getName() + ".");
|
||||
int groupCount = 0;
|
||||
for (Calculable group : world.getAll(CalculableType.GROUP)) {
|
||||
groupCount++;
|
||||
String groupName = group.getName().toLowerCase();
|
||||
if (group.getName().equalsIgnoreCase(world.getDefaultGroup())) {
|
||||
groupName = "default";
|
||||
}
|
||||
|
||||
// Make a LuckPerms group for the one being migrated.
|
||||
plugin.getDatastore().createAndLoadGroup(groupName);
|
||||
me.lucko.luckperms.groups.Group lpGroup = plugin.getGroupManager().get(groupName);
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("create")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
migrateHolder(plugin, world, group, lpGroup);
|
||||
plugin.getDatastore().saveGroup(lpGroup);
|
||||
}
|
||||
log.info("bPermissions Migration: Migrated " + groupCount + " groups in world " + world.getName() + ".");
|
||||
|
||||
// Migrate all users
|
||||
log.info("bPermissions Migration: Starting user migration in world " + world.getName() + ".");
|
||||
int userCount = 0;
|
||||
for (Calculable user : world.getAll(CalculableType.USER)) {
|
||||
userCount++;
|
||||
|
||||
// There is no mention of UUIDs in the API. I assume that name = uuid. idk?
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = UUID.fromString(user.getName());
|
||||
} catch (IllegalArgumentException e) {
|
||||
uuid = plugin.getUUID(user.getName());
|
||||
}
|
||||
|
||||
if (uuid == null) {
|
||||
log.info("bPermissions Migration: Unable to migrate user " + user.getName() + ". Unable to get UUID.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make a LuckPerms user for the one being migrated.
|
||||
plugin.getDatastore().loadUser(uuid, "null");
|
||||
me.lucko.luckperms.users.User lpUser = plugin.getUserManager().get(uuid);
|
||||
|
||||
migrateHolder(plugin, world, user, lpUser);
|
||||
|
||||
plugin.getDatastore().saveUser(lpUser);
|
||||
plugin.getUserManager().cleanup(lpUser);
|
||||
}
|
||||
|
||||
log.info("bPermissions Migration: Migrated " + userCount + " users in world " + world.getName() + ".");
|
||||
}
|
||||
|
||||
log.info("bPermissions Migration: Success! Completed without any errors.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static void migrateHolder(LuckPermsPlugin plugin, World world, Calculable c, PermissionHolder holder) {
|
||||
// Migrate the groups permissions in this world
|
||||
for (Permission p : c.getPermissions()) {
|
||||
try {
|
||||
holder.setPermission(p.name(), p.isTrue(), "global", world.getName());
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + p.name() + " " + p.isTrue() + " global " + world.getName())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Include any child permissions
|
||||
for (Map.Entry<String, Boolean> child : p.getChildren().entrySet()) {
|
||||
try {
|
||||
holder.setPermission(child.getKey(), child.getValue(), "global", world.getName());
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + child.getKey() + " " + child.getValue() + " global " + world.getName())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate any inherited groups
|
||||
for (Group parent : c.getGroups()) {
|
||||
try {
|
||||
holder.setPermission("group." + parent.getName(), true, "global", world.getName());
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("setinherit " + parent.getName() + " global " + world.getName())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate existing meta
|
||||
for (Map.Entry<String, String> meta : c.getMeta().entrySet()) {
|
||||
if (meta.getKey().equalsIgnoreCase("prefix") || meta.getKey().equalsIgnoreCase("suffix")) {
|
||||
String chatMeta = ArgumentChecker.escapeCharacters(meta.getValue());
|
||||
try {
|
||||
holder.setPermission(meta.getKey().toLowerCase() + "." + c.getPriority() + "." + chatMeta, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + meta.getKey().toLowerCase() + "." + c.getPriority() + "." + chatMeta + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission("meta." + meta.getKey() + "." + meta.getValue(), true, "global", world.getName());
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set meta." + meta.getKey() + "." + meta.getValue() + " true global " + world.getName())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
-50
@@ -24,6 +24,7 @@ package me.lucko.luckperms.commands.migration.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.PlatformType;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
@@ -43,41 +44,11 @@ import ru.tehkode.permissions.bukkit.PermissionsEx;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
|
||||
private static Class<?> bukkitPlayer = null;
|
||||
private static Method getUniqueIdMethod = null;
|
||||
private static Method getPlayerMethod = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
bukkitPlayer = Class.forName("org.bukkit.entity.Player");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (bukkitPlayer != null) {
|
||||
try {
|
||||
getUniqueIdMethod = bukkitPlayer.getMethod("getUniqueId");
|
||||
getUniqueIdMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
getPlayerMethod = PermissionUser.class.getMethod("getPlayer");
|
||||
getPlayerMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public MigrationPermissionsEx() {
|
||||
super("permissionsex", "Migration from PermissionsEx", "/%s migration permissionsex [world names]",
|
||||
Permission.MIGRATION, Predicate.alwaysFalse());
|
||||
@@ -92,7 +63,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
if (plugin.getType() != LuckPermsPlugin.Type.BUKKIT) {
|
||||
if (plugin.getType() != PlatformType.BUKKIT) {
|
||||
// Sponge uses a completely different version of PEX.
|
||||
log.severe("PEX import is not supported on this platform.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
@@ -123,9 +94,15 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
|
||||
// Migrate all groups.
|
||||
log.info("PermissionsEx Migration: Starting group migration.");
|
||||
|
||||
int maxGroupWeight = 0;
|
||||
int groupCount = 0;
|
||||
|
||||
for (PermissionGroup group : manager.getGroupList()) {
|
||||
int groupWeight = group.getWeight() * -1;
|
||||
groupCount ++;
|
||||
maxGroupWeight = Math.max(maxGroupWeight, groupWeight);
|
||||
|
||||
final String name = group.getName().toLowerCase();
|
||||
plugin.getDatastore().createAndLoadGroup(name);
|
||||
Group lpGroup = plugin.getGroupManager().get(name);
|
||||
@@ -224,10 +201,10 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
if (prefix != null && !prefix.equals("")) {
|
||||
prefix = ArgumentChecker.escapeCharacters(prefix);
|
||||
try {
|
||||
lpGroup.setPermission("prefix.50." + prefix, true);
|
||||
lpGroup.setPermission("prefix." + groupWeight + "." + prefix, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("set prefix.50." + prefix + " true")
|
||||
.acted(lpGroup).action("set prefix." + groupWeight + "." + prefix + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
@@ -239,10 +216,10 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
if (suffix != null && !suffix.equals("")) {
|
||||
suffix = ArgumentChecker.escapeCharacters(suffix);
|
||||
try {
|
||||
lpGroup.setPermission("suffix.50." + suffix, true);
|
||||
lpGroup.setPermission("suffix." + groupWeight + "." + suffix, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("set suffix.50." + suffix + " true")
|
||||
.acted(lpGroup).action("set suffix." + groupWeight + "." + suffix + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
@@ -251,6 +228,8 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getDatastore().saveGroup(lpGroup);
|
||||
|
||||
}
|
||||
|
||||
log.info("PermissionsEx Migration: Migrated " + groupCount + " groups");
|
||||
@@ -258,25 +237,16 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
// Migrate all users
|
||||
log.info("PermissionsEx Migration: Starting user migration.");
|
||||
int userCount = 0;
|
||||
maxGroupWeight++;
|
||||
for (PermissionUser user : manager.getUsers()) {
|
||||
UUID u = null;
|
||||
|
||||
try {
|
||||
u = UUID.fromString(user.getIdentifier());
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
u = ni.nameToUUID(user.getIdentifier());
|
||||
|
||||
if (u == null) {
|
||||
if (bukkitPlayer != null) {
|
||||
try {
|
||||
Object playerObj = getPlayerMethod.invoke(user);
|
||||
u = (UUID) getUniqueIdMethod.invoke(playerObj);
|
||||
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
u = plugin.getUUID(user.getIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,10 +345,10 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
if (prefix != null && !prefix.equals("")) {
|
||||
prefix = ArgumentChecker.escapeCharacters(prefix);
|
||||
try {
|
||||
lpUser.setPermission("prefix.100." + prefix, true);
|
||||
lpUser.setPermission("prefix." + maxGroupWeight + "." + prefix, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpUser).action("set prefix.100." + prefix + " true")
|
||||
.acted(lpUser).action("set prefix." + maxGroupWeight + "." + prefix + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
@@ -390,10 +360,10 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
if (suffix != null && !suffix.equals("")) {
|
||||
suffix = ArgumentChecker.escapeCharacters(suffix);
|
||||
try {
|
||||
lpUser.setPermission("suffix.100." + suffix, true);
|
||||
lpUser.setPermission("suffix." + maxGroupWeight + "." + suffix, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpUser).action("set suffix.100." + suffix + " true")
|
||||
.acted(lpUser).action("set suffix." + maxGroupWeight + "." + suffix + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
@@ -402,6 +372,22 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
}
|
||||
}
|
||||
|
||||
String primary = null;
|
||||
int weight = -100;
|
||||
for (PermissionGroup group : user.getOwnParents()) {
|
||||
if (group.getRank() > weight) {
|
||||
primary = group.getName();
|
||||
weight = group.getWeight();
|
||||
}
|
||||
}
|
||||
|
||||
if (primary != null) {
|
||||
try {
|
||||
lpUser.setPermission("group." + primary.toLowerCase(), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
lpUser.setPrimaryGroup(primary);
|
||||
}
|
||||
|
||||
plugin.getUserManager().cleanup(lpUser);
|
||||
plugin.getDatastore().saveUser(lpUser);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,15 @@ public class UserMainCommand extends MainCommand<User> {
|
||||
.add(new UserPromote())
|
||||
.add(new UserDemote())
|
||||
.add(new UserShowPos())
|
||||
.add(new UserChatMeta())
|
||||
.add(new UserAddPrefix())
|
||||
.add(new UserAddSuffix())
|
||||
.add(new UserRemovePrefix())
|
||||
.add(new UserRemoveSuffix())
|
||||
.add(new UserAddTempPrefix())
|
||||
.add(new UserAddTempSuffix())
|
||||
.add(new UserRemoveTempPrefix())
|
||||
.add(new UserRemoveTempSuffix())
|
||||
.add(new UserClear())
|
||||
.build()
|
||||
);
|
||||
@@ -84,7 +93,10 @@ public class UserMainCommand extends MainCommand<User> {
|
||||
}
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadUser(u, "null")) {
|
||||
String name = plugin.getDatastore().getName(u);
|
||||
if (name == null) name = "null";
|
||||
|
||||
if (!plugin.getDatastore().loadUser(u, name)) {
|
||||
Message.LOADING_ERROR.send(sender);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserAddPrefix extends SubCommand<User> {
|
||||
public UserAddPrefix() {
|
||||
super("addprefix", "Adds a prefix to the user", "/%s user <user> addprefix <priority> <prefix> [server] [world]",
|
||||
Permission.USER_ADDPREFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
final String prefix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
user.setPermission(node, true, server);
|
||||
Message.ADDPREFIX_SERVER_SUCCESS.send(sender, user.getName(), prefix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addprefix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
user.setPermission(node, true, server, world);
|
||||
Message.ADDPREFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), prefix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addprefix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.setPermission(node, true);
|
||||
Message.ADDPREFIX_SUCCESS.send(sender, user.getName(), prefix, priority);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addprefix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.ALREADY_HAS_PREFIX.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserAddSuffix extends SubCommand<User> {
|
||||
public UserAddSuffix() {
|
||||
super("addsuffix", "Adds a suffix to the user", "/%s user <user> addsuffix <priority> <suffix> [server] [world]",
|
||||
Permission.USER_ADDSUFFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
final String suffix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
user.setPermission(node, true, server);
|
||||
Message.ADDSUFFIX_SERVER_SUCCESS.send(sender, user.getName(), suffix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addsuffix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
user.setPermission(node, true, server, world);
|
||||
Message.ADDSUFFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), suffix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addsuffix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.setPermission(node, true);
|
||||
Message.ADDSUFFIX_SUCCESS.send(sender, user.getName(), suffix, priority);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addsuffix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.ALREADY_HAS_SUFFIX.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
import me.lucko.luckperms.utils.DateUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserAddTempPrefix extends SubCommand<User> {
|
||||
public UserAddTempPrefix() {
|
||||
super("addtempprefix", "Adds a prefix to the user temporarily", "/%s user <user> addtempprefix <priority> <prefix> <duration> [server] [world]",
|
||||
Permission.USER_ADD_TEMP_PREFIX, Predicate.notInRange(3, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
final String prefix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
long duration;
|
||||
try {
|
||||
duration = Long.parseLong(args.get(2));
|
||||
} catch (NumberFormatException e) {
|
||||
try {
|
||||
duration = DateUtil.parseDateDiff(args.get(2), true);
|
||||
} catch (DateUtil.IllegalDateException e1) {
|
||||
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
if (DateUtil.shouldExpire(duration)) {
|
||||
Message.PAST_DATE_ERROR.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 4) {
|
||||
final String server = args.get(3).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 4) {
|
||||
user.setPermission(node, true, server, duration);
|
||||
Message.ADD_TEMP_PREFIX_SERVER_SUCCESS.send(sender, user.getName(), prefix, priority, server, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(4).toLowerCase();
|
||||
user.setPermission(node, true, server, world, duration);
|
||||
Message.ADD_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), prefix, priority, server, world, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.setPermission(node, true, duration);
|
||||
Message.ADD_TEMP_PREFIX_SUCCESS.send(sender, user.getName(), prefix, priority, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.ALREADY_HAS_PREFIX.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
import me.lucko.luckperms.utils.DateUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserAddTempSuffix extends SubCommand<User> {
|
||||
public UserAddTempSuffix() {
|
||||
super("addtempsuffix", "Adds a suffix to the user temporarily", "/%s user <user> addtempsuffix <priority> <suffix> <duration> [server] [world]",
|
||||
Permission.USER_ADD_TEMP_SUFFIX, Predicate.notInRange(3, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
final String suffix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
long duration;
|
||||
try {
|
||||
duration = Long.parseLong(args.get(2));
|
||||
} catch (NumberFormatException e) {
|
||||
try {
|
||||
duration = DateUtil.parseDateDiff(args.get(2), true);
|
||||
} catch (DateUtil.IllegalDateException e1) {
|
||||
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
if (DateUtil.shouldExpire(duration)) {
|
||||
Message.PAST_DATE_ERROR.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 4) {
|
||||
final String server = args.get(3).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 4) {
|
||||
user.setPermission(node, true, server, duration);
|
||||
Message.ADD_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, user.getName(), suffix, priority, server, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(4).toLowerCase();
|
||||
user.setPermission(node, true, server, world, duration);
|
||||
Message.ADD_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), suffix, priority, server, world, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.setPermission(node, true, duration);
|
||||
Message.ADD_TEMP_SUFFIX_SUCCESS.send(sender, user.getName(), suffix, priority, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.ALREADY_HAS_SUFFIX.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.commands.*;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class UserChatMeta extends SubCommand<User> {
|
||||
public UserChatMeta() {
|
||||
super("chatmeta", "Displays a users chat meta", "/%s user <user> chatmeta", Permission.USER_CHATMETA,
|
||||
Predicate.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
SortedSet<Map.Entry<Integer, String>> prefixes = new TreeSet<>(Util.getMetaComparator().reversed());
|
||||
SortedSet<Map.Entry<Integer, String>> suffixes = new TreeSet<>(Util.getMetaComparator().reversed());
|
||||
|
||||
for (Node node : user.getAllNodes(null)) {
|
||||
if (!node.isSuffix() && !node.isPrefix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (node.isServerSpecific()) {
|
||||
if (node.isWorldSpecific()) {
|
||||
sb.append("&6W=").append(node.getWorld().get()).append(" ");
|
||||
}
|
||||
sb.append("&6S=").append(node.getServer().get()).append(" ");
|
||||
}
|
||||
|
||||
if (node.isPrefix()) {
|
||||
sb.append(node.getPrefix().getValue());
|
||||
prefixes.add(new SimpleEntry<>(node.getPrefix().getKey(), sb.toString()));
|
||||
}
|
||||
|
||||
if (node.isSuffix()) {
|
||||
sb.append(node.getSuffix().getValue());
|
||||
suffixes.add(new SimpleEntry<>(node.getSuffix().getKey(), sb.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (prefixes.isEmpty()) {
|
||||
Message.CHAT_META_PREFIX_NONE.send(sender, user.getName());
|
||||
} else {
|
||||
Message.CHAT_META_PREFIX_HEADER.send(sender, user.getName());
|
||||
for (Map.Entry<Integer, String> e : prefixes) {
|
||||
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (suffixes.isEmpty()) {
|
||||
Message.CHAT_META_SUFFIX_NONE.send(sender, user.getName());
|
||||
} else {
|
||||
Message.CHAT_META_SUFFIX_HEADER.send(sender, user.getName());
|
||||
for (Map.Entry<Integer, String> e : suffixes) {
|
||||
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -30,8 +30,6 @@ import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
public class UserListNodes extends SubCommand<User> {
|
||||
public UserListNodes() {
|
||||
super("listnodes", "Lists the permission nodes the user has", "/%s user <user> listnodes",
|
||||
@@ -40,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(exportToLegacy(user.getPermanentNodes())));
|
||||
Message.LISTNODES_TEMP.send(sender, user.getName(), Util.tempNodesToString(user.getTemporaryNodesLegacy()));
|
||||
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;
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserRemovePrefix extends SubCommand<User> {
|
||||
public UserRemovePrefix() {
|
||||
super("removeprefix", "Removes a prefix from a user", "/%s user <user> removeprefix <priority> <prefix> [server] [world]",
|
||||
Permission.USER_REMOVEPREFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
final String prefix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
user.unsetPermission(node, server);
|
||||
Message.REMOVEPREFIX_SERVER_SUCCESS.send(sender, user.getName(), prefix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removeprefix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
user.unsetPermission(node, server, world);
|
||||
Message.REMOVEPREFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), prefix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removeprefix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.unsetPermission(node);
|
||||
Message.REMOVEPREFIX_SUCCESS.send(sender, user.getName(), prefix, priority);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removeprefix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.DOES_NOT_HAVE_PREFIX.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserRemoveSuffix extends SubCommand<User> {
|
||||
public UserRemoveSuffix() {
|
||||
super("removesuffix", "Removes a suffix from a user", "/%s user <user> removesuffix <priority> <suffix> [server] [world]",
|
||||
Permission.USER_REMOVESUFFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
final String suffix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
user.unsetPermission(node, server);
|
||||
Message.REMOVESUFFIX_SERVER_SUCCESS.send(sender, user.getName(), suffix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removesuffix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
user.unsetPermission(node, server, world);
|
||||
Message.REMOVESUFFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), suffix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removesuffix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.unsetPermission(node);
|
||||
Message.REMOVESUFFIX_SUCCESS.send(sender, user.getName(), suffix, priority);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removesuffix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.DOES_NOT_HAVE_SUFFIX.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserRemoveTempPrefix extends SubCommand<User> {
|
||||
public UserRemoveTempPrefix() {
|
||||
super("removetempprefix", "Removes a temporary prefix from a user", "/%s user <user> removetempprefix <priority> <prefix> [server] [world]",
|
||||
Permission.USER_REMOVE_TEMP_PREFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
final String prefix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
user.unsetPermission(node, server, true);
|
||||
Message.REMOVE_TEMP_PREFIX_SERVER_SUCCESS.send(sender, user.getName(), prefix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removetempprefix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
user.unsetPermission(node, server, world, true);
|
||||
Message.REMOVE_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), prefix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removetempprefix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.unsetPermission(node, true);
|
||||
Message.REMOVE_TEMP_PREFIX_SUCCESS.send(sender, user.getName(), prefix, priority);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removetempprefix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.DOES_NOT_HAVE_PREFIX.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserRemoveTempSuffix extends SubCommand<User> {
|
||||
public UserRemoveTempSuffix() {
|
||||
super("removetempsuffix", "Removes a temporary suffix from a user", "/%s user <user> removetempsuffix <priority> <suffix> [server] [world]",
|
||||
Permission.USER_REMOVE_TEMP_SUFFIX, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
final String suffix = args.get(1).replace("{SPACE}", " ");
|
||||
int priority;
|
||||
try {
|
||||
priority = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
user.unsetPermission(node, server, true);
|
||||
Message.REMOVE_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, user.getName(), suffix, priority, server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removetempsuffix " + priority + " " + args.get(1) + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
user.unsetPermission(node, server, world, true);
|
||||
Message.REMOVE_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), suffix, priority, server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removetempsuffix " + priority + " " + args.get(1) + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.unsetPermission(node, true);
|
||||
Message.REMOVE_TEMP_SUFFIX_SUCCESS.send(sender, user.getName(), suffix, priority);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removetempsuffix " + priority + " " + args.get(1))
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.DOES_NOT_HAVE_SUFFIX.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -30,6 +30,7 @@ import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
@@ -55,8 +56,10 @@ public class UserSetPrimaryGroup extends SubCommand<User> {
|
||||
}
|
||||
|
||||
if (!user.isInGroup(group)) {
|
||||
Message.USER_PRIMARYGROUP_ERROR_NOTMEMBER.send(sender, label);
|
||||
return CommandResult.STATE_ERROR;
|
||||
Message.USER_PRIMARYGROUP_ERROR_NOTMEMBER.send(sender, user.getName(), group.getName());
|
||||
try {
|
||||
user.addGroup(group);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
}
|
||||
|
||||
user.setPrimaryGroup(group.getName());
|
||||
|
||||
@@ -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),
|
||||
@@ -168,6 +169,46 @@ public enum Message {
|
||||
ILLEGAL_DATE_ERROR("Could not parse date '%s'.", true),
|
||||
PAST_DATE_ERROR("You cannot set a date in the past!", true),
|
||||
|
||||
CHAT_META_PREFIX_HEADER("&e%s's Prefixes", true),
|
||||
CHAT_META_SUFFIX_HEADER("&e%s's Suffixes", true),
|
||||
CHAT_META_ENTRY("&d-> &e%s &6- &f\"%s&f\"", true),
|
||||
CHAT_META_PREFIX_NONE("&e%s has no prefixes.", true),
|
||||
CHAT_META_SUFFIX_NONE("&e%s has no suffixes.", true),
|
||||
|
||||
META_INVALID_PRIORITY("Invalid priority '%s'. Expected a number.", true),
|
||||
ALREADY_HAS_PREFIX("%s already has that prefix set.", true),
|
||||
ALREADY_HAS_SUFFIX("%s already has that suffix set.", true),
|
||||
DOES_NOT_HAVE_PREFIX("%s doesn't have that prefix set.", true),
|
||||
DOES_NOT_HAVE_SUFFIX("%s doesn't have that suffix set.", true),
|
||||
|
||||
ADDPREFIX_SUCCESS("&b%s&a had prefix &f\"%s&f\"&a set at a priority of &b%s&a.", true),
|
||||
ADDPREFIX_SERVER_SUCCESS("&b%s&a had prefix &f\"%s&f\"&a set at a priority of &b%s&a on server &b%s&a.", true),
|
||||
ADDPREFIX_SERVER_WORLD_SUCCESS("&b%s&a had prefix &f\"%s&f\"&a set at a priority of &b%s&a on server &b%s&a, world &b%s&a.", true),
|
||||
REMOVEPREFIX_SUCCESS("&b%s&a had prefix &f\"%s&f\"&a at priority &b%s&a removed.", true),
|
||||
REMOVEPREFIX_SERVER_SUCCESS("&b%s&a had prefix &f\"%s&f\"&a at priority &b%s&a removed on server &b%s&a.", true),
|
||||
REMOVEPREFIX_SERVER_WORLD_SUCCESS("&b%s&a had prefix &f\"%s&f\"&a at priority &b%s&a removed on server &b%s&a, world &b%s&a.", true),
|
||||
|
||||
ADDSUFFIX_SUCCESS("&b%s&a had suffix &f\"%s&f\"&a set at a priority of &b%s&a.", true),
|
||||
ADDSUFFIX_SERVER_SUCCESS("&b%s&a had suffix &f\"%s&f\"&a set at a priority of &b%s&a on server &b%s&a.", true),
|
||||
ADDSUFFIX_SERVER_WORLD_SUCCESS("&b%s&a had suffix &f\"%s&f\"&a set at a priority of &b%s&a on server &b%s&a, world &b%s&a.", true),
|
||||
REMOVESUFFIX_SUCCESS("&b%s&a had suffix &f\"%s&f\"&a at priority &b%s&a removed.", true),
|
||||
REMOVESUFFIX_SERVER_SUCCESS("&b%s&a had suffix &f\"%s&f\"&a at priority &b%s&a removed on server &b%s&a.", true),
|
||||
REMOVESUFFIX_SERVER_WORLD_SUCCESS("&b%s&a had suffix &f\"%s&f\"&a at priority &b%s&a removed on server &b%s&a, world &b%s&a.", true),
|
||||
|
||||
ADD_TEMP_PREFIX_SUCCESS("&b%s&a had prefix &f\"%s&f\"&a set at a priority of &b%s&a for a duration of &b%s&a.", true),
|
||||
ADD_TEMP_PREFIX_SERVER_SUCCESS("&b%s&a had prefix &f\"%s&f\"&a set at a priority of &b%s&a on server &b%s&a, for a duration of &b%s&a.", true),
|
||||
ADD_TEMP_PREFIX_SERVER_WORLD_SUCCESS("&b%s&a had prefix &f\"%s&f\"&a set at a priority of &b%s&a on server &b%s&a, world &b%s&a, for a duration of &b%s&a.", true),
|
||||
REMOVE_TEMP_PREFIX_SUCCESS("&b%s&a had temporary prefix &f\"%s&f\"&a at priority &b%s&a removed.", true),
|
||||
REMOVE_TEMP_PREFIX_SERVER_SUCCESS("&b%s&a had temporary prefix &f\"%s&f\"&a at priority &b%s&a removed on server &b%s&a.", true),
|
||||
REMOVE_TEMP_PREFIX_SERVER_WORLD_SUCCESS("&b%s&a had temporary prefix &f\"%s&f\"&a at priority &b%s&a removed on server &b%s&a, world &b%s&a.", true),
|
||||
|
||||
ADD_TEMP_SUFFIX_SUCCESS("&b%s&a had suffix &f\"%s&f\"&a set at a priority of &b%s&a for a duration of &b%s&a.", true),
|
||||
ADD_TEMP_SUFFIX_SERVER_SUCCESS("&b%s&a had suffix &f\"%s&f\"&a set at a priority of &b%s&a on server &b%s&a, for a duration of &b%s&a.", true),
|
||||
ADD_TEMP_SUFFIX_SERVER_WORLD_SUCCESS("&b%s&a had suffix &f\"%s&f\"&a set at a priority of &b%s&a on server &b%s&a, world &b%s&a, for a duration of &b%s&a.", true),
|
||||
REMOVE_TEMP_SUFFIX_SUCCESS("&b%s&a had temporary suffix &f\"%s&f\"&a at priority &b%s&a removed.", true),
|
||||
REMOVE_TEMP_SUFFIX_SERVER_SUCCESS("&b%s&a had temporary suffix &f\"%s&f\"&a at priority &b%s&a removed on server &b%s&a.", true),
|
||||
REMOVE_TEMP_SUFFIX_SERVER_WORLD_SUCCESS("&b%s&a had temporary suffix &f\"%s&f\"&a at priority &b%s&a removed on server &b%s&a, world &b%s&a.", true),
|
||||
|
||||
USER_INFO(
|
||||
PREFIX + "&d-> &eUser: &6%s" + "\n" +
|
||||
PREFIX + "&d-> &eUUID: &6%s" + "\n" +
|
||||
@@ -195,7 +236,7 @@ public enum Message {
|
||||
USER_REMOVEGROUP_ERROR_PRIMARY("You cannot remove a user from their primary group.", true),
|
||||
USER_PRIMARYGROUP_SUCCESS("&b%s&a's primary group was set to &b%s&a.", true),
|
||||
USER_PRIMARYGROUP_ERROR_ALREADYHAS("The user already has this group set as their primary group.", true),
|
||||
USER_PRIMARYGROUP_ERROR_NOTMEMBER("The user must be a member of the group first! Use &4/%s user <user> addgroup <group>", true),
|
||||
USER_PRIMARYGROUP_ERROR_NOTMEMBER("&b%s&a was not already a member of &b%s&a, adding them now.", true),
|
||||
USER_SHOWTRACKS_INFO("&aShowing tracks that contain the group '&b%s&a' (%s's primary group)", true),
|
||||
USER_PROMOTE_SUCCESS_PROMOTE("&aPromoting user along track &b%s&a from &b%s&a to &b%s&a.", true),
|
||||
USER_PROMOTE_SUCCESS_REMOVE("&b%s&a was removed from &b%s&a, added to &b%s&a, and their primary group was set to &b%s&a.", true),
|
||||
|
||||
@@ -40,7 +40,7 @@ public class Patterns {
|
||||
public static final Pattern DOT = Pattern.compile("\\.");
|
||||
public static final Pattern VERTICAL_BAR = Pattern.compile("\\|");
|
||||
public static final Pattern GROUP_MATCH = Pattern.compile("group\\..*");
|
||||
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[^A-Za-z0-9]");
|
||||
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[\\/\\$\\.\\-]");
|
||||
public static final Pattern NON_USERNAME = Pattern.compile("[^A-Za-z0-9_]");
|
||||
public static final Pattern SHORTHAND_NODE = Pattern.compile("\\.\\([^.]+\\)");
|
||||
public static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf('§') + "[0-9A-FK-OR]");
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -60,6 +62,15 @@ public enum Permission {
|
||||
USER_PROMOTE("promote", "user"),
|
||||
USER_DEMOTE("demote", "user"),
|
||||
USER_SHOWPOS("showpos", "user"),
|
||||
USER_CHATMETA("chatmeta", "user"),
|
||||
USER_ADDPREFIX("addprefix", "user"),
|
||||
USER_REMOVEPREFIX("removeprefix", "user"),
|
||||
USER_ADDSUFFIX("addsuffix", "user"),
|
||||
USER_REMOVESUFFIX("removesuffix", "user"),
|
||||
USER_ADD_TEMP_PREFIX("addtempprefix", "user"),
|
||||
USER_REMOVE_TEMP_PREFIX("removetempprefix", "user"),
|
||||
USER_ADD_TEMP_SUFFIX("addtempsuffix", "user"),
|
||||
USER_REMOVE_TEMP_SUFFIX("removetempsuffix", "user"),
|
||||
USER_CLEAR("clear", "user"),
|
||||
|
||||
GROUP_INFO("info", "group"),
|
||||
@@ -75,6 +86,15 @@ public enum Permission {
|
||||
GROUP_SET_TEMP_INHERIT("settempinherit", "group"),
|
||||
GROUP_UNSET_TEMP_INHERIT("unsettempinherit", "group"),
|
||||
GROUP_SHOWTRACKS("showtracks", "group"),
|
||||
GROUP_CHATMETA("chatmeta", "group"),
|
||||
GROUP_ADDPREFIX("addprefix", "group"),
|
||||
GROUP_REMOVEPREFIX("removeprefix", "group"),
|
||||
GROUP_ADDSUFFIX("addsuffix", "group"),
|
||||
GROUP_REMOVESUFFIX("removesuffix", "group"),
|
||||
GROUP_ADD_TEMP_PREFIX("addtempprefix", "group"),
|
||||
GROUP_REMOVE_TEMP_PREFIX("removetempprefix", "group"),
|
||||
GROUP_ADD_TEMP_SUFFIX("addtempsuffix", "group"),
|
||||
GROUP_REMOVE_TEMP_SUFFIX("removetempsuffix", "group"),
|
||||
GROUP_CLEAR("clear", "group"),
|
||||
GROUP_RENAME("rename", "group"),
|
||||
|
||||
@@ -95,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) {
|
||||
|
||||
@@ -28,6 +28,9 @@ import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.storage.DatastoreConfiguration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class LPConfiguration<T extends LuckPermsPlugin> {
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
@@ -67,17 +70,19 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
|
||||
}
|
||||
|
||||
/**
|
||||
* As of 1.6, this value is a constant
|
||||
* As of 2.6, this value is a constant
|
||||
* @return the default group node
|
||||
*/
|
||||
@SuppressWarnings("SameReturnValue")
|
||||
public String getDefaultGroupNode() {
|
||||
return "group.default";
|
||||
}
|
||||
|
||||
/**
|
||||
* As of 1.6, this value is a constant
|
||||
* As of 2.6, this value is a constant
|
||||
* @return the name of the default group
|
||||
*/
|
||||
@SuppressWarnings("SameReturnValue")
|
||||
public String getDefaultGroupName() {
|
||||
return "default";
|
||||
}
|
||||
@@ -102,6 +107,26 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
|
||||
return getBoolean("apply-shorthand", true);
|
||||
}
|
||||
|
||||
public boolean getLogNotify() {
|
||||
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");
|
||||
}
|
||||
|
||||
public boolean getVaultIncludeGlobal() {
|
||||
return getBoolean("vault-include-global", true);
|
||||
}
|
||||
|
||||
public DatastoreConfiguration getDatabaseValues() {
|
||||
return new DatastoreConfiguration(
|
||||
getString("data.address", null),
|
||||
@@ -114,4 +139,19 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
|
||||
public String getStorageMethod() {
|
||||
return getString("storage-method", defaultStorage);
|
||||
}
|
||||
|
||||
public boolean getSplitStorage() {
|
||||
return getBoolean("split-storage.enabled", false);
|
||||
}
|
||||
|
||||
public Map<String, String> getSplitStorageOptions() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("user", getString("split-storage.methods.user", defaultStorage));
|
||||
map.put("group", getString("split-storage.methods.group", defaultStorage));
|
||||
map.put("track", getString("split-storage.methods.track", defaultStorage));
|
||||
map.put("uuid", getString("split-storage.methods.uuid", defaultStorage));
|
||||
map.put("log", getString("split-storage.methods.log", defaultStorage));
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,6 @@ import me.lucko.luckperms.groups.Group;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -78,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,8 +144,7 @@ public abstract class PermissionHolder {
|
||||
* @return a set of nodes
|
||||
*/
|
||||
public SortedSet<Node> getAllNodes(List<String> excludedGroups) {
|
||||
SortedSet<Node> all = new ConcurrentSkipListSet<>(PRIORITY_COMPARATOR);
|
||||
all.addAll(getPermissions());
|
||||
SortedSet<Node> all = getPermissions(true);
|
||||
|
||||
if (excludedGroups == null) {
|
||||
excludedGroups = new ArrayList<>();
|
||||
@@ -148,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());
|
||||
@@ -192,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;
|
||||
@@ -210,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);
|
||||
}
|
||||
|
||||
@@ -230,6 +242,13 @@ public abstract class PermissionHolder {
|
||||
Map<String, Boolean> perms = new HashMap<>();
|
||||
|
||||
for (Node node : getAllNodesFiltered(server, world, extraContext, includeGlobal, applyGroups)) {
|
||||
if (node.getPermission().equals("*") || node.getPermission().equals("'*'")) {
|
||||
if (possibleNodes != null && plugin.getConfiguration().getApplyWildcards()) {
|
||||
possibleNodes.forEach(n -> perms.put(n, true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
perms.put(node.getPermission(), node.getValue());
|
||||
|
||||
if (plugin.getConfiguration().getApplyShorthand()) {
|
||||
@@ -286,7 +305,7 @@ public abstract class PermissionHolder {
|
||||
|
||||
private static Tristate hasPermission(Set<Node> toQuery, Node node) {
|
||||
for (Node n : toQuery) {
|
||||
if (n.equalsIgnoringValue(node)) {
|
||||
if (n.almostEquals(node)) {
|
||||
return n.getTristate();
|
||||
}
|
||||
}
|
||||
@@ -423,11 +442,17 @@ public abstract class PermissionHolder {
|
||||
* @throws ObjectLacksException if the holder doesn't have this node already
|
||||
*/
|
||||
public void unsetPermission(Node node) throws ObjectLacksException {
|
||||
if (hasPermission(node, false) == Tristate.FALSE) {
|
||||
if (hasPermission(node, false) != Tristate.TRUE) {
|
||||
throw new ObjectLacksException();
|
||||
}
|
||||
|
||||
nodes.remove(node);
|
||||
Iterator<Node> iterator = nodes.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Node entry = iterator.next();
|
||||
if (entry.almostEquals(node)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (node.isGroupNode()) {
|
||||
plugin.getApiProvider().fireEventAsync(new GroupRemoveEvent(new PermissionHolderLink(this),
|
||||
@@ -447,7 +472,13 @@ public abstract class PermissionHolder {
|
||||
throw new ObjectLacksException();
|
||||
}
|
||||
|
||||
transientNodes.remove(node);
|
||||
Iterator<Node> iterator = transientNodes.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Node entry = iterator.next();
|
||||
if (entry.almostEquals(node)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (node.isGroupNode()) {
|
||||
plugin.getApiProvider().fireEventAsync(new GroupRemoveEvent(new PermissionHolderLink(this),
|
||||
@@ -485,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
|
||||
@@ -503,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());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -524,47 +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.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;
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @see me.lucko.luckperms.api.UuidCache
|
||||
* @see me.lucko.luckperms.api.UuidCache for docs
|
||||
*/
|
||||
public class UuidCache {
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ public class Importer {
|
||||
|
||||
running = true;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public void start(Sender executor, List<String> commands) {
|
||||
|
||||
@@ -52,6 +52,7 @@ public class LogEntry extends me.lucko.luckperms.api.LogEntry {
|
||||
plugin.getDatastore().logAction(this);
|
||||
|
||||
LogNotifyEvent event = new LogNotifyEvent(this);
|
||||
event.setCancelled(!plugin.getConfiguration().getLogNotify());
|
||||
plugin.getApiProvider().fireEvent(event);
|
||||
if (event.isCancelled()) return;
|
||||
|
||||
|
||||
@@ -26,17 +26,16 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.event.events.GroupAddEvent;
|
||||
import me.lucko.luckperms.api.implementation.internal.GroupLink;
|
||||
import me.lucko.luckperms.api.implementation.internal.PermissionHolderLink;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.utils.Identifiable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ToString(of = {"name"})
|
||||
@@ -321,10 +320,11 @@ public class Group extends PermissionHolder implements Identifiable<String> {
|
||||
*/
|
||||
private List<String> getGroups(String server, String world, boolean includeGlobal) {
|
||||
// Call super #getPermissions method, and just sort through those
|
||||
Map<String, Boolean> perms = exportNodes(server, world, null, includeGlobal, true, null);
|
||||
return perms.keySet().stream()
|
||||
.filter(s -> Patterns.GROUP_MATCH.matcher(s).matches())
|
||||
.map(s -> Patterns.DOT.split(s, 2)[1])
|
||||
return getNodes().stream()
|
||||
.filter(n -> n.shouldApplyOnWorld(world, includeGlobal, true))
|
||||
.filter(n -> n.shouldApplyOnServer(server, includeGlobal, true))
|
||||
.filter(Node::isGroupNode)
|
||||
.map(Node::getGroupName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,6 @@ public class UpdateTask implements Runnable {
|
||||
// Refresh all online users.
|
||||
plugin.getUserManager().updateAllUsers();
|
||||
|
||||
plugin.getApiProvider().fireEvent(new PostSyncEvent());;
|
||||
plugin.getApiProvider().fireEvent(new PostSyncEvent());
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,7 @@ public abstract class Datastore {
|
||||
public abstract boolean deleteTrack(Track track);
|
||||
public abstract boolean saveUUIDData(String username, UUID uuid);
|
||||
public abstract UUID getUUID(String username);
|
||||
public abstract String getName(UUID uuid);
|
||||
|
||||
|
||||
|
||||
@@ -219,4 +220,11 @@ public abstract class Datastore {
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void getName(UUID uuid, Callback<String> callback) {
|
||||
doAsync(() -> {
|
||||
String result = getName(uuid);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package me.lucko.luckperms.storage;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.data.Log;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SplitDatastore extends Datastore {
|
||||
private final Map<String, Datastore> backing;
|
||||
private final Map<String, String> types;
|
||||
|
||||
protected SplitDatastore(LuckPermsPlugin plugin, Map<String, Datastore> backing, Map<String, String> types) {
|
||||
super(plugin, "Split Storage");
|
||||
this.backing = ImmutableMap.copyOf(backing);
|
||||
this.types = ImmutableMap.copyOf(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
backing.values().forEach(Datastore::init);
|
||||
for (Datastore ds : backing.values()) {
|
||||
if (!ds.isAcceptingLogins()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setAcceptingLogins(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
backing.values().forEach(Datastore::shutdown);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean logAction(LogEntry entry) {
|
||||
return backing.get(types.get("log")).logAction(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getLog() {
|
||||
return backing.get(types.get("log")).getLog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(UUID uuid, String username) {
|
||||
return backing.get(types.get("user")).loadUser(uuid, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
return backing.get(types.get("user")).saveUser(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cleanupUsers() {
|
||||
return backing.get(types.get("user")).cleanupUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueUsers() {
|
||||
return backing.get(types.get("user")).getUniqueUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
return backing.get(types.get("group")).createAndLoadGroup(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
return backing.get(types.get("group")).loadGroup(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
return backing.get(types.get("group")).loadAllGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
return backing.get(types.get("group")).saveGroup(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteGroup(Group group) {
|
||||
return backing.get(types.get("group")).deleteGroup(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(String name) {
|
||||
return backing.get(types.get("track")).createAndLoadTrack(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(String name) {
|
||||
return backing.get(types.get("track")).loadTrack(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
return backing.get(types.get("track")).loadAllTracks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(Track track) {
|
||||
return backing.get(types.get("track")).saveTrack(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(Track track) {
|
||||
return backing.get(types.get("track")).deleteTrack(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUUIDData(String username, UUID uuid) {
|
||||
return backing.get(types.get("uuid")).saveUUIDData(username, uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String username) {
|
||||
return backing.get(types.get("uuid")).getUUID(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
return backing.get(types.get("uuid")).getName(uuid);
|
||||
}
|
||||
}
|
||||
@@ -28,48 +28,75 @@ import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.storage.methods.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@UtilityClass
|
||||
public class StorageFactory {
|
||||
private static final Set<String> TYPES = ImmutableSet.of("flatfile", "mongodb", "mysql", "sqlite", "h2");
|
||||
private static final Set<String> TYPES = ImmutableSet.of("json", "yaml", "flatfile", "mongodb", "mysql", "sqlite", "h2");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Datastore getDatastore(LuckPermsPlugin plugin, String defaultMethod) {
|
||||
Datastore datastore;
|
||||
|
||||
plugin.getLog().info("Detecting storage method...");
|
||||
String storageMethod = plugin.getConfiguration().getStorageMethod().toLowerCase();
|
||||
if (plugin.getConfiguration().getSplitStorage()) {
|
||||
plugin.getLog().info("Using split storage.");
|
||||
|
||||
if (!TYPES.contains(storageMethod)) {
|
||||
plugin.getLog().severe("Storage method '" + storageMethod + "' not recognised. Using the default instead.");
|
||||
storageMethod = defaultMethod;
|
||||
}
|
||||
// java sucks
|
||||
Map<String, String> types = (Map<String, String>) plugin.getConfiguration().getSplitStorageOptions();
|
||||
|
||||
switch (storageMethod) {
|
||||
case "mysql":
|
||||
plugin.getLog().info("Using MySQL as storage method.");
|
||||
datastore = new MySQLDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
|
||||
break;
|
||||
case "sqlite":
|
||||
plugin.getLog().info("Using SQLite as storage method.");
|
||||
datastore = new SQLiteDatastore(plugin, new File(plugin.getDataFolder(), "luckperms.sqlite"));
|
||||
break;
|
||||
case "h2":
|
||||
plugin.getLog().info("Using H2 as storage method.");
|
||||
datastore = new H2Datastore(plugin, new File(plugin.getDataFolder(), "luckperms.db"));
|
||||
break;
|
||||
case "mongodb":
|
||||
plugin.getLog().info("Using MongoDB as storage method.");
|
||||
datastore = new MongoDBDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
|
||||
break;
|
||||
default:
|
||||
plugin.getLog().info("Using Flatfile (JSON) as storage method.");
|
||||
datastore = new FlatfileDatastore(plugin, plugin.getDataFolder());
|
||||
break;
|
||||
types.entrySet().stream()
|
||||
.filter(e -> !TYPES.contains(e.getValue().toLowerCase()))
|
||||
.forEach(e -> {
|
||||
plugin.getLog().severe("Storage method for " + e.getKey() + " - " + e.getValue() + " not recognised. " +
|
||||
"Using the default instead.");
|
||||
e.setValue(defaultMethod);
|
||||
});
|
||||
|
||||
Set<String> neededTypes = new HashSet<>();
|
||||
neededTypes.addAll(types.values());
|
||||
|
||||
Map<String, Datastore> backing = new HashMap<>();
|
||||
|
||||
for (String type : neededTypes) {
|
||||
backing.put(type, fromString(type, plugin));
|
||||
}
|
||||
|
||||
datastore = new SplitDatastore(plugin, backing, types);
|
||||
|
||||
} else {
|
||||
String storageMethod = plugin.getConfiguration().getStorageMethod().toLowerCase();
|
||||
if (!TYPES.contains(storageMethod)) {
|
||||
plugin.getLog().severe("Storage method '" + storageMethod + "' not recognised. Using the default instead.");
|
||||
storageMethod = defaultMethod;
|
||||
}
|
||||
|
||||
datastore = fromString(storageMethod, plugin);
|
||||
plugin.getLog().info("Using " + datastore.getName() + " as storage method.");
|
||||
}
|
||||
|
||||
plugin.getLog().info("Initialising datastore...");
|
||||
datastore.init();
|
||||
return datastore;
|
||||
}
|
||||
|
||||
private static Datastore fromString(String storageMethod, LuckPermsPlugin plugin) {
|
||||
switch (storageMethod) {
|
||||
case "mysql":
|
||||
return new MySQLDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
|
||||
case "sqlite":
|
||||
return new SQLiteDatastore(plugin, new File(plugin.getDataFolder(), "luckperms.sqlite"));
|
||||
case "h2":
|
||||
return new H2Datastore(plugin, new File(plugin.getDataFolder(), "luckperms.db"));
|
||||
case "mongodb":
|
||||
return new MongoDBDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
|
||||
case "yaml":
|
||||
return new YAMLDatastore(plugin, plugin.getDataFolder());
|
||||
default:
|
||||
return new JSONDatastore(plugin, plugin.getDataFolder());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,75 +22,37 @@
|
||||
|
||||
package me.lucko.luckperms.storage.methods;
|
||||
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.data.Log;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.Node;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.*;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
@SuppressWarnings({"ResultOfMethodCallIgnored", "UnnecessaryLocalVariable"})
|
||||
public class FlatfileDatastore extends Datastore {
|
||||
abstract class FlatfileDatastore extends Datastore {
|
||||
private static final String LOG_FORMAT = "%s(%s): [%s] %s(%s) --> %s";
|
||||
|
||||
private final Logger actionLogger = Logger.getLogger("lp_actions");
|
||||
private Map<String, String> uuidCache = new ConcurrentHashMap<>();
|
||||
|
||||
private final File pluginDir;
|
||||
private File usersDir;
|
||||
private File groupsDir;
|
||||
private File tracksDir;
|
||||
private File uuidData;
|
||||
private File actionLog;
|
||||
final File pluginDir;
|
||||
File usersDir;
|
||||
File groupsDir;
|
||||
File tracksDir;
|
||||
File uuidData;
|
||||
File actionLog;
|
||||
|
||||
public FlatfileDatastore(LuckPermsPlugin plugin, File pluginDir) {
|
||||
super(plugin, "Flatfile - JSON");
|
||||
FlatfileDatastore(LuckPermsPlugin plugin, String name, File pluginDir) {
|
||||
super(plugin, name);
|
||||
this.pluginDir = pluginDir;
|
||||
}
|
||||
|
||||
private boolean doWrite(File file, WriteOperation writeOperation) {
|
||||
boolean success = false;
|
||||
try {
|
||||
@Cleanup FileWriter fileWriter = new FileWriter(file);
|
||||
@Cleanup BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||
@Cleanup JsonWriter jsonWriter = new JsonWriter(bufferedWriter);
|
||||
jsonWriter.setIndent(" ");
|
||||
success = writeOperation.onRun(jsonWriter);
|
||||
jsonWriter.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private boolean doRead(File file, ReadOperation readOperation) {
|
||||
boolean success = false;
|
||||
try {
|
||||
@Cleanup FileReader fileReader = new FileReader(file);
|
||||
@Cleanup BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
@Cleanup JsonReader jsonReader = new JsonReader(bufferedReader);
|
||||
success = readOperation.onRun(jsonReader);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
try {
|
||||
@@ -119,7 +81,6 @@ public class FlatfileDatastore extends Datastore {
|
||||
}
|
||||
|
||||
cleanupUsers();
|
||||
|
||||
setAcceptingLogins(true);
|
||||
}
|
||||
|
||||
@@ -167,404 +128,6 @@ public class FlatfileDatastore extends Datastore {
|
||||
return Log.builder().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(UUID uuid, String username) {
|
||||
User user = plugin.getUserManager().make(uuid, username);
|
||||
boolean success = false;
|
||||
|
||||
File userFile = new File(usersDir, uuid.toString() + ".json");
|
||||
if (userFile.exists()) {
|
||||
final String[] name = new String[1];
|
||||
success = doRead(userFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // uuid record
|
||||
reader.nextString(); // uuid
|
||||
reader.nextName(); // name record
|
||||
name[0] = reader.nextString(); // name
|
||||
reader.nextName(); // primaryGroup record
|
||||
user.setPrimaryGroup(reader.nextString()); // primaryGroup
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
user.getNodes().add(Node.fromSerialisedNode(node, b));
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (user.getName().equalsIgnoreCase("null")) {
|
||||
user.setName(name[0]);
|
||||
} else {
|
||||
if (!name[0].equals(user.getName())) {
|
||||
doWrite(userFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("uuid").value(user.getUuid().toString());
|
||||
writer.name("name").value(user.getName());
|
||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (success) plugin.getUserManager().updateOrSet(user);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
File userFile = new File(usersDir, user.getUuid().toString() + ".json");
|
||||
if (!userFile.exists()) {
|
||||
try {
|
||||
userFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doWrite(userFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("uuid").value(user.getUuid().toString());
|
||||
writer.name("name").value(user.getName());
|
||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cleanupUsers() {
|
||||
File[] files = usersDir.listFiles((dir, name) -> name.endsWith(".json"));
|
||||
if (files == null) return false;
|
||||
|
||||
for (File file : files) {
|
||||
Map<String, Boolean> nodes = new HashMap<>();
|
||||
doRead(file, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // uuid record
|
||||
reader.nextString(); // uuid
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); // primaryGroup record
|
||||
reader.nextString(); // primaryGroup
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
nodes.put(node, b);
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
boolean shouldDelete = false;
|
||||
if (nodes.size() == 1) {
|
||||
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
|
||||
// There's only one
|
||||
shouldDelete = e.getKey().equalsIgnoreCase("group.default") && e.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDelete) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueUsers() {
|
||||
String[] fileNames = usersDir.list((dir, name) -> name.endsWith(".json"));
|
||||
if (fileNames == null) return null;
|
||||
return Arrays.stream(fileNames)
|
||||
.map(s -> s.substring(0, s.length() - 5))
|
||||
.map(UUID::fromString)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().make(name);
|
||||
|
||||
File groupFile = new File(groupsDir, name + ".json");
|
||||
if (!groupFile.exists()) {
|
||||
try {
|
||||
groupFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doWrite(groupFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(group.getName());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(group.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!success) return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(groupFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
group.getNodes().add(Node.fromSerialisedNode(node, b));
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().make(name);
|
||||
|
||||
File groupFile = new File(groupsDir, name + ".json");
|
||||
if (!groupFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(groupFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
group.getNodes().add(Node.fromSerialisedNode(node, b));
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
String[] fileNames = groupsDir.list((dir, name) -> name.endsWith(".json"));
|
||||
if (fileNames == null) return false;
|
||||
List<String> groups = Arrays.stream(fileNames)
|
||||
.map(s -> s.substring(0, s.length() - 5))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
plugin.getGroupManager().unloadAll();
|
||||
groups.forEach(this::loadGroup);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
File groupFile = new File(groupsDir, group.getName() + ".json");
|
||||
if (!groupFile.exists()) {
|
||||
try {
|
||||
groupFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doWrite(groupFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(group.getName());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(group.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteGroup(Group group) {
|
||||
File groupFile = new File(groupsDir, group.getName() + ".json");
|
||||
if (groupFile.exists()) {
|
||||
groupFile.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().make(name);
|
||||
List<String> groups = new ArrayList<>();
|
||||
|
||||
File trackFile = new File(tracksDir, name + ".json");
|
||||
if (!trackFile.exists()) {
|
||||
try {
|
||||
trackFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doWrite(trackFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(track.getName());
|
||||
writer.name("groups");
|
||||
writer.beginArray();
|
||||
for (String s : track.getGroups()) {
|
||||
writer.value(s);
|
||||
}
|
||||
writer.endArray();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!success) return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(trackFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); // groups record
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
groups.add(reader.nextString());
|
||||
}
|
||||
reader.endArray();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
track.setGroups(groups);
|
||||
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().make(name);
|
||||
List<String> groups = new ArrayList<>();
|
||||
|
||||
File trackFile = new File(tracksDir, name + ".json");
|
||||
if (!trackFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(trackFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); // groups record
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
groups.add(reader.nextString());
|
||||
}
|
||||
reader.endArray();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
track.setGroups(groups);
|
||||
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
String[] fileNames = tracksDir.list((dir, name) -> name.endsWith(".json"));
|
||||
if (fileNames == null) return false;
|
||||
List<String> tracks = Arrays.stream(fileNames)
|
||||
.map(s -> s.substring(0, s.length() - 5))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
plugin.getTrackManager().unloadAll();
|
||||
tracks.forEach(this::loadTrack);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(Track track) {
|
||||
File trackFile = new File(tracksDir, track.getName() + ".json");
|
||||
if (!trackFile.exists()) {
|
||||
try {
|
||||
trackFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doWrite(trackFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(track.getName());
|
||||
writer.name("groups");
|
||||
writer.beginArray();
|
||||
for (String s : track.getGroups()) {
|
||||
writer.value(s);
|
||||
}
|
||||
writer.endArray();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(Track track) {
|
||||
File trackFile = new File(tracksDir, track.getName() + ".json");
|
||||
if (trackFile.exists()) {
|
||||
trackFile.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Map<String, String> getUUIDCache() {
|
||||
Map<String, String> cache = new HashMap<>();
|
||||
|
||||
@@ -612,11 +175,13 @@ public class FlatfileDatastore extends Datastore {
|
||||
return UUID.fromString(uuidCache.get(username));
|
||||
}
|
||||
|
||||
interface WriteOperation {
|
||||
boolean onRun(JsonWriter writer) throws IOException;
|
||||
}
|
||||
|
||||
interface ReadOperation {
|
||||
boolean onRun(JsonReader reader) throws IOException;
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
for (Map.Entry<String, String> e : uuidCache.entrySet()) {
|
||||
if (e.getValue().equalsIgnoreCase(uuid.toString())) {
|
||||
return e.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@ public class H2Datastore extends SQLDatastore {
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
|
||||
queryPS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
|
||||
success = true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
@@ -84,7 +85,6 @@ public class H2Datastore extends SQLDatastore {
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
|
||||
queryRS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
|
||||
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
|
||||
success = queryRS.onResult(resultSet);
|
||||
|
||||
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* 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.storage.methods;
|
||||
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.Node;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
@SuppressWarnings({"ResultOfMethodCallIgnored", "UnnecessaryLocalVariable"})
|
||||
public class JSONDatastore extends FlatfileDatastore {
|
||||
public JSONDatastore(LuckPermsPlugin plugin, File pluginDir) {
|
||||
super(plugin, "Flatfile - JSON", pluginDir);
|
||||
}
|
||||
|
||||
private boolean doWrite(File file, WriteOperation writeOperation) {
|
||||
boolean success = false;
|
||||
try {
|
||||
@Cleanup FileWriter fileWriter = new FileWriter(file);
|
||||
@Cleanup BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||
@Cleanup JsonWriter jsonWriter = new JsonWriter(bufferedWriter);
|
||||
jsonWriter.setIndent(" ");
|
||||
success = writeOperation.onRun(jsonWriter);
|
||||
jsonWriter.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private boolean doRead(File file, ReadOperation readOperation) {
|
||||
boolean success = false;
|
||||
try {
|
||||
@Cleanup FileReader fileReader = new FileReader(file);
|
||||
@Cleanup BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
@Cleanup JsonReader jsonReader = new JsonReader(bufferedReader);
|
||||
success = readOperation.onRun(jsonReader);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(UUID uuid, String username) {
|
||||
User user = plugin.getUserManager().make(uuid, username);
|
||||
boolean success = false;
|
||||
|
||||
File userFile = new File(usersDir, uuid.toString() + ".json");
|
||||
if (userFile.exists()) {
|
||||
final String[] name = new String[1];
|
||||
success = doRead(userFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // uuid record
|
||||
reader.nextString(); // uuid
|
||||
reader.nextName(); // name record
|
||||
name[0] = reader.nextString(); // name
|
||||
reader.nextName(); // primaryGroup record
|
||||
user.setPrimaryGroup(reader.nextString()); // primaryGroup
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
user.getNodes().add(Node.fromSerialisedNode(node, b));
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (user.getName().equalsIgnoreCase("null")) {
|
||||
user.setName(name[0]);
|
||||
} else {
|
||||
if (!name[0].equals(user.getName())) {
|
||||
doWrite(userFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("uuid").value(user.getUuid().toString());
|
||||
writer.name("name").value(user.getName());
|
||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (success) plugin.getUserManager().updateOrSet(user);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
File userFile = new File(usersDir, user.getUuid().toString() + ".json");
|
||||
if (!plugin.getUserManager().shouldSave(user)) {
|
||||
if (userFile.exists()) {
|
||||
userFile.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!userFile.exists()) {
|
||||
try {
|
||||
userFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doWrite(userFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("uuid").value(user.getUuid().toString());
|
||||
writer.name("name").value(user.getName());
|
||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cleanupUsers() {
|
||||
File[] files = usersDir.listFiles((dir, name) -> name.endsWith(".json"));
|
||||
if (files == null) return false;
|
||||
|
||||
for (File file : files) {
|
||||
Map<String, Boolean> nodes = new HashMap<>();
|
||||
doRead(file, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // uuid record
|
||||
reader.nextString(); // uuid
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); // primaryGroup record
|
||||
reader.nextString(); // primaryGroup
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
nodes.put(node, b);
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
boolean shouldDelete = false;
|
||||
if (nodes.size() == 1) {
|
||||
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
|
||||
// There's only one
|
||||
shouldDelete = e.getKey().equalsIgnoreCase("group.default") && e.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDelete) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueUsers() {
|
||||
String[] fileNames = usersDir.list((dir, name) -> name.endsWith(".json"));
|
||||
if (fileNames == null) return null;
|
||||
return Arrays.stream(fileNames)
|
||||
.map(s -> s.substring(0, s.length() - 5))
|
||||
.map(UUID::fromString)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().make(name);
|
||||
|
||||
File groupFile = new File(groupsDir, name + ".json");
|
||||
if (!groupFile.exists()) {
|
||||
try {
|
||||
groupFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doWrite(groupFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(group.getName());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(group.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!success) return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(groupFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
group.getNodes().add(Node.fromSerialisedNode(node, b));
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().make(name);
|
||||
|
||||
File groupFile = new File(groupsDir, name + ".json");
|
||||
if (!groupFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(groupFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); //perms
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String node = reader.nextName();
|
||||
boolean b = reader.nextBoolean();
|
||||
group.getNodes().add(Node.fromSerialisedNode(node, b));
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
String[] fileNames = groupsDir.list((dir, name) -> name.endsWith(".json"));
|
||||
if (fileNames == null) return false;
|
||||
List<String> groups = Arrays.stream(fileNames)
|
||||
.map(s -> s.substring(0, s.length() - 5))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
plugin.getGroupManager().unloadAll();
|
||||
groups.forEach(this::loadGroup);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
File groupFile = new File(groupsDir, group.getName() + ".json");
|
||||
if (!groupFile.exists()) {
|
||||
try {
|
||||
groupFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doWrite(groupFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(group.getName());
|
||||
writer.name("perms");
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, Boolean> e : exportToLegacy(group.getNodes()).entrySet()) {
|
||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||
}
|
||||
writer.endObject();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteGroup(Group group) {
|
||||
File groupFile = new File(groupsDir, group.getName() + ".json");
|
||||
if (groupFile.exists()) {
|
||||
groupFile.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().make(name);
|
||||
List<String> groups = new ArrayList<>();
|
||||
|
||||
File trackFile = new File(tracksDir, name + ".json");
|
||||
if (!trackFile.exists()) {
|
||||
try {
|
||||
trackFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doWrite(trackFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(track.getName());
|
||||
writer.name("groups");
|
||||
writer.beginArray();
|
||||
for (String s : track.getGroups()) {
|
||||
writer.value(s);
|
||||
}
|
||||
writer.endArray();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!success) return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(trackFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); // groups record
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
groups.add(reader.nextString());
|
||||
}
|
||||
reader.endArray();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
track.setGroups(groups);
|
||||
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().make(name);
|
||||
List<String> groups = new ArrayList<>();
|
||||
|
||||
File trackFile = new File(tracksDir, name + ".json");
|
||||
if (!trackFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(trackFile, reader -> {
|
||||
reader.beginObject();
|
||||
reader.nextName(); // name record
|
||||
reader.nextString(); // name
|
||||
reader.nextName(); // groups record
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
groups.add(reader.nextString());
|
||||
}
|
||||
reader.endArray();
|
||||
reader.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
track.setGroups(groups);
|
||||
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
String[] fileNames = tracksDir.list((dir, name) -> name.endsWith(".json"));
|
||||
if (fileNames == null) return false;
|
||||
List<String> tracks = Arrays.stream(fileNames)
|
||||
.map(s -> s.substring(0, s.length() - 5))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
plugin.getTrackManager().unloadAll();
|
||||
tracks.forEach(this::loadTrack);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(Track track) {
|
||||
File trackFile = new File(tracksDir, track.getName() + ".json");
|
||||
if (!trackFile.exists()) {
|
||||
try {
|
||||
trackFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doWrite(trackFile, writer -> {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(track.getName());
|
||||
writer.name("groups");
|
||||
writer.beginArray();
|
||||
for (String s : track.getGroups()) {
|
||||
writer.value(s);
|
||||
}
|
||||
writer.endArray();
|
||||
writer.endObject();
|
||||
return true;
|
||||
});
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(Track track) {
|
||||
File trackFile = new File(tracksDir, track.getName() + ".json");
|
||||
if (trackFile.exists()) {
|
||||
trackFile.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
interface WriteOperation {
|
||||
boolean onRun(JsonWriter writer) throws IOException;
|
||||
}
|
||||
|
||||
interface ReadOperation {
|
||||
boolean onRun(JsonReader reader) throws IOException;
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,11 @@ public class MongoDBDatastore extends Datastore {
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
if (!plugin.getUserManager().shouldSave(user)) {
|
||||
return true;
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("users");
|
||||
return c.deleteOne(new Document("_id", user.getUuid())).wasAcknowledged();
|
||||
}, false);
|
||||
return success;
|
||||
}
|
||||
|
||||
boolean success = call(() -> {
|
||||
@@ -413,6 +417,20 @@ public class MongoDBDatastore extends Datastore {
|
||||
}, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
return call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("uuid");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", uuid)).iterator()) {
|
||||
if (cursor.hasNext()) {
|
||||
return cursor.next().get("name", String.class);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, null);
|
||||
}
|
||||
|
||||
private static <T> T call(Callable<T> c, T def) {
|
||||
try {
|
||||
return c.call();
|
||||
@@ -427,14 +445,12 @@ public class MongoDBDatastore extends Datastore {
|
||||
The following two methods convert the node maps so they can be stored. */
|
||||
private static <V> Map<String, V> convert(Map<String, V> map) {
|
||||
return map.entrySet().stream()
|
||||
.map(e -> new AbstractMap.SimpleEntry<>(e.getKey().replace(".", "[**DOT**]").replace("$", "[**DOLLAR**]"), e.getValue()))
|
||||
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
|
||||
.collect(Collectors.toMap(e -> e.getKey().replace(".", "[**DOT**]").replace("$", "[**DOLLAR**]"), Map.Entry::getValue));
|
||||
}
|
||||
|
||||
private static <V> Map<String, V> revert(Map<String, V> map) {
|
||||
return map.entrySet().stream()
|
||||
.map(e -> new AbstractMap.SimpleEntry<>(e.getKey().replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$"), e.getValue()))
|
||||
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
|
||||
.collect(Collectors.toMap(e -> e.getKey().replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$"), Map.Entry::getValue));
|
||||
}
|
||||
|
||||
private static Document fromUser(User user) {
|
||||
|
||||
@@ -85,6 +85,7 @@ public class MySQLDatastore extends SQLDatastore {
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
|
||||
queryPS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
|
||||
success = true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
@@ -103,7 +104,6 @@ public class MySQLDatastore extends SQLDatastore {
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
|
||||
queryRS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
|
||||
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
|
||||
success = queryRS.onResult(resultSet);
|
||||
|
||||
@@ -55,7 +55,8 @@ abstract class SQLDatastore extends Datastore {
|
||||
private static final String USER_SELECT = "SELECT * FROM lp_users WHERE uuid=?";
|
||||
private static final String USER_SELECT_ALL = "SELECT uuid FROM lp_users";
|
||||
private static final String USER_UPDATE = "UPDATE lp_users SET name=?, primary_group = ?, perms=? WHERE uuid=?";
|
||||
private static final String USER_DELETE = "DELETE FROM lp_users WHERE perms=?";
|
||||
private static final String USER_DELETE = "DELETE FROM lp_users WHERE uuid=?";
|
||||
private static final String USER_DELETE_ALL = "DELETE FROM lp_users WHERE perms=?";
|
||||
|
||||
private static final String GROUP_INSERT = "INSERT INTO lp_groups VALUES(?, ?)";
|
||||
private static final String GROUP_SELECT = "SELECT perms FROM lp_groups WHERE name=?";
|
||||
@@ -71,6 +72,7 @@ abstract class SQLDatastore extends Datastore {
|
||||
|
||||
private static final String UUIDCACHE_INSERT = "INSERT INTO lp_uuid VALUES(?, ?)";
|
||||
private static final String UUIDCACHE_SELECT = "SELECT uuid FROM lp_uuid WHERE name=?";
|
||||
private static final String UUIDCACHE_SELECT_NAME = "SELECT name FROM lp_uuid WHERE uuid=?";
|
||||
private static final String UUIDCACHE_UPDATE = "UPDATE lp_uuid SET uuid=? WHERE name=?";
|
||||
|
||||
private static final String ACTION_INSERT = "INSERT INTO lp_actions(`time`, `actor_uuid`, `actor_name`, `type`, `acted_uuid`, `acted_name`, `action`) VALUES(?, ?, ?, ?, ?, ?, ?)";
|
||||
@@ -188,7 +190,13 @@ abstract class SQLDatastore extends Datastore {
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
if (!plugin.getUserManager().shouldSave(user)) {
|
||||
return true;
|
||||
boolean success = runQuery(new QueryPS(USER_DELETE) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, user.getUuid().toString());
|
||||
}
|
||||
});
|
||||
return success;
|
||||
}
|
||||
|
||||
boolean success = runQuery(new QueryRS(USER_SELECT) {
|
||||
@@ -233,7 +241,7 @@ abstract class SQLDatastore extends Datastore {
|
||||
|
||||
@Override
|
||||
public boolean cleanupUsers() {
|
||||
boolean success = runQuery(new QueryPS(USER_DELETE) {
|
||||
boolean success = runQuery(new QueryPS(USER_DELETE_ALL) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, "{\"group.default\":true}");
|
||||
@@ -541,6 +549,30 @@ abstract class SQLDatastore extends Datastore {
|
||||
return success ? uuid[0] : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
final String u = uuid.toString();
|
||||
final String[] name = {null};
|
||||
|
||||
boolean success = runQuery(new QueryRS(UUIDCACHE_SELECT_NAME) {
|
||||
@Override
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException {
|
||||
preparedStatement.setString(1, u);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
if (resultSet.next()) {
|
||||
name[0] = resultSet.getString("name");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return success ? name[0] : null;
|
||||
}
|
||||
|
||||
private class Query extends QueryPS {
|
||||
Query(String query) {
|
||||
super(query);
|
||||
|
||||
@@ -66,6 +66,7 @@ public class SQLiteDatastore extends SQLDatastore {
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
|
||||
queryPS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
|
||||
success = true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
@@ -84,7 +85,6 @@ public class SQLiteDatastore extends SQLDatastore {
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
|
||||
queryRS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
|
||||
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
|
||||
success = queryRS.onResult(resultSet);
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* 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.storage.methods;
|
||||
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.Node;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
@SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
|
||||
public class YAMLDatastore extends FlatfileDatastore {
|
||||
public YAMLDatastore(LuckPermsPlugin plugin, File pluginDir) {
|
||||
super(plugin, "Flatfile - YAML", pluginDir);
|
||||
}
|
||||
|
||||
private static Yaml getYaml() {
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
return new Yaml(options);
|
||||
}
|
||||
|
||||
private boolean doRead(File file, ReadOperation readOperation) {
|
||||
boolean success = false;
|
||||
try {
|
||||
@Cleanup FileReader fileReader = new FileReader(file);
|
||||
@Cleanup BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
success = readOperation.onRun((Map<String, Object>) getYaml().load(bufferedReader));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private boolean doWrite(File file, Map<String, Object> values) {
|
||||
try {
|
||||
@Cleanup FileWriter fileWriter = new FileWriter(file);
|
||||
@Cleanup BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||
getYaml().dump(values, bufferedWriter);
|
||||
bufferedWriter.flush();
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(UUID uuid, String username) {
|
||||
User user = plugin.getUserManager().make(uuid, username);
|
||||
boolean success = false;
|
||||
|
||||
File userFile = new File(usersDir, uuid.toString() + ".yml");
|
||||
if (userFile.exists()) {
|
||||
final String[] name = {null};
|
||||
success = doRead(userFile, values -> {
|
||||
name[0] = (String) values.get("name");
|
||||
user.setPrimaryGroup((String) values.get("primary-group"));
|
||||
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
|
||||
user.getNodes().add(Node.fromSerialisedNode(e.getKey(), e.getValue()));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (user.getName().equalsIgnoreCase("null")) {
|
||||
user.setName(name[0]);
|
||||
} else {
|
||||
if (!name[0].equals(user.getName())) {
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put("uuid", user.getUuid().toString());
|
||||
values.put("name", user.getName());
|
||||
values.put("primary-group", user.getPrimaryGroup());
|
||||
values.put("perms", exportToLegacy(user.getNodes()));
|
||||
doWrite(userFile, values);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (success) plugin.getUserManager().updateOrSet(user);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
File userFile = new File(usersDir, user.getUuid().toString() + ".yml");
|
||||
if (!plugin.getUserManager().shouldSave(user)) {
|
||||
if (userFile.exists()) {
|
||||
userFile.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!userFile.exists()) {
|
||||
try {
|
||||
userFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put("uuid", user.getUuid().toString());
|
||||
values.put("name", user.getName());
|
||||
values.put("primary-group", user.getPrimaryGroup());
|
||||
values.put("perms", exportToLegacy(user.getNodes()));
|
||||
return doWrite(userFile, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cleanupUsers() {
|
||||
File[] files = usersDir.listFiles((dir, name) -> name.endsWith(".yml"));
|
||||
if (files == null) return false;
|
||||
|
||||
for (File file : files) {
|
||||
Map<String, Boolean> nodes = new HashMap<>();
|
||||
doRead(file, values -> {
|
||||
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||
nodes.putAll(perms);
|
||||
return true;
|
||||
});
|
||||
|
||||
boolean shouldDelete = false;
|
||||
if (nodes.size() == 1) {
|
||||
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
|
||||
// There's only one
|
||||
shouldDelete = e.getKey().equalsIgnoreCase("group.default") && e.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDelete) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueUsers() {
|
||||
String[] fileNames = usersDir.list((dir, name) -> name.endsWith(".yml"));
|
||||
if (fileNames == null) return null;
|
||||
return Arrays.stream(fileNames)
|
||||
.map(s -> s.substring(0, s.length() - 4))
|
||||
.map(UUID::fromString)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().make(name);
|
||||
|
||||
File groupFile = new File(groupsDir, name + ".yml");
|
||||
if (!groupFile.exists()) {
|
||||
try {
|
||||
groupFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put("name", group.getName());
|
||||
values.put("perms", exportToLegacy(group.getNodes()));
|
||||
|
||||
if (!doWrite(groupFile, values)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doRead(groupFile, values -> {
|
||||
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
|
||||
group.getNodes().add(Node.fromSerialisedNode(e.getKey(), e.getValue()));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().make(name);
|
||||
|
||||
File groupFile = new File(groupsDir, name + ".yml");
|
||||
if (!groupFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(groupFile, values -> {
|
||||
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
|
||||
group.getNodes().add(Node.fromSerialisedNode(e.getKey(), e.getValue()));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
String[] fileNames = groupsDir.list((dir, name) -> name.endsWith(".yml"));
|
||||
if (fileNames == null) return false;
|
||||
List<String> groups = Arrays.stream(fileNames)
|
||||
.map(s -> s.substring(0, s.length() - 4))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
plugin.getGroupManager().unloadAll();
|
||||
groups.forEach(this::loadGroup);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
File groupFile = new File(groupsDir, group.getName() + ".yml");
|
||||
if (!groupFile.exists()) {
|
||||
try {
|
||||
groupFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put("name", group.getName());
|
||||
values.put("perms", exportToLegacy(group.getNodes()));
|
||||
return doWrite(groupFile, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteGroup(Group group) {
|
||||
File groupFile = new File(groupsDir, group.getName() + ".yml");
|
||||
if (groupFile.exists()) {
|
||||
groupFile.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().make(name);
|
||||
List<String> groups = new ArrayList<>();
|
||||
|
||||
File trackFile = new File(tracksDir, name + ".yml");
|
||||
if (!trackFile.exists()) {
|
||||
try {
|
||||
trackFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put("name", track.getName());
|
||||
values.put("groups", track.getGroups());
|
||||
|
||||
if (!doWrite(trackFile, values)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = doRead(trackFile, values -> {
|
||||
groups.addAll((List<String>) values.get("groups"));
|
||||
return true;
|
||||
});
|
||||
|
||||
track.setGroups(groups);
|
||||
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().make(name);
|
||||
List<String> groups = new ArrayList<>();
|
||||
|
||||
File trackFile = new File(tracksDir, name + ".yml");
|
||||
if (!trackFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success = doRead(trackFile, values -> {
|
||||
groups.addAll((List<String>) values.get("groups"));
|
||||
return true;
|
||||
});
|
||||
|
||||
track.setGroups(groups);
|
||||
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
String[] fileNames = tracksDir.list((dir, name) -> name.endsWith(".yml"));
|
||||
if (fileNames == null) return false;
|
||||
List<String> tracks = Arrays.stream(fileNames)
|
||||
.map(s -> s.substring(0, s.length() - 4))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
plugin.getTrackManager().unloadAll();
|
||||
tracks.forEach(this::loadTrack);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(Track track) {
|
||||
File trackFile = new File(tracksDir, track.getName() + ".yml");
|
||||
if (!trackFile.exists()) {
|
||||
try {
|
||||
trackFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put("name", track.getName());
|
||||
values.put("groups", track.getGroups());
|
||||
return doWrite(trackFile, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(Track track) {
|
||||
File trackFile = new File(tracksDir, track.getName() + ".yml");
|
||||
if (trackFile.exists()) {
|
||||
trackFile.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
interface ReadOperation {
|
||||
boolean onRun(Map<String, Object> values);
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public class TrackManager extends AbstractManager<String, Track> {
|
||||
* @return a set of tracks that the groups could be a member of
|
||||
*/
|
||||
public Set<Track> getApplicableTracks(String group) {
|
||||
return objects.values().stream()
|
||||
return getAll().values().stream()
|
||||
.filter(t -> t.containsGroup(group))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@@ -27,10 +27,10 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.event.events.GroupAddEvent;
|
||||
import me.lucko.luckperms.api.implementation.internal.GroupLink;
|
||||
import me.lucko.luckperms.api.implementation.internal.PermissionHolderLink;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
@@ -38,7 +38,6 @@ import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.Identifiable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -325,12 +324,13 @@ public abstract class User extends PermissionHolder implements Identifiable<UUID
|
||||
* @param includeGlobal Whether to include global groups
|
||||
* @return a {@link List} of group names
|
||||
*/
|
||||
private List<String> getGroups(String server, String world, boolean includeGlobal) {
|
||||
public List<String> getGroups(String server, String world, boolean includeGlobal) {
|
||||
// Call super #getPermissions method, and just sort through those
|
||||
Map<String, Boolean> perms = exportNodes(server, world, null, includeGlobal, true, null);
|
||||
return perms.keySet().stream()
|
||||
.filter(s -> Patterns.GROUP_MATCH.matcher(s).matches())
|
||||
.map(s -> Patterns.DOT.split(s, 2)[1])
|
||||
return getNodes().stream()
|
||||
.filter(n -> n.shouldApplyOnWorld(world, includeGlobal, true))
|
||||
.filter(n -> n.shouldApplyOnServer(server, includeGlobal, true))
|
||||
.filter(Node::isGroupNode)
|
||||
.map(Node::getGroupName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ public abstract class UserManager extends AbstractManager<UUID, User> {
|
||||
@SuppressWarnings("OptionalGetWithoutIsPresent")
|
||||
public User get(String name) {
|
||||
try {
|
||||
return objects.values().stream()
|
||||
return getAll().values().stream()
|
||||
.filter(u -> u.getName().equalsIgnoreCase(name))
|
||||
.limit(1).findAny().get();
|
||||
} catch (NoSuchElementException e) {
|
||||
@@ -54,15 +54,17 @@ public abstract class UserManager extends AbstractManager<UUID, User> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(User u) {
|
||||
public void preSet(User u) {
|
||||
giveDefaultIfNeeded(u, true);
|
||||
super.set(u);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copy(User from, User to) {
|
||||
to.setNodes(from.getNodes());
|
||||
to.setPrimaryGroup(from.getPrimaryGroup());
|
||||
if (from.getPrimaryGroup() != null) {
|
||||
// This isn't just a black user. we shouldn't override in that case.
|
||||
to.setNodes(from.getNodes());
|
||||
to.setPrimaryGroup(from.getPrimaryGroup());
|
||||
}
|
||||
to.refreshPermissions();
|
||||
}
|
||||
|
||||
@@ -72,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;
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
|
||||
package me.lucko.luckperms.utils;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* An abstract manager class
|
||||
@@ -31,10 +33,12 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* @param <T> the class this manager is "managing"
|
||||
*/
|
||||
public abstract class AbstractManager<I, T extends Identifiable<I>> {
|
||||
protected final Map<I, T> objects = new ConcurrentHashMap<>();
|
||||
private final Map<I, T> objects = new HashMap<>();
|
||||
|
||||
public Map<I, T> getAll() {
|
||||
return objects;
|
||||
public final Map<I, T> getAll() {
|
||||
synchronized (objects) {
|
||||
return ImmutableMap.copyOf(objects);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,28 +46,39 @@ public abstract class AbstractManager<I, T extends Identifiable<I>> {
|
||||
* @param id The id to search by
|
||||
* @return a {@link T} object if the object is loaded, returns null if the object is not loaded
|
||||
*/
|
||||
public T get(I id) {
|
||||
return objects.get(id);
|
||||
public final T get(I id) {
|
||||
synchronized (objects) {
|
||||
return objects.get(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a object to the loaded objects map
|
||||
* @param t The object to add
|
||||
*/
|
||||
public void set(T t) {
|
||||
objects.put(t.getId(), t);
|
||||
public final void set(T t) {
|
||||
preSet(t);
|
||||
synchronized (objects) {
|
||||
objects.put(t.getId(), t);
|
||||
}
|
||||
}
|
||||
|
||||
protected void preSet(T t) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates (or sets if the object wasn't already loaded) an object in the objects map
|
||||
* @param t The object to update or set
|
||||
*/
|
||||
public void updateOrSet(T t) {
|
||||
if (!isLoaded(t.getId())) {
|
||||
// The object isn't already loaded
|
||||
set(t);
|
||||
} else {
|
||||
copy(t, objects.get(t.getId()));
|
||||
public final void updateOrSet(T t) {
|
||||
synchronized (objects) {
|
||||
if (!isLoaded(t.getId())) {
|
||||
// The object isn't already loaded
|
||||
set(t);
|
||||
} else {
|
||||
copy(t, objects.get(t.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,25 +89,36 @@ public abstract class AbstractManager<I, T extends Identifiable<I>> {
|
||||
* @param id The id of the object
|
||||
* @return true if the object is loaded
|
||||
*/
|
||||
public boolean isLoaded(I id) {
|
||||
return objects.containsKey(id);
|
||||
public final boolean isLoaded(I id) {
|
||||
synchronized (objects) {
|
||||
return objects.containsKey(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and unloads the object from the manager
|
||||
* @param t The object to unload
|
||||
*/
|
||||
public void unload(T t) {
|
||||
public final void unload(T t) {
|
||||
if (t != null) {
|
||||
objects.remove(t.getId());
|
||||
preUnload(t);
|
||||
synchronized (objects) {
|
||||
objects.remove(t.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void preUnload(T t) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Unloads all objects from the manager
|
||||
*/
|
||||
public void unloadAll() {
|
||||
objects.clear();
|
||||
public final void unloadAll() {
|
||||
synchronized (objects) {
|
||||
objects.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loaded 100 of 110 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user