Compare commits

..
104 Commits
Author SHA1 Message Date
Luck aea44fc8bc API changes for 2.17 - closes #123 2017-01-16 20:01:41 +00:00
Luck c0da9d49d9 make clickable message invert filter more specific 2017-01-16 16:55:59 +00:00
Luck ce42573f43 Properly invalidate user caches when defaults chance - fixes #118 2017-01-15 17:47:59 +00:00
Luck 148fe4c729 Make prefix/suffix string optional in the meta remove commands - related to #83 2017-01-15 15:11:35 +00:00
Luck 32fd484b58 Change promote / demote behaviour at the end of tracks - towards #112 2017-01-15 13:22:50 +00:00
Luck 7d24e748b7 Fix reading and writing UTF-8 characters from storage files - closes #129 2017-01-15 12:18:12 +00:00
Luck f1a1612f5d Subscribe to default permissions too 2017-01-14 23:49:45 +00:00
Luck 6501e5cf8d Fix bukkit permission subscriptions 2017-01-14 23:19:11 +00:00
Luck cd4a684613 Fix demote command not removing old group 2017-01-14 08:27:09 +00:00
Luck d06fda6d9d Add /lp search command 2017-01-13 20:11:25 +00:00
Luck 139010e75b Fix repo 2017-01-12 21:59:38 +00:00
Luck 7638b07e34 bump fanciful version 2017-01-12 21:48:16 +00:00
Luck f7bf4416c9 Fix illegal cast from LPSubject to SpongeGroup - fixes #126 2017-01-12 21:19:34 +00:00
Luck 2b96b656a9 constants do not need getters 2017-01-12 21:14:27 +00:00
Luck 0fe251b6ec Fix promote/demote commands and primary groups conflicting 2017-01-12 19:45:44 +00:00
Luck a1afc70bcb Cache regex permissions when they get processed 2017-01-12 19:45:15 +00:00
Luck ced3e6959c Add methods to get a list of users/groups with a specific permission 2017-01-11 21:25:57 +00:00
Luck 1c229d54d9 Cleanup 2017-01-11 18:55:46 +00:00
Luck dd50193c18 Fix Sponge subjects from being unloaded and never reinitialized - closes #124 2017-01-10 19:17:45 +00:00
Luck ab0f9bbdbd Fix creating new tracks with SQLBacking 2017-01-09 19:24:12 +00:00
Luck 055d181c67 Fix KCauldron dependency loading - closes #121 2017-01-09 18:20:03 +00:00
Luck 7042c45deb Fix retrieving log from SQLBacking 2017-01-08 20:12:33 +00:00
Luck 960c2291b6 Fully implement new SQL schema & add migration code 2017-01-08 19:33:27 +00:00
Luck 773bfe1407 Automatically sort YAML/JSON storage - closes #113 2017-01-08 11:02:13 +00:00
Luck a23f995717 Hopefully fix #118 2017-01-08 10:44:48 +00:00
Luck bd509b3c75 Fix build 2017-01-05 18:30:09 +00:00
Luck a0f8ba9afb Fix NPE in LuckPermsSubjectData - closes #115 2017-01-05 18:27:58 +00:00
Luck a71e040c6d Fix NPE with Vault transient permissions - closes #117 2017-01-05 18:20:17 +00:00
Luck 454abec468 Cleanup vault hook 2017-01-05 18:19:14 +00:00
Luck 96035d5257 Fix clickable node list 2016-12-30 15:02:22 +00:00
Luck 9f2b59f2a2 Refactor SQLBacking - still towards #77 2016-12-30 14:27:43 +00:00
Luck a54046907d change first login event handling 2016-12-30 12:46:24 +00:00
Luck 2ce5679373 Fix issue where only the first request for a user subject would wait for the loading task to complete. Closes #108 2016-12-30 00:42:33 +00:00
Luck 2dad9f84fc Fixes towards #77 2016-12-27 14:55:21 +00:00
Luck a81a361a93 Fully implement new SQLBacking - towards #77 2016-12-27 14:27:05 +00:00
Luck 4660e68abf Some small fixes for new SQL backing 2016-12-27 13:03:59 +00:00
bakatrouble f8a77cf809 Change comments on configs; default ports for all storage backends 2016-12-27 12:39:54 +00:00
bakatrouble 0abe9598f6 It shouldn't be here 2016-12-27 12:39:54 +00:00
bakatrouble 20de713716 Some readability 2016-12-27 12:39:54 +00:00
bakatrouble 9dbef6acc2 Change providers syntax; fix port for PostgreSQL provider 2016-12-27 12:39:54 +00:00
bakatrouble 4c93bf7cf0 Fix connection leaking on batch inserts; fix IDEA analyser warning 2016-12-27 12:39:54 +00:00
bakatrouble a8fea0fc49 Implement NodeDataHolder 2016-12-27 12:39:54 +00:00
Luck 2d5975d6e3 Vault only save if a change was made 2016-12-27 12:24:19 +00:00
Luck 6874cfd5b1 WIP: implement better sql schema - towards #77 2016-12-24 20:30:35 +00:00
Luck d34013396a woops 2016-12-23 16:59:01 +00:00
Luck a35b0915ab Refactor SQL storage - towards #77 2016-12-23 16:55:35 +00:00
Luck b35f3b4375 Properly cleanup in the case of a reload - towards #100 2016-12-23 11:28:42 +00:00
Luck f4f9612789 Fix MongoDB auth-less connection 2016-12-23 10:14:41 +00:00
Luck bfc79c6051 Reduce page entry count to 15 - resolves #95 2016-12-22 22:06:41 +00:00
Luck d3e60487bb Download dependencies at runtime instead of shading them in the jar 2016-12-22 21:17:02 +00:00
Luck f36f411a8d Fix broken inheritance caching system - closes #97 2016-12-22 17:50:56 +00:00
Luck 35f4aea69f Maybe fix caching issues - closes #99 2016-12-22 15:34:22 +00:00
Luck 8795383e7c Make sync command reload sponge data too - resolves #98 2016-12-21 21:34:43 +00:00
Luck fc4750706b Cleanup sponge files and don't persist empty sections - resolves #96 2016-12-21 21:33:32 +00:00
Luck 0ae59bd3e6 show group weight value in the group info command output 2016-12-21 21:26:22 +00:00
Luck 61fd14c816 Add group setweight command - closes #94 2016-12-21 21:22:48 +00:00
Luck c7d3d87b09 Fix verbose recording filters (again) 2016-12-20 13:59:56 +00:00
Luck 5e68f7b58c Implement paginated permission listings - closes #80 2016-12-20 13:55:42 +00:00
Luck 8a692200d5 Improve memory footprint in low throughput caches 2016-12-20 12:42:20 +00:00
Luck 829eacb0fb Fix verbose recording not taking note of filters 2016-12-20 02:53:37 +00:00
Luck 9aeca91f22 Allow space on Sponge Group subjectcollection 2016-12-19 21:52:26 +00:00
Luck 1bdb512826 Ease handling of group names containing spaces, after a faulty migration process 2016-12-19 21:50:34 +00:00
Luck 060fa6e5f7 change weight node 2016-12-19 18:22:32 +00:00
Luck 171a54c0fc PEX migration - include username too. Closes #92 2016-12-19 01:22:47 +00:00
Luck 17406b448d Add more detail to the group info command 2016-12-18 23:34:33 +00:00
Luck b4b661a3ad Set default port 2016-12-18 10:16:05 +00:00
Luck 4857969ca4 Cache calls querying parent groups in bridge subjects - closes #69 2016-12-18 09:57:39 +00:00
Luck d9d01e09aa Cache collation keys - resolves #90 2016-12-18 09:42:27 +00:00
Luck dadca97d8a actually remove 2016-12-17 00:04:04 +00:00
Luck 8afba8b53d remove /p alias 2016-12-17 00:03:21 +00:00
Luck 85dac1184c silence NPE in autoop listener 2016-12-16 22:47:44 +00:00
Luck 4167460d28 Print true/false alongside permission info output for consoles without color. Closes #84 2016-12-16 19:21:36 +00:00
Eric Coan 1d8a60749d help tame mysql connection settings
this commit further helps tame the mysql connection pool (and really
reconnecting to the pool even when the underlying db goes down) further
from commit: #31a597c

this sets up `setValidationTimeout`, and `setConnectionTestQuery`
in order to better (more speedily(?)/fastly(?)/<other adective>ly(?))
handle connection timeouts in a timely manner. (although admittedly
this is already handeled well imo with the cache). however, it could
be better ™️.

in order to do this I did the following things:
  1. Switch to `TimeUnit.SECONDS.toMillis` instead of manually entering
     milliseconds, and having the time in seconds as a comment. just
     makes it more readable imo. if you want me to change it back I can
     I'm not like attached to this or anything.
  2. Perform more common validation timeouts with `setValidationTimeout`
     this allows us to potentially bump back up the connection timeout
     (although I see no harm leaving it where it is), although allows
     us to still "fail-fast" in a way when doing validations.
  3. Use `setConnectionTestQuery` for people who somehow someway
     may not be using a JDBC4 compliant driver.
2016-12-16 17:14:24 +00:00
Luck 31a597ca81 lower mysql connection timeout - may help with #81 2016-12-12 22:21:54 +00:00
Luck e5e77ffec5 Add PEX track migration - closes #78 2016-12-12 19:51:21 +00:00
Luck 41c3df41b4 Allow group weights as permission nodes - resolves #73 2016-12-12 19:30:42 +00:00
Luck 053066f1a7 add parent clear command - closes #67 2016-12-12 19:06:23 +00:00
Luck 21135dac07 Implement (partially) clickable permission lists - towards #68 2016-12-12 18:56:48 +00:00
Luck 22ccce3208 Default the value to true in set/settemp commands if no arg is given. Closes #82 2016-12-12 16:52:15 +00:00
Luck 70aa3964ee Run all commands on the same thread - fixes #79 2016-12-11 11:34:18 +00:00
Luck 167489823a more lenient command blocking 2016-12-09 19:39:05 +00:00
Luck d1426f1b37 change jar names 2016-12-08 19:33:49 +00:00
Luck 7dcdc59c8e Fix IllegalArgumentException with BiMap#put 2016-12-08 16:30:00 +00:00
Luck 1e13ee87af cleanup imports 2016-12-07 22:21:22 +00:00
Luck 5101c1a759 fix build 2016-12-07 22:16:01 +00:00
Slind14 74bb079625 Fix zPermissions imports (PR #72, fixes #61)
* removed zPerm inherit loop check. (blocked the import due to throwing NPE)

* should fix zperm migration (group inheritance and memberships)

* zperm import, include username

* zperm import: fixed memberships
2016-12-07 22:13:50 +00:00
Luck 2da7979d94 Partially add clickable command listings - towards #68 2016-12-07 22:09:11 +00:00
Luck 4ecb2c7c27 Closes #58 - Disable OP commands on Sponge 2016-12-07 21:27:50 +00:00
Luck 251f51b01c add missing messages 2016-12-07 21:20:54 +00:00
Luck 2fba9b83af apply group rewrites to vault - resolves #59 2016-12-07 21:18:57 +00:00
Luck 1c97cb3cec Sponge: Fix migration for subjects with identifiers containing spaces 2016-12-07 21:14:24 +00:00
Luck 25511f898c implement clickable message base - towards #68 2016-12-07 21:08:40 +00:00
Luck d820f153a9 idk 2016-12-06 22:35:06 +00:00
Luck 77b06acad4 declare child states 2016-12-06 21:53:57 +00:00
Luck 6760a96527 Ensure holder state is always declared 2016-12-06 21:48:37 +00:00
Luck 257f426ab9 implement cached state for all permission holders. towards #69 2016-12-06 21:33:55 +00:00
Luck 3771a50f30 cleanup 2016-12-06 19:21:48 +00:00
dracnis 85ee211172 Update VaultChatHook.java
need update as soon as possible.
2016-12-06 19:03:01 +00:00
Luck 1b7a66b41a Fix #66 2016-12-04 23:09:12 +00:00
Luck 8f9a1aa931 Add verbose pastebin upload functionality - resolves #55 2016-12-03 19:30:25 +00:00
Luck 8b60fd0e55 Sponge: remove spammy user not already loaded message 2016-12-03 14:11:53 +00:00
Luck cd7b3b4f6e Fix compat with older guava versions 2016-12-03 13:55:51 +00:00
Luck 83b0f62d59 Implement full caching for non user/group subjects 2016-12-03 13:26:17 +00:00
Luck dd3a78ada8 Fix #65 2016-12-03 11:08:47 +00:00
227 changed files with 7801 additions and 3190 deletions

No files matched your search

+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.16-SNAPSHOT</version>
<version>2.17-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -27,13 +27,16 @@ import me.lucko.luckperms.api.LuckPermsApi;
import java.util.Optional;
/**
* Static access to LuckPerms
* Singleton for the {@link LuckPermsApi}.
*
* <p> Ideally, the ServiceManager for the platform should be used to obtain and cache an instance, however, this can be
* used if you need static access.
*/
public final class LuckPerms {
private static LuckPermsApi api = null;
/**
* Gets an instance of {@link LuckPermsApi}
* Gets an instance of {@link LuckPermsApi}, throwing {@link IllegalStateException} if the API is not loaded.
*
* @return an api instance
* @throws IllegalStateException if the api is not loaded
@@ -46,8 +49,10 @@ public final class LuckPerms {
}
/**
* Gets an instance of {@link LuckPermsApi} safely. Unlike {@link LuckPerms#getApi}, this method will not throw an
* {@link IllegalStateException} if the api is not loaded, rather return an empty {@link Optional}.
* Gets an instance of {@link LuckPermsApi} safely.
*
* <p> Unlike {@link LuckPerms#getApi}, this method will not throw an {@link IllegalStateException} if the API is
* not loaded, rather return an empty {@link Optional}.
*
* @return an optional api instance
*/
@@ -27,8 +27,9 @@ import me.lucko.luckperms.api.context.ContextSet;
import java.util.Map;
/**
* Represents the context and options for a permission lookup.
* All values are immutable.
* Context and options for a permission lookup.
*
* <p> All values are immutable.
*
* @since 2.11
*/
@@ -67,28 +68,34 @@ public class Contexts {
* The keys for servers and worlds are defined as static values.
*/
private final ContextSet context;
/**
* The mode to parse defaults on Bukkit
*
* @since 2.12
*/
private final boolean op;
/**
* If global or non server specific nodes should be applied
*/
private final boolean includeGlobal;
/**
* If global or non world specific nodes should be applied
*/
private final boolean includeGlobalWorld;
/**
* If parent groups should be applied
*/
private final boolean applyGroups;
/**
* If global or non server specific group memberships should be applied
*/
private final boolean applyGlobalGroups;
/**
* If global or non world specific group memberships should be applied
*/
@@ -28,7 +28,7 @@ import java.util.Set;
import java.util.UUID;
/**
* Interface for the internal Datastore instance
* Deprecated Storage interface. Use {@link Storage} instead.
*
* @deprecated as of version 2.14 in favour of {@link Storage}.
*/
@@ -26,14 +26,16 @@ import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.OptionalInt;
/**
* Interface for internal Group instances
* A group which holds permission data.
*/
@SuppressWarnings("unused")
public interface Group extends PermissionHolder {
/**
* Get the name of the group
*
* @return the name of the group
*/
String getName();
@@ -220,11 +222,6 @@ public interface Group extends PermissionHolder {
*/
void unsetInheritGroup(Group group, String server, String world, boolean temporary) throws ObjectLacksException;
/**
* Clear all of the groups permission nodes
*/
void clearNodes();
/**
* Get a {@link List} of all of the groups the group inherits, on all servers
*
@@ -236,6 +233,17 @@ public interface Group extends PermissionHolder {
* Get a {@link List} of the groups the group inherits on a specific server
*
* @param server the server to check
* @return a {@link List} of group names
* @throws NullPointerException if the server is null
* @throws IllegalArgumentException if the server is invalid
*/
List<String> getLocalGroups(String server);
/**
* Get a {@link List} of the groups the group inherits on a specific server and world
*
* @param server the server to check
* @param world the world to check
* @return a {@link List} of group names
* @throws NullPointerException if the server or world is null
@@ -244,12 +252,11 @@ public interface Group extends PermissionHolder {
List<String> getLocalGroups(String server, String world);
/**
* Get a {@link List} of the groups the group inherits on a specific server
* Gets the weight of this group, is present.
*
* @param server the server to check
* @return a {@link List} of group names
* @throws NullPointerException if the server is null
* @throws IllegalArgumentException if the server is invalid
* @return the group weight
* @since 2.17
*/
List<String> getLocalGroups(String server);
OptionalInt getWeight();
}
@@ -0,0 +1,94 @@
/*
* 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 com.google.common.collect.Multimap;
import java.util.Optional;
import java.util.OptionalLong;
/**
* A relationship between a Holder and a permission
*
* @param <T> the identifier type of the holder
* @since 2.17
*/
public interface HeldPermission<T> {
/**
* Gets the holder of the permission
*
* @return the holder
*/
T getHolder();
/**
* Gets the permission being held
*
* @return the permission
*/
String getPermission();
/**
* Gets the value of the permission
*
* @return the value
*/
boolean getValue();
/**
* Gets the server where the permission is held
*
* @return the server
*/
Optional<String> getServer();
/**
* Gets the world where the permission is held
*
* @return the world
*/
Optional<String> getWorld();
/**
* Gets the time in unix time when the permission will expire
*
* @return the expiry time
*/
OptionalLong getExpiry();
/**
* Gets the context for the permission.
*
* @return the context
*/
Multimap<String, String> getContext();
/**
* Converts this permission into a Node
*
* @return a Node copy of this permission
*/
Node asNode();
}
@@ -28,22 +28,24 @@ import me.lucko.luckperms.api.data.MySQLConfiguration;
import java.util.Map;
/**
* A wrapper interface for the internal LuckPerms configuration, providing read only access.
* Read-only access to the LuckPerms configuration settings
*/
@SuppressWarnings("unused")
public interface LPConfiguration {
/**
* Returns the name of this server
* @return the name of this server
*/
String getServer();
/**
* Returns how often a sync task will run in minutes
* @return how often a sync task will run in minutes
*/
int getSyncTime();
/**
* Returns the default group, in a node representation
* @return the default group, in a node representation
* @deprecated as of 2.6, the default group is always "default"
*/
@@ -51,6 +53,7 @@ public interface LPConfiguration {
String getDefaultGroupNode();
/**
* Returns the name of the default group
* @return the name of the default group
* @deprecated as of 2.6, the default group is always "default"
*/
@@ -58,55 +61,65 @@ public interface LPConfiguration {
String getDefaultGroupName();
/**
* Returns if the users on this server will have their global permissions applied
* @return if the users on this server will have their global permissions applied
*/
boolean getIncludeGlobalPerms();
/**
* Returns if the users on this server will have their global world permissions applied
* @return if the users on this server will have their global world permissions applied
* @since 2.9
*/
boolean getIncludeGlobalWorldPerms();
/**
* Returns true if the platform is applying global groups
* @return true if the platform is applying global groups
* @since 2.9
*/
boolean getApplyGlobalGroups();
/**
* Returns true if the platform is applying global world groups
* @return true if the platform is applying global world groups
* @since 2.9
*/
boolean getApplyGlobalWorldGroups();
/**
* @return the online mode setting in the config
* Returns the online mode setting
* @return the online mode setting
*/
boolean getOnlineMode();
/**
* Returns if LuckPerms is applying wildcard permissions
* @return if LuckPerms is applying wildcard permissions
*/
boolean getApplyWildcards();
/**
* Returns if LuckPerms is resolving and applying regex permissions
* @return if LuckPerms is resolving and applying regex permissions
*/
boolean getApplyRegex();
/**
* Returns if LuckPerms is expanding shorthand permissions
* @return if LuckPerms is expanding shorthand permissions
*/
boolean getApplyShorthand();
/**
* Returns if LuckPerms will send notifications to users when permissions are modified
* @return if LuckPerms will send notifications to users when permissions are modified
* @since 2.7
*/
boolean getLogNotify();
/**
* Returns true if permission checks are being recorded / debugged
* @return true if permission checks are being recorded / debugged
* @since 2.9
* @deprecated as this value is now always false. Functionality was replaced by the verbose command.
@@ -115,36 +128,42 @@ public interface LPConfiguration {
boolean getDebugPermissionChecks();
/**
* Returns true if the vanilla op system is enabled
* @return true if the vanilla op system is enabled
* @since 2.8
*/
boolean getEnableOps();
/**
* Returns true if opped players are allowed to use LuckPerms commands
* @return true if opped players are allowed to use LuckPerms commands
* @since 2.8
*/
boolean getCommandsAllowOp();
/**
* Returns true if auto op is enabled
* @return true if auto op is enabled
* @since 2.9
*/
boolean getAutoOp();
/**
* Returns the name of the server used within Vault operations
* @return the name of the server used within Vault operations
* @since 2.7
*/
String getVaultServer();
/**
* Returns true if global permissions should be considered when retrieving meta or player groups
* @return true if global permissions should be considered when retrieving meta or player groups
* @since 2.7
*/
boolean getVaultIncludeGlobal();
/**
* Returns the database values set in the configuration
* @return the database values set in the configuration
* @deprecated use {@link #getDatastoreConfig()}
*/
@@ -153,22 +172,26 @@ public interface LPConfiguration {
MySQLConfiguration getDatabaseValues();
/**
* Returns the values set for data storage in the configuration
* @return the values set for data storage in the configuration
*/
DatastoreConfiguration getDatastoreConfig();
/**
* Returns the storage method string from the configuration
* @return the storage method string from the configuration
*/
String getStorageMethod();
/**
* Returns true if split storage is enabled
* @return true if split storage is enabled
* @since 2.7
*/
boolean getSplitStorage();
/**
* Returns a map of split storage options
* @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
@@ -23,14 +23,14 @@
package me.lucko.luckperms.api;
/**
* Represents a Node and where it was inherited from.
* A node with a traceable origin
*
* @since 2.11
*/
public interface LocalizedNode extends Node {
/**
* Gets the node
* Gets the delegate node
*
* @return the node this instance is representing
*/
@@ -27,10 +27,11 @@ import java.util.SortedSet;
import java.util.UUID;
/**
* Represents the internal LuckPerms log. All content internally is immutable. You can add to the log using the {@link
* Datastore}, and then request an updated copy.
* Represents the internal LuckPerms log.
*
* <p> The returned instance provides a copy of the data at the time of retrieval. Any changes made to log entries will
* only apply to this instance of the log. You can add to the log using the {@link Storage}, and then request an updated copy.
*/
@SuppressWarnings("unused")
public interface Log {
/**
@@ -48,6 +49,8 @@ public interface Log {
*
* @param pageNo the page number
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getRecentMaxPages()}}
*/
SortedMap<Integer, LogEntry> getRecent(int pageNo);
@@ -69,6 +72,8 @@ public interface Log {
* @param pageNo the page number
* @param actor the uuid of the actor to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getRecentMaxPages(UUID)}}
*/
SortedMap<Integer, LogEntry> getRecent(int pageNo, UUID actor);
@@ -91,6 +96,8 @@ public interface Log {
* @param pageNo the page number
* @param uuid the uuid of the acted user to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getUserHistoryMaxPages(UUID)}}
*/
SortedMap<Integer, LogEntry> getUserHistory(int pageNo, UUID uuid);
@@ -113,6 +120,8 @@ public interface Log {
* @param pageNo the page number
* @param name the name of the acted group to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getGroupHistoryMaxPages(String)}}
*/
SortedMap<Integer, LogEntry> getGroupHistory(int pageNo, String name);
@@ -141,9 +150,12 @@ public interface Log {
/**
* @param name the name to filter by
* @return the max page number allowed in the {@link #getTrackHistory(int, String)} method
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getTrackHistoryMaxPages(String)}}
*/
int getTrackHistoryMaxPages(String name);
/**
* @param query the query to filter by
* @return all content in this log where the content matches query
@@ -156,6 +168,8 @@ public interface Log {
* @param pageNo the page number
* @param query the query to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getSearchMaxPages(String)}}
*/
SortedMap<Integer, LogEntry> getSearch(int pageNo, String query);
@@ -25,9 +25,10 @@ package me.lucko.luckperms.api;
import java.util.UUID;
/**
* Represents a single entry in a log
* A single entry in the log
*
* <p> Implements {@link Comparable} ordering based upon the timestamp of the entry.
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public class LogEntry implements Comparable<LogEntry> {
private static final String FORMAT = "&8(&e%s&8) [&a%s&8] (&b%s&8) &7--> &f%s";
@@ -154,9 +155,15 @@ public class LogEntry implements Comparable<LogEntry> {
@Override
public String toString() {
return "LogEntry(timestamp=" + this.getTimestamp() + ", actor=" + this.getActor() + ", actorName=" +
this.getActorName() + ", type=" + this.getType() + ", acted=" + this.getActed() + ", actedName=" +
this.getActedName() + ", action=" + this.getAction() + ")";
return "LogEntry(" +
"timestamp=" + this.getTimestamp() + ", " +
"actor=" + this.getActor() + ", " +
"actorName=" + this.getActorName() + ", " +
"type=" + this.getType() + ", " +
"acted=" + this.getActed() + ", " +
"actedName=" + this.getActedName() + ", " +
"action=" + this.getAction() +
")";
}
@Override
@@ -165,41 +172,25 @@ public class LogEntry implements Comparable<LogEntry> {
if (!(o instanceof LogEntry)) return false;
final LogEntry other = (LogEntry) o;
if (this.getTimestamp() != other.getTimestamp()) return false;
final Object this$actor = this.getActor();
final Object other$actor = other.getActor();
if (this$actor == null ? other$actor != null : !this$actor.equals(other$actor)) return false;
final Object this$actorName = this.getActorName();
final Object other$actorName = other.getActorName();
if (this$actorName == null ? other$actorName != null : !this$actorName.equals(other$actorName)) return false;
if (this.getActor() == null ? other.getActor() != null : !this.getActor().equals(other.getActor())) return false;
if (this.getActorName() == null ? other.getActorName() != null : !this.getActorName().equals(other.getActorName())) return false;
if (this.getType() != other.getType()) return false;
final Object this$acted = this.getActed();
final Object other$acted = other.getActed();
if (this$acted == null ? other$acted != null : !this$acted.equals(other$acted)) return false;
final Object this$actedName = this.getActedName();
final Object other$actedName = other.getActedName();
if (this$actedName == null ? other$actedName != null : !this$actedName.equals(other$actedName)) return false;
final Object this$action = this.getAction();
final Object other$action = other.getAction();
return this$action == null ? other$action == null : this$action.equals(other$action);
if (this.getActed() == null ? other.getActed() != null : !this.getActed().equals(other.getActed())) return false;
if (this.getActedName() == null ? other.getActedName() != null : !this.getActedName().equals(other.getActedName())) return false;
return this.getAction() == null ? other.getAction() == null : this.getAction().equals(other.getAction());
}
@Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
final long $timestamp = this.getTimestamp();
result = result * PRIME + (int) ($timestamp >>> 32 ^ $timestamp);
final Object $actor = this.getActor();
result = result * PRIME + ($actor == null ? 43 : $actor.hashCode());
final Object $actorName = this.getActorName();
result = result * PRIME + ($actorName == null ? 43 : $actorName.hashCode());
result = result * PRIME + (int) (this.getTimestamp() >>> 32 ^ this.getTimestamp());
result = result * PRIME + (this.getActor() == null ? 43 : this.getActor().hashCode());
result = result * PRIME + (this.getActorName() == null ? 43 : this.getActorName().hashCode());
result = result * PRIME + this.getType();
final Object $acted = this.getActed();
result = result * PRIME + ($acted == null ? 43 : $acted.hashCode());
final Object $actedName = this.getActedName();
result = result * PRIME + ($actedName == null ? 43 : $actedName.hashCode());
final Object $action = this.getAction();
result = result * PRIME + ($action == null ? 43 : $action.hashCode());
result = result * PRIME + (this.getActed() == null ? 43 : this.getActed().hashCode());
result = result * PRIME + (this.getActedName() == null ? 43 : this.getActedName().hashCode());
result = result * PRIME + (this.getAction() == null ? 43 : this.getAction().hashCode());
return result;
}
@@ -214,6 +205,7 @@ public class LogEntry implements Comparable<LogEntry> {
protected LogEntryBuilder getThis() {
return this;
}
}
public static abstract class AbstractLogEntryBuilder<T extends LogEntry, B extends AbstractLogEntryBuilder<T, B>> {
@@ -311,9 +303,15 @@ public class LogEntry implements Comparable<LogEntry> {
@Override
public String toString() {
return "LogEntry.LogEntryBuilder(timestamp=" + getTimestamp() + ", actor=" + getActor() + ", actorName=" +
getActorName() + ", type=" + getType() + ", acted=" + getActed() + ", actedName=" + getActedName() +
", action=" + getAction() + ")";
return "LogEntry.LogEntryBuilder(" +
"timestamp=" + this.getTimestamp() + ", " +
"actor=" + this.getActor() + ", " +
"actorName=" + this.getActorName() + ", " +
"type=" + this.getType() + ", " +
"acted=" + this.getActed() + ", " +
"actedName=" + this.getActedName() + ", " +
"action=" + this.getAction() +
")";
}
}
@@ -23,7 +23,7 @@
package me.lucko.luckperms.api;
/**
* A wrapper interface 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.
@@ -23,6 +23,7 @@
package me.lucko.luckperms.api;
import me.lucko.luckperms.api.context.ContextListener;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.IContextCalculator;
import me.lucko.luckperms.api.event.LPListener;
@@ -31,9 +32,8 @@ import java.util.Set;
import java.util.UUID;
/**
* The root API interface in LuckPerms
* The root API interface for LuckPerms
*/
@SuppressWarnings("unused")
public interface LuckPermsApi {
/**
@@ -250,6 +250,13 @@ public interface LuckPermsApi {
*/
boolean isTrackLoaded(String name);
/**
* Gets the node factory instance for the platform
*
* @return the node factory
*/
NodeFactory getNodeFactory();
/**
* Returns a permission builder instance
*
@@ -279,11 +286,21 @@ public interface LuckPermsApi {
/**
* Gets a calculated context instance for the user using the rules of the platform.
* These values are calculated using the options in the configuration, and the provided calculators.
*
* <p> These values are calculated using the options in the configuration, and the provided calculators.
*
* @param user the user to get contexts for
* @return an optional containing contexts. Will return empty if the user is not online.
*/
Optional<Contexts> getContextForUser(User user);
/**
* Gets set of contexts applicable to a player using the platforms {@link IContextCalculator}s.
*
* @param player the player to calculate for. Must be the player instance for the platform.
* @return a set of contexts.
* @since 2.17
*/
ContextSet getContextForPlayer(Object player);
}
@@ -23,7 +23,7 @@
package me.lucko.luckperms.api;
/**
* Exposes any networking provider being used on the platform. e.g. Redis
* A means to push changes to other servers using the platforms networking
*
* @since 2.14
*/
@@ -31,7 +31,9 @@ public interface MessagingService {
/**
* Uses the messaging service to inform other servers about changes.
* This will push the update asynchronously, and this method will return almost immediately.
*
* <p> This will push the update asynchronously, and this method will return immediately. Calling this method is
* equivalent to running "/lp networksync", except will not sync this server.
*/
void pushUpdate();
@@ -31,12 +31,12 @@ import java.util.Optional;
import java.util.Set;
/**
* Represents an immutable node object
* An immutable permission node
*
* <p> Use {@link LuckPermsApi#buildNode(String)} to get an instance.
*
* @since 2.6
*/
@SuppressWarnings("unused")
public interface Node extends Map.Entry<String, Boolean> {
/**
@@ -0,0 +1,101 @@
/*
* 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;
/**
* Builds {@link Node} instances
*
* @since 2.17
*/
public interface NodeFactory {
/**
* Creates a node from a serialised node string
*
* @param serialisedPermission the serialised permission string
* @param value the value of the node
* @return a node instance
* @throws NullPointerException if the permission is null
*/
Node fromSerialisedNode(String serialisedPermission, boolean value);
/**
* Creates a new node builder from a given base permission string
*
* @param permission the permission
* @return a node builder instance
* @throws NullPointerException if the permission is null
*/
Node.Builder newBuilder(String permission);
/**
* Creates a node builder instance from an existing node
*
* @param other the other node
* @return a node builder instance
* @throws NullPointerException if the other node is null
*/
Node.Builder newBuilderFromExisting(Node other);
/**
* Creates a node builder from a serialised node string
* @param serialisedPermission the serialised permission string
* @param value the value of the node
* @return a node builder instance
* @throws NullPointerException if the permission is null
*/
Node.Builder newBuilderFromSerialisedNode(String serialisedPermission, boolean value);
/**
* Creates a node builder from a key value pair
*
* @param key the key
* @param value the value
* @return a node builder instance
* @throws NullPointerException if the key or value is null
*/
Node.Builder makeMetaNode(String key, String value);
/**
* Creates a node builder from a prefix string and priority
*
* @param priority the priority
* @param prefix the prefix string
* @return a node builder instance
* @throws NullPointerException if the prefix is null
*/
Node.Builder makePrefixNode(int priority, String prefix);
/**
* Creates a node builder from a prefix string and priority
*
* @param priority the priority
* @param suffix the suffix string
* @return a node builder instance
* @throws NullPointerException if the suffix is null
*/
Node.Builder makeSuffixNode(int priority, String suffix);
}
@@ -31,19 +31,24 @@ import java.util.Set;
import java.util.SortedSet;
/**
* Interface for internal PermissionHolder (user/group) instances
* An object capable of holding permissions
*
* <p> Any changes made will be lost unless the instance is saved back to the {@link Storage}.
*/
@SuppressWarnings("unused")
public interface PermissionHolder {
/**
* @return the identifier for this object. either a uuid string or name However, you should really just use {@link
* User#getUuid()}, {@link User#getName()} or {@link Group#getName()}
* Gets the objects name
*
* <p> {@link User#getUuid()}, {@link User#getName()} or {@link Group#getName()} should normally be used instead of
* this method.
*
* @return the identifier for this object. Either a uuid string or name.
*/
String getObjectName();
/**
* Gets an immutable Set of the objects permission nodes
* Gets a sorted set of all held permissions.
*
* @return an immutable set of permissions in priority order
* @since 2.6
@@ -51,20 +56,22 @@ public interface PermissionHolder {
SortedSet<? extends Node> getPermissions();
/**
* Similar to {@link #getPermissions()}, except excluding transient permissions
* Similar to {@link #getPermissions()}, except without transient permissions
*
* @return a set of nodes
* @since 2.6
*/
Set<Node> getEnduringPermissions();
Set<? extends Node> getEnduringPermissions();
/**
* Similar to {@link #getPermissions()}, except excluding non-transient permissions
* Gets an immutable set of all transiently held permissions.
*
* <p> Transient permissions only exist for the duration of the session.
*
* @return a set of nodes
* @since 2.6
*/
Set<Node> getTransientPermissions();
Set<? extends Node> getTransientPermissions();
/**
@@ -91,7 +98,7 @@ public interface PermissionHolder {
SortedSet<LocalizedNode> getAllNodes(Contexts contexts);
/**
* Gets a mutable set of the nodes that is objects has and inherits, filtered by context.
* Gets a mutable set of the nodes that this object has and inherits, filtered by context.
* Unlike {@link #getAllNodes(Contexts)}, this method WILL filter individual nodes, and only return ones that fully
* meet the context provided.
*
@@ -102,6 +109,14 @@ public interface PermissionHolder {
*/
Set<LocalizedNode> getAllNodesFiltered(Contexts contexts);
/**
* Converts the output of {@link #getAllNodesFiltered(Contexts)}, and expands shorthand permissions.
* @param contexts the context for the lookup
* @param lowerCase if the keys should be made lowercase whilst being exported
* @return a mutable map of permissions
*/
Map<String, Boolean> exportNodes(Contexts contexts, boolean lowerCase);
/**
* Gets an immutable Map of the objects permission nodes
*
@@ -111,6 +126,11 @@ public interface PermissionHolder {
@Deprecated
Map<String, Boolean> getNodes();
/**
* Removes temporary permissions that have expired
*/
void auditTemporaryPermissions();
/**
* Checks to see if the object has a certain permission
*
@@ -508,6 +528,109 @@ public interface PermissionHolder {
@Deprecated
void unsetPermission(String node, String server, String world, boolean temporary) throws ObjectLacksException;
/**
* Clears all nodes held by the object
*
* @since 2.17
*/
void clearNodes();
/**
* Clears all nodes held by the object on a specific server
*
* @param server the server to filter by, can be null
* @since 2.17
*/
void clearNodes(String server);
/**
* Clears all nodes held by the object on a specific server and world
*
* @param server the server to filter by, can be null
* @param world the world to filter by, can be null
* @since 2.17
*/
void clearNodes(String server, String world);
/**
* Clears all parent groups
*
* @since 2.17
*/
void clearParents();
/**
* Clears all parents on a specific server
*
* @param server the server to filter by, can be null
* @since 2.17
*/
void clearParents(String server);
/**
* Clears all parents on a specific server and world
*
* @param server the server to filter by, can be null
* @param world the world to filter by, can be null
* @since 2.17
*/
void clearParents(String server, String world);
/**
* Clears all meta held by the object
*
* @since 2.17
*/
void clearMeta();
/**
* Clears all meta held by the object on a specific server
*
* @param server the server to filter by, can be null
* @since 2.17
*/
void clearMeta(String server);
/**
* Clears all meta held by the object on a specific server and world
*
* @param server the server to filter by, can be null
* @param world the world to filter by, can be null
* @since 2.17
*/
void clearMeta(String server, String world);
/**
* Clears all meta for a given key.
*
* @param key the meta key
* @param server the server to filter by, can be null
* @param world the world to filter by, can be null
* @param temporary whether the query is for temporary nodes or not.
*/
void clearMetaKeys(String key, String server, String world, boolean temporary);
/**
* Clears all transient permissions the holder has.
*/
void clearTransientNodes();
/**
* Processes the nodes and returns the non-temporary ones.
*
* @return a set of permanent nodes
* @since 2.6
*/
Set<Node> getPermanentPermissionNodes();
/**
* Processes the nodes and returns the temporary ones.
*
* @return a set of temporary nodes
* @since 2.6
*/
Set<Node> getTemporaryPermissionNodes();
/**
* Gets the permissions and inherited permissions that apply to a specific server and world
*
@@ -581,14 +704,6 @@ public interface PermissionHolder {
@Deprecated
Map<Map.Entry<String, Boolean>, Long> getTemporaryNodes();
/**
* Processes the nodes and returns the temporary ones.
*
* @return a set of temporary nodes
* @since 2.6
*/
Set<Node> getTemporaryPermissionNodes();
/**
* Processes the nodes and returns the non-temporary ones.
*
@@ -598,17 +713,4 @@ public interface PermissionHolder {
@Deprecated
Map<String, Boolean> getPermanentNodes();
/**
* Processes the nodes and returns the non-temporary ones.
*
* @return a set of permanent nodes
* @since 2.6
*/
Set<Node> getPermanentPermissionNodes();
/**
* Removes temporary permissions that have expired
*/
void auditTemporaryPermissions();
}
@@ -23,7 +23,7 @@
package me.lucko.luckperms.api;
/**
* Represents the platform type that LuckPerms is running on
* The platforms which LuckPerms can run on
*
* @since 2.7
*/
@@ -22,6 +22,7 @@
package me.lucko.luckperms.api;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@@ -29,7 +30,7 @@ import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* Interface for the internal Storage instance
* A means of loading and saving data to/from the Storage provider.
*
* <p>All methods return {@link CompletableFuture}s, which will be populated with the result once the data has been
* loaded asynchronously. Care should be taken when using the methods to ensure that the main server thread is not
@@ -124,6 +125,16 @@ public interface Storage {
*/
CompletableFuture<Set<UUID>> getUniqueUsers();
/**
* Searches for a list of users with a given permission.
*
* @param permission the permission to search for
* @return a list of held permissions, or null if the operation failed
* @throws NullPointerException if the permission is null
* @since 2.17
*/
CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(String permission);
/**
* Creates and loads a group into the plugins local storage
*
@@ -171,6 +182,16 @@ public interface Storage {
*/
CompletableFuture<Boolean> deleteGroup(Group group);
/**
* Searches for a list of groups with a given permission.
*
* @param permission the permission to search for
* @return a list of held permissions, or null if the operation failed
* @throws NullPointerException if the permission is null
* @since 2.17
*/
CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(String permission);
/**
* Creates and loads a track into the plugins local storage
*
@@ -239,4 +260,14 @@ public interface Storage {
*/
CompletableFuture<UUID> getUUID(String username);
/**
* Gets a username from a UUID
*
* @param uuid the corresponding uuid
* @return a name string, could be null
* @throws NullPointerException if either parameters are null
* @since 2.17
*/
CompletableFuture<String> getName(UUID uuid);
}
@@ -28,19 +28,20 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
/**
* Interface for internal Track instances
* An ordered collection of groups for easy promotions and demotions
*/
@SuppressWarnings("unused")
public interface Track {
/**
* Gets the name of this track
* @return the name of this track
*/
String getName();
/**
* Gets an ordered list of the groups on this track
* Index 0 is the first/lowest group in (or start of) the track
*
* <p> Index 0 is the first/lowest group in (or start of) the track
*
* @return an ordered {@link List} of the groups on this track
*/
@@ -136,7 +137,7 @@ public interface Track {
boolean containsGroup(String group);
/**
* Clear all of the groups within this track
* Clear all of the groups from this track
*/
void clearGroups();
@@ -23,14 +23,34 @@
package me.lucko.luckperms.api;
/**
* Represents a permission value
* Represents a permission setting.
*
* <p> Consider a value of {@link #FALSE} to be a "negated" setting, and a value of {@link #UNDEFINED} to be a
* non-existent value.
*/
public enum Tristate {
/**
* A value indicating a holder has a permission set.
*/
TRUE(true),
/**
* A value indicating a holder has a negated value for a permission.
*/
FALSE(false),
/**
* A value indicating a holder doesn't have a value for a permission set.
*/
UNDEFINED(false);
/**
* Converts from {@link Boolean} a boolean
*
* @param b the boolean
* @return {@link #TRUE} or {@link #FALSE}, depending on the value of the boolean.
*/
public static Tristate fromBoolean(boolean b) {
return b ? TRUE : FALSE;
}
@@ -41,6 +61,12 @@ public enum Tristate {
this.booleanValue = booleanValue;
}
/**
* Returns the value of the Tristate as a boolean.
* <p> A value of {@link #UNDEFINED} converts to false.
*
* @return a boolean representation of the Tristate.
*/
public boolean asBoolean() {
return booleanValue;
}
@@ -31,17 +31,20 @@ import java.util.Optional;
import java.util.UUID;
/**
* Interface for internal User instances
* A player holding permission data
*/
@SuppressWarnings("unused")
public interface User extends PermissionHolder {
/**
* Gets the users unique ID
*
* @return the users Mojang assigned unique id
*/
UUID getUuid();
/**
* Gets the users username
*
* @return the Users Username
*/
String getName();
@@ -64,7 +67,10 @@ public interface User extends PermissionHolder {
void setPrimaryGroup(String group) throws ObjectAlreadyHasException;
/**
* Refresh and re-assign the users permissions
* Refresh and re-assign the users permissions.
*
* <p> This request is not buffered, and the refresh call will be ran directly. This should ideally be called on
* an asynchronous thread.
*/
void refreshPermissions();
@@ -76,6 +82,13 @@ public interface User extends PermissionHolder {
*/
Optional<UserData> getUserDataCache();
/**
* Sets up the users data cache, if the don't have one setup already.
*
* @since 2.17
*/
void setupDataCache();
/**
* Check to see if the user is a member of a group
*
@@ -255,11 +268,6 @@ public interface User extends PermissionHolder {
*/
void removeGroup(Group group, String server, String world, boolean temporary) throws ObjectLacksException;
/**
* Clear all of the users permission nodes
*/
void clearNodes();
/**
* Get a {@link List} of all of the groups the user is a member of, on all servers
*
@@ -28,16 +28,15 @@ import java.util.UUID;
* 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
* servers or mixed offline mode and online mode servers. Platforms running in offline mode generate a UUID for a
* user when they first join the server, but this UUID will then not be consistent across the network. LuckPerms will
* instead check the datastore cache, to get a UUID for a user that is consistent across an entire network.
*
* <p> If you want to get a user object from the Storage using the api on a server in offline mode, you will need to use
* this cache, OR use Storage#getUUID, for users that are not online.
*
* <p> WARNING: THIS IS ONLY EFFECTIVE FOR ONLINE PLAYERS. USE THE DATASTORE METHODS FOR OFFLINE PLAYERS.
* <p> THIS IS ONLY EFFECTIVE FOR ONLINE PLAYERS. USE THE DATASTORE METHODS FOR OFFLINE PLAYERS.
*/
@SuppressWarnings("unused")
public interface UuidCache {
/**
@@ -44,7 +44,8 @@ public interface PermissionData {
/**
* Invalidates the underlying permission calculator cache.
* Can be called to allow for an update in defaults.
*
* <p> Can be called to allow for an update in defaults.
*/
void invalidateCache();
@@ -38,7 +38,8 @@ public interface UserData {
/**
* Gets PermissionData from the cache, given a specified context.
* If the data is not cached, it is calculated. Therefore, this call could be costly.
*
* <p> If the data is not cached, it is calculated. Therefore, this call could be costly.
*
* @param contexts the contexts to get the permission data in
* @return a permission data instance
@@ -48,7 +49,8 @@ public interface UserData {
/**
* Gets MetaData from the cache, given a specified context.
* If the data is not cached, it is calculated. Therefore, this call could be costly.
*
* <p> If the data is not cached, it is calculated. Therefore, this call could be costly.
*
* @param contexts the contexts to get the permission data in
* @return a meta data instance
@@ -75,8 +77,10 @@ public interface UserData {
MetaData calculateMeta(Contexts contexts);
/**
* Calculates permission data and stores it in the cache. If there is already data cached for the given contexts,
* and if the resultant output is different, the cached value is updated.
* Calculates permission data and stores it in the cache.
*
* <p> If there is already data cached for the given contexts, and if the resultant output is different,
* the cached value is updated.
*
* @param contexts the contexts to recalculate in.
* @throws NullPointerException if contexts is null
@@ -84,8 +88,10 @@ public interface UserData {
void recalculatePermissions(Contexts contexts);
/**
* Calculates meta data and stores it in the cache. If there is already data cached for the given contexts,
* and if the resultant output is different, the cached value is updated.
* Calculates meta data and stores it in the cache.
*
* <p> If there is already data cached for the given contexts, and if the resultant output is different,
* the cached value is updated.
*
* @param contexts the contexts to recalculate in.
* @throws NullPointerException if contexts is null
@@ -111,8 +117,9 @@ public interface UserData {
void preCalculate(Set<Contexts> contexts);
/**
* Ensures that PermissionData and MetaData is cached for a context. If the cache does not contain any data for the
* context, it will be calculated and saved.
* Ensures that PermissionData and MetaData is cached for a context.
*
* <p> If the cache does not contain any data for the context, it will be calculated and saved.
*
* @param contexts the contexts to pre-calculate for
* @throws NullPointerException if contexts is null
@@ -65,7 +65,7 @@ public interface ContextSet {
* @return a new ImmutableContextSet representing the pairs in the iterable
* @throws NullPointerException if the iterable is null
*/
static ImmutableContextSet fromEntries(Iterable<Map.Entry<String, String>> iterable) {
static ImmutableContextSet fromEntries(Iterable<? extends Map.Entry<String, String>> iterable) {
return ImmutableContextSet.fromEntries(iterable);
}
@@ -22,7 +22,6 @@
package me.lucko.luckperms.api.context;
import java.util.HashMap;
import java.util.Map;
/**
@@ -40,37 +39,9 @@ public interface IContextCalculator<T> {
* @param subject the subject to add contexts to
* @param accumulator a map of contexts to add to
* @return the map
* @deprecated in favour of {@link #giveApplicableContext(Object, MutableContextSet)}. Older implementations of this
* interface will still work, as the replacement method is given as a default, and falls back to using this method.
*/
@Deprecated
default Map<String, String> giveApplicableContext(T subject, Map<String, String> accumulator) {
MutableContextSet acc = new MutableContextSet();
giveApplicableContext(subject, acc);
accumulator.putAll(acc.toMap());
return accumulator;
}
/**
* Gives the subject all of the applicable contexts they meet
*
* <p><b>You MUST implement this method. The default is only provided for backwards compatibility with
* {@link #giveApplicableContext(Object, Map)}.</b>
*
* @param subject the subject to add contexts to
* @param accumulator a map of contexts to add to
* @return the map
* @since 2.13
*/
@SuppressWarnings("deprecation")
default MutableContextSet giveApplicableContext(T subject, MutableContextSet accumulator) {
Map<String, String> acc = new HashMap<>();
giveApplicableContext(subject, acc);
accumulator.addAll(acc.entrySet());
return accumulator;
}
MutableContextSet giveApplicableContext(T subject, MutableContextSet accumulator);
/**
* Checks to see if a context is applicable to a subject
@@ -30,7 +30,6 @@ import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* An immutable implementation of {@link ContextSet}.
@@ -71,13 +70,12 @@ public final class ImmutableContextSet implements ContextSet {
throw new NullPointerException("map");
}
return new ImmutableContextSet(ImmutableMultimap.copyOf(
map.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey().toLowerCase(),
Map.Entry::getValue
)).entrySet()
));
ImmutableMultimap.Builder<String, String> b = ImmutableMultimap.builder();
for (Map.Entry<String, String> e : map.entrySet()) {
b.put(e.getKey(), e.getValue());
}
return new ImmutableContextSet(b.build());
}
/**
@@ -87,7 +85,7 @@ public final class ImmutableContextSet implements ContextSet {
* @return a new ImmutableContextSet representing the pairs in the iterable
* @throws NullPointerException if the iterable is null
*/
public static ImmutableContextSet fromEntries(Iterable<Map.Entry<String, String>> iterable) {
public static ImmutableContextSet fromEntries(Iterable<? extends Map.Entry<String, String>> iterable) {
if (iterable == null) {
throw new NullPointerException("iterable");
}
@@ -160,7 +158,12 @@ public final class ImmutableContextSet implements ContextSet {
@Override
public Map<String, String> toMap() {
return ImmutableMap.copyOf(map.entries());
ImmutableMap.Builder<String, String> m = ImmutableMap.builder();
for (Map.Entry<String, String> e : map.entries()) {
m.put(e.getKey(), e.getValue());
}
return m.build();
}
@Override
@@ -84,7 +84,7 @@ public final class MutableContextSet implements ContextSet {
* @return a new MutableContextSet representing the pairs in the iterable
* @throws NullPointerException if the iterable is null
*/
public static MutableContextSet fromEntries(Iterable<Map.Entry<String, String>> iterable) {
public static MutableContextSet fromEntries(Iterable<? extends Map.Entry<String, String>> iterable) {
if (iterable == null) {
throw new NullPointerException("iterable");
}
@@ -168,7 +168,12 @@ public final class MutableContextSet implements ContextSet {
@Override
public Map<String, String> toMap() {
return ImmutableMap.copyOf(map.entries());
ImmutableMap.Builder<String, String> m = ImmutableMap.builder();
for (Map.Entry<String, String> e : map.entries()) {
m.put(e.getKey(), e.getValue());
}
return m.build();
}
@Override
@@ -277,7 +282,7 @@ public final class MutableContextSet implements ContextSet {
* @param iterable an iterable of key value context pairs
* @throws NullPointerException if iterable is null
*/
public void addAll(Iterable<Map.Entry<String, String>> iterable) {
public void addAll(Iterable<? extends Map.Entry<String, String>> iterable) {
if (iterable == null) {
throw new NullPointerException("contexts");
}
+4 -32
View File
@@ -5,14 +5,14 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.16-SNAPSHOT</version>
<version>2.17-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-bukkit-legacy</artifactId>
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>LuckPerms-bukkit-legacy-${release.version}.${git.closest.tag.commit.count}</finalName>
<finalName>LuckPerms-Bukkit-Legacy-${release.version}.${git.closest.tag.commit.count}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
@@ -47,26 +47,6 @@
</excludes>
</artifactSet>
<relocations>
<relocation>
<pattern>org.slf4j</pattern>
<shadedPattern>me.lucko.luckperms.lib.slf4j</shadedPattern>
</relocation>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
</relocation>
<relocation>
<pattern>com.mongodb</pattern>
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
</relocation>
<relocation>
<pattern>org.bson</pattern>
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
</relocation>
<relocation>
<pattern>org.h2</pattern>
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
</relocation>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>me.lucko.luckperms.lib.guava</shadedPattern>
@@ -76,16 +56,8 @@
<shadedPattern>me.lucko.luckperms.lib.gson</shadedPattern>
</relocation>
<relocation>
<pattern>redis.clients.jedis</pattern>
<shadedPattern>me.lucko.luckperms.lib.jedis.jedis</shadedPattern>
</relocation>
<relocation>
<pattern>redis.clients.util</pattern>
<shadedPattern>me.lucko.luckperms.lib.jedis.util</shadedPattern>
</relocation>
<relocation>
<pattern>org.apache.commons.pool2</pattern>
<shadedPattern>me.lucko.luckperms.lib.jedis.pool2</shadedPattern>
<pattern>io.github.mkremins.fanciful</pattern>
<shadedPattern>me.lucko.luckperms.lib.fanciful</shadedPattern>
</relocation>
</relocations>
</configuration>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.16-SNAPSHOT</version>
<version>2.17-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+13 -39
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.16-SNAPSHOT</version>
<version>2.17-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -14,7 +14,7 @@
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>LuckPerms-${release.version}.${git.closest.tag.commit.count}</finalName>
<finalName>LuckPerms-Bukkit-${release.version}.${git.closest.tag.commit.count}</finalName>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
@@ -44,43 +44,10 @@
</goals>
<configuration>
<minimizeJar>false</minimizeJar>
<artifactSet>
<excludes>
<exclude>org.xerial:*</exclude>
</excludes>
</artifactSet>
<relocations>
<relocation>
<pattern>org.slf4j</pattern>
<shadedPattern>me.lucko.luckperms.lib.slf4j</shadedPattern>
</relocation>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
</relocation>
<relocation>
<pattern>com.mongodb</pattern>
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
</relocation>
<relocation>
<pattern>org.bson</pattern>
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
</relocation>
<relocation>
<pattern>org.h2</pattern>
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
</relocation>
<relocation>
<pattern>redis.clients.jedis</pattern>
<shadedPattern>me.lucko.luckperms.lib.jedis.jedis</shadedPattern>
</relocation>
<relocation>
<pattern>redis.clients.util</pattern>
<shadedPattern>me.lucko.luckperms.lib.jedis.util</shadedPattern>
</relocation>
<relocation>
<pattern>org.apache.commons.pool2</pattern>
<shadedPattern>me.lucko.luckperms.lib.jedis.pool2</shadedPattern>
<pattern>io.github.mkremins.fanciful</pattern>
<shadedPattern>me.lucko.luckperms.lib.fanciful</shadedPattern>
</relocation>
</relocations>
</configuration>
@@ -108,8 +75,8 @@
<dependencies>
<!-- BukkitAPI -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@@ -134,6 +101,13 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- HikariCP - needed as source -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.5.1</version>
<scope>provided</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
@@ -50,8 +50,7 @@ class BukkitCommand extends CommandManager implements CommandExecutor, TabExecut
onCommand(
plugin.getSenderFactory().wrap(sender),
label,
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
null
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args)))
);
return true;
}
@@ -117,7 +117,7 @@ class BukkitListener extends AbstractListener implements Listener {
plugin.getWorldCalculator().getWorldCache().remove(internal);
// Remove the custom permissible
Injector.unInject(player);
Injector.unInject(player, true);
// Handle auto op
if (plugin.getConfiguration().isAutoOp()) {
@@ -140,7 +140,7 @@ class BukkitListener extends AbstractListener implements Listener {
.replace("spigot:", "")
.replace("minecraft:", "");
if (s.startsWith("op") || s.startsWith("deop")) {
if (s.equals("op") || s.startsWith("op ") || s.equals("deop") || s.startsWith("deop ")) {
e.setCancelled(true);
e.getPlayer().sendMessage(Message.OP_DISABLED.toString());
}
@@ -22,6 +22,7 @@
package me.lucko.luckperms.bukkit;
import me.lucko.luckperms.bukkit.compat.MessageHandler;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.sender.SenderFactory;
import me.lucko.luckperms.common.constants.Constants;
@@ -29,11 +30,16 @@ import me.lucko.luckperms.common.constants.Constants;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import io.github.mkremins.fanciful.FancyMessage;
import java.util.UUID;
public class BukkitSenderFactory extends SenderFactory<CommandSender> {
private final MessageHandler messageHandler;
public BukkitSenderFactory(LuckPermsPlugin plugin) {
super(plugin);
messageHandler = new MessageHandler();
}
@Override
@@ -41,7 +47,7 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> {
if (sender instanceof Player) {
return sender.getName();
}
return Constants.getConsoleName();
return Constants.CONSOLE_NAME;
}
@Override
@@ -49,7 +55,7 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> {
if (sender instanceof Player) {
return ((Player) sender).getUniqueId();
}
return Constants.getConsoleUUID();
return Constants.CONSOLE_UUID;
}
@Override
@@ -57,6 +63,11 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> {
sender.sendMessage(s);
}
@Override
protected void sendMessage(CommandSender sender, FancyMessage message) {
messageHandler.sendJsonMessage(sender, message);
}
@Override
protected boolean hasPermission(CommandSender sender, String node) {
return sender.hasPermission(node);
@@ -26,7 +26,6 @@ import lombok.Getter;
import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.ApiHandler;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.LuckPermsApi;
@@ -34,13 +33,16 @@ import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.bukkit.calculators.AutoOPListener;
import me.lucko.luckperms.bukkit.inject.Injector;
import me.lucko.luckperms.bukkit.model.ChildPermissionProvider;
import me.lucko.luckperms.bukkit.model.DefaultsProvider;
import me.lucko.luckperms.bukkit.model.LPPermissible;
import me.lucko.luckperms.bukkit.vault.VaultHook;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.api.ApiHandler;
import me.lucko.luckperms.common.api.ApiProvider;
import me.lucko.luckperms.common.caching.handlers.CachedStateManager;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.commands.ConsecutiveExecutor;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.config.LPConfiguration;
import me.lucko.luckperms.common.constants.Permission;
@@ -49,6 +51,7 @@ import me.lucko.luckperms.common.contexts.ServerCalculator;
import me.lucko.luckperms.common.core.UuidCache;
import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.data.Importer;
import me.lucko.luckperms.common.dependencies.DependencyManager;
import me.lucko.luckperms.common.managers.GroupManager;
import me.lucko.luckperms.common.managers.TrackManager;
import me.lucko.luckperms.common.managers.UserManager;
@@ -58,6 +61,8 @@ import me.lucko.luckperms.common.managers.impl.GenericUserManager;
import me.lucko.luckperms.common.messaging.RedisMessaging;
import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.storage.StorageType;
import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
import me.lucko.luckperms.common.tasks.UpdateTask;
import me.lucko.luckperms.common.utils.BufferedRequest;
@@ -69,12 +74,14 @@ import me.lucko.luckperms.common.utils.PermissionCache;
import org.bukkit.World;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -89,7 +96,7 @@ import java.util.stream.Collectors;
@Getter
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
private Set<UUID> ignoringLogs;
private Executor syncExecutor;
private Executor asyncExecutor;
private VaultHook vaultHook = null;
@@ -100,13 +107,14 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private Storage storage;
private RedisMessaging redisMessaging = null;
private UuidCache uuidCache;
private BukkitListener listener;
private ApiProvider apiProvider;
private Logger log;
private Importer importer;
private ConsecutiveExecutor consecutiveExecutor;
private DefaultsProvider defaultsProvider;
private ChildPermissionProvider childPermissionProvider;
private LocaleManager localeManager;
private CachedStateManager cachedStateManager;
private ContextManager<Player> contextManager;
private WorldCalculator worldCalculator;
private CalculatorFactory calculatorFactory;
@@ -124,13 +132,17 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
Executor bukkitAsyncExecutor = r -> getServer().getScheduler().runTaskAsynchronously(this, r);
log = LogFactory.wrap(getLogger());
debugHandler = new DebugHandler(bukkitAsyncExecutor);
ignoringLogs = ConcurrentHashMap.newKeySet();
debugHandler = new DebugHandler(bukkitAsyncExecutor, getVersion());
senderFactory = new BukkitSenderFactory(this);
permissionCache = new PermissionCache(bukkitAsyncExecutor);
getLog().info("Loading configuration...");
configuration = new BukkitConfig(this);
Set<StorageType> storageTypes = StorageFactory.getRequiredTypes(this, StorageType.H2);
DependencyManager.loadDependencies(this, storageTypes);
// setup the Bukkit defaults hook
defaultsProvider = new DefaultsProvider();
childPermissionProvider = new ChildPermissionProvider();
@@ -162,10 +174,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
// register events
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new BukkitListener(this), this);
listener = new BukkitListener(this);
pm.registerEvents(listener, this);
// initialise datastore
storage = StorageFactory.getInstance(this, "h2");
storage = StorageFactory.getInstance(this, StorageType.H2);
// initialise redis
if (getConfiguration().isRedisEnabled()) {
@@ -207,7 +220,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
PluginCommand main = getServer().getPluginCommand("luckperms");
main.setExecutor(commandManager);
main.setTabCompleter(commandManager);
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
main.setAliases(Arrays.asList("perms", "lp", "permissions", "perm"));
// load internal managers
getLog().info("Loading internal permission managers...");
@@ -216,8 +229,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
groupManager = new GenericGroupManager(this);
trackManager = new GenericTrackManager();
importer = new Importer(commandManager);
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
calculatorFactory = new BukkitCalculatorFactory(this);
cachedStateManager = new CachedStateManager(this);
contextManager = new ContextManager<>();
worldCalculator = new WorldCalculator(this);
@@ -244,7 +257,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
long ticks = mins * 60 * 20;
getServer().getScheduler().runTaskTimerAsynchronously(this, () -> updateTaskBuffer.request(), 20L, ticks);
getServer().getScheduler().runTaskTimerAsynchronously(this, () -> updateTaskBuffer.request(), 40L, ticks);
}
// run an update instantly.
@@ -252,7 +265,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
// register tasks
getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpireTemporaryTask(this), 60L, 60L);
getServer().getScheduler().runTaskTimerAsynchronously(this, consecutiveExecutor, 20L, 20L);
getServer().getScheduler().runTaskTimerAsynchronously(this, new CacheHousekeepingTask(this), 2400L, 2400L);
// register permissions
registerPermissions(getConfiguration().isCommandsAllowOp() ? PermissionDefault.OP : PermissionDefault.FALSE);
@@ -265,6 +278,24 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
asyncExecutor = bukkitAsyncExecutor;
});
// Load any online users (in the case of a reload)
for (Player player : getServer().getOnlinePlayers()) {
doAsync(() -> {
listener.onAsyncLogin(player.getUniqueId(), player.getName());
User user = getUserManager().get(getUuidCache().getUUID(player.getUniqueId()));
if (user != null) {
doSync(() -> {
try {
LPPermissible lpPermissible = new LPPermissible(player, user, this);
Injector.inject(player, lpPermissible);
} catch (Throwable t) {
t.printStackTrace();
}
});
}
});
}
started = true;
getLog().info("Successfully loaded.");
}
@@ -272,6 +303,24 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
@Override
public void onDisable() {
started = false;
defaultsProvider.close();
permissionCache.setShutdown(true);
debugHandler.setShutdown(true);
for (Player player : getServer().getOnlinePlayers()) {
Injector.unInject(player, false);
if (getConfiguration().isAutoOp()) {
player.setOp(false);
}
final User user = getUserManager().get(getUuidCache().getUUID(player.getUniqueId()));
if (user != null) {
user.unregisterData();
getUserManager().unload(user);
}
}
getLog().info("Closing datastore...");
storage.shutdown();
@@ -287,6 +336,38 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
if (vaultHook != null) {
vaultHook.unhook(this);
}
// Bukkit will do this again when #onDisable completes, but we do it early to prevent NPEs elsewhere.
getServer().getScheduler().cancelTasks(this);
HandlerList.unregisterAll(this);
// Null everything
ignoringLogs = null;
syncExecutor = null;
asyncExecutor = null;
vaultHook = null;
configuration = null;
userManager = null;
groupManager = null;
trackManager = null;
storage = null;
redisMessaging = null;
uuidCache = null;
listener = null;
apiProvider = null;
log = null;
importer = null;
defaultsProvider = null;
childPermissionProvider = null;
localeManager = null;
cachedStateManager = null;
contextManager = null;
worldCalculator = null;
calculatorFactory = null;
updateTaskBuffer = null;
debugHandler = null;
senderFactory = null;
permissionCache = null;
}
public void tryVaultHook(boolean force) {
@@ -310,6 +391,14 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
}
}
@Override
public void onUserRefresh(User user) {
LPPermissible lpp = Injector.getPermissible(uuidCache.getExternalUUID(user.getUuid()));
if (lpp != null) {
lpp.updateSubscriptions();
}
}
@Override
public void doAsync(Runnable r) {
asyncExecutor.execute(r);
@@ -335,11 +424,26 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return PlatformType.BUKKIT;
}
@Override
public String getServerName() {
return getServer().getName();
}
@Override
public String getServerVersion() {
return getServer().getVersion();
}
@Override
public File getMainDir() {
return getDataFolder();
}
@Override
public InputStream getResourceStream(String path) {
return getResource(path);
}
@Override
public Player getPlayer(User user) {
return getServer().getPlayer(uuidCache.getExternalUUID(user.getUuid()));
@@ -35,14 +35,16 @@ public class AutoOPListener implements ContextListener<Player> {
@Override
public void onContextChange(Player subject, Map.Entry<String, String> before, Map.Entry<String, String> current) throws Exception {
LPPermissible permissible = Injector.getPermissible(subject.getUniqueId());
if (permissible == null) {
return;
}
try {
LPPermissible permissible = Injector.getPermissible(subject.getUniqueId());
if (permissible == null) {
return;
}
Map<String, Boolean> backing = permissible.getUser().getUserData().getPermissionData(permissible.calculateContexts()).getImmutableBacking();
boolean op = Optional.ofNullable(backing.get("luckperms.autoop")).orElse(false);
subject.setOp(op);
Map<String, Boolean> backing = permissible.getUser().getUserData().getPermissionData(permissible.calculateContexts()).getImmutableBacking();
boolean op = Optional.ofNullable(backing.get("luckperms.autoop")).orElse(false);
subject.setOp(op);
} catch (Exception ignored) {}
}
}
@@ -0,0 +1,122 @@
/*
* 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.bukkit.compat;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class BukkitJsonMessageHandler {
private static boolean setup = false;
private static boolean triedAndFailed = false;
private static Method GET_HANDLE_METHOD;
private static Field PLAYER_CONNECTION_FIELD;
private static Method SEND_PACKET_METHOD;
private static Constructor<?> PACKET_CHAT_CONSTRUCTOR;
private static Method SERIALIZE_METHOD;
private static void setup(Object player) throws Exception {
Class<?> craftPlayerClass = player.getClass();
GET_HANDLE_METHOD = craftPlayerClass.getDeclaredMethod("getHandle");
Object handleObject = GET_HANDLE_METHOD.invoke(player);
Class<?> handleClass = handleObject.getClass();
PLAYER_CONNECTION_FIELD = handleClass.getDeclaredField("playerConnection");
Object playerConnectionObject = PLAYER_CONNECTION_FIELD.get(handleObject);
Method[] playerConnectionMethods = playerConnectionObject.getClass().getDeclaredMethods();
for (Method m : playerConnectionMethods) {
if (m.getName().equals("sendPacket")) {
SEND_PACKET_METHOD = m;
break;
}
}
Class<?> packetChatClass = Class.forName(getVersionedClassName("PacketPlayOutChat"));
Constructor[] packetConstructors = packetChatClass.getDeclaredConstructors();
for (Constructor c : packetConstructors) {
Class<?>[] parameters = c.getParameterTypes();
if (parameters.length == 1 && parameters[0].getName().endsWith("IChatBaseComponent")) {
PACKET_CHAT_CONSTRUCTOR = c;
break;
}
}
Class<?> baseComponentClass = Class.forName(getVersionedClassName("IChatBaseComponent"));
Class<?> chatSerializerClass = baseComponentClass.getClasses()[0];
SERIALIZE_METHOD = chatSerializerClass.getDeclaredMethod("a", String.class);
}
private static String getVersionedClassName(String className) {
Class server = Bukkit.getServer().getClass();
if (!server.getSimpleName().equals("CraftServer")) {
throw new RuntimeException("Couldn't reflect into server " + server);
}
String version;
if (server.getName().equals("org.bukkit.craftbukkit.CraftServer")) {
// Non versioned class
version = ".";
} else {
version = server.getName().substring("org.bukkit.craftbukkit".length());
version = version.substring(0, version.length() - "CraftServer".length());
}
return "net.minecraft.server" + version + className;
}
private static synchronized boolean trySetup(Object player) {
if (setup) return true;
if (triedAndFailed) return false;
try {
setup(player);
setup = true;
return true;
} catch (Exception e) {
triedAndFailed = true;
return false;
}
}
public boolean sendJsonMessage(Player player, String json) {
if (!trySetup(player)) {
return false;
}
try {
Object connection = PLAYER_CONNECTION_FIELD.get(GET_HANDLE_METHOD.invoke(player));
SEND_PACKET_METHOD.invoke(connection, PACKET_CHAT_CONSTRUCTOR.newInstance(SERIALIZE_METHOD.invoke(null, json)));
return true;
} catch (Exception e) {
return false;
}
}
}
@@ -0,0 +1,68 @@
/*
* 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.bukkit.compat;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import io.github.mkremins.fanciful.FancyMessage;
public class MessageHandler {
private final BukkitJsonMessageHandler bukkitHandler;
private final SpigotJsonMessageHandler spigotHandler;
public MessageHandler() {
bukkitHandler = new BukkitJsonMessageHandler();
spigotHandler = isSpigot() ? new SpigotJsonMessageHandler() : null;
}
public void sendJsonMessage(CommandSender sender, FancyMessage message) {
if (sender instanceof Player) {
Player player = (Player) sender;
String json = message.toJSONString();
// Try Bukkit.
if (bukkitHandler.sendJsonMessage(player, json)) {
return;
}
// Try Spigot.
if (spigotHandler != null && spigotHandler.sendJsonMessage(player, json)) {
return;
}
}
// Fallback to Bukkit
sender.sendMessage(message.toOldMessageFormat());
}
private static boolean isSpigot() {
try {
Class.forName("net.md_5.bungee.chat.ComponentSerializer");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
@@ -0,0 +1,40 @@
/*
* 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.bukkit.compat;
import net.md_5.bungee.chat.ComponentSerializer;
import org.bukkit.entity.Player;
public class SpigotJsonMessageHandler {
public boolean sendJsonMessage(Player player, String json) {
try {
player.spigot().sendMessage(ComponentSerializer.parse(json));
return true;
} catch (Exception e) {
return false;
}
}
}
@@ -28,9 +28,11 @@ import me.lucko.luckperms.bukkit.model.LPPermissible;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.PermissionAttachment;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -41,21 +43,44 @@ import java.util.concurrent.ConcurrentHashMap;
@UtilityClass
public class Injector {
private static final Map<UUID, LPPermissible> INJECTED_PERMISSIBLES = new ConcurrentHashMap<>();
private static Field HUMAN_ENTITY_FIELD;
private static Field PERMISSIBLEBASE_ATTACHMENTS;
static {
try {
HUMAN_ENTITY_FIELD = Class.forName(getVersionedClassName("entity.CraftHumanEntity")).getDeclaredField("perm");
HUMAN_ENTITY_FIELD.setAccessible(true);
PERMISSIBLEBASE_ATTACHMENTS = PermissibleBase.class.getDeclaredField("attachments");
PERMISSIBLEBASE_ATTACHMENTS.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean inject(Player player, LPPermissible permissible) {
public static boolean inject(Player player, LPPermissible lpPermissible) {
try {
HUMAN_ENTITY_FIELD.set(player, permissible);
INJECTED_PERMISSIBLES.put(player.getUniqueId(), permissible);
PermissibleBase existing = (PermissibleBase) HUMAN_ENTITY_FIELD.get(player);
if (existing instanceof LPPermissible) {
// uh oh
throw new IllegalStateException();
}
// Move attachments over from the old permissible.
List<PermissionAttachment> attachments = (List<PermissionAttachment>) PERMISSIBLEBASE_ATTACHMENTS.get(existing);
lpPermissible.addAttachments(attachments);
attachments.clear();
existing.clearPermissions();
lpPermissible.recalculatePermissions();
lpPermissible.setOldPermissible(existing);
lpPermissible.updateSubscriptionsAsync();
HUMAN_ENTITY_FIELD.set(player, lpPermissible);
INJECTED_PERMISSIBLES.put(player.getUniqueId(), lpPermissible);
return true;
} catch (Exception e) {
e.printStackTrace();
@@ -63,14 +88,31 @@ public class Injector {
}
}
public static boolean unInject(Player player) {
public static boolean unInject(Player player, boolean dummy) {
try {
Permissible permissible = (Permissible) HUMAN_ENTITY_FIELD.get(player);
PermissibleBase permissible = (PermissibleBase) HUMAN_ENTITY_FIELD.get(player);
if (permissible instanceof LPPermissible) {
/* The player is most likely leaving. Bukkit will attempt to call #clearPermissions, so we cannot set to null.
However, there's no need to re-inject a real PermissibleBase, so we just inject a dummy instead.
This saves tick time, pointlessly recalculating defaults when the instance will never be used. */
HUMAN_ENTITY_FIELD.set(player, new DummyPermissibleBase());
permissible.clearPermissions();
((LPPermissible) permissible).unsubscribeFromAllAsync();
if (dummy) {
HUMAN_ENTITY_FIELD.set(player, new DummyPermissibleBase());
} else {
LPPermissible lpp = ((LPPermissible) permissible);
List<PermissionAttachment> attachments = lpp.getAttachments();
PermissibleBase newPb = lpp.getOldPermissible();
if (newPb == null) {
newPb = new PermissibleBase(player);
}
List<PermissionAttachment> newAttachments = (List<PermissionAttachment>) PERMISSIBLEBASE_ATTACHMENTS.get(newPb);
newAttachments.addAll(attachments);
attachments.clear();
HUMAN_ENTITY_FIELD.set(player, newPb);
}
}
INJECTED_PERMISSIBLES.remove(player.getUniqueId());
return true;
@@ -99,7 +99,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
try {
holder.setPermission(p.name(), p.isTrue(), "global", world.getName());
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("set " + p.name() + " " + p.isTrue() + " global " + world.getName())
.build().submit(plugin);
} catch (Exception ex) {
@@ -113,7 +113,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
try {
holder.setPermission(child.getKey(), child.getValue(), "global", world.getName());
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("set " + child.getKey() + " " + child.getValue() + " global " + world.getName())
.build().submit(plugin);
} catch (Exception ex) {
@@ -129,7 +129,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
try {
holder.setPermission("group." + parent.getName(), true, "global", world.getName());
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("setinherit " + parent.getName() + " global " + world.getName())
.build().submit(plugin);
} catch (Exception ex) {
@@ -146,7 +146,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
try {
holder.setPermission(meta.getKey().toLowerCase() + "." + c.getPriority() + "." + chatMeta, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("set " + meta.getKey().toLowerCase() + "." + c.getPriority() + "." + chatMeta + " true")
.build().submit(plugin);
} catch (Exception ex) {
@@ -160,7 +160,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
try {
holder.setPermission("meta." + meta.getKey() + "." + meta.getValue(), true, "global", world.getName());
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("set meta." + meta.getKey() + "." + meta.getValue() + " true global " + world.getName())
.build().submit(plugin);
} catch (Exception ex) {
@@ -215,7 +215,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
me.lucko.luckperms.common.core.model.Group lpGroup = plugin.getGroupManager().getIfLoaded(groupName);
try {
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpGroup).action("create")
.build().submit(plugin);
} catch (Exception ex) {
@@ -81,7 +81,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
me.lucko.luckperms.common.core.model.Group group = plugin.getGroupManager().getIfLoaded(g.getName().toLowerCase());
try {
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("create")
.build().submit(plugin);
} catch (Exception ex) {
@@ -101,7 +101,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
try {
group.setPermission(node, value);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("set " + node + " " + value)
.build().submit(plugin);
} catch (Exception ex) {
@@ -115,7 +115,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
try {
group.setPermission("group." + s.toLowerCase(), true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("setinherit " + s.toLowerCase())
.build().submit(plugin);
} catch (Exception ex) {
@@ -204,7 +204,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
me.lucko.luckperms.common.core.model.Group group = plugin.getGroupManager().getIfLoaded(e.getKey());
try {
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("create")
.build().submit(plugin);
} catch (Exception ex) {
@@ -222,12 +222,12 @@ public class MigrationGroupManager extends SubCommand<Object> {
if (n.getKey().getValue().startsWith("group.")) {
String groupName = n.getKey().getValue().substring(6);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("setinherit " + groupName + " global " + n.getKey().getKey())
.build().submit(plugin);
} else {
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("set " + n.getKey().getValue() + " " + n.getValue() + " global " + n.getKey().getKey())
.build().submit(plugin);
}
@@ -256,12 +256,12 @@ public class MigrationGroupManager extends SubCommand<Object> {
if (n.getKey().getValue().startsWith("group.")) {
String group = n.getKey().getValue().substring(6);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("addgroup " + group + " global " + n.getKey().getKey())
.build().submit(plugin);
} else {
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("set " + n.getKey().getValue() + " " + n.getValue() + " global " + n.getKey().getKey())
.build().submit(plugin);
}
@@ -39,17 +39,17 @@ import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import ru.tehkode.permissions.NativeInterface;
import ru.tehkode.permissions.PermissionGroup;
import ru.tehkode.permissions.PermissionManager;
import ru.tehkode.permissions.PermissionUser;
import ru.tehkode.permissions.bukkit.PermissionsEx;
import java.lang.reflect.Field;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
public class MigrationPermissionsEx extends SubCommand<Object> {
public MigrationPermissionsEx() {
super("permissionsex", "Migration from PermissionsEx", Permission.MIGRATION, Predicates.alwaysFalse(),
@@ -105,7 +105,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
Group lpGroup = plugin.getGroupManager().getIfLoaded(name);
try {
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpGroup).action("create")
.build().submit(plugin);
} catch (Exception ex) {
@@ -123,7 +123,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpGroup.setPermission(node, value);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpGroup).action("set " + node + " " + value)
.build().submit(plugin);
} catch (Exception ex) {
@@ -148,7 +148,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpGroup.setPermission(node, value, "global", world);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpGroup).action("set " + node + " " + value + " global " + world)
.build().submit(plugin);
} catch (Exception ex) {
@@ -164,7 +164,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpGroup.setPermission("group." + g.getName().toLowerCase(), true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpGroup).action("setinherit " + g.getName().toLowerCase())
.build().submit(plugin);
} catch (Exception ex) {
@@ -180,7 +180,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpGroup.setPermission("group." + g.getName().toLowerCase(), true, "global", world);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpGroup).action("setinherit " + g.getName().toLowerCase() + " global " + world)
.build().submit(plugin);
} catch (Exception ex) {
@@ -200,7 +200,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpGroup.setPermission("prefix." + groupWeight + "." + prefix, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpGroup).action("set prefix." + groupWeight + "." + prefix + " true")
.build().submit(plugin);
} catch (Exception ex) {
@@ -215,7 +215,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpGroup.setPermission("suffix." + groupWeight + "." + suffix, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpGroup).action("set suffix." + groupWeight + "." + suffix + " true")
.build().submit(plugin);
} catch (Exception ex) {
@@ -253,7 +253,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
}
userCount++;
plugin.getStorage().loadUser(u, "null").join();
plugin.getStorage().loadUser(u, user.getName()).join();
User lpUser = plugin.getUserManager().get(u);
try {
@@ -267,7 +267,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpUser.setPermission(node, value);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpUser).action("set " + node + " " + value)
.build().submit(plugin);
} catch (Exception ex) {
@@ -292,7 +292,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpUser.setPermission(node, value, "global", world);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpUser).action("set " + node + " " + value + " global " + world)
.build().submit(plugin);
} catch (Exception ex) {
@@ -308,7 +308,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpUser.setPermission("group." + s.toLowerCase(), true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpUser).action("addgroup " + s.toLowerCase())
.build().submit(plugin);
} catch (Exception ex) {
@@ -324,7 +324,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpUser.setPermission("group." + s.toLowerCase(), true, "global", world);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpUser).action("addgroup " + s.toLowerCase() + " global " + world)
.build().submit(plugin);
} catch (Exception ex) {
@@ -344,7 +344,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpUser.setPermission("prefix." + maxGroupWeight + "." + prefix, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpUser).action("set prefix." + maxGroupWeight + "." + prefix + " true")
.build().submit(plugin);
} catch (Exception ex) {
@@ -359,7 +359,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
try {
lpUser.setPermission("suffix." + maxGroupWeight + "." + suffix, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(lpUser).action("set suffix." + maxGroupWeight + "." + suffix + " true")
.build().submit(plugin);
} catch (Exception ex) {
@@ -271,7 +271,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
final me.lucko.luckperms.common.core.model.Group group = plugin.getGroupManager().getIfLoaded(g.getName().toLowerCase());
try {
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("create")
.build().submit(plugin);
} catch (Exception ex) {
@@ -286,7 +286,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
group.setPermission("group." + parent.getName().toLowerCase(), true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("setinherit " + parent.getName().toLowerCase()) // All versions
.build().submit(plugin);
} catch (Exception ex) {
@@ -353,7 +353,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
user.setPermission("group." + g.getName().toLowerCase(), true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("addgroup " + g.getName().toLowerCase())
.build().submit(plugin);
} catch (Exception ex) {
@@ -365,7 +365,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
user.setPermission("group." + g.getName().toLowerCase(), true, server);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("addgroup " + g.getName().toLowerCase() + " " + server)
.build().submit(plugin);
} catch (Exception ex) {
@@ -386,7 +386,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
user.setPermission("group." + group.getName().toLowerCase(), true, g.getExpirationDate().getTime() / 1000L);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("addtempgroup " + group.getName().toLowerCase() + " " + g.getExpirationDate().getTime() / 1000L)
.build().submit(plugin);
} catch (Exception ex) {
@@ -398,7 +398,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
user.setPermission("group." + group.getName().toLowerCase(), true, server, g.getExpirationDate().getTime() / 1000L);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("addtempgroup " + group.getName().toLowerCase() + " " + g.getExpirationDate().getTime() / 1000L + " " + server)
.build().submit(plugin);
} catch (Exception ex) {
@@ -413,7 +413,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
user.setPermission("group." + group.getName().toLowerCase(), true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("addgroup " + group.getName().toLowerCase())
.build().submit(plugin);
} catch (Exception ex) {
@@ -425,7 +425,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
user.setPermission("group." + group.getName().toLowerCase(), true, server);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("addgroup " + group.getName().toLowerCase() + " " + server)
.build().submit(plugin);
} catch (Exception ex) {
@@ -549,7 +549,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
holder.setPermission(node, value, server, world);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("set " + node + " " + value + " " + server + " " + world)
.build().submit(plugin);
} catch (Exception ex) {
@@ -561,7 +561,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
holder.setPermission(node, value, server, world, expireAt);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("settemp " + node + " " + value + " " + expireAt + " " + server + " " + world)
.build().submit(plugin);
} catch (Exception ex) {
@@ -576,7 +576,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
holder.setPermission(node, value, server);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("set " + node + " " + value + " " + server)
.build().submit(plugin);
} catch (Exception ex) {
@@ -588,7 +588,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
holder.setPermission(node, value, server, expireAt);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("settemp " + node + " " + value + " " + expireAt + " " + server)
.build().submit(plugin);
} catch (Exception ex) {
@@ -602,7 +602,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
holder.setPermission(node, value);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("set " + node + " " + value)
.build().submit(plugin);
} catch (Exception ex) {
@@ -614,7 +614,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
try {
holder.setPermission(node, value, expireAt);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(holder).action("settemp " + node + " " + value + " " + expireAt)
.build().submit(plugin);
} catch (Exception ex) {
@@ -42,6 +42,7 @@ import org.tyrannyofheaven.bukkit.zPermissions.dao.PermissionService;
import org.tyrannyofheaven.bukkit.zPermissions.model.EntityMetadata;
import org.tyrannyofheaven.bukkit.zPermissions.model.Entry;
import org.tyrannyofheaven.bukkit.zPermissions.model.Inheritance;
import org.tyrannyofheaven.bukkit.zPermissions.model.Membership;
import org.tyrannyofheaven.bukkit.zPermissions.model.PermissionEntity;
import java.lang.reflect.Field;
@@ -49,6 +50,7 @@ import java.util.List;
import java.util.UUID;
public class MigrationZPermissions extends SubCommand<Object> {
public MigrationZPermissions() {
super("zpermissions", "Migration from zPermissions", Permission.MIGRATION, Predicates.alwaysFalse(), null);
}
@@ -85,7 +87,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
Group group = plugin.getGroupManager().getIfLoaded(g.toLowerCase());
PermissionEntity entity = internalService.getEntity(g, null, true);
migrateEntity(group, entity);
migrateEntity(group, entity, null);
plugin.getStorage().saveGroup(group);
}
@@ -106,10 +108,14 @@ public class MigrationZPermissions extends SubCommand<Object> {
User user = plugin.getUserManager().get(u);
PermissionEntity entity = internalService.getEntity(null, u, false);
migrateEntity(user, entity);
migrateEntity(user, entity, internalService.getGroups(u));
user.setPrimaryGroup(service.getPlayerPrimaryGroup(u));
if (!entity.isGroup()) {
user.setName(entity.getDisplayName());
}
plugin.getUserManager().cleanup(user);
plugin.getStorage().saveUser(user);
}
@@ -118,7 +124,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
return CommandResult.SUCCESS;
}
private void migrateEntity(PermissionHolder group, PermissionEntity entity) {
private void migrateEntity(PermissionHolder group, PermissionEntity entity, List<Membership> memberships) {
for (Entry e : entity.getPermissions()) {
if (e.getWorld() != null) {
try {
@@ -133,15 +139,22 @@ public class MigrationZPermissions extends SubCommand<Object> {
}
}
for (Inheritance inheritance : entity.getInheritancesAsChild()) {
if (!inheritance.getChild().getId().equals(entity.getId())) {
new Throwable("Illegal inheritance").printStackTrace();
continue;
if (entity.isGroup()) {
for (Inheritance inheritance : entity.getInheritancesAsChild()) {
try {
if (!inheritance.getParent().getName().equals(group.getObjectName())) {
group.setPermission("group." + inheritance.getParent().getName(), true);
}
} catch (ObjectAlreadyHasException ignored) {
}
}
try {
group.setPermission("group." + inheritance.getParent(), true);
} catch (ObjectAlreadyHasException ignored) {
} else {
// entity.getMemberships() doesn't work (always returns 0 records)
for (Membership membership : memberships) {
try {
group.setPermission("group." + membership.getGroup().getDisplayName(), true);
} catch (ObjectAlreadyHasException ignored) {
}
}
}
@@ -84,6 +84,7 @@ public class DefaultsProvider {
@Getter
private Map<String, Boolean> opDefaults = ImmutableMap.of();
private final DummyPermissible opDummy = new DummyPermissible(this::refreshOp);
@Getter
private Map<String, Boolean> nonOpDefaults = ImmutableMap.of();
private final DummyPermissible nonOpDummy = new DummyPermissible(this::refreshNonOp);
@@ -111,6 +112,11 @@ public class DefaultsProvider {
nonOpDefaults = ImmutableMap.copyOf(builder);
}
public void close() {
unregisterDefaults(opDefaults, opDummy);
unregisterDefaults(nonOpDefaults, nonOpDummy);
}
public Tristate hasDefault(String permission, boolean isOp) {
Map<String, Boolean> map = isOp ? opDefaults : nonOpDefaults;
@@ -24,6 +24,7 @@ package me.lucko.luckperms.bukkit.model;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Tristate;
@@ -39,12 +40,13 @@ import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.permissions.PermissionRemovedExecutor;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.stream.Collectors;
@@ -59,22 +61,62 @@ public class LPPermissible extends PermissibleBase {
@Getter
private final Player parent;
@Getter
private final LPBukkitPlugin plugin;
@Getter
private final SubscriptionManager subscriptions;
@Getter
@Setter
private PermissibleBase oldPermissible = null;
// Attachment stuff.
@Getter
private final Map<String, PermissionAttachmentInfo> attachmentPermissions = new HashMap<>();
private final List<PermissionAttachment> attachments = new LinkedList<>();
private final Map<String, PermissionAttachmentInfo> attachmentPermissions = new ConcurrentHashMap<>();
@Getter
private final List<PermissionAttachment> attachments = Collections.synchronizedList(new LinkedList<>());
public LPPermissible(@NonNull Player parent, User user, LPBukkitPlugin plugin) {
super(parent);
this.user = user;
this.parent = parent;
this.plugin = plugin;
this.subscriptions = new SubscriptionManager(this);
recalculatePermissions();
}
public void updateSubscriptionsAsync() {
plugin.doAsync(this::updateSubscriptions);
}
public void updateSubscriptions() {
Set<String> ent = new HashSet<>(user.getUserData().getPermissionData(calculateContexts()).getImmutableBacking().keySet());
if (parent.isOp()) {
ent.addAll(plugin.getDefaultsProvider().getOpDefaults().keySet());
} else {
ent.addAll(plugin.getDefaultsProvider().getNonOpDefaults().keySet());
}
subscriptions.subscribe(ent);
}
public void unsubscribeFromAllAsync() {
plugin.doAsync(this::unsubscribeFromAll);
}
public void unsubscribeFromAll() {
subscriptions.subscribe(Collections.emptySet());
}
public void addAttachments(List<PermissionAttachment> attachments) {
for (PermissionAttachment attachment : attachments) {
this.attachments.add(attachment);
}
}
public Contexts calculateContexts() {
return new Contexts(
plugin.getContextManager().getApplicableContext(parent),
@@ -195,7 +237,7 @@ public class LPPermissible extends PermissibleBase {
}
PermissionAttachment result = addAttachment(plugin);
if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> result.remove(), ticks) == -1) {
if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, result::remove, ticks) == -1) {
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add PermissionAttachment to " + parent + " for plugin " + plugin.getDescription().getFullName() + ": Scheduler returned -1");
result.remove();
return null;
@@ -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.bukkit.model;
import lombok.RequiredArgsConstructor;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@RequiredArgsConstructor
public class SubscriptionManager {
private final LPPermissible permissible;
private Set<String> currentSubscriptions = ImmutableSet.of();
public synchronized void subscribe(Set<String> perms) {
Set<String> newPerms = ImmutableSet.copyOf(perms);
Map.Entry<Set<String>, Set<String>> changes = compareSets(newPerms, currentSubscriptions);
Set<String> toAdd = changes.getKey();
Set<String> toRemove = changes.getValue();
permissible.getPlugin().doSync(() -> {
for (String s : toAdd) {
permissible.getPlugin().getServer().getPluginManager().subscribeToPermission(s, permissible.getParent());
}
for (String s : toRemove) {
permissible.getPlugin().getServer().getPluginManager().unsubscribeFromPermission(s, permissible.getParent());
}
});
this.currentSubscriptions = newPerms;
}
/**
* Compares two sets
* @param local the local set
* @param remote the remote set
* @return the entries to add to remote, and the entries to remove from remote
*/
private static Map.Entry<Set<String>, Set<String>> compareSets(Set<String> local, Set<String> remote) {
// entries in local but not remote need to be added
// entries in remote but not local need to be removed
Set<String> toAdd = new HashSet<>(local);
toAdd.removeAll(remote);
Set<String> toRemove = new HashSet<>(remote);
toRemove.removeAll(local);
return Maps.immutableEntry(toAdd, toRemove);
}
}
@@ -60,7 +60,7 @@ import static me.lucko.luckperms.api.MetaUtils.unescapeCharacters;
* Normal inheritance rules DO NOT apply.
* Permission Nodes = meta.node.value
*
* Node that special characters used within LuckPerms are escaped:
* Note that special characters used within LuckPerms are escaped:
* See {@link me.lucko.luckperms.api.MetaUtils#unescapeCharacters(String)}
*/
public class VaultChatHook extends Chat {
@@ -86,7 +86,7 @@ public class VaultChatHook extends Chat {
perms.log("Setting meta: '" + node + "' for " + holder.getObjectName() + " on world " + world + ", server " + perms.getServer());
perms.getScheduler().scheduleTask(() -> {
perms.getScheduler().execute(() -> {
List<Node> toRemove = holder.getNodes().stream()
.filter(n -> n.isMeta() && n.getMeta().getKey().equals(node))
.collect(Collectors.toList());
@@ -122,7 +122,7 @@ public class VaultChatHook extends Chat {
perms.log("Setting " + (prefix ? "prefix" : "suffix") + " for " + holder.getObjectName() + " on world " + world + ", server " + perms.getServer());
perms.getScheduler().scheduleTask(() -> {
perms.getScheduler().execute(() -> {
Node.Builder node = new NodeBuilder((prefix ? "prefix" : "suffix") + ".1000." + escapeCharacters(value));
node.setValue(true);
if (!perms.getServer().equalsIgnoreCase("global")) {
@@ -153,7 +153,7 @@ public class VaultChatHook extends Chat {
return defaultValue;
}
return unescapeCharacters(user.getUserData().getMetaData(perms.createContext(perms.getServer(), world)).getMeta().getOrDefault(node, defaultValue));
return unescapeCharacters(user.getUserData().getMetaData(perms.createContextForWorld(world)).getMeta().getOrDefault(node, defaultValue));
}
private String getUserChatMeta(boolean prefix, User user, String world) {
@@ -166,7 +166,7 @@ public class VaultChatHook extends Chat {
return "";
}
MetaData data = user.getUserData().getMetaData(perms.createContext(perms.getServer(), world));
MetaData data = user.getUserData().getMetaData(perms.createContextForWorld(world));
String v = prefix ? data.getPrefix() : data.getSuffix();
return v == null ? "" : unescapeCharacters(v);
}
@@ -270,7 +270,7 @@ public class VaultChatHook extends Chat {
public String getGroupPrefix(String world, @NonNull String group) {
final Group g = perms.getPlugin().getGroupManager().getIfLoaded(group);
return getGroupChatMeta(false, g, world);
return getGroupChatMeta(true, g, world);
}
public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) {
@@ -32,6 +32,9 @@ import net.milkbowl.vault.permission.Permission;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.ServicesManager;
/**
* Handles hooking with the Vault API
*/
@Getter
public class VaultHook {
private VaultChatHook chatHook = null;
@@ -40,17 +43,8 @@ public class VaultHook {
public void hook(LPBukkitPlugin plugin) {
try {
if (permissionHook == null) {
permissionHook = new VaultPermissionHook();
permissionHook = new VaultPermissionHook(plugin);
}
permissionHook.setPlugin(plugin);
permissionHook.setServer(plugin.getConfiguration().getVaultServer());
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIncludingGlobal());
permissionHook.setIgnoreWorld(plugin.getConfiguration().isVaultIgnoreWorld());
permissionHook.setPgo(plugin.getConfiguration().isVaultPrimaryGroupOverrides());
permissionHook.setPgoCheckInherited(plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckInherited());
permissionHook.setPgoCheckExists(plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckExists());
permissionHook.setPgoCheckMemberOf(plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckMemberOf());
permissionHook.setup();
if (chatHook == null) {
chatHook = new VaultChatHook(permissionHook);
@@ -69,9 +63,12 @@ public class VaultHook {
final ServicesManager sm = plugin.getServer().getServicesManager();
if (permissionHook != null) {
sm.unregister(Permission.class, permissionHook);
permissionHook.getScheduler().cancelTask();
permissionHook = null;
}
if (chatHook != null) {
sm.unregister(Chat.class, chatHook);
chatHook = null;
}
}
@@ -22,10 +22,8 @@
package me.lucko.luckperms.bukkit.vault;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LocalizedNode;
@@ -44,31 +42,44 @@ import net.milkbowl.vault.permission.Permission;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
/**
* The LuckPerms Vault Permission implementation
* Most lookups are cached.
*/
@Getter
@Setter
public class VaultPermissionHook extends Permission {
private LPBukkitPlugin plugin;
@Setter(value = AccessLevel.NONE)
private VaultScheduler scheduler;
private final String name = "LuckPerms";
private String server = "global";
private boolean includeGlobal = true;
private boolean ignoreWorld = false;
// Primary Group override settings
private boolean pgo = false;
private boolean pgoCheckInherited = false;
private boolean pgoCheckExists = true;
private boolean pgoCheckMemberOf = true;
public void setup() {
scheduler = new VaultScheduler(plugin);
private Function<String, String> WORLD_CORRECTION_FUNCTION = s -> ignoreWorld ? null : s;
public VaultPermissionHook(LPBukkitPlugin plugin) {
this.plugin = plugin;
this.scheduler = new VaultScheduler(plugin);
super.plugin = plugin;
// Config options
this.server = plugin.getConfiguration().getVaultServer();
this.includeGlobal = plugin.getConfiguration().isVaultIncludingGlobal();
this.ignoreWorld = plugin.getConfiguration().isVaultIgnoreWorld();
this.pgo = plugin.getConfiguration().isVaultPrimaryGroupOverrides();
this.pgoCheckInherited = plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckInherited();
this.pgoCheckExists = plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckExists();
this.pgoCheckMemberOf = plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckMemberOf();
}
public void log(String s) {
@@ -77,14 +88,9 @@ public class VaultPermissionHook extends Permission {
}
}
@Override
public String getName() {
return "LuckPerms";
}
@Override
public boolean isEnabled() {
return plugin.getStorage().isAcceptingLogins();
return plugin.isEnabled();
}
@Override
@@ -99,17 +105,18 @@ public class VaultPermissionHook extends Permission {
* @param holder the holder to add the permission to
* @param permission the permission to add
*/
private void add(String world, PermissionHolder holder, String permission) {
try {
if (world != null && !world.equals("")) {
holder.setPermission(permission, true, server, world);
} else {
holder.setPermission(permission, true, server);
}
} catch (ObjectAlreadyHasException ignored) {
}
private CompletableFuture<Void> add(String world, PermissionHolder holder, String permission) {
return CompletableFuture.runAsync(() -> {
try {
if (world != null && !world.equals("") && !world.equalsIgnoreCase("global")) {
holder.setPermission(permission, true, server, world);
} else {
holder.setPermission(permission, true, server);
}
save(holder);
save(holder);
} catch (ObjectAlreadyHasException ignored) {}
}, scheduler);
}
/**
@@ -119,36 +126,37 @@ public class VaultPermissionHook extends Permission {
* @param holder the holder to remove the permission from
* @param permission the permission to remove
*/
private void remove(String world, PermissionHolder holder, String permission) {
try {
if (world != null && !world.equals("")) {
holder.unsetPermission(permission, server, world);
} else {
holder.unsetPermission(permission, server);
}
} catch (ObjectLacksException ignored) {
}
private CompletableFuture<Void> remove(String world, PermissionHolder holder, String permission) {
return CompletableFuture.runAsync(() -> {
try {
if (world != null && !world.equals("") && !world.equalsIgnoreCase("global")) {
holder.unsetPermission(permission, server, world);
} else {
holder.unsetPermission(permission, server);
}
save(holder);
save(holder);
} catch (ObjectLacksException ignored) {}
}, scheduler);
}
/**
* Utility method for saving a user or group
* Utility method to asynchronously save a user or group
*
* @param holder the holder instance
*/
void save(PermissionHolder holder) {
public void save(PermissionHolder holder) {
if (holder instanceof User) {
plugin.getStorage().saveUser(((User) holder))
.thenRunAsync(() -> ((User) holder).getRefreshBuffer().request(), plugin.getAsyncExecutor());
User u = (User) holder;
plugin.getStorage().saveUser(u).thenRunAsync(() -> u.getRefreshBuffer().request(), plugin.getAsyncExecutor());
}
if (holder instanceof Group) {
plugin.getStorage().saveGroup(((Group) holder))
.thenRunAsync(() -> plugin.getUpdateTaskBuffer().request(), plugin.getAsyncExecutor());
Group g = (Group) holder;
plugin.getStorage().saveGroup(g).thenRunAsync(() -> plugin.getUpdateTaskBuffer().request(), plugin.getAsyncExecutor());
}
}
Contexts createContext(String server, String world) {
public Contexts createContextForWorld(String world) {
Map<String, String> context = new HashMap<>();
if (world != null && !world.equals("")) {
context.put("world", world);
@@ -159,7 +167,7 @@ public class VaultPermissionHook extends Permission {
@Override
public boolean playerHas(String world, @NonNull String player, @NonNull String permission) {
world = ignoreWorld ? null : world; // Correct world value
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Checking if player " + player + " has permission: " + permission + " on world " + world + ", server " + server);
User user = plugin.getUserManager().getByUsername(player);
@@ -170,92 +178,91 @@ public class VaultPermissionHook extends Permission {
}
// Effectively fallback to the standard Bukkit #hasPermission check.
return user.getUserData().getPermissionData(createContext(server, world)).getPermissionValue(permission).asBoolean();
return user.getUserData().getPermissionData(createContextForWorld(world)).getPermissionValue(permission).asBoolean();
}
@Override
public boolean playerAdd(String world, @NonNull String player, @NonNull String permission) {
String finalWorld = ignoreWorld ? null : world; // Correct world value
log("Adding permission to player " + player + ": '" + permission + "' on world " + finalWorld + ", server " + server);
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Adding permission to player " + player + ": '" + permission + "' on world " + world + ", server " + server);
final User user = plugin.getUserManager().getByUsername(player);
if (user == null) return false;
scheduler.scheduleTask(() -> add(finalWorld, user, permission));
add(world, user, permission);
return true;
}
@Override
public boolean playerRemove(String world, @NonNull String player, @NonNull String permission) {
String finalWorld = ignoreWorld ? null : world; // Correct world value
log("Removing permission from player " + player + ": '" + permission + "' on world " + finalWorld + ", server " + server);
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Removing permission from player " + player + ": '" + permission + "' on world " + world + ", server " + server);
final User user = plugin.getUserManager().getByUsername(player);
if (user == null) return false;
scheduler.scheduleTask(() -> remove(finalWorld, user, permission));
remove(world, user, permission);
return true;
}
@Override
public boolean groupHas(String world, @NonNull String groupName, @NonNull String permission) {
world = ignoreWorld ? null : world; // Correct world value
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Checking if group " + groupName + " has permission: " + permission + " on world " + world + ", server " + server);
final Group group = plugin.getGroupManager().getIfLoaded(groupName);
if (group == null) return false;
// This is a nasty call. Groups aren't cached. :(
Map<String, Boolean> permissions = group.exportNodes(createContext(server, world), true);
return permissions.containsKey(permission) && permissions.get(permission);
Map<String, Boolean> permissions = group.exportNodes(createContextForWorld(world), true);
return permissions.containsKey(permission.toLowerCase()) && permissions.get(permission.toLowerCase());
}
@Override
public boolean groupAdd(String world, @NonNull String groupName, @NonNull String permission) {
String finalWorld = ignoreWorld ? null : world; // Correct world value
log("Adding permission to group " + groupName + ": '" + permission + "' on world " + finalWorld + ", server " + server);
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Adding permission to group " + groupName + ": '" + permission + "' on world " + world + ", server " + server);
final Group group = plugin.getGroupManager().getIfLoaded(groupName);
if (group == null) return false;
scheduler.scheduleTask(() -> add(finalWorld, group, permission));
add(world, group, permission);
return true;
}
@Override
public boolean groupRemove(String world, @NonNull String groupName, @NonNull String permission) {
String finalWorld = ignoreWorld ? null : world; // Correct world value
log("Removing permission from group " + groupName + ": '" + permission + "' on world " + finalWorld + ", server " + server);
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Removing permission from group " + groupName + ": '" + permission + "' on world " + world + ", server " + server);
final Group group = plugin.getGroupManager().getIfLoaded(groupName);
if (group == null) return false;
scheduler.scheduleTask(() -> remove(finalWorld, group, permission));
remove(world, group, permission);
return true;
}
@Override
public boolean playerInGroup(String world, @NonNull String player, @NonNull String group) {
String finalWorld = ignoreWorld ? null : world; // Correct world value
log("Checking if player " + player + " is in group: " + group + " on world " + finalWorld + ", server " + server);
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Checking if player " + player + " is in group: " + group + " on world " + world + ", server " + server);
final User user = plugin.getUserManager().getByUsername(player);
if (user == null) return false;
String w = world; // screw effectively final
return user.getNodes().stream()
.filter(Node::isGroupNode)
.filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false))
.filter(n -> n.shouldApplyOnWorld(finalWorld, true, false))
.filter(n -> n.shouldApplyOnWorld(w, true, false))
.map(Node::getGroupName)
.filter(s -> s.equalsIgnoreCase(group))
.findAny().isPresent();
.anyMatch(s -> s.equalsIgnoreCase(group));
}
@Override
public boolean playerAddGroup(String world, @NonNull String player, @NonNull String groupName) {
String finalWorld = ignoreWorld ? null : world; // Correct world value
log("Adding player " + player + " to group: '" + groupName + "' on world " + finalWorld + ", server " + server);
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Adding player " + player + " to group: '" + groupName + "' on world " + world + ", server " + server);
final User user = plugin.getUserManager().getByUsername(player);
if (user == null) return false;
@@ -263,24 +270,25 @@ public class VaultPermissionHook extends Permission {
final Group group = plugin.getGroupManager().getIfLoaded(groupName);
if (group == null) return false;
scheduler.scheduleTask(() -> {
String w = world;
scheduler.execute(() -> {
try {
if (finalWorld != null && !finalWorld.equals("")) {
user.setInheritGroup(group, server, finalWorld);
if (w != null && !w.equals("") && !w.equalsIgnoreCase("global")) {
user.setInheritGroup(group, server, w);
} else {
user.setInheritGroup(group, server);
}
} catch (ObjectAlreadyHasException ignored) {
}
save(user);
save(user);
} catch (ObjectAlreadyHasException ignored) {}
});
return true;
}
@Override
public boolean playerRemoveGroup(String world, @NonNull String player, @NonNull String groupName) {
String finalWorld = ignoreWorld ? null : world; // Correct world value
log("Removing player " + player + " from group: '" + groupName + "' on world " + finalWorld + ", server " + server);
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Removing player " + player + " from group: '" + groupName + "' on world " + world + ", server " + server);
final User user = plugin.getUserManager().getByUsername(player);
if (user == null) return false;
@@ -288,39 +296,41 @@ public class VaultPermissionHook extends Permission {
final Group group = plugin.getGroupManager().getIfLoaded(groupName);
if (group == null) return false;
scheduler.scheduleTask(() -> {
String w = world;
scheduler.execute(() -> {
try {
if (finalWorld != null && !finalWorld.equals("")) {
user.unsetInheritGroup(group, server, finalWorld);
if (w != null && !w.equals("") && !w.equalsIgnoreCase("global")) {
user.unsetInheritGroup(group, server, w);
} else {
user.unsetInheritGroup(group, server);
}
} catch (ObjectLacksException ignored) {
}
save(user);
save(user);
} catch (ObjectLacksException ignored) {}
});
return true;
}
@Override
public String[] getPlayerGroups(String world, @NonNull String player) {
String finalWorld = ignoreWorld ? null : world; // Correct world value
log("Getting groups of player: " + player + ", on world " + finalWorld + ", server " + server);
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Getting groups of player: " + player + ", on world " + world + ", server " + server);
User user = plugin.getUserManager().getByUsername(player);
if (user == null) return new String[0];
String w = world; // screw effectively final
return user.getNodes().stream()
.filter(Node::isGroupNode)
.filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false))
.filter(n -> n.shouldApplyOnWorld(finalWorld, true, false))
.filter(n -> n.shouldApplyOnWorld(w, true, false))
.map(Node::getGroupName)
.toArray(String[]::new);
}
@Override
public String getPrimaryGroup(String world, @NonNull String player) {
world = ignoreWorld ? null : world; // Correct world value
world = WORLD_CORRECTION_FUNCTION.apply(world);
log("Getting primary group of player: " + player);
final User user = plugin.getUserManager().getByUsername(player);
@@ -329,11 +339,12 @@ public class VaultPermissionHook extends Permission {
}
if (!pgo) {
return user.getPrimaryGroup();
String g = user.getPrimaryGroup();
return plugin.getConfiguration().getGroupNameRewrites().getOrDefault(g, g);
}
if (pgoCheckInherited) {
PermissionData data = user.getUserData().getPermissionData(createContext(server, world));
PermissionData data = user.getUserData().getPermissionData(createContextForWorld(world));
for (Map.Entry<String, Boolean> e : data.getImmutableBacking().entrySet()) {
if (!e.getValue()) {
continue;
@@ -394,7 +405,8 @@ public class VaultPermissionHook extends Permission {
}
// Fallback
return user.getPrimaryGroup();
String g = user.getPrimaryGroup();
return plugin.getConfiguration().getGroupNameRewrites().getOrDefault(g, g);
}
@Override
@@ -24,17 +24,26 @@ package me.lucko.luckperms.bukkit.vault;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import org.bukkit.scheduler.BukkitTask;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
public class VaultScheduler implements Runnable {
/**
* Sequential executor for Vault modifications
*/
public class VaultScheduler implements Runnable, Executor {
private BukkitTask task = null;
private final List<Runnable> tasks = new ArrayList<>();
public VaultScheduler(LPBukkitPlugin plugin) {
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, this, 1L, 1L);
task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, this, 1L, 1L);
}
public void scheduleTask(Runnable r) {
@Override
public void execute(Runnable r) {
synchronized (tasks) {
tasks.add(r);
}
@@ -42,12 +51,24 @@ public class VaultScheduler implements Runnable {
@Override
public void run() {
List<Runnable> toRun = new ArrayList<>();
List<Runnable> toRun;
synchronized (tasks) {
if (tasks.isEmpty()) {
return;
}
toRun = new ArrayList<>();
toRun.addAll(tasks);
tasks.clear();
}
toRun.forEach(Runnable::run);
}
public void cancelTask() {
if (task != null) {
task.cancel();
task = null;
}
}
}
+14 -4
View File
@@ -148,8 +148,8 @@ group-name-rewrite:
# +------------------------------------------------------------------------+ #
# Which storage method the plugin should use.
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
# Fill out connection info below if you're using MySQL or MongoDB
# Currently supported: mysql, postgresql, sqlite, h2, json, yaml, mongodb
# Fill out connection info below if you're using MySQL, PostgreSQL or MongoDB
storage-method: h2
# This block enables support for split datastores.
@@ -163,12 +163,20 @@ split-storage:
log: h2
data:
address: localhost:3306
# Uses standard DB engine port by default
# MySQL: 3306, PostgreSQL: 5432, MongoDB: 27017
# Specify as "host:port" if differs
address: localhost
database: minecraft
username: root
password: ''
pool-size: 10 # The size of the MySQL connection pool.
# The prefix for all LuckPerms tables. Change this is you want to use different tables for different servers.
# This should *not* be set to "lp_" if you have previously ran LuckPerms v2.16.81 or earlier with this database.
table_prefix: 'luckperms_'
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
sync-minutes: 3
@@ -181,9 +189,11 @@ data:
#
# If you decide to enable this feature, you should set "sync-minutes" to -1, as there is no need for LuckPerms
# to poll the database for changes.
#
# Port 6379 is used by default; set address to "host:port" if differs
redis:
enabled: false
address: localhost:6379
address: localhost
password: ''
+1 -1
View File
@@ -15,7 +15,7 @@ loadbefore: [Vault]
commands:
luckperms:
description: Manage permissions
aliases: [perms, permissions, lp, p, perm]
aliases: [perms, permissions, lp, perm]
# Permissions are registered programmatically instead of here.
+11 -36
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.16-SNAPSHOT</version>
<version>2.17-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -14,7 +14,7 @@
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>LuckPermsBungee-${release.version}.${git.closest.tag.commit.count}</finalName>
<finalName>LuckPerms-Bungee-${release.version}.${git.closest.tag.commit.count}</finalName>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
@@ -46,40 +46,8 @@
<minimizeJar>false</minimizeJar>
<relocations>
<relocation>
<pattern>org.slf4j</pattern>
<shadedPattern>me.lucko.luckperms.lib.slf4j</shadedPattern>
</relocation>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
</relocation>
<relocation>
<pattern>com.mongodb</pattern>
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
</relocation>
<relocation>
<pattern>org.bson</pattern>
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
</relocation>
<relocation>
<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>
<relocation>
<pattern>redis.clients.jedis</pattern>
<shadedPattern>me.lucko.luckperms.lib.jedis.jedis</shadedPattern>
</relocation>
<relocation>
<pattern>redis.clients.util</pattern>
<shadedPattern>me.lucko.luckperms.lib.jedis.util</shadedPattern>
</relocation>
<relocation>
<pattern>org.apache.commons.pool2</pattern>
<shadedPattern>me.lucko.luckperms.lib.jedis.pool2</shadedPattern>
<pattern>io.github.mkremins.fanciful</pattern>
<shadedPattern>me.lucko.luckperms.lib.fanciful</shadedPattern>
</relocation>
</relocations>
</configuration>
@@ -126,6 +94,13 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- slf4j library -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.9</version>
<scope>provided</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
@@ -50,8 +50,7 @@ class BungeeCommand extends Command implements TabExecutor {
manager.onCommand(
plugin.getSenderFactory().wrap(sender),
"bperms",
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
null
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args)))
);
}
@@ -108,8 +108,8 @@ public class BungeeListener extends AbstractListener implements Listener {
plugin.getStorage().force().saveUUIDData(c.getName(), c.getUniqueId()).join();
}
} else {
UUID uuid = plugin.getStorage().getUUID(c.getName()).join();
if (uuid == null) {
String name = plugin.getStorage().getName(c.getUniqueId()).join();
if (name == null) {
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName()));
}
@@ -29,6 +29,9 @@ import me.lucko.luckperms.common.constants.Constants;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.chat.ComponentSerializer;
import io.github.mkremins.fanciful.FancyMessage;
import java.util.UUID;
@@ -42,7 +45,7 @@ public class BungeeSenderFactory extends SenderFactory<CommandSender> {
if (sender instanceof ProxiedPlayer) {
return sender.getName();
}
return Constants.getConsoleName();
return Constants.CONSOLE_NAME;
}
@Override
@@ -50,7 +53,7 @@ public class BungeeSenderFactory extends SenderFactory<CommandSender> {
if (sender instanceof ProxiedPlayer) {
return ((ProxiedPlayer) sender).getUniqueId();
}
return Constants.getConsoleUUID();
return Constants.CONSOLE_UUID;
}
@Override
@@ -58,6 +61,15 @@ public class BungeeSenderFactory extends SenderFactory<CommandSender> {
sender.sendMessage(new TextComponent(s));
}
@Override
protected void sendMessage(CommandSender sender, FancyMessage message) {
try {
sender.sendMessage(ComponentSerializer.parse(message.toJSONString()));
} catch (Exception e) {
sendMessage(sender, message.toOldMessageFormat());
}
}
@Override
protected boolean hasPermission(CommandSender sender, String node) {
return sender.hasPermission(node);
@@ -24,17 +24,17 @@ package me.lucko.luckperms.bungee;
import lombok.Getter;
import me.lucko.luckperms.ApiHandler;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.api.ApiHandler;
import me.lucko.luckperms.common.api.ApiProvider;
import me.lucko.luckperms.common.caching.handlers.CachedStateManager;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.commands.CommandManager;
import me.lucko.luckperms.common.commands.ConsecutiveExecutor;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.config.LPConfiguration;
import me.lucko.luckperms.common.contexts.ContextManager;
@@ -42,6 +42,7 @@ import me.lucko.luckperms.common.contexts.ServerCalculator;
import me.lucko.luckperms.common.core.UuidCache;
import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.data.Importer;
import me.lucko.luckperms.common.dependencies.DependencyManager;
import me.lucko.luckperms.common.managers.GroupManager;
import me.lucko.luckperms.common.managers.TrackManager;
import me.lucko.luckperms.common.managers.UserManager;
@@ -51,6 +52,8 @@ import me.lucko.luckperms.common.managers.impl.GenericUserManager;
import me.lucko.luckperms.common.messaging.RedisMessaging;
import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.storage.StorageType;
import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
import me.lucko.luckperms.common.tasks.UpdateTask;
import me.lucko.luckperms.common.utils.BufferedRequest;
@@ -64,6 +67,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.File;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -87,8 +91,8 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
private ApiProvider apiProvider;
private Logger log;
private Importer importer;
private ConsecutiveExecutor consecutiveExecutor;
private LocaleManager localeManager;
private CachedStateManager cachedStateManager;
private ContextManager<ProxiedPlayer> contextManager;
private CalculatorFactory calculatorFactory;
private BufferedRequest<Void> updateTaskBuffer;
@@ -100,18 +104,21 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
public void onEnable() {
executor = r -> getProxy().getScheduler().runAsync(this, r);
log = LogFactory.wrap(getLogger());
debugHandler = new DebugHandler(executor);
debugHandler = new DebugHandler(executor, getVersion());
senderFactory = new BungeeSenderFactory(this);
permissionCache = new PermissionCache(executor);
getLog().info("Loading configuration...");
configuration = new BungeeConfig(this);
Set<StorageType> storageTypes = StorageFactory.getRequiredTypes(this, StorageType.H2);
DependencyManager.loadDependencies(this, storageTypes);
// register events
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
// initialise datastore
storage = StorageFactory.getInstance(this, "h2");
storage = StorageFactory.getInstance(this, StorageType.H2);
// initialise redis
if (getConfiguration().isRedisEnabled()) {
@@ -162,8 +169,8 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
groupManager = new GenericGroupManager(this);
trackManager = new GenericTrackManager();
importer = new Importer(commandManager);
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
calculatorFactory = new BungeeCalculatorFactory(this);
cachedStateManager = new CachedStateManager(this);
contextManager = new ContextManager<>();
BackendServerCalculator serverCalculator = new BackendServerCalculator();
@@ -187,7 +194,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
// register tasks
getProxy().getScheduler().schedule(this, new ExpireTemporaryTask(this), 3L, 3L, TimeUnit.SECONDS);
getProxy().getScheduler().schedule(this, consecutiveExecutor, 1L, 1L, TimeUnit.SECONDS);
getProxy().getScheduler().schedule(this, new CacheHousekeepingTask(this), 2L, 2L, TimeUnit.MINUTES);
getLog().info("Successfully loaded.");
}
@@ -216,11 +223,26 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
return PlatformType.BUNGEE;
}
@Override
public String getServerName() {
return getProxy().getName();
}
@Override
public String getServerVersion() {
return getProxy().getVersion();
}
@Override
public File getMainDir() {
return getDataFolder();
}
@Override
public InputStream getResourceStream(String path) {
return getResourceAsStream(path);
}
@Override
public ProxiedPlayer getPlayer(User user) {
return getProxy().getPlayer(uuidCache.getExternalUUID(user.getUuid()));
@@ -73,7 +73,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
me.lucko.luckperms.common.core.model.Group group = plugin.getGroupManager().getIfLoaded(g.getName().toLowerCase());
try {
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("create")
.build().submit(plugin);
} catch (Exception ex) {
@@ -86,7 +86,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
group.setPermission(perm, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("set " + perm + " true")
.build().submit(plugin);
} catch (Exception ex) {
@@ -102,7 +102,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
group.setPermission(perm, true, e.getKey());
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("set " + perm + " true " + e.getKey())
.build().submit(plugin);
} catch (Exception ex) {
@@ -118,7 +118,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
group.setPermission(perm, true, e.getKey(), we.getKey());
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("set " + perm + " true " + e.getKey() + " " + we.getKey())
.build().submit(plugin);
} catch (Exception ex) {
@@ -135,7 +135,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
group.setPermission("group." + inherit, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("setinherit " + group)
.build().submit(plugin);
} catch (Exception ex) {
@@ -154,7 +154,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
group.setPermission("prefix.50." + prefix, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("set prefix.50." + prefix + " true")
.build().submit(plugin);
} catch (Exception ex) {
@@ -169,7 +169,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
group.setPermission("suffix.50." + suffix, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(group).action("set suffix.50." + suffix + " true")
.build().submit(plugin);
} catch (Exception ex) {
@@ -201,7 +201,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
user.setPermission(perm, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("set " + perm + " true")
.build().submit(plugin);
} catch (Exception ex) {
@@ -217,7 +217,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
user.setPermission(perm, true, e.getKey());
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("set " + perm + " true " + e.getKey())
.build().submit(plugin);
} catch (Exception ex) {
@@ -233,7 +233,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
user.setPermission(perm, true, e.getKey(), we.getKey());
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("set " + perm + " true " + e.getKey() + " " + we.getKey())
.build().submit(plugin);
} catch (Exception ex) {
@@ -250,7 +250,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
user.setPermission("group." + group, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("addgroup " + group)
.build().submit(plugin);
} catch (Exception ex) {
@@ -269,7 +269,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
user.setPermission("prefix.100." + prefix, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("set prefix.100." + prefix + " true")
.build().submit(plugin);
} catch (Exception ex) {
@@ -284,7 +284,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
try {
user.setPermission("suffix.100." + suffix, true);
LogEntry.build()
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
.actor(Constants.CONSOLE_UUID).actorName(Constants.CONSOLE_NAME)
.acted(user).action("set suffix.100." + suffix + " true")
.build().submit(plugin);
} catch (Exception ex) {
+14 -4
View File
@@ -90,8 +90,8 @@ group-weight:
# +------------------------------------------------------------------------+ #
# Which storage method the plugin should use.
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
# Fill out connection info below if you're using MySQL or MongoDB
# Currently supported: mysql, postgresql, sqlite, h2, json, yaml, mongodb
# Fill out connection info below if you're using MySQL, PostgreSQL or MongoDB
storage-method: h2
# This block enables support for split datastores.
@@ -105,12 +105,20 @@ split-storage:
log: h2
data:
address: localhost:3306
# Uses standard DB engine port by default
# MySQL: 3306, PostgreSQL: 5432, MongoDB: 27017
# Specify as "host:port" if differs
address: localhost
database: minecraft
username: root
password: ''
pool-size: 10 # The size of the MySQL connection pool.
# The prefix for all LuckPerms tables. Change this is you want to use different tables for different servers.
# This should *not* be set to "lp_" if you have previously ran LuckPerms v2.16.81 or earlier with this database.
table_prefix: 'luckperms_'
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
sync-minutes: 3
@@ -123,9 +131,11 @@ data:
#
# If you decide to enable this feature, you should set "sync-minutes" to -1, as there is no need for LuckPerms
# to poll the database for changes.
#
# Port 6379 is used by default; set address to "host:port" if differs
redis:
enabled: false
address: localhost:6379
address: localhost
password: ''
+28 -7
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.16-SNAPSHOT</version>
<version>2.17-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -30,49 +30,70 @@
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<!-- fanciful -->
<dependency>
<groupId>io.github.mkremins</groupId>
<artifactId>fanciful</artifactId>
<version>1.2.0</version>
<scope>compile</scope>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
<scope>provided</scope>
</dependency>
<!-- HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.5.1</version>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
<!-- Jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
<!-- SQLite -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.8.11.2</version>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
<!-- H2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.192</version>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1212</version>
<scope>provided</scope>
</dependency>
<!-- MongoDB -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.3.0</version>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
<!-- slf4j library -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.9</version>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
<!-- SnakeYAML -->
<dependency>
@@ -26,9 +26,9 @@ import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.common.api.ApiProvider;
import me.lucko.luckperms.common.caching.handlers.CachedStateManager;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.commands.BaseCommand;
import me.lucko.luckperms.common.commands.ConsecutiveExecutor;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.config.LPConfiguration;
import me.lucko.luckperms.common.constants.Message;
@@ -47,6 +47,7 @@ import me.lucko.luckperms.common.utils.LocaleManager;
import me.lucko.luckperms.common.utils.PermissionCache;
import java.io.File;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
@@ -131,13 +132,6 @@ public interface LuckPermsPlugin {
*/
Importer getImporter();
/**
* Gets the consecutive command executor instance
*
* @return the consecutive executor
*/
ConsecutiveExecutor getConsecutiveExecutor();
/**
* Gets the instance providing locale translations for the plugin
*
@@ -153,6 +147,13 @@ public interface LuckPermsPlugin {
*/
ContextManager getContextManager();
/**
* Gets the cached state manager for the platform.
*
* @return the cached state manager
*/
CachedStateManager getCachedStateManager();
/**
* Gets the class responsible for constructing PermissionCalculators on this platform.
*
@@ -214,6 +215,18 @@ public interface LuckPermsPlugin {
*/
PlatformType getType();
/**
* Gets the name or "brand" of the running platform
* @return the server brand
*/
String getServerName();
/**
* Gets the version of the running platform
* @return the server version
*/
String getServerVersion();
/**
* Gets the plugins main directory
*
@@ -228,6 +241,14 @@ public interface LuckPermsPlugin {
*/
File getDataFolder();
/**
* Gets a bundled resource file from the jar
*
* @param path the path of the file
* @return the file as an input stream
*/
InputStream getResourceStream(String path);
/**
* Returns a colored string indicating the status of a player
*
@@ -366,4 +387,20 @@ public interface LuckPermsPlugin {
*/
BufferedRequest<Void> getUpdateTaskBuffer();
/**
* Called at the end of the sync task.
*/
default void onPostUpdate() {
}
/**
* Called when a users data is refreshed
*
* @param user the user
*/
default void onUserRefresh(User user) {
}
}
@@ -0,0 +1,61 @@
/*
* 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.common.api;
import me.lucko.luckperms.LuckPerms;
import me.lucko.luckperms.api.LuckPermsApi;
import java.lang.reflect.Method;
public class ApiHandler {
private static Method REGISTER;
private static Method UNREGISTER;
static {
try {
REGISTER = LuckPerms.class.getDeclaredMethod("registerProvider", LuckPermsApi.class);
REGISTER.setAccessible(true);
UNREGISTER = LuckPerms.class.getDeclaredMethod("unregisterProvider");
UNREGISTER.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void registerProvider(LuckPermsApi luckPermsApi) {
try {
REGISTER.invoke(null, luckPermsApi);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void unregisterProvider() {
try {
UNREGISTER.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -35,24 +35,26 @@ import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.LuckPermsApi;
import me.lucko.luckperms.api.MessagingService;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.NodeFactory;
import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.api.Storage;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.UuidCache;
import me.lucko.luckperms.api.context.ContextListener;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.IContextCalculator;
import me.lucko.luckperms.api.event.LPEvent;
import me.lucko.luckperms.api.event.LPListener;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.api.internal.DatastoreLink;
import me.lucko.luckperms.common.api.internal.GroupLink;
import me.lucko.luckperms.common.api.internal.LPConfigurationLink;
import me.lucko.luckperms.common.api.internal.StorageLink;
import me.lucko.luckperms.common.api.internal.TrackLink;
import me.lucko.luckperms.common.api.internal.UserLink;
import me.lucko.luckperms.common.api.internal.Utils;
import me.lucko.luckperms.common.api.internal.UuidCacheLink;
import me.lucko.luckperms.common.api.delegate.DatastoreDelegate;
import me.lucko.luckperms.common.api.delegate.GroupDelegate;
import me.lucko.luckperms.common.api.delegate.LPConfigurationDelegate;
import me.lucko.luckperms.common.api.delegate.NodeFactoryDelegate;
import me.lucko.luckperms.common.api.delegate.StorageDelegate;
import me.lucko.luckperms.common.api.delegate.TrackDelegate;
import me.lucko.luckperms.common.api.delegate.UserDelegate;
import me.lucko.luckperms.common.api.delegate.UuidCacheDelegate;
import me.lucko.luckperms.common.core.NodeBuilder;
import me.lucko.luckperms.common.core.UserIdentifier;
@@ -61,7 +63,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import static me.lucko.luckperms.common.api.internal.Utils.checkNode;
import static me.lucko.luckperms.common.api.ApiUtils.checkNode;
/**
* Implements the LuckPerms API using the plugin instance
@@ -92,7 +94,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public double getApiVersion() {
return 2.16;
return 2.17;
}
@Override
@@ -117,18 +119,18 @@ public class ApiProvider implements LuckPermsApi {
@Override
public LPConfiguration getConfiguration() {
return new LPConfigurationLink(plugin.getConfiguration());
return new LPConfigurationDelegate(plugin.getConfiguration());
}
@Override
public Storage getStorage() {
return new StorageLink(plugin, plugin.getStorage());
return new StorageDelegate(plugin, plugin.getStorage());
}
@SuppressWarnings("deprecation")
@Override
public Datastore getDatastore() {
return new DatastoreLink(plugin, plugin.getStorage());
return new DatastoreDelegate(plugin, plugin.getStorage());
}
@Override
@@ -138,7 +140,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public UuidCache getUuidCache() {
return new UuidCacheLink(plugin.getUuidCache());
return new UuidCacheDelegate(plugin.getUuidCache());
}
@Override
@@ -149,7 +151,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public User getUser(@NonNull UUID uuid) {
final me.lucko.luckperms.common.core.model.User user = plugin.getUserManager().get(uuid);
return user == null ? null : new UserLink(user);
return user == null ? null : new UserDelegate(user);
}
@Override
@@ -160,7 +162,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public User getUser(@NonNull String name) {
final me.lucko.luckperms.common.core.model.User user = plugin.getUserManager().getByUsername(name);
return user == null ? null : new UserLink(user);
return user == null ? null : new UserDelegate(user);
}
@Override
@@ -170,7 +172,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Set<User> getUsers() {
return plugin.getUserManager().getAll().values().stream().map(UserLink::new).collect(Collectors.toSet());
return plugin.getUserManager().getAll().values().stream().map(UserDelegate::new).collect(Collectors.toSet());
}
@Override
@@ -180,14 +182,14 @@ public class ApiProvider implements LuckPermsApi {
@Override
public void cleanupUser(@NonNull User user) {
Utils.checkUser(user);
plugin.getUserManager().cleanup(((UserLink) user).getMaster());
ApiUtils.checkUser(user);
plugin.getUserManager().cleanup(((UserDelegate) user).getMaster());
}
@Override
public Group getGroup(@NonNull String name) {
final me.lucko.luckperms.common.core.model.Group group = plugin.getGroupManager().getIfLoaded(name);
return group == null ? null : new GroupLink(group);
return group == null ? null : new GroupDelegate(group);
}
@Override
@@ -197,7 +199,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Set<Group> getGroups() {
return plugin.getGroupManager().getAll().values().stream().map(GroupLink::new).collect(Collectors.toSet());
return plugin.getGroupManager().getAll().values().stream().map(GroupDelegate::new).collect(Collectors.toSet());
}
@Override
@@ -208,7 +210,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Track getTrack(@NonNull String name) {
final me.lucko.luckperms.common.core.model.Track track = plugin.getTrackManager().getIfLoaded(name);
return track == null ? null : new TrackLink(track);
return track == null ? null : new TrackDelegate(track);
}
@Override
@@ -218,7 +220,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Set<Track> getTracks() {
return plugin.getTrackManager().getAll().values().stream().map(TrackLink::new).collect(Collectors.toSet());
return plugin.getTrackManager().getAll().values().stream().map(TrackDelegate::new).collect(Collectors.toSet());
}
@Override
@@ -226,6 +228,11 @@ public class ApiProvider implements LuckPermsApi {
return plugin.getTrackManager().isLoaded(name);
}
@Override
public NodeFactory getNodeFactory() {
return NodeFactoryDelegate.INSTANCE;
}
@Override
public Node.Builder buildNode(@NonNull String permission) throws IllegalArgumentException {
return new NodeBuilder(checkNode(permission));
@@ -245,7 +252,13 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Optional<Contexts> getContextForUser(User user) {
Utils.checkUser(user);
return Optional.ofNullable(plugin.getContextForUser(((UserLink) user).getMaster()));
ApiUtils.checkUser(user);
return Optional.ofNullable(plugin.getContextForUser(((UserDelegate) user).getMaster()));
}
@SuppressWarnings("unchecked")
@Override
public ContextSet getContextForPlayer(Object player) {
return plugin.getContextManager().getApplicableContext(player);
}
}
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.internal;
package me.lucko.luckperms.common.api;
import lombok.experimental.UtilityClass;
@@ -29,21 +29,24 @@ import com.google.common.base.Preconditions;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.common.api.delegate.GroupDelegate;
import me.lucko.luckperms.common.api.delegate.TrackDelegate;
import me.lucko.luckperms.common.api.delegate.UserDelegate;
import me.lucko.luckperms.common.utils.ArgumentChecker;
@UtilityClass
public class Utils {
public class ApiUtils {
public static void checkUser(User user) {
Preconditions.checkState(user instanceof UserLink, "User instance cannot be handled by this implementation.");
Preconditions.checkState(user instanceof UserDelegate, "User instance cannot be handled by this implementation.");
}
public static void checkGroup(Group group) {
Preconditions.checkState(group instanceof GroupLink, "Group instance cannot be handled by this implementation.");
Preconditions.checkState(group instanceof GroupDelegate, "Group instance cannot be handled by this implementation.");
}
public static void checkTrack(Track track) {
Preconditions.checkState(track instanceof TrackLink, "Track instance cannot be handled by this implementation.");
Preconditions.checkState(track instanceof TrackDelegate, "Track instance cannot be handled by this implementation.");
}
public static String checkUsername(String s) {
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.internal;
package me.lucko.luckperms.common.api.delegate;
import lombok.AllArgsConstructor;
import lombok.NonNull;
@@ -39,19 +39,14 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import static me.lucko.luckperms.common.api.internal.Utils.checkGroup;
import static me.lucko.luckperms.common.api.internal.Utils.checkName;
import static me.lucko.luckperms.common.api.internal.Utils.checkTrack;
import static me.lucko.luckperms.common.api.internal.Utils.checkUser;
import static me.lucko.luckperms.common.api.internal.Utils.checkUsername;
import static me.lucko.luckperms.common.api.ApiUtils.checkGroup;
import static me.lucko.luckperms.common.api.ApiUtils.checkName;
import static me.lucko.luckperms.common.api.ApiUtils.checkTrack;
import static me.lucko.luckperms.common.api.ApiUtils.checkUser;
import static me.lucko.luckperms.common.api.ApiUtils.checkUsername;
/**
* Provides a link between {@link Datastore} and {@link Storage}
*
* Note that this class only provides for the old deprecated interface, see {@link StorageLink} for the new one.
*/
@SuppressWarnings({"unused", "WeakerAccess", "deprecation"})
public class DatastoreLink implements Datastore {
@SuppressWarnings("deprecation")
public class DatastoreDelegate implements Datastore {
private final LuckPermsPlugin plugin;
private final Storage master;
@@ -59,7 +54,7 @@ public class DatastoreLink implements Datastore {
private final Sync sync;
private final Future future;
public DatastoreLink(@NonNull LuckPermsPlugin plugin, @NonNull Storage master) {
public DatastoreDelegate(@NonNull LuckPermsPlugin plugin, @NonNull Storage master) {
this.plugin = plugin;
this.master = master;
this.async = new Async(master);
@@ -109,7 +104,7 @@ public class DatastoreLink implements Datastore {
@Override
public void getLog(@NonNull Callback<Log> callback) {
master.force().getLog().thenAcceptAsync(log -> callback.onComplete(new LogLink(log)), plugin.getSyncExecutor());
master.force().getLog().thenAcceptAsync(log -> callback.onComplete(new LogDelegate(log)), plugin.getSyncExecutor());
}
@Override
@@ -130,7 +125,7 @@ public class DatastoreLink implements Datastore {
@Override
public void saveUser(@NonNull User user, Callback<Boolean> callback) {
checkUser(user);
registerCallback(master.force().saveUser(((UserLink) user).getMaster()), callback);
registerCallback(master.force().saveUser(((UserDelegate) user).getMaster()), callback);
}
@Override
@@ -161,7 +156,7 @@ public class DatastoreLink implements Datastore {
@Override
public void saveGroup(@NonNull Group group, Callback<Boolean> callback) {
checkGroup(group);
registerCallback(master.force().saveGroup(((GroupLink) group).getMaster()), callback);
registerCallback(master.force().saveGroup(((GroupDelegate) group).getMaster()), callback);
}
@Override
@@ -170,7 +165,7 @@ public class DatastoreLink implements Datastore {
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
registerCallback(master.force().deleteGroup(((GroupLink) group).getMaster()), callback);
registerCallback(master.force().deleteGroup(((GroupDelegate) group).getMaster()), callback);
}
@Override
@@ -191,13 +186,13 @@ public class DatastoreLink implements Datastore {
@Override
public void saveTrack(@NonNull Track track, Callback<Boolean> callback) {
checkTrack(track);
registerCallback(master.force().saveTrack(((TrackLink) track).getMaster()), callback);
registerCallback(master.force().saveTrack(((TrackDelegate) track).getMaster()), callback);
}
@Override
public void deleteTrack(@NonNull Track track, Callback<Boolean> callback) {
checkTrack(track);
registerCallback(master.force().deleteTrack(((TrackLink) track).getMaster()), callback);
registerCallback(master.force().deleteTrack(((TrackDelegate) track).getMaster()), callback);
}
@Override
@@ -226,7 +221,7 @@ public class DatastoreLink implements Datastore {
if (log == null) {
return null;
}
return new LogLink(log);
return new LogDelegate(log);
}
@Override
@@ -247,7 +242,7 @@ public class DatastoreLink implements Datastore {
@Override
public boolean saveUser(@NonNull User user) {
checkUser(user);
return master.force().saveUser(((UserLink) user).getMaster()).join();
return master.force().saveUser(((UserDelegate) user).getMaster()).join();
}
@Override
@@ -278,7 +273,7 @@ public class DatastoreLink implements Datastore {
@Override
public boolean saveGroup(@NonNull Group group) {
checkGroup(group);
return master.force().saveGroup(((GroupLink) group).getMaster()).join();
return master.force().saveGroup(((GroupDelegate) group).getMaster()).join();
}
@Override
@@ -287,7 +282,7 @@ public class DatastoreLink implements Datastore {
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
return master.force().deleteGroup(((GroupLink) group).getMaster()).join();
return master.force().deleteGroup(((GroupDelegate) group).getMaster()).join();
}
@Override
@@ -308,13 +303,13 @@ public class DatastoreLink implements Datastore {
@Override
public boolean saveTrack(@NonNull Track track) {
checkTrack(track);
return master.force().saveTrack(((TrackLink) track).getMaster()).join();
return master.force().saveTrack(((TrackDelegate) track).getMaster()).join();
}
@Override
public boolean deleteTrack(@NonNull Track track) {
checkTrack(track);
return master.force().deleteTrack(((TrackLink) track).getMaster()).join();
return master.force().deleteTrack(((TrackDelegate) track).getMaster()).join();
}
@Override
@@ -339,7 +334,7 @@ public class DatastoreLink implements Datastore {
@Override
public java.util.concurrent.Future<Log> getLog() {
return master.force().getLog().thenApply(log -> log == null ? null : new LogLink(log));
return master.force().getLog().thenApply(log -> log == null ? null : new LogDelegate(log));
}
@Override
@@ -360,7 +355,7 @@ public class DatastoreLink implements Datastore {
@Override
public java.util.concurrent.Future<Boolean> saveUser(@NonNull User user) {
checkUser(user);
return master.force().saveUser(((UserLink) user).getMaster());
return master.force().saveUser(((UserDelegate) user).getMaster());
}
@Override
@@ -391,7 +386,7 @@ public class DatastoreLink implements Datastore {
@Override
public java.util.concurrent.Future<Boolean> saveGroup(@NonNull Group group) {
checkGroup(group);
return master.force().saveGroup(((GroupLink) group).getMaster());
return master.force().saveGroup(((GroupDelegate) group).getMaster());
}
@Override
@@ -400,7 +395,7 @@ public class DatastoreLink implements Datastore {
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
return master.force().deleteGroup(((GroupLink) group).getMaster());
return master.force().deleteGroup(((GroupDelegate) group).getMaster());
}
@Override
@@ -421,13 +416,13 @@ public class DatastoreLink implements Datastore {
@Override
public java.util.concurrent.Future<Boolean> saveTrack(@NonNull Track track) {
checkTrack(track);
return master.force().saveTrack(((TrackLink) track).getMaster());
return master.force().saveTrack(((TrackDelegate) track).getMaster());
}
@Override
public java.util.concurrent.Future<Boolean> deleteTrack(@NonNull Track track) {
checkTrack(track);
return master.force().deleteTrack(((TrackLink) track).getMaster());
return master.force().deleteTrack(((TrackDelegate) track).getMaster());
}
@Override
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.internal;
package me.lucko.luckperms.common.api.delegate;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
@@ -32,17 +32,17 @@ import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.OptionalInt;
import static me.lucko.luckperms.common.api.internal.Utils.checkGroup;
import static me.lucko.luckperms.common.api.internal.Utils.checkServer;
import static me.lucko.luckperms.common.api.internal.Utils.checkTime;
import static me.lucko.luckperms.common.api.ApiUtils.checkGroup;
import static me.lucko.luckperms.common.api.ApiUtils.checkServer;
import static me.lucko.luckperms.common.api.ApiUtils.checkTime;
/**
* Provides a link between {@link Group} and {@link me.lucko.luckperms.common.core.model.Group}
*/
@EqualsAndHashCode(of = {"name"}, callSuper = false)
@SuppressWarnings("unused")
public class GroupLink extends PermissionHolderLink implements Group {
public class GroupDelegate extends PermissionHolderDelegate implements Group {
@Getter(AccessLevel.PACKAGE)
private final me.lucko.luckperms.common.core.model.Group master;
@@ -50,7 +50,7 @@ public class GroupLink extends PermissionHolderLink implements Group {
@Getter
private final String name;
public GroupLink(@NonNull me.lucko.luckperms.common.core.model.Group master) {
public GroupDelegate(@NonNull me.lucko.luckperms.common.core.model.Group master) {
super(master);
this.master = master;
this.name = master.getName();
@@ -59,91 +59,91 @@ public class GroupLink extends PermissionHolderLink implements Group {
@Override
public boolean inheritsGroup(@NonNull Group group) {
checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster());
return master.inheritsGroup(((GroupDelegate) group).getMaster());
}
@Override
public boolean inheritsGroup(@NonNull Group group, @NonNull String server) {
checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster(), server);
return master.inheritsGroup(((GroupDelegate) group).getMaster(), server);
}
@Override
public boolean inheritsGroup(@NonNull Group group, @NonNull String server, @NonNull String world) {
checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster(), server, world);
return master.inheritsGroup(((GroupDelegate) group).getMaster(), server, world);
}
@Override
public void setInheritGroup(@NonNull Group group) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster());
master.setInheritGroup(((GroupDelegate) group).getMaster());
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server));
master.setInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server));
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world);
master.setInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), world);
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull long expireAt) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkTime(expireAt));
master.setInheritGroup(((GroupDelegate) group).getMaster(), checkTime(expireAt));
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server, @NonNull long expireAt) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), checkTime(expireAt));
master.setInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), checkTime(expireAt));
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull long expireAt) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world, checkTime(expireAt));
master.setInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), world, checkTime(expireAt));
}
@Override
public void unsetInheritGroup(@NonNull Group group) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster());
master.unsetInheritGroup(((GroupDelegate) group).getMaster());
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull boolean temporary) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), temporary);
master.unsetInheritGroup(((GroupDelegate) group).getMaster(), temporary);
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server));
master.unsetInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server));
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world);
master.unsetInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), world);
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server, @NonNull boolean temporary) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), temporary);
master.unsetInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), temporary);
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull boolean temporary) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world, temporary);
master.unsetInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), world, temporary);
}
@Override
@@ -161,6 +161,11 @@ public class GroupLink extends PermissionHolderLink implements Group {
return master.getLocalGroups(checkServer(server), world);
}
@Override
public OptionalInt getWeight() {
return master.getWeight();
}
@Override
public List<String> getLocalGroups(@NonNull String server) {
return master.getLocalGroups(checkServer(server));
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.internal;
package me.lucko.luckperms.common.api.delegate;
import lombok.AllArgsConstructor;
@@ -34,7 +34,7 @@ import java.util.Map;
* Provides a link between {@link LPConfiguration} and {@link me.lucko.luckperms.common.config.LPConfiguration}
*/
@AllArgsConstructor
public class LPConfigurationLink implements LPConfiguration {
public class LPConfigurationDelegate implements LPConfiguration {
private final me.lucko.luckperms.common.config.LPConfiguration master;
@Override
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.internal;
package me.lucko.luckperms.common.api.delegate;
import lombok.AllArgsConstructor;
import lombok.NonNull;
@@ -32,13 +32,13 @@ import java.util.SortedMap;
import java.util.SortedSet;
import java.util.UUID;
import static me.lucko.luckperms.common.api.internal.Utils.checkName;
import static me.lucko.luckperms.common.api.ApiUtils.checkName;
/**
* Provides a link between {@link Log} and {@link me.lucko.luckperms.common.data.Log}
*/
@AllArgsConstructor
public class LogLink implements Log {
public class LogDelegate implements Log {
private final me.lucko.luckperms.common.data.Log master;
@Override
@@ -0,0 +1,67 @@
/*
* 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.common.api.delegate;
import lombok.NonNull;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.core.NodeFactory;
public class NodeFactoryDelegate implements me.lucko.luckperms.api.NodeFactory {
public static final NodeFactoryDelegate INSTANCE = new NodeFactoryDelegate();
@Override
public Node fromSerialisedNode(@NonNull String serialisedPermission, boolean value) {
return NodeFactory.fromSerialisedNode(serialisedPermission, value);
}
@Override
public Node.Builder newBuilder(@NonNull String permission) {
return NodeFactory.newBuilder(permission);
}
@Override
public Node.Builder newBuilderFromExisting(@NonNull Node other) {
return NodeFactory.builderFromExisting(other);
}
@Override
public Node.Builder newBuilderFromSerialisedNode(@NonNull String serialisedPermission, boolean value) {
return NodeFactory.builderFromSerialisedNode(serialisedPermission, value);
}
@Override
public Node.Builder makeMetaNode(@NonNull String key, @NonNull String value) {
return NodeFactory.makeMetaNode(key, value);
}
@Override
public Node.Builder makePrefixNode(int priority, @NonNull String prefix) {
return NodeFactory.makePrefixNode(priority, prefix);
}
@Override
public Node.Builder makeSuffixNode(int priority, @NonNull String suffix) {
return NodeFactory.makeSuffixNode(priority, suffix);
}
}
@@ -20,11 +20,15 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.internal;
package me.lucko.luckperms.common.api.delegate;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node;
@@ -36,16 +40,17 @@ import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import static me.lucko.luckperms.common.api.internal.Utils.checkNode;
import static me.lucko.luckperms.common.api.internal.Utils.checkServer;
import static me.lucko.luckperms.common.api.internal.Utils.checkTime;
import static me.lucko.luckperms.common.api.ApiUtils.checkNode;
import static me.lucko.luckperms.common.api.ApiUtils.checkServer;
import static me.lucko.luckperms.common.api.ApiUtils.checkTime;
import static me.lucko.luckperms.common.core.model.PermissionHolder.exportToLegacy;
/**
@@ -53,7 +58,7 @@ import static me.lucko.luckperms.common.core.model.PermissionHolder.exportToLega
*/
@SuppressWarnings("unused")
@AllArgsConstructor
public class PermissionHolderLink implements PermissionHolder {
public class PermissionHolderDelegate implements PermissionHolder {
private final me.lucko.luckperms.common.core.model.PermissionHolder master;
@Override
@@ -63,37 +68,42 @@ public class PermissionHolderLink implements PermissionHolder {
@Override
public SortedSet<? extends Node> getPermissions() {
return master.getPermissions(false);
return ImmutableSortedSet.copyOf(master.getPermissions(false));
}
@Override
public Set<Node> getEnduringPermissions() {
return master.getNodes();
return ImmutableSet.copyOf(master.getNodes());
}
@Override
public Set<Node> getTransientPermissions() {
return master.getTransientNodes();
return ImmutableSet.copyOf(master.getTransientNodes());
}
@Override
public Set<Node> getAllNodes() {
return Collections.unmodifiableSet(master.getAllNodes(null, ExtractedContexts.generate(Contexts.allowAll())));
return ImmutableSet.copyOf(master.getAllNodes(null, ExtractedContexts.generate(Contexts.allowAll())));
}
@Override
public SortedSet<LocalizedNode> getAllNodes(@NonNull Contexts contexts) {
return master.getAllNodes(null, ExtractedContexts.generate(contexts));
return new TreeSet<>(master.getAllNodes(null, ExtractedContexts.generate(contexts)));
}
@Override
public Set<LocalizedNode> getAllNodesFiltered(@NonNull Contexts contexts) {
return master.getAllNodesFiltered(ExtractedContexts.generate(contexts));
return new HashSet<>(master.getAllNodesFiltered(ExtractedContexts.generate(contexts)));
}
@Override
public Map<String, Boolean> exportNodes(Contexts contexts, boolean lowerCase) {
return new HashMap<>(master.exportNodes(contexts, lowerCase));
}
@Override
public Map<String, Boolean> getNodes() {
return exportToLegacy(master.getNodes());
return ImmutableMap.copyOf(exportToLegacy(master.getNodes()));
}
@Override
@@ -251,6 +261,61 @@ public class PermissionHolderLink implements PermissionHolder {
master.unsetPermission(checkNode(node), checkServer(server), world, temporary);
}
@Override
public void clearNodes() {
master.clearNodes();
}
@Override
public void clearNodes(String server) {
master.clearNodes(server);
}
@Override
public void clearNodes(String server, String world) {
master.clearNodes(server, world);
}
@Override
public void clearParents() {
master.clearParents();
}
@Override
public void clearParents(String server) {
master.clearParents(server);
}
@Override
public void clearParents(String server, String world) {
master.clearParents(server, world);
}
@Override
public void clearMeta() {
master.clearMeta();
}
@Override
public void clearMeta(String server) {
master.clearMeta(server);
}
@Override
public void clearMeta(String server, String world) {
master.clearMeta(server, world);
}
@Override
public void clearMetaKeys(String key, String server, String world, boolean temporary) {
master.clearMetaKeys(key, server, world, temporary);
}
@Override
public void clearTransientNodes() {
master.clearTransientNodes();
}
@Override
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups, List<String> possibleNodes) {
Map<String, String> context = new HashMap<>();
@@ -20,12 +20,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.internal;
package me.lucko.luckperms.common.api.delegate;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.api.Log;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.Storage;
@@ -33,22 +34,23 @@ import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.common.LuckPermsPlugin;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import static me.lucko.luckperms.common.api.internal.Utils.checkGroup;
import static me.lucko.luckperms.common.api.internal.Utils.checkName;
import static me.lucko.luckperms.common.api.internal.Utils.checkTrack;
import static me.lucko.luckperms.common.api.internal.Utils.checkUser;
import static me.lucko.luckperms.common.api.internal.Utils.checkUsername;
import static me.lucko.luckperms.common.api.ApiUtils.checkGroup;
import static me.lucko.luckperms.common.api.ApiUtils.checkName;
import static me.lucko.luckperms.common.api.ApiUtils.checkTrack;
import static me.lucko.luckperms.common.api.ApiUtils.checkUser;
import static me.lucko.luckperms.common.api.ApiUtils.checkUsername;
/**
* Provides a link between {@link Storage} and {@link me.lucko.luckperms.common.storage.Storage}
*/
@AllArgsConstructor
public class StorageLink implements Storage {
public class StorageDelegate implements Storage {
private final LuckPermsPlugin plugin;
private final me.lucko.luckperms.common.storage.Storage master;
@@ -79,7 +81,7 @@ public class StorageLink implements Storage {
@Override
public CompletableFuture<Log> getLog() {
return master.force().getLog().thenApply(log -> log == null ? null : new LogLink(log));
return master.force().getLog().thenApply(log -> log == null ? null : new LogDelegate(log));
}
@Override
@@ -90,7 +92,7 @@ public class StorageLink implements Storage {
@Override
public CompletableFuture<Boolean> saveUser(User user) {
checkUser(user);
return master.force().saveUser(((UserLink) user).getMaster());
return master.force().saveUser(((UserDelegate) user).getMaster());
}
@Override
@@ -103,6 +105,11 @@ public class StorageLink implements Storage {
return master.force().getUniqueUsers();
}
@Override
public CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(@NonNull String permission) {
return master.force().getUsersWithPermission(permission);
}
@Override
public CompletableFuture<Boolean> createAndLoadGroup(String name) {
return master.force().createAndLoadGroup(checkName(name));
@@ -121,7 +128,7 @@ public class StorageLink implements Storage {
@Override
public CompletableFuture<Boolean> saveGroup(Group group) {
checkGroup(group);
return master.force().saveGroup(((GroupLink) group).getMaster());
return master.force().saveGroup(((GroupDelegate) group).getMaster());
}
@Override
@@ -130,7 +137,12 @@ public class StorageLink implements Storage {
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
return master.force().deleteGroup(((GroupLink) group).getMaster());
return master.force().deleteGroup(((GroupDelegate) group).getMaster());
}
@Override
public CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(@NonNull String permission) {
return master.force().getGroupsWithPermission(permission);
}
@Override
@@ -151,13 +163,13 @@ public class StorageLink implements Storage {
@Override
public CompletableFuture<Boolean> saveTrack(Track track) {
checkTrack(track);
return master.force().saveTrack(((TrackLink) track).getMaster());
return master.force().saveTrack(((TrackDelegate) track).getMaster());
}
@Override
public CompletableFuture<Boolean> deleteTrack(Track track) {
checkTrack(track);
return master.force().deleteTrack(((TrackLink) track).getMaster());
return master.force().deleteTrack(((TrackDelegate) track).getMaster());
}
@Override
@@ -169,4 +181,9 @@ public class StorageLink implements Storage {
public CompletableFuture<UUID> getUUID(String username) {
return master.force().getUUID(checkUsername(username));
}
@Override
public CompletableFuture<String> getName(@NonNull UUID uuid) {
return master.force().getName(uuid);
}
}
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.internal;
package me.lucko.luckperms.common.api.delegate;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
@@ -34,14 +34,14 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import static me.lucko.luckperms.common.api.internal.Utils.checkGroup;
import static me.lucko.luckperms.common.api.ApiUtils.checkGroup;
/**
* Provides a link between {@link Track} and {@link me.lucko.luckperms.common.core.model.Track}
*/
@EqualsAndHashCode(of = {"name"})
@SuppressWarnings("unused")
public class TrackLink implements Track {
public class TrackDelegate implements Track {
@Getter(AccessLevel.PACKAGE)
private final me.lucko.luckperms.common.core.model.Track master;
@@ -49,7 +49,7 @@ public class TrackLink implements Track {
@Getter
private final String name;
public TrackLink(@NonNull me.lucko.luckperms.common.core.model.Track master) {
public TrackDelegate(@NonNull me.lucko.luckperms.common.core.model.Track master) {
this.master = master;
this.name = master.getName();
}
@@ -67,31 +67,31 @@ public class TrackLink implements Track {
@Override
public String getNext(@NonNull Group current) throws ObjectLacksException {
checkGroup(current);
return master.getNext(((GroupLink) current).getMaster());
return master.getNext(((GroupDelegate) current).getMaster());
}
@Override
public String getPrevious(@NonNull Group current) throws ObjectLacksException {
checkGroup(current);
return master.getPrevious(((GroupLink) current).getMaster());
return master.getPrevious(((GroupDelegate) current).getMaster());
}
@Override
public void appendGroup(@NonNull Group group) throws ObjectAlreadyHasException {
checkGroup(group);
master.appendGroup(((GroupLink) group).getMaster());
master.appendGroup(((GroupDelegate) group).getMaster());
}
@Override
public void insertGroup(@NonNull Group group, @NonNull int position) throws ObjectAlreadyHasException, IndexOutOfBoundsException {
checkGroup(group);
master.insertGroup(((GroupLink) group).getMaster(), position);
master.insertGroup(((GroupDelegate) group).getMaster(), position);
}
@Override
public void removeGroup(@NonNull Group group) throws ObjectLacksException {
checkGroup(group);
master.removeGroup(((GroupLink) group).getMaster());
master.removeGroup(((GroupDelegate) group).getMaster());
}
@Override
@@ -102,7 +102,7 @@ public class TrackLink implements Track {
@Override
public boolean containsGroup(@NonNull Group group) {
checkGroup(group);
return master.containsGroup(((GroupLink) group).getMaster());
return master.containsGroup(((GroupDelegate) group).getMaster());
}
@Override
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.internal;
package me.lucko.luckperms.common.api.delegate;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -36,16 +36,16 @@ import java.util.List;
import java.util.Optional;
import java.util.UUID;
import static me.lucko.luckperms.common.api.internal.Utils.checkGroup;
import static me.lucko.luckperms.common.api.internal.Utils.checkServer;
import static me.lucko.luckperms.common.api.internal.Utils.checkTime;
import static me.lucko.luckperms.common.api.ApiUtils.checkGroup;
import static me.lucko.luckperms.common.api.ApiUtils.checkServer;
import static me.lucko.luckperms.common.api.ApiUtils.checkTime;
/**
* Provides a link between {@link User} and {@link me.lucko.luckperms.common.core.model.User}
*/
@EqualsAndHashCode(of = {"uuid"}, callSuper = false)
@SuppressWarnings("unused")
public class UserLink extends PermissionHolderLink implements User {
public class UserDelegate extends PermissionHolderDelegate implements User {
@Getter
private final me.lucko.luckperms.common.core.model.User master;
@@ -53,7 +53,7 @@ public class UserLink extends PermissionHolderLink implements User {
@Getter
private final UUID uuid;
public UserLink(@NonNull me.lucko.luckperms.common.core.model.User master) {
public UserDelegate(@NonNull me.lucko.luckperms.common.core.model.User master) {
super(master);
this.master = master;
this.uuid = master.getUuid();
@@ -92,94 +92,99 @@ public class UserLink extends PermissionHolderLink implements User {
return Optional.ofNullable(master.getUserData());
}
@Override
public void setupDataCache() {
master.setupData(false);
}
@Override
public boolean isInGroup(@NonNull Group group) {
checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster());
return master.inheritsGroup(((GroupDelegate) group).getMaster());
}
@Override
public boolean isInGroup(@NonNull Group group, @NonNull String server) {
checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster(), server);
return master.inheritsGroup(((GroupDelegate) group).getMaster(), server);
}
@Override
public boolean isInGroup(@NonNull Group group, @NonNull String server, @NonNull String world) {
checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster(), server, world);
return master.inheritsGroup(((GroupDelegate) group).getMaster(), server, world);
}
@Override
public void addGroup(@NonNull Group group) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster());
master.setInheritGroup(((GroupDelegate) group).getMaster());
}
@Override
public void addGroup(@NonNull Group group, @NonNull String server) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server));
master.setInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server));
}
@Override
public void addGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world);
master.setInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), world);
}
@Override
public void addGroup(@NonNull Group group, @NonNull long expireAt) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkTime(expireAt));
master.setInheritGroup(((GroupDelegate) group).getMaster(), checkTime(expireAt));
}
@Override
public void addGroup(@NonNull Group group, @NonNull String server, @NonNull long expireAt) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), checkTime(expireAt));
master.setInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), checkTime(expireAt));
}
@Override
public void addGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull long expireAt) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world, checkTime(expireAt));
master.setInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), world, checkTime(expireAt));
}
@Override
public void removeGroup(@NonNull Group group) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster());
master.unsetInheritGroup(((GroupDelegate) group).getMaster());
}
@Override
public void removeGroup(@NonNull Group group, @NonNull boolean temporary) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), temporary);
master.unsetInheritGroup(((GroupDelegate) group).getMaster(), temporary);
}
@Override
public void removeGroup(@NonNull Group group, @NonNull String server) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server));
master.unsetInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server));
}
@Override
public void removeGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world);
master.unsetInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), world);
}
@Override
public void removeGroup(@NonNull Group group, @NonNull String server, @NonNull boolean temporary) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), temporary);
master.unsetInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), temporary);
}
@Override
public void removeGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull boolean temporary) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world, temporary);
master.unsetInheritGroup(((GroupDelegate) group).getMaster(), checkServer(server), world, temporary);
}
@Override
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.internal;
package me.lucko.luckperms.common.api.delegate;
import lombok.AllArgsConstructor;
import lombok.NonNull;
@@ -33,7 +33,7 @@ import java.util.UUID;
* Provides a link between {@link UuidCache} and {@link me.lucko.luckperms.common.core.UuidCache}
*/
@AllArgsConstructor
public class UuidCacheLink implements UuidCache {
public class UuidCacheDelegate implements UuidCache {
private final me.lucko.luckperms.common.core.UuidCache master;
@Override
@@ -41,6 +41,7 @@ import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.utils.ExtractedContexts;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Holds an easily accessible cache of a user's data in a number of contexts
@@ -59,6 +60,7 @@ public class UserCache implements UserData {
private final CalculatorFactory calculatorFactory;
private final LoadingCache<Contexts, PermissionCache> permission = CacheBuilder.newBuilder()
.expireAfterAccess(10, TimeUnit.MINUTES)
.build(new CacheLoader<Contexts, PermissionCache>() {
@Override
public PermissionCache load(Contexts contexts) {
@@ -73,6 +75,7 @@ public class UserCache implements UserData {
});
private final LoadingCache<Contexts, MetaCache> meta = CacheBuilder.newBuilder()
.expireAfterAccess(10, TimeUnit.MINUTES)
.build(new CacheLoader<Contexts, MetaCache>() {
@Override
public MetaCache load(Contexts contexts) {
@@ -153,4 +156,9 @@ public class UserCache implements UserData {
permission.asMap().values().forEach(PermissionData::invalidateCache);
}
public void cleanup() {
permission.cleanUp();
meta.cleanUp();
}
}
@@ -0,0 +1,129 @@
/*
* 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.common.caching.handlers;
import lombok.RequiredArgsConstructor;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.core.model.PermissionHolder;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
/**
* Manages the cached state of all permission holders
*/
@RequiredArgsConstructor
public class CachedStateManager {
private static final Consumer<PermissionHolder> INVALIDATE_CONSUMER = PermissionHolder::invalidateInheritanceCaches;
private final LuckPermsPlugin plugin;
// Group --> Groups that inherit from that group. (reverse relationship)
private final Multimap<HolderReference, HolderReference> map = HashMultimap.create();
private final ReentrantLock lock = new ReentrantLock();
/**
* Gets a set of holder names that inherit permissions (either directly or via other groups)
* from the given holder name
*
* @param holder the holder name to query for
* @return a set of inherited groups
*/
public Set<HolderReference> getInheritances(HolderReference holder) {
Set<HolderReference> set = new HashSet<>();
set.add(holder);
lock.lock();
try {
while (true) {
Set<HolderReference> clone = new HashSet<>(set);
boolean work = false;
for (HolderReference s : clone) {
if (set.addAll(map.get(s))) {
work = true;
}
}
if (!work) {
break;
}
}
} finally {
lock.unlock();
}
set.remove(holder);
return set;
}
/**
* Registers a holder and the groups they inherit from within this map.
*
* @param holder the holder to add
* @param inheritedGroups a list of groups the holder inherits from
*/
public void putAll(HolderReference holder, Set<HolderReference> inheritedGroups) {
lock.lock();
try {
map.entries().removeIf(entry -> entry.getValue().equals(holder));
for (HolderReference child : inheritedGroups) {
map.put(child, holder);
}
} finally {
lock.unlock();
}
}
/**
* Clears defined inheritances for the given holder name.
*
* @param holder the holder name to clear
*/
public void clear(HolderReference holder) {
lock.lock();
try {
map.entries().removeIf(entry -> entry.getValue().equals(holder));
} finally {
lock.unlock();
}
}
public void invalidateInheritances(HolderReference holder) {
Set<HolderReference> toInvalidate = getInheritances(holder);
invalidateInheritances(plugin, toInvalidate);
}
public static void invalidateInheritances(LuckPermsPlugin plugin, Set<HolderReference> references) {
references.forEach(hr -> hr.apply(plugin, INVALIDATE_CONSUMER));
}
}
@@ -0,0 +1,57 @@
/*
* 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.common.caching.handlers;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.core.model.PermissionHolder;
import java.util.function.Consumer;
@Getter
@ToString
@EqualsAndHashCode
@AllArgsConstructor(staticName = "of")
public class GroupReference implements HolderReference<String> {
private final String id;
@Override
public HolderType getType() {
return HolderType.GROUP;
}
@Override
public void apply(LuckPermsPlugin plugin, Consumer<PermissionHolder> consumer) {
Group group = plugin.getGroupManager().getIfLoaded(id);
if (group == null) return;
consumer.accept(group);
}
}
@@ -0,0 +1,36 @@
/*
* 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.common.caching.handlers;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.utils.Identifiable;
import java.util.function.Consumer;
public interface HolderReference<T> extends Identifiable<T> {
HolderType getType();
void apply(LuckPermsPlugin plugin, Consumer<PermissionHolder> consumer);
}
@@ -20,18 +20,8 @@
* SOFTWARE.
*/
package me.lucko.luckperms;
import me.lucko.luckperms.api.LuckPermsApi;
public class ApiHandler {
public static void registerProvider(LuckPermsApi luckPermsApi) {
LuckPerms.registerProvider(luckPermsApi);
}
public static void unregisterProvider() {
LuckPerms.unregisterProvider();
}
package me.lucko.luckperms.common.caching.handlers;
public enum HolderType {
USER, GROUP
}
@@ -0,0 +1,57 @@
/*
* 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.common.caching.handlers;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.core.UserIdentifier;
import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.core.model.User;
import java.util.function.Consumer;
@Getter
@ToString
@EqualsAndHashCode
@AllArgsConstructor(staticName = "of")
public class UserReference implements HolderReference<UserIdentifier> {
private final UserIdentifier id;
@Override
public HolderType getType() {
return HolderType.USER;
}
@Override
public void apply(LuckPermsPlugin plugin, Consumer<PermissionHolder> consumer) {
User user = plugin.getUserManager().getIfLoaded(id);
if (user == null) return;
consumer.accept(user);
}
}
@@ -0,0 +1,41 @@
/*
* 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.common.caching.holder;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.api.Contexts;
@Getter
@ToString
@EqualsAndHashCode
@AllArgsConstructor(staticName = "of")
public class ExportNodesHolder {
private final Contexts contexts;
private final Boolean lowerCase;
}
@@ -0,0 +1,43 @@
/*
* 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.common.caching.holder;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.utils.ExtractedContexts;
@Getter
@ToString
@EqualsAndHashCode
@AllArgsConstructor(staticName = "of")
public class GetAllNodesRequest {
private final ImmutableList<String> excludedGroups;
private final ExtractedContexts contexts;
}
@@ -57,7 +57,10 @@ public class RegexProcessor implements PermissionProcessor {
continue;
}
regexPermissions.put(e.getKey().substring(2), e.getValue());
String pattern = e.getKey().substring(2);
Patterns.compile(pattern); // Cache the lookup for later.
regexPermissions.put(pattern, e.getValue());
}
}
}
@@ -37,7 +37,7 @@ import me.lucko.luckperms.common.commands.misc.ExportCommand;
import me.lucko.luckperms.common.commands.misc.ImportCommand;
import me.lucko.luckperms.common.commands.misc.InfoCommand;
import me.lucko.luckperms.common.commands.misc.NetworkSyncCommand;
import me.lucko.luckperms.common.commands.misc.QueueCommand;
import me.lucko.luckperms.common.commands.misc.SearchCommand;
import me.lucko.luckperms.common.commands.misc.SyncCommand;
import me.lucko.luckperms.common.commands.misc.VerboseCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
@@ -50,15 +50,186 @@ import me.lucko.luckperms.common.commands.usersbulkedit.UsersBulkEditMainCommand
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import io.github.mkremins.fanciful.ChatColor;
import io.github.mkremins.fanciful.FancyMessage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
public class CommandManager {
@Getter
private final LuckPermsPlugin plugin;
private final ExecutorService executor;
@Getter
private final List<BaseCommand> mainCommands;
public CommandManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
this.executor = Executors.newSingleThreadExecutor();
ImmutableList.Builder<BaseCommand> l = ImmutableList.builder();
l.add(new UserMainCommand())
.add(new GroupMainCommand())
.add(new TrackMainCommand())
.addAll(plugin.getExtraCommands())
.add(new LogMainCommand())
.add(new SyncCommand())
.add(new InfoCommand())
.add(new VerboseCommand())
.add(new SearchCommand())
.add(new NetworkSyncCommand())
.add(new ImportCommand())
.add(new ExportCommand())
.add(new MigrationMainCommand())
.add(new UsersBulkEditMainCommand())
.add(new CreateGroup())
.add(new DeleteGroup())
.add(new ListGroups())
.add(new CreateTrack())
.add(new DeleteTrack())
.add(new ListTracks());
mainCommands = l.build();
}
/**
* Generic on command method to be called from the command executor object of the platform
* Unlike {@link #onCommand(Sender, String, List)}, this method is called in a new thread
* @param sender who sent the command
* @param label the command label used
* @param args the arguments provided
*/
public Future<CommandResult> onCommand(Sender sender, String label, List<String> args) {
return executor.submit(() -> execute(sender, label, args));
}
@SuppressWarnings("unchecked")
private CommandResult execute(Sender sender, String label, List<String> args) {
// Handle no arguments
if (args.size() == 0) {
sendCommandUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Look for the main command.
Optional<BaseCommand> o = mainCommands.stream()
.filter(m -> m.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
// Main command not found
if (!o.isPresent()) {
sendCommandUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Check the Sender has permission to use the main command.
final Command main = o.get();
if (!main.isAuthorized(sender)) {
sendCommandUsage(sender, label);
return CommandResult.NO_PERMISSION;
}
List<String> arguments = new ArrayList<>(args);
handleRewrites(arguments);
arguments.remove(0); // remove the main command arg.
// Check the correct number of args were given for the main command
if (main.getArgumentCheck().test(arguments.size())) {
main.sendUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Try to execute the command.
CommandResult result;
try {
result = main.execute(plugin, sender, null, arguments, label);
} catch (CommandException e) {
result = handleException(e, sender, label, main);
} catch (Exception e) {
e.printStackTrace();
result = CommandResult.FAILURE;
}
return result;
}
/**
* Generic tab complete method to be called from the command executor object of the platform
*
* @param sender who is tab completing
* @param args the arguments provided so far
* @return a list of suggestions
*/
@SuppressWarnings("unchecked")
public List<String> onTabComplete(Sender sender, List<String> args) {
final List<Command> mains = mainCommands.stream()
.filter(m -> m.isAuthorized(sender))
.collect(Collectors.toList());
// Not yet past the point of entering a main command
if (args.size() <= 1) {
// Nothing yet entered
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return mains.stream()
.map(m -> m.getName().toLowerCase())
.collect(Collectors.toList());
}
// Started typing a main command
return mains.stream()
.map(m -> m.getName().toLowerCase())
.filter(s -> s.startsWith(args.get(0).toLowerCase()))
.collect(Collectors.toList());
}
// Find a main command matching the first arg
Optional<Command> o = mains.stream()
.filter(m -> m.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
if (!o.isPresent()) {
return Collections.emptyList();
}
// Pass the processing onto the main command
return o.get().tabComplete(plugin, sender, args.subList(1, args.size()));
}
private void sendCommandUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&2Running &bLuckPerms v" + plugin.getVersion() + "&2.");
mainCommands.stream()
.filter(c -> c.isAuthorized(sender))
.forEach(c -> {
@SuppressWarnings("unchecked")
String permission = (String) c.getPermission().map(p -> ((Permission) p).getExample()).orElse("None");
FancyMessage msg = new FancyMessage("> ").color(ChatColor.getByChar('3')).then().text(String.format(c.getUsage(), label)).color(ChatColor.getByChar('a'))
.formattedTooltip(
new FancyMessage("Command: ").color(ChatColor.getByChar('b')).then().text(c.getName()).color(ChatColor.getByChar('2')),
new FancyMessage("Description: ").color(ChatColor.getByChar('b')).then().text(c.getDescription()).color(ChatColor.getByChar('2')),
new FancyMessage("Usage: ").color(ChatColor.getByChar('b')).then().text(String.format(c.getUsage(), label)).color(ChatColor.getByChar('2')),
new FancyMessage("Permission: ").color(ChatColor.getByChar('b')).then().text(permission).color(ChatColor.getByChar('2')),
new FancyMessage(" "),
new FancyMessage("Click to auto-complete.").color(ChatColor.getByChar('7'))
)
.suggest(String.format(c.getUsage(), label));
sender.sendMessage(msg);
});
}
public static CommandResult handleException(CommandException e, Sender sender, String label, Command command) {
if (e instanceof ArgumentUtils.ArgumentException) {
if (e instanceof ArgumentUtils.DetailedUsageException) {
@@ -223,165 +394,4 @@ public class CommandManager {
}
}
}
@Getter
private final LuckPermsPlugin plugin;
@Getter
private final List<BaseCommand> mainCommands;
public CommandManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
ImmutableList.Builder<BaseCommand> l = ImmutableList.builder();
l.add(new UserMainCommand())
.add(new GroupMainCommand())
.add(new TrackMainCommand())
.addAll(plugin.getExtraCommands())
.add(new LogMainCommand())
.add(new SyncCommand())
.add(new NetworkSyncCommand())
.add(new InfoCommand())
.add(new VerboseCommand())
.add(new ImportCommand())
.add(new ExportCommand())
.add(new QueueCommand())
.add(new MigrationMainCommand())
.add(new UsersBulkEditMainCommand())
.add(new CreateGroup())
.add(new DeleteGroup())
.add(new ListGroups())
.add(new CreateTrack())
.add(new DeleteTrack())
.add(new ListTracks());
mainCommands = l.build();
}
/**
* Generic on command method to be called from the command executor object of the platform
* Unlike {@link #onCommand(Sender, String, List)}, this method is called in a new thread
*
* @param sender who sent the command
* @param label the command label used
* @param args the arguments provided
* @param result the callback to be called when the command has fully executed
*/
public void onCommand(Sender sender, String label, List<String> args, Consumer<CommandResult> result) {
plugin.doAsync(() -> {
CommandResult r = onCommand(sender, label, args);
if (result != null) {
plugin.doSync(() -> result.accept(r));
}
});
}
/**
* Generic on command method to be called from the command executor object of the platform
*
* @param sender who sent the command
* @param label the command label used
* @param args the arguments provided
* @return if the command was successful
*/
@SuppressWarnings("unchecked")
public CommandResult onCommand(Sender sender, String label, List<String> args) {
// Handle no arguments
if (args.size() == 0) {
sendCommandUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Look for the main command.
Optional<BaseCommand> o = mainCommands.stream()
.filter(m -> m.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
// Main command not found
if (!o.isPresent()) {
sendCommandUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Check the Sender has permission to use the main command.
final Command main = o.get();
if (!main.isAuthorized(sender)) {
sendCommandUsage(sender, label);
return CommandResult.NO_PERMISSION;
}
List<String> arguments = new ArrayList<>(args);
handleRewrites(arguments);
arguments.remove(0); // remove the main command arg.
// Check the correct number of args were given for the main command
if (main.getArgumentCheck().test(arguments.size())) {
main.sendUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Try to execute the command.
CommandResult result;
try {
result = main.execute(plugin, sender, null, arguments, label);
} catch (CommandException e) {
result = handleException(e, sender, label, main);
} catch (Exception e) {
e.printStackTrace();
result = CommandResult.FAILURE;
}
return result;
}
/**
* Generic tab complete method to be called from the command executor object of the platform
*
* @param sender who is tab completing
* @param args the arguments provided so far
* @return a list of suggestions
*/
@SuppressWarnings("unchecked")
public List<String> onTabComplete(Sender sender, List<String> args) {
final List<Command> mains = mainCommands.stream()
.filter(m -> m.isAuthorized(sender))
.collect(Collectors.toList());
// Not yet past the point of entering a main command
if (args.size() <= 1) {
// Nothing yet entered
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return mains.stream()
.map(m -> m.getName().toLowerCase())
.collect(Collectors.toList());
}
// Started typing a main command
return mains.stream()
.map(m -> m.getName().toLowerCase())
.filter(s -> s.startsWith(args.get(0).toLowerCase()))
.collect(Collectors.toList());
}
// Find a main command matching the first arg
Optional<Command> o = mains.stream()
.filter(m -> m.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
if (!o.isPresent()) {
return Collections.emptyList();
}
// Pass the processing onto the main command
return o.get().tabComplete(plugin, sender, args.subList(1, args.size()));
}
private void sendCommandUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&2Running &bLuckPerms v" + plugin.getVersion() + "&2.");
mainCommands.stream()
.filter(c -> c.isAuthorized(sender))
.forEach(c -> Util.sendPluginMessage(sender, "&3> &a" + String.format(c.getUsage(), label)));
}
}
@@ -122,7 +122,7 @@ public class SharedMainCommand<T extends PermissionHolder> extends SubCommand<T>
CommandResult result;
try {
result = sub.execute(plugin, sender, t, strippedArgs);
result = sub.execute(plugin, sender, t, strippedArgs, label);
} catch (CommandException e) {
result = handleException(e, sender, sub);
}
@@ -82,7 +82,7 @@ public abstract class SharedSubCommand {
private final Predicate<? super Integer> isArgumentInvalid;
private final ImmutableList<Arg> args;
public abstract CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException;
public abstract CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException;
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
return Collections.emptyList();
@@ -55,9 +55,9 @@ public class MetaAddPrefix extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String prefix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String prefix = ArgumentUtils.handleString(1, args);
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
@@ -55,9 +55,9 @@ public class MetaAddSuffix extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String suffix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String suffix = ArgumentUtils.handleString(1, args);
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
@@ -57,9 +57,9 @@ public class MetaAddTempPrefix extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String prefix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String prefix = ArgumentUtils.handleString(1, args);
long duration = ArgumentUtils.handleDuration(2, args);
String server = ArgumentUtils.handleServer(3, args);
String world = ArgumentUtils.handleWorld(4, args);
@@ -57,9 +57,9 @@ public class MetaAddTempSuffix extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String suffix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String suffix = ArgumentUtils.handleString(1, args);
long duration = ArgumentUtils.handleDuration(2, args);
String server = ArgumentUtils.handleServer(3, args);
String world = ArgumentUtils.handleWorld(4, args);
@@ -50,7 +50,7 @@ public class MetaClear extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
int before = holder.getNodes().size();
String server = ArgumentUtils.handleServer(0, args);
@@ -54,7 +54,7 @@ public class MetaInfo extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
SortedSet<Map.Entry<Integer, LocalizedNode>> prefixes = new TreeSet<>(Util.META_COMPARATOR.reversed());
SortedSet<Map.Entry<Integer, LocalizedNode>> suffixes = new TreeSet<>(Util.META_COMPARATOR.reversed());
Set<LocalizedNode> meta = new HashSet<>();
@@ -46,10 +46,10 @@ import java.util.stream.Collectors;
public class MetaRemovePrefix extends SharedSubCommand {
public MetaRemovePrefix() {
super("removeprefix", "Removes a prefix", Permission.USER_META_REMOVEPREFIX, Permission.GROUP_META_REMOVEPREFIX,
Predicates.notInRange(2, 4),
Predicates.notInRange(1, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
Arg.create("prefix", true, "the prefix string"),
Arg.create("prefix", false, "the prefix string"),
Arg.create("server", false, "the server to add the prefix on"),
Arg.create("world", false, "the world to add the prefix on")
)
@@ -57,9 +57,9 @@ public class MetaRemovePrefix extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String prefix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String prefix = ArgumentUtils.handleStringOrElse(1, args, "null");
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
@@ -46,10 +46,10 @@ import java.util.stream.Collectors;
public class MetaRemoveSuffix extends SharedSubCommand {
public MetaRemoveSuffix() {
super("removesuffix", "Removes a suffix", Permission.USER_META_REMOVESUFFIX, Permission.GROUP_META_REMOVESUFFIX,
Predicates.notInRange(2, 4),
Predicates.notInRange(1, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
Arg.create("suffix", true, "the suffix string"),
Arg.create("suffix", false, "the suffix string"),
Arg.create("server", false, "the server to add the suffix on"),
Arg.create("world", false, "the world to add the suffix on")
)
@@ -57,9 +57,9 @@ public class MetaRemoveSuffix extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String suffix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String suffix = ArgumentUtils.handleStringOrElse(1, args, "null");
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
@@ -45,10 +45,11 @@ import java.util.stream.Collectors;
public class MetaRemoveTempPrefix extends SharedSubCommand {
public MetaRemoveTempPrefix() {
super("removetempprefix", "Removes a temporary prefix", Permission.USER_META_REMOVETEMP_PREFIX, Permission.GROUP_META_REMOVETEMP_PREFIX, Predicates.notInRange(2, 4),
super("removetempprefix", "Removes a temporary prefix", Permission.USER_META_REMOVETEMP_PREFIX, Permission.GROUP_META_REMOVETEMP_PREFIX,
Predicates.notInRange(1, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
Arg.create("prefix", true, "the prefix string"),
Arg.create("prefix", false, "the prefix string"),
Arg.create("server", false, "the server to add the prefix on"),
Arg.create("world", false, "the world to add the prefix on")
)
@@ -56,9 +57,9 @@ public class MetaRemoveTempPrefix extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String prefix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String prefix = ArgumentUtils.handleStringOrElse(1, args, "null");
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
@@ -90,8 +91,7 @@ public class MetaRemoveTempPrefix extends SharedSubCommand {
toRemove.forEach(n -> {
try {
holder.unsetPermission(n);
} catch (ObjectLacksException ignored) {
}
} catch (ObjectLacksException ignored) {}
});
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
@@ -45,10 +45,11 @@ import java.util.stream.Collectors;
public class MetaRemoveTempSuffix extends SharedSubCommand {
public MetaRemoveTempSuffix() {
super("removetempsuffix", "Removes a temporary suffix", Permission.USER_META_REMOVETEMP_SUFFIX, Permission.GROUP_META_REMOVETEMP_SUFFIX, Predicates.notInRange(2, 4),
super("removetempsuffix", "Removes a temporary suffix", Permission.USER_META_REMOVETEMP_SUFFIX, Permission.GROUP_META_REMOVETEMP_SUFFIX,
Predicates.notInRange(1, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
Arg.create("suffix", true, "the suffix string"),
Arg.create("suffix", false, "the suffix string"),
Arg.create("server", false, "the server to add the suffix on"),
Arg.create("world", false, "the world to add the suffix on")
)
@@ -56,9 +57,9 @@ public class MetaRemoveTempSuffix extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String suffix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String suffix = ArgumentUtils.handleStringOrElse(1, args, "null");
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
@@ -55,7 +55,7 @@ public class MetaSet extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
String key = args.get(0);
String value = args.get(1);
@@ -57,7 +57,7 @@ public class MetaSetTemp extends SharedSubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args, String label) throws CommandException {
String key = args.get(0);
String value = args.get(1);
long duration = ArgumentUtils.handleDuration(2, args);
Loaded 100 of 227 files, more files were not shown because too many files have changed in this diff. Show more