Compare commits

...
68 Commits
Author SHA1 Message Date
Luck 563dd4683d Changes for & release of API 2.14 2016-11-12 14:10:42 +00:00
Luck e9131f729a add methods for older sponge api versions 2016-11-11 22:54:09 +00:00
Luck c4ea626e33 Fix PM migration 2016-11-11 20:43:05 +00:00
Luck fefba7976b Actually register new migration command 2016-11-11 20:35:11 +00:00
Luck 2ce8555692 Add Sponge PermissionManager migration support 2016-11-11 20:31:42 +00:00
Luck 9fe9c386bb Sponge: rely less on dummy subjects 2016-11-11 19:32:25 +00:00
Luck e8cd2c7548 More command refactors 2016-11-10 22:13:53 +00:00
Luck 158d8b086a Command refactor 2016-11-10 19:19:43 +00:00
Luck 1c534d7475 More cleanup 2016-11-08 20:46:29 +00:00
Luck 90f8dbe243 Refactor commands 2016-11-07 22:02:48 +00:00
Luck 0c33b26fa9 Refactor meta accumulation 2016-11-07 19:01:15 +00:00
Luck d320679f69 Implement proper meta inheritance handling 2016-11-07 17:32:17 +00:00
Luck 8d5398b5a3 Make nodes with more contexts take priority over nodes with less 2016-11-06 16:15:45 +00:00
Luck 6cd8593fa5 Fix vault primary group override feature 2016-11-06 15:11:28 +00:00
Luck 5ebbc178a5 Remove messenger system & more cleanup 2016-11-06 14:56:13 +00:00
Luck 4f6e229943 Small cleanup 2016-11-05 23:23:08 +00:00
Luck 3e846d9527 Maybe fix split storage - closes #38 2016-11-05 21:43:48 +00:00
Luck 981d745b74 Fix verbose system 2016-11-05 19:19:29 +00:00
Luck 2dd0858960 Allow multiple verbose filters 2016-11-05 19:01:06 +00:00
Luck f72819a664 Try to reduce contention in PermissionHolder 2016-11-05 17:49:52 +00:00
Luck 5361b1e87b Implement group weights 2016-11-05 09:04:26 +00:00
Luck e15d03ed4e Fix parents being cleared on promote/demote 2016-11-05 07:53:18 +00:00
Luck 6c9041ce40 Improve meta info command 2016-11-04 19:13:39 +00:00
Luck 8da96e6e48 Re-add showtracks/showpos commands 2016-11-04 18:36:32 +00:00
Luck 385aa6d438 Add set "none" command as an alternative to unset 2016-11-04 16:40:55 +00:00
Luck 79f24a5944 Improve track functionality. Resolves #39 2016-11-01 21:34:54 +00:00
Luck 80570717f9 Fix slow datastore performance when using the API 2016-11-01 19:41:40 +00:00
Luck ebab79c4ca Maybe fix blocking issue with #getPermissions 2016-11-01 19:38:08 +00:00
Luck 42882ebe11 Update some ugly messages 2016-10-31 22:25:42 +00:00
Luck d2de26f765 Move hasperm/inheritsperm commands & add parent set command. Resolves #40 2016-10-31 19:27:04 +00:00
Luck e2cebfbd16 Refactor Node class 2016-10-31 18:18:31 +00:00
Luck a58cc6bdf3 Refactor PermissionHolder 2016-10-30 21:29:14 +00:00
Luck 36bc1553c0 Implement Sponge timings 2016-10-30 19:35:11 +00:00
Luck 17b06c39e9 Ignore negated primary group override nodes & fix broken message 2016-10-30 15:29:55 +00:00
Luck ba2f6eb7be Update .gitignore 2016-10-30 13:37:25 +00:00
Luck b93145f26d Change some listener priorities 2016-10-30 13:23:45 +00:00
Luck e88ea9c13d Don't fully unload Sponge user subjects 2016-10-30 13:21:43 +00:00
Luck 1275d0023d Listen to PlayerQuit on monitor priority 2016-10-29 22:58:06 +01:00
Luck 27f6f225c9 whoops 2016-10-29 21:56:55 +01:00
Luck 41362aa34a Use a temporary executor until the bukkit one has started 2016-10-29 21:54:13 +01:00
Luck a99609e016 Don't wrap buffer tasks in scheduler calls 2016-10-29 21:23:30 +01:00
Luck c0ea2d8ec3 Fix data not being loaded sync when the plugin starts 2016-10-29 21:14:59 +01:00
Luck bb6b31d715 change Sponge listener priorities 2016-10-29 21:12:55 +01:00
Luck 21695dd2cb Implement support for Bukkit child permissions 2016-10-28 19:16:32 +01:00
Luck 531835c948 Fix GroupManager primary group migration 2016-10-28 18:00:18 +01:00
Luck 77e3b351fd Fix GroupManager user migration 2016-10-28 17:58:36 +01:00
Luck 66f756575a Remove redundant config option 2016-10-27 18:48:38 +01:00
Luck 7acc8bc7ed Add verbose command 2016-10-27 17:46:44 +01:00
Luck 0a4d337a53 Cache context lookups & refactor Sponge subjects 2016-10-27 16:32:14 +01:00
Luck 0198068a13 Improve permission lookup speed (slightly) 2016-10-26 21:35:44 +01:00
Luck 1c15f8462f Don't run commands through the buffer system 2016-10-26 19:52:03 +01:00
Luck 3929ce0dfc Fix compile 2016-10-26 19:32:41 +01:00
Luck 7deeaf305d Experimental: Run I/O after commands in a new thread 2016-10-26 17:55:38 +01:00
Luck 0f04c06e13 Remove redundant method 2016-10-26 17:19:56 +01:00
Luck d1863fa714 Implement more customizable primary groups 2016-10-26 17:19:33 +01:00
Luck 46b122a167 Fix memory leak preventing users from being unloaded 2016-10-25 18:44:11 +01:00
Luck ee3db1e5c5 Maybe fix GroupManager primary group migration 2016-10-25 15:02:49 +01:00
Luck bd830617c9 Small cleanup 2016-10-25 11:14:56 +01:00
Luck a9b6493091 A few small optimizations 2016-10-24 18:48:39 +01:00
Luck 9894e45516 Fix issue with Vault lookups not being preprocessed 2016-10-24 15:57:05 +01:00
Luck 2cfc82f3aa Implement support for instant data propagation with Redis 2016-10-24 14:38:12 +01:00
Luck bb9eab0989 Lower sync wait buffer & fix export command 2016-10-24 13:02:26 +01:00
Luck dc87ec1c82 Update placeholder expansion 2016-10-24 09:57:29 +01:00
Luck 98b7b65ce7 Remove PEX dependency 2016-10-24 09:22:53 +01:00
Luck 9f8f32b33e Fix suffixes not being applied 2016-10-23 22:02:48 +01:00
Luck a80ec6d893 Implement PermissionsEx 2.0 migration for Sponge 2016-10-23 20:42:58 +01:00
Luck 4d85930f5a Refactor migration classes 2016-10-23 20:42:25 +01:00
Luck f722f4112d Update default-lang.yml 2016-10-23 17:59:34 +01:00
238 changed files with 7831 additions and 5545 deletions

No files matched your search

+151 -24
View File
@@ -1,31 +1,27 @@
# built application files
*.jar
# Created by https://www.gitignore.io/
# Java class files
*.class
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# Local configuration file (sdk path, etc)
logs/
# Eclipse project files
.classpath
.project
# Intellij project files
*.iml
*.ipr
*.iws
# User-specific stuff:
.idea/
*.iws
/out/
*.iml
.idea_modules/
# Gradle
.gradletasknamecache
.gradle/
build/
bin/
gradle/
gradlew*
# JIRA plugin
atlassian-ide-plugin.xml
# Maven
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
@@ -34,4 +30,135 @@ pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/timing.properties
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### Java ###
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version>
<version>2.14-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -29,226 +29,50 @@ import java.util.UUID;
/**
* Interface for the internal Datastore instance
* @deprecated as of version 2.14 in favour of {@link Storage}.
*/
@SuppressWarnings("unused")
@Deprecated
public interface Datastore {
String getName();
boolean isAcceptingLogins();
/**
* Gets the {@link Sync} interface.
*
* All operations through this interface are called immediately and in the same thread as they are called.
* Datastore operations are thread blocking, and Sync operations should not be called on the main server thread.
* @return the sync interface
*/
@Deprecated
Sync sync();
/**
* Gets the {@link Async} interface.
*
* All operations through this interface are called in a new, separate asynchronous thread.
* When the operation is complete, the provided callback method is called, in applicable, in the main server thread.
* @return the async interface
*/
@Deprecated
Async async();
/**
* Gets the {@link Future} interface.
*
* All operations through this interface are called in a new, separate asynchronous thread, similar to {@link Async}.
* The only difference is that instead of providing a callback, a {@link java.util.concurrent.Future} is returned.
* See the Oracle JavaDocs for usage of the Future class.
* @return the future interface
*/
@Deprecated
Future future();
/**
* All operations through this interface are called immediately and in the same thread as they are called.
* Datastore operations are thread blocking, and Sync operations should not be called on the main server thread.
*/
@Deprecated
interface Sync {
/**
* Saves an action to the datastore
* @param entry the log entry to be saved
* @return true if the operation completed successfully.
* @throws NullPointerException if entry is null
*/
boolean logAction(LogEntry entry);
/**
* Loads and returns the log from the datastore
* @return a log instance, could be null
*/
Log getLog();
/**
* Either loads or creates a user object, and loads it into the plugins internal storage
* @param uuid the uuid of the user
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
* @return true if the operation completed successfully.
* @throws NullPointerException if uuid or username is null
* @throws IllegalArgumentException if either of the parameters are invalid
* @deprecated functionality of this method is taken on by {@link #loadUser(UUID, String)}
*/
@Deprecated
boolean loadOrCreateUser(UUID uuid, String username);
/**
* Loads a user from the datastore into the plugins internal storage.
* @param uuid the uuid of the user to load
* @return true if the user exists, and was loaded correctly.
* @throws NullPointerException if uuid is null
* @deprecated replaced by {@link #loadUser(UUID, String)}
*/
@Deprecated
boolean loadUser(UUID uuid);
/**
* Loads a user's data into the plugins internal storage.
* @param uuid the uuid of the user to load
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
* @return if the operation was performed successfully
* @throws NullPointerException if uuid or username is null
* @since 2.6
*/
boolean loadUser(UUID uuid, String username);
/**
* Saves a user object into the datastore. You should call this after you make any changes to a user.
* @param user the user to save
* @return true if the operation completed successfully.
* @throws NullPointerException if user is null
* @throws IllegalStateException if the user instance was not obtained from LuckPerms.
*/
boolean saveUser(User user);
/**
* Removes users from the datastore who are "default". This is called every time the plugin loads.
* @return true if the operation completed successfully
* @since 2.6
*/
boolean cleanupUsers();
/**
* Gets a set all user's UUIDs who are "unique", and aren't just a member of the "default" group.
* @return a set of uuids, or null if the operation failed.
* @since 2.6
*/
Set<UUID> getUniqueUsers();
/**
* Creates and loads a group into the plugins internal storage
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean createAndLoadGroup(String name);
/**
* Loads a group into the plugins internal storage.
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean loadGroup(String name);
/**
* Loads all groups from the datastore into the plugins internal storage
* @return true if the operation completed successfully.
*/
boolean loadAllGroups();
/**
* Saves a group back to the datastore. You should call this after you make any changes to a group.
* @param group the group to save
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
boolean saveGroup(Group group);
/**
* Permanently deletes a group from the datastore
* @param group the group to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
boolean deleteGroup(Group group);
/**
* Creates and loads a track into the plugins internal storage
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean createAndLoadTrack(String name);
/**
* Loads a track into the plugins internal storage.
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean loadTrack(String name);
/**
* Loads all tracks from the datastore into the plugins internal storage
* @return true if the operation completed successfully.
*/
boolean loadAllTracks();
/**
* Saves a track back to the datastore. You should call this after you make any changes to a track.
* @param track the track to save
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
*/
boolean saveTrack(Track track);
/**
* Permanently deletes a track from the datastore
* @param track the track to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
*/
boolean deleteTrack(Track track);
/**
* Saves UUID caching data to the datastore
* @param username the users username
* @param uuid the users mojang unique id
* @return true if the operation completed successfully.
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
*/
boolean saveUUIDData(String username, UUID uuid);
/**
* Gets a UUID from a username
* @param username the corresponding username
* @return a uuid object, could be null
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
*/
UUID getUUID(String username);
}
/**
* All operations through this interface are called in a new, separate asynchronous thread.
* When the operation is complete, the provided callback method is called, in applicable, in the main server thread.
*
* See {@link Sync} for method documentation.
*/
@Deprecated
interface Async {
void logAction(LogEntry entry, Callback<Boolean> callback);
void getLog(Callback<Log> callback);
@@ -274,13 +98,7 @@ public interface Datastore {
void getUUID(String username, Callback<UUID> callback);
}
/**
* All operations through this interface are called in a new, separate asynchronous thread, similar to {@link Async}.
* The only difference is that instead of providing a callback, a {@link java.util.concurrent.Future} is returned.
* See the Oracle JavaDocs for usage of the Future class.
*
* See {@link Sync} for method documentation.
*/
@Deprecated
interface Future {
java.util.concurrent.Future<Boolean> logAction(LogEntry entry);
java.util.concurrent.Future<Log> getLog();
@@ -109,7 +109,9 @@ public interface LPConfiguration {
/**
* @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.
*/
@Deprecated
boolean getDebugPermissionChecks();
/**
@@ -79,11 +79,27 @@ public interface LuckPermsApi {
LPConfiguration getConfiguration();
/**
* Gets a wrapped {@link Datastore} instance, with somewhat limited access
* @return a datastore instance
* Gets a wrapped {@link Storage} instance.
* @return a storage instance
* @since 2.14
*/
Storage getStorage();
/**
* Gets a wrapped Datastore instance.
* @return a datastore instance
* @deprecated in favour of {@link #getStorage()}
*/
@SuppressWarnings("deprecation")
@Deprecated
Datastore getDatastore();
/**
* Gets the messaging service in use on the platform, if present.
* @return an optional that may contain a messaging service instance.
*/
Optional<MessagingService> getMessagingService();
/**
* Gets the {@link Logger} wrapping used by the platform
* @return the logger instance
@@ -92,7 +108,7 @@ public interface LuckPermsApi {
/**
* Gets a wrapped {@link UuidCache} instance, providing read access to the LuckPerms internal uuid caching system
* @return a uuidcache instance
* @return a uuid cache instance
*/
UuidCache getUuidCache();
@@ -0,0 +1,37 @@
/*
* 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;
/**
* Exposes any networking provider being used on the platform. e.g. Redis
* @since 2.14
*/
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.
*/
void pushUpdate();
}
@@ -0,0 +1,217 @@
/*
* 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 java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* Interface for the internal Storage instance
*
* 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 blocked.
*
* Methods such as {@link CompletableFuture#get()} and equivalent should <strong>not</strong> be called on the main server thread.
* If you need to use the result of these operations on the main server thread, please register a callback using
* {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)} and {@link #getSyncExecutor()}.
*
* @since 2.14
*/
public interface Storage {
/**
* Get the name of the storage implementation.
* @return the name of the implementation
*/
String getName();
/**
* Return whether the storage instance is allowing logins on the platform.
* @return true if logins are enabled
*/
boolean isAcceptingLogins();
/**
* Returns an executor which will run all passed runnables on the main server thread.
* @return an executor instance
*/
Executor getSyncExecutor();
/**
* Returns an executor which will run all passed runnables asynchronously using the platforms scheduler & thread pools.
* @return an executor instance
*/
Executor getAsyncExecutor();
/**
* Saves an action to storage
* @param entry the log entry to be saved
* @return true if the operation completed successfully.
* @throws NullPointerException if entry is null
*/
CompletableFuture<Boolean> logAction(LogEntry entry);
/**
* Loads and returns the entire log from storage
* @return a log instance, could be null if loading failed
*/
CompletableFuture<Log> getLog();
/**
* Loads a user's data from the main storage into the plugins local storage.
* @param uuid the uuid of the user to load
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
* @return if the operation completed successfully
* @throws NullPointerException if uuid or username is null
*/
CompletableFuture<Boolean> loadUser(UUID uuid, String username);
/**
* Saves a user object back to storage. You should call this after you make any changes to a user.
* @param user the user to save
* @return true if the operation completed successfully.
* @throws NullPointerException if user is null
* @throws IllegalStateException if the user instance was not obtained from LuckPerms.
*/
CompletableFuture<Boolean> saveUser(User user);
/**
* Removes users from the main storage who are "default". This is called every time the plugin loads.
* @return true if the operation completed successfully
*/
CompletableFuture<Boolean> cleanupUsers();
/**
* Gets a set all "unique" user UUIDs.
* "Unique" meaning the user isn't just a member of the "default" group.
* @return a set of uuids, or null if the operation failed.
*/
CompletableFuture<Set<UUID>> getUniqueUsers();
/**
* Creates and loads a group into the plugins local storage
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
CompletableFuture<Boolean> createAndLoadGroup(String name);
/**
* Loads a group into the plugins local storage.
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
CompletableFuture<Boolean> loadGroup(String name);
/**
* Loads all groups from the storage into memory
* @return true if the operation completed successfully.
*/
CompletableFuture<Boolean> loadAllGroups();
/**
* Saves a group back to storage. You should call this after you make any changes to a group.
* @param group the group to save
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
CompletableFuture<Boolean> saveGroup(Group group);
/**
* Permanently deletes a group from storage.
* @param group the group to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
CompletableFuture<Boolean> deleteGroup(Group group);
/**
* Creates and loads a track into the plugins local storage
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
CompletableFuture<Boolean> createAndLoadTrack(String name);
/**
* Loads a track into the plugins local storage.
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
CompletableFuture<Boolean> loadTrack(String name);
/**
* Loads all tracks from the storage into memory
* @return true if the operation completed successfully.
*/
CompletableFuture<Boolean> loadAllTracks();
/**
* Saves a track back to storage. You should call this after you make any changes to a track.
* @param track the track to save
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
*/
CompletableFuture<Boolean> saveTrack(Track track);
/**
* Permanently deletes a track from storage
* @param track the track to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
*/
CompletableFuture<Boolean> deleteTrack(Track track);
/**
* Saves UUID caching data to the global cache
* @param username the users username
* @param uuid the users mojang unique id
* @return true if the operation completed successfully.
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
*/
CompletableFuture<Boolean> saveUUIDData(String username, UUID uuid);
/**
* Gets a UUID from a username
* @param username the corresponding username
* @return a uuid object, could be null
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
*/
CompletableFuture<UUID> getUUID(String username);
}
@@ -32,8 +32,8 @@ import java.util.UUID;
* 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 datastore using the api on a server in offline mode, you will need to use this cache,
* OR use Datastore#getUUID, for users that are not online.
* <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.
*/
@@ -303,4 +303,9 @@ public class ContextSet {
public int hashCode() {
return 59 + (this.contexts == null ? 43 : this.contexts.hashCode());
}
@Override
public String toString() {
return "ContextSet(contexts=" + this.contexts + ")";
}
}
@@ -28,7 +28,9 @@ import java.util.function.Consumer;
* A callback used to wait for the completion of asynchronous operations.
* All callbacks are ran on the main server thread.
* @param <T> the return type
* @deprecated in favour of {@link Consumer}
*/
@Deprecated
public interface Callback<T> {
/**
@@ -55,4 +57,17 @@ public interface Callback<T> {
return consumer::accept;
}
/**
* Helper method for converting old {@link Callback}s to use the new {@link me.lucko.luckperms.api.Storage} interface.
* @param callback the callback to convert
* @param <T> the return type
* @return a consumer instance
* @since 2.14
* @deprecated in favour of just using {@link Consumer}s.
*/
@Deprecated
static <T> Consumer<T> convertToConsumer(Callback<T> callback) {
return callback::onComplete;
}
}
+13 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version>
<version>2.14-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -75,6 +75,18 @@
<pattern>com.google.gson</pattern>
<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>
</relocation>
</relocations>
</configuration>
</execution>
+2 -2
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version>
<version>2.14-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -30,7 +30,7 @@
<dependency>
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId>
<version>2.8</version>
<version>2.13-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- BukkitAPI -->
@@ -26,16 +26,20 @@ import me.clip.placeholderapi.PlaceholderAPIPlugin;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import me.clip.placeholderapi.util.TimeUtil;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.api.context.MutableContextSet;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.Optional;
import java.util.stream.Collectors;
/*
* PlaceholderAPI Expansion for LuckPerms, implemented using the LuckPerms API.
*
* Placeholders:
* - group_name
* - groups
* - has_permission_<node>
* - inherits_permission_<node>
* - in_group_<name>
@@ -71,7 +75,14 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
@Override
public String getVersion() {
return "2.8";
return "2.13";
}
private Contexts makeContexts(Player player) {
MutableContextSet contextSet = new MutableContextSet();
contextSet.add("server", api.getConfiguration().getVaultServer());
contextSet.add("world", player.getWorld().getName());// ignore world?
return Contexts.of(contextSet.makeImmutable(), api.getConfiguration().getVaultIncludeGlobal(), true, true, true, true, player.isOp());
}
@Override
@@ -84,14 +95,24 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
if (!u.isPresent()) {
return "";
}
final User user = u.get();
Optional<UserData> d = user.getUserDataCache();
if (!d.isPresent()) {
return "";
}
final UserData data = d.get();
identifier = identifier.toLowerCase();
final User user = u.get();
if (identifier.equalsIgnoreCase("group_name")) {
return user.getPrimaryGroup();
}
if (identifier.equalsIgnoreCase("groups")) {
return user.getGroupNames().stream().collect(Collectors.joining(", "));
}
if (identifier.startsWith("has_permission_") && identifier.length() > "has_permission_".length()) {
String node = identifier.substring("has_permission_".length());
return formatBoolean(user.hasPermission(node, true));
@@ -99,7 +120,7 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
if (identifier.startsWith("inherits_permission_") && identifier.length() > "inherits_permission_".length()) {
String node = identifier.substring("inherits_permission_".length());
return formatBoolean(user.inheritsPermission(node, true));
return formatBoolean(data.getPermissionData(makeContexts(player)).getPermissionValue(node).asBoolean());
}
if (identifier.startsWith("in_group_") && identifier.length() > "in_group_".length()) {
@@ -109,7 +130,7 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
if (identifier.startsWith("inherits_group_") && identifier.length() > "inherits_group_".length()) {
String groupName = identifier.substring("inherits_group_".length());
return formatBoolean(user.getLocalGroups("global").contains(groupName));
return formatBoolean(data.getPermissionData(makeContexts(player)).getPermissionValue("group." + groupName).asBoolean());
}
if (identifier.startsWith("on_track_") && identifier.length() > "on_track_".length()) {
@@ -125,7 +146,7 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
String node = identifier.substring("expiry_time_".length());
long currentTime = System.currentTimeMillis() / 1000L;
for (Node n : user.getTemporaryPermissionNodes()) {
if (n.getPermission().equalsIgnoreCase(node)) {
if (n.toSerializedNode().equalsIgnoreCase(node)) {
return TimeUtil.getTime((int) (n.getExpiryUnixTime() - currentTime));
}
}
@@ -146,16 +167,28 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
}
if (identifier.equalsIgnoreCase("prefix")) {
return MetaUtils.getPrefix(user, null, null, true);
String prefix = data.calculateMeta(makeContexts(player)).getPrefix();
if (prefix == null) {
prefix = "";
}
return prefix;
}
if (identifier.equalsIgnoreCase("suffix")) {
return MetaUtils.getSuffix(user, null, null, true);
String suffix = data.calculateMeta(makeContexts(player)).getSuffix();
if (suffix == null) {
suffix = "";
}
return suffix;
}
if (identifier.startsWith("meta_") && identifier.length() > "meta_".length()) {
String node = identifier.substring("meta_".length());
return MetaUtils.getMeta(user, null, null, node, "", true);
String meta = data.getMetaData(makeContexts(player)).getMeta().get(node);
if (meta == null) {
meta = "";
}
return meta;
}
return null;
+54 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version>
<version>2.14-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -70,6 +70,18 @@
<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>
</relocation>
</relocations>
</configuration>
</execution>
@@ -129,5 +141,46 @@
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
<!-- **************Migration Plugins************** -->
<dependency>
<groupId>org.tyrannyofheaven.bukkit</groupId>
<artifactId>zPermissions</artifactId>
<version>1.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ru.tehkode</groupId>
<artifactId>PermissionsEx</artifactId>
<version>1.23</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
</exclusion>
<exclusion>
<groupId>net.gravitydevelopment.updater</groupId>
<artifactId>updater</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.cheesesoftware</groupId>
<artifactId>PowerfulPermsAPI</artifactId>
<version>1.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.anjocaido</groupId>
<artifactId>GroupManager</artifactId>
<version>1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.bananaco</groupId>
<artifactId>bpermissions-api</artifactId>
<version>2.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -22,18 +22,17 @@
package me.lucko.luckperms.bukkit;
import com.google.common.collect.ImmutableList;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.bukkit.calculators.AttachmentProcessor;
import me.lucko.luckperms.bukkit.calculators.ChildProcessor;
import me.lucko.luckperms.bukkit.calculators.DefaultsProcessor;
import me.lucko.luckperms.bukkit.inject.Injector;
import me.lucko.luckperms.bukkit.inject.LPPermissible;
import me.lucko.luckperms.common.calculators.*;
import me.lucko.luckperms.common.users.User;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@AllArgsConstructor
@@ -41,23 +40,24 @@ public class BukkitCalculatorFactory implements CalculatorFactory {
private final LPBukkitPlugin plugin;
@Override
public PermissionCalculator build(Contexts contexts, User user, Map<String, Boolean> map) {
public PermissionCalculator build(Contexts contexts, User user) {
UUID uuid = plugin.getUuidCache().getExternalUUID(user.getUuid());
List<PermissionProcessor> processors = new ArrayList<>(5);
processors.add(new MapProcessor(map));
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
processors.add(new MapProcessor());
processors.add(new ChildProcessor(plugin.getChildPermissionProvider()));
processors.add(new AttachmentProcessor(() -> {
LPPermissible permissible = Injector.getPermissible(uuid);
return permissible == null ? null : permissible.getAttachmentPermissions();
}));
if (plugin.getConfiguration().isApplyingWildcards()) {
processors.add(new WildcardProcessor(map));
processors.add(new WildcardProcessor());
}
if (plugin.getConfiguration().isApplyingRegex()) {
processors.add(new RegexProcessor(map));
processors.add(new RegexProcessor());
}
processors.add(new DefaultsProcessor(contexts.isOp(), plugin.getDefaultsProvider()));
return new PermissionCalculator(plugin, user.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors);
return new PermissionCalculator(plugin, user.getName(), processors.build());
}
}
@@ -25,9 +25,8 @@ package me.lucko.luckperms.bukkit;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandManager;
import me.lucko.luckperms.common.commands.Util;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Patterns;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@@ -38,14 +37,17 @@ import java.util.Arrays;
import java.util.List;
class BukkitCommand extends CommandManager implements CommandExecutor, TabExecutor {
BukkitCommand(LuckPermsPlugin plugin) {
private final LPBukkitPlugin plugin;
BukkitCommand(LPBukkitPlugin plugin) {
super(plugin);
this.plugin = plugin;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
onCommand(
BukkitSenderFactory.get(getPlugin()).wrap(sender),
plugin.getSenderFactory().wrap(sender),
label,
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
Callback.empty()
@@ -53,9 +55,8 @@ class BukkitCommand extends CommandManager implements CommandExecutor, TabExecut
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
return onTabComplete(BukkitSenderFactory.get(getPlugin()).wrap(sender), Arrays.asList(args));
return onTabComplete(plugin.getSenderFactory().wrap(sender), Arrays.asList(args));
}
}
@@ -48,7 +48,7 @@ class BukkitListener extends AbstractListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
if (!plugin.isStarted() || !plugin.getDatastore().isAcceptingLogins()) {
if (!plugin.isStarted() || !plugin.getStorage().isAcceptingLogins()) {
// The datastore is disabled, prevent players from joining the server
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
@@ -61,7 +61,7 @@ class BukkitListener extends AbstractListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerPreLoginMonitor(AsyncPlayerPreLoginEvent e) {
if (plugin.isStarted() && plugin.getDatastore().isAcceptingLogins() && e.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
if (plugin.isStarted() && plugin.getStorage().isAcceptingLogins() && e.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
// Login event was cancelled by another plugin
onLeave(e.getUniqueId());
@@ -106,7 +106,7 @@ class BukkitListener extends AbstractListener implements Listener {
}
}
@EventHandler(priority = EventPriority.HIGHEST) // Allow other plugins to see data when this event gets called.
@EventHandler(priority = EventPriority.MONITOR) // Allow other plugins to see data when this event gets called.
public void onPlayerQuit(PlayerQuitEvent e) {
final Player player = e.getPlayer();
final UUID internal = plugin.getUuidCache().getUUID(player.getUniqueId());
@@ -23,7 +23,7 @@
package me.lucko.luckperms.bukkit;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.SenderFactory;
import me.lucko.luckperms.common.commands.sender.SenderFactory;
import me.lucko.luckperms.common.constants.Constants;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -31,19 +31,10 @@ import org.bukkit.entity.Player;
import java.util.UUID;
public class BukkitSenderFactory extends SenderFactory<CommandSender> {
private static BukkitSenderFactory instance = null;
private BukkitSenderFactory(LuckPermsPlugin plugin) {
public BukkitSenderFactory(LuckPermsPlugin plugin) {
super(plugin);
}
public static synchronized BukkitSenderFactory get(LuckPermsPlugin plugin) {
if (instance == null) {
instance = new BukkitSenderFactory(plugin);
}
return instance;
}
@Override
protected String getName(CommandSender sender) {
if (sender instanceof Player) {
@@ -31,13 +31,14 @@ 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.calculators.ChildPermissionProvider;
import me.lucko.luckperms.bukkit.calculators.DefaultsProvider;
import me.lucko.luckperms.bukkit.vault.VaultHook;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.api.ApiProvider;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.commands.ConsecutiveExecutor;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.config.LPConfiguration;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.contexts.ContextManager;
@@ -45,13 +46,15 @@ import me.lucko.luckperms.common.contexts.ServerCalculator;
import me.lucko.luckperms.common.core.UuidCache;
import me.lucko.luckperms.common.data.Importer;
import me.lucko.luckperms.common.groups.GroupManager;
import me.lucko.luckperms.common.messaging.RedisMessaging;
import me.lucko.luckperms.common.runnables.ExpireTemporaryTask;
import me.lucko.luckperms.common.runnables.UpdateTask;
import me.lucko.luckperms.common.storage.Datastore;
import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.tracks.TrackManager;
import me.lucko.luckperms.common.users.UserManager;
import me.lucko.luckperms.common.utils.BufferedRequest;
import me.lucko.luckperms.common.utils.DebugHandler;
import me.lucko.luckperms.common.utils.LocaleManager;
import me.lucko.luckperms.common.utils.LogFactory;
import org.bukkit.World;
@@ -65,10 +68,16 @@ import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
@Getter
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private ExecutorService executorService;
private Executor syncExecutor;
private Executor asyncExecutor;
private VaultHook vaultHook = null;
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
@@ -76,27 +85,78 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private UserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
private Storage storage;
private RedisMessaging redisMessaging = null;
private UuidCache uuidCache;
private ApiProvider apiProvider;
private Logger log;
private Importer importer;
private ConsecutiveExecutor consecutiveExecutor;
private DefaultsProvider defaultsProvider;
private ChildPermissionProvider childPermissionProvider;
private LocaleManager localeManager;
private ContextManager<Player> contextManager;
private WorldCalculator worldCalculator;
private CalculatorFactory calculatorFactory;
private BufferedRequest<Void> updateTaskBuffer;
private boolean started = false;
private DebugHandler debugHandler;
private BukkitSenderFactory senderFactory;
@Override
public void onEnable() {
// Used whilst the server is still starting
executorService = Executors.newCachedThreadPool();
asyncExecutor = executorService;
syncExecutor = r -> getServer().getScheduler().runTask(this, r);
log = LogFactory.wrap(getLogger());
debugHandler = new DebugHandler();
senderFactory = new BukkitSenderFactory(this);
getLog().info("Loading configuration...");
configuration = new BukkitConfig(this);
// setup the Bukkit defaults hook
defaultsProvider = new DefaultsProvider();
childPermissionProvider = new ChildPermissionProvider();
// give all plugins a chance to load their defaults, then refresh.
getServer().getScheduler().runTaskLater(this, () -> {
defaultsProvider.refresh();
childPermissionProvider.setup();
}, 1L);
// register events
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new BukkitListener(this), this);
// initialise datastore
storage = StorageFactory.getInstance(this, "h2");
// initialise redis
if (getConfiguration().isRedisEnabled()) {
getLog().info("Loading redis...");
redisMessaging = new RedisMessaging(this);
try {
redisMessaging.init(getConfiguration().getRedisAddress(), getConfiguration().getRedisPassword());
getLog().info("Loaded redis successfully...");
} catch (Exception e) {
getLog().info("Couldn't load redis...");
e.printStackTrace();
}
}
// setup the update task buffer
updateTaskBuffer = new BufferedRequest<Void>(1000L, this::doAsync) {
@Override
protected Void perform() {
new UpdateTask(LPBukkitPlugin.this).run();
return null;
}
};
// load locale
localeManager = new LocaleManager();
File locale = new File(getDataFolder(), "lang.yml");
if (locale.exists()) {
@@ -108,13 +168,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
}
}
defaultsProvider = new DefaultsProvider();
getServer().getScheduler().runTaskLater(this, () -> defaultsProvider.refresh(), 1L);
// register events
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new BukkitListener(this), this);
// register commands
getLog().info("Registering commands...");
BukkitCommand commandManager = new BukkitCommand(this);
@@ -123,8 +176,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
main.setTabCompleter(commandManager);
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
datastore = StorageFactory.getDatastore(this, "h2");
// load internal managers
getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().isOnlineMode());
userManager = new UserManager(this);
@@ -140,29 +192,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
contextManager.registerCalculator(worldCalculator);
contextManager.registerCalculator(new ServerCalculator<>(getConfiguration().getServer()));
// handle server operators
if (getConfiguration().isAutoOp()) {
contextManager.registerListener(new AutoOPListener());
}
final LPBukkitPlugin i = this;
updateTaskBuffer = new BufferedRequest<Void>(6000L, this::doAsync) {
@Override
protected Void perform() {
getServer().getScheduler().runTaskAsynchronously(i, new UpdateTask(i));
return null;
}
};
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
long ticks = mins * 60 * 20;
getServer().getScheduler().runTaskTimerAsynchronously(this, () -> updateTaskBuffer.request(), ticks, ticks);
}
getServer().getScheduler().runTaskTimer(this, BukkitSenderFactory.get(this), 1L, 1L);
getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpireTemporaryTask(this), 60L, 60L);
getServer().getScheduler().runTaskTimerAsynchronously(this, consecutiveExecutor, 20L, 20L);
// Provide vault support
getLog().info("Attempting to hook into Vault...");
try {
@@ -178,20 +212,38 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
e.printStackTrace();
}
// register with the LP API
getLog().info("Registering API...");
apiProvider = new ApiProvider(this);
ApiHandler.registerProvider(apiProvider);
getServer().getServicesManager().register(LuckPermsApi.class, apiProvider, this, ServicePriority.Normal);
// Run update task to refresh any online users
getLog().info("Scheduling Update Task to refresh any online users.");
updateTaskBuffer.request();
// schedule update tasks
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
long ticks = mins * 60 * 20;
getServer().getScheduler().runTaskTimerAsynchronously(this, () -> updateTaskBuffer.request(), 20L, ticks);
}
// run an update instantly.
updateTaskBuffer.requestDirectly();
// register tasks
getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpireTemporaryTask(this), 60L, 60L);
getServer().getScheduler().runTaskTimerAsynchronously(this, consecutiveExecutor, 20L, 20L);
// register permissions
registerPermissions(getConfiguration().isCommandsAllowOp() ? PermissionDefault.OP : PermissionDefault.FALSE);
if (!getConfiguration().isOpsEnabled()) {
getServer().getOperators().forEach(o -> o.setOp(false));
}
// replace the temporary executor when the Bukkit one starts
getServer().getScheduler().runTaskAsynchronously(this, () -> {
asyncExecutor = r -> getServer().getScheduler().runTaskAsynchronously(this, r);
});
started = true;
getLog().info("Successfully loaded.");
}
@@ -200,7 +252,12 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
public void onDisable() {
started = false;
getLog().info("Closing datastore...");
datastore.shutdown();
storage.shutdown();
if (redisMessaging != null) {
getLog().info("Closing redis...");
redisMessaging.shutdown();
}
getLog().info("Unregistering API...");
ApiHandler.unregisterProvider();
@@ -213,12 +270,12 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
@Override
public void doAsync(Runnable r) {
getServer().getScheduler().runTaskAsynchronously(this, r);
asyncExecutor.execute(r);
}
@Override
public void doSync(Runnable r) {
getServer().getScheduler().runTask(this, r);
syncExecutor.execute(r);
}
@Override
@@ -262,16 +319,15 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
}
@Override
public List<Sender> getNotifyListeners() {
public List<Sender> getSenders() {
return getServer().getOnlinePlayers().stream()
.map(p -> BukkitSenderFactory.get(this).wrap(p, Collections.singleton(Permission.LOG_NOTIFY)))
.filter(Permission.LOG_NOTIFY::isAuthorized)
.map(p -> getSenderFactory().wrap(p))
.collect(Collectors.toList());
}
@Override
public Sender getConsoleSender() {
return BukkitSenderFactory.get(this).wrap(getServer().getConsoleSender());
return getSenderFactory().wrap(getServer().getConsoleSender());
}
@Override
@@ -324,12 +380,12 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
);
// Check for and include varying Vault config options
try {
assert getConfiguration().isVaultIncludingGlobal() == getConfiguration().isIncludingGlobalPerms();
assert getConfiguration().isIncludingGlobalWorldPerms();
assert getConfiguration().isApplyingGlobalGroups();
assert getConfiguration().isApplyingGlobalWorldGroups();
} catch (AssertionError e) {
boolean vaultDiff = getConfiguration().isVaultIncludingGlobal() != getConfiguration().isIncludingGlobalPerms() ||
!getConfiguration().isIncludingGlobalWorldPerms() ||
!getConfiguration().isApplyingGlobalGroups() ||
!getConfiguration().isApplyingGlobalWorldGroups();
if (vaultDiff) {
contexts.addAll(c.stream()
.map(map -> new Contexts(map, getConfiguration().isVaultIncludingGlobal(), true, true, true, true, op))
.collect(Collectors.toSet())
@@ -71,11 +71,11 @@ public class WorldCalculator extends ContextCalculator<Player> implements Listen
private String getWorld(Player player) {
UUID internal = plugin.getUuidCache().getUUID(player.getUniqueId());
if (!worldCache.containsKey(internal)) {
String world = worldCache.get(internal);
if (world == null) {
return null;
}
String world = worldCache.get(internal);
return plugin.getConfiguration().getWorldRewrites().getOrDefault(world, world);
}
@@ -48,4 +48,9 @@ public class AttachmentProcessor implements PermissionProcessor {
return pai == null ? Tristate.UNDEFINED : Tristate.fromBoolean(pai.getValue());
}
@Override
public void updateBacking(Map<String, Boolean> map) {
// Do nothing, this doesn't use the backing
}
}
@@ -0,0 +1,75 @@
/*
* 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.calculators;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.permissions.Permission;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class ChildPermissionProvider {
@Getter
private ImmutableMap<Map.Entry<String, Boolean>, ImmutableMap<String, Boolean>> permissions = ImmutableMap.of();
public void setup() {
ImmutableMap.Builder<Map.Entry<String, Boolean>, ImmutableMap<String, Boolean>> permissions = ImmutableMap.builder();
for (Permission permission : Bukkit.getServer().getPluginManager().getPermissions()) {
// handle true
Map<String, Boolean> children = new HashMap<>();
resolveChildren(children, Collections.singletonMap(permission.getName(), true), false);
permissions.put(Maps.immutableEntry(permission.getName().toLowerCase(), true), ImmutableMap.copyOf(children));
// handle false
Map<String, Boolean> nChildren = new HashMap<>();
resolveChildren(nChildren, Collections.singletonMap(permission.getName(), false), false);
permissions.put(Maps.immutableEntry(permission.getName().toLowerCase(), false), ImmutableMap.copyOf(nChildren));
}
this.permissions = permissions.build();
}
private static void resolveChildren(Map<String, Boolean> accumulator, Map<String, Boolean> children, boolean invert) {
for (Map.Entry<String, Boolean> e : children.entrySet()) {
if (accumulator.containsKey(e.getKey())) {
continue; // Prevent infinite loops
}
Permission perm = Bukkit.getServer().getPluginManager().getPermission(e.getKey());
boolean value = e.getValue() ^ invert;
String lName = e.getKey().toLowerCase();
accumulator.put(lName, value);
if (perm != null) {
resolveChildren(accumulator, perm.getChildren(), !value);
}
}
}
}
@@ -20,49 +20,34 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.utils;
package me.lucko.luckperms.bukkit.calculators;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.calculators.PermissionProcessor;
public class AbstractFuture<R> implements LPFuture<R> {
private final CountDownLatch latch = new CountDownLatch(1);
private R value;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public void complete(R r) {
value = r;
latch.countDown();
@RequiredArgsConstructor
public class ChildProcessor implements PermissionProcessor {
private final ChildPermissionProvider provider;
private Map<String, Boolean> childPermissions = new ConcurrentHashMap<>();
@Override
public Tristate hasPermission(String permission) {
Boolean b = childPermissions.get(permission);
return b == null ? Tristate.UNDEFINED : Tristate.fromBoolean(b);
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
// Not supported
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return latch.getCount() == 0;
}
@Override
public R get() throws InterruptedException {
latch.await();
return value;
}
@Override
public R get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
if (latch.await(timeout, unit)) {
return value;
} else {
throw new TimeoutException();
public void updateBacking(Map<String, Boolean> map) {
childPermissions.clear();
for (Map.Entry<String, Boolean> e : map.entrySet()) {
Map<String, Boolean> children = provider.getPermissions().get(e);
if (children != null) {
childPermissions.putAll(children);
}
}
}
}
@@ -28,6 +28,8 @@ import me.lucko.luckperms.common.calculators.PermissionProcessor;
import org.bukkit.Bukkit;
import org.bukkit.permissions.Permission;
import java.util.Map;
@AllArgsConstructor
public class DefaultsProcessor implements PermissionProcessor {
private final boolean isOp;
@@ -43,4 +45,9 @@ public class DefaultsProcessor implements PermissionProcessor {
Permission defPerm = Bukkit.getServer().getPluginManager().getPermission(permission);
return defPerm == null ? Tristate.UNDEFINED : Tristate.fromBoolean(defPerm.getDefault().getValue(isOp));
}
@Override
public void updateBacking(Map<String, Boolean> map) {
// Do nothing, this doesn't use the backing
}
}
@@ -26,7 +26,6 @@ import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.users.User;
import org.bukkit.Bukkit;
@@ -67,7 +66,7 @@ public class LPPermissible extends PermissibleBase {
public Contexts calculateContexts() {
return new Contexts(
plugin.getContextManager().giveApplicableContext(parent, new MutableContextSet()),
plugin.getContextManager().getApplicableContext(parent),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
@@ -185,7 +184,7 @@ public class LPPermissible extends PermissibleBase {
}
PermissionAttachment result = addAttachment(plugin);
if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new RemoveAttachmentRunnable(result), 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;
@@ -255,16 +254,4 @@ public class LPPermissible extends PermissibleBase {
}
}
}
private class RemoveAttachmentRunnable implements Runnable {
private PermissionAttachment attachment;
private RemoveAttachmentRunnable(PermissionAttachment attachment) {
this.attachment = attachment;
}
public void run() {
attachment.remove();
}
}
}
@@ -20,19 +20,20 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.commands.migration.subcommands;
package me.lucko.luckperms.bukkit.migration;
import de.bananaco.bpermissions.api.*;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.core.PermissionHolder;
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;
@@ -82,11 +83,11 @@ public class MigrationBPermissions extends SubCommand<Object> {
}
public MigrationBPermissions() {
super("bpermissions", "Migration from bPermissions", MIGRATION, Predicate.alwaysFalse(), null);
super("bpermissions", "Migration from bPermissions", MIGRATION, Predicates.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
final Logger log = plugin.getLog();
WorldManager worldManager = WorldManager.getInstance();
@@ -121,7 +122,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
}
// Make a LuckPerms group for the one being migrated.
plugin.getDatastore().createAndLoadGroup(groupName).getUnchecked();
plugin.getStorage().createAndLoadGroup(groupName).join();
me.lucko.luckperms.common.groups.Group lpGroup = plugin.getGroupManager().get(groupName);
try {
LogEntry.build()
@@ -133,7 +134,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
}
migrateHolder(plugin, world, group, lpGroup);
plugin.getDatastore().saveGroup(lpGroup);
plugin.getStorage().saveGroup(lpGroup);
}
log.info("bPermissions Migration: Migrated " + groupCount + " groups in world " + world.getName() + ".");
@@ -157,12 +158,12 @@ public class MigrationBPermissions extends SubCommand<Object> {
}
// Make a LuckPerms user for the one being migrated.
plugin.getDatastore().loadUser(uuid, "null").getUnchecked();
plugin.getStorage().loadUser(uuid, "null").join();
me.lucko.luckperms.common.users.User lpUser = plugin.getUserManager().get(uuid);
migrateHolder(plugin, world, user, lpUser);
plugin.getDatastore().saveUser(lpUser);
plugin.getStorage().saveUser(lpUser);
plugin.getUserManager().cleanup(lpUser);
}
@@ -20,15 +20,22 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.commands.migration.subcommands;
package me.lucko.luckperms.bukkit.migration;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import org.anjocaido.groupmanager.GlobalGroups;
import org.anjocaido.groupmanager.GroupManager;
import org.anjocaido.groupmanager.data.Group;
@@ -36,19 +43,18 @@ import org.anjocaido.groupmanager.data.User;
import org.anjocaido.groupmanager.dataholder.WorldDataHolder;
import org.anjocaido.groupmanager.dataholder.worlds.WorldsHolder;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;
public class MigrationGroupManager extends SubCommand<Object> {
public MigrationGroupManager() {
super("groupmanager", "Migration from GroupManager", Permission.MIGRATION, Predicate.is(0),
super("groupmanager", "Migration from GroupManager", Permission.MIGRATION, Predicates.is(0),
Arg.list(Arg.create("world names...", false, "a list of worlds to migrate permissions from"))
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
final Logger log = plugin.getLog();
if (!plugin.isPluginLoaded("GroupManager")) {
log.severe("GroupManager Migration: Error -> GroupManager is not loaded.");
@@ -63,17 +69,10 @@ public class MigrationGroupManager extends SubCommand<Object> {
// Migrate Global Groups
log.info("GroupManager Migration: Starting Global Group migration.");
GlobalGroups gg;
try {
gg = (GlobalGroups) GroupManager.class.getMethod("getGlobalGroups").invoke(gm);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
return CommandResult.FAILURE;
}
GlobalGroups gg = GroupManager.getGlobalGroups();
for (Group g : gg.getGroupList()) {
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase()).getUnchecked();
plugin.getStorage().createAndLoadGroup(g.getName().toLowerCase()).join();
me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
try {
LogEntry.build()
@@ -121,33 +120,21 @@ public class MigrationGroupManager extends SubCommand<Object> {
}
}
plugin.getDatastore().saveGroup(group);
plugin.getStorage().saveGroup(group);
}
Map<UUID, Map<Map.Entry<String, String>, Boolean>> users = new HashMap<>();
Map<UUID, String> primaryGroups = new HashMap<>();
Map<String, Map<Map.Entry<String, String>, Boolean>> groups = new HashMap<>();
WorldsHolder wh;
try {
wh = (WorldsHolder) GroupManager.class.getMethod("getWorldsHolder").invoke(gm);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
return CommandResult.FAILURE;
}
WorldsHolder wh = gm.getWorldsHolder();
// Collect data for all users and groups.
log.info("GroupManager Migration: Starting user and group migration.");
for (String world : worlds) {
world = world.toLowerCase();
WorldDataHolder wdh;
try {
wdh = (WorldDataHolder) WorldsHolder.class.getMethod("getWorldData", String.class).invoke(wh, world);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
return CommandResult.FAILURE;
}
WorldDataHolder wdh = wh.getWorldData(world);
for (Group g : wdh.getGroupList()) {
groups.putIfAbsent(g.getName().toLowerCase(), new HashMap<>());
@@ -193,7 +180,13 @@ public class MigrationGroupManager extends SubCommand<Object> {
users.get(uuid).put(new AbstractMap.SimpleEntry<>(world, node), value);
}
users.get(uuid).put(new AbstractMap.SimpleEntry<>(world, "group." + user.getGroupName().toLowerCase()), true);
String finalWorld = world;
users.get(uuid).putAll(user.subGroupListStringCopy().stream()
.map(n -> "group." + n)
.map(n -> new AbstractMap.SimpleEntry<>(finalWorld, n))
.collect(Collectors.toMap(n -> n, n -> true))
);
primaryGroups.put(uuid, user.getGroupName());
}
}
@@ -202,7 +195,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
log.info("GroupManager Migration: Found a total of " + users.size() + " users and " + groups.size() + " groups.");
for (Map.Entry<String, Map<Map.Entry<String, String>, Boolean>> e : groups.entrySet()) {
plugin.getDatastore().createAndLoadGroup(e.getKey()).getUnchecked();
plugin.getStorage().createAndLoadGroup(e.getKey()).join();
me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(e.getKey());
try {
LogEntry.build()
@@ -219,7 +212,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
// n.key.value = node
// n.value = true/false
try {
group.setPermission("global-" + n.getKey().getKey() + "/" + n.getKey().getValue(), n.getValue());
group.setPermission(NodeFactory.fromSerialisedNode("global-" + n.getKey().getKey() + "/" + n.getKey().getValue(), n.getValue()));
if (n.getKey().getValue().startsWith("group.")) {
String groupName = n.getKey().getValue().substring(6);
@@ -241,11 +234,11 @@ public class MigrationGroupManager extends SubCommand<Object> {
}
}
plugin.getDatastore().saveGroup(group);
plugin.getStorage().saveGroup(group);
}
for (Map.Entry<UUID, Map<Map.Entry<String, String>, Boolean>> e : users.entrySet()) {
plugin.getDatastore().loadUser(e.getKey(), "null").getUnchecked();
plugin.getStorage().loadUser(e.getKey(), "null").join();
me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(e.getKey());
for (Map.Entry<Map.Entry<String, String>, Boolean> n : e.getValue().entrySet()) {
@@ -253,7 +246,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
// n.key.value = node
// n.value = true/false
try {
user.setPermission("global-" + n.getKey().getKey() + "/" + n.getKey().getValue(), n.getValue());
user.setPermission(NodeFactory.fromSerialisedNode("global-" + n.getKey().getKey() + "/" + n.getKey().getValue(), n.getValue()));
if (n.getKey().getValue().startsWith("group.")) {
String group = n.getKey().getValue().substring(6);
@@ -275,7 +268,18 @@ public class MigrationGroupManager extends SubCommand<Object> {
}
}
plugin.getDatastore().saveUser(user);
String primaryGroup = primaryGroups.get(e.getKey());
if (primaryGroup != null) {
try {
user.setPermission("group." + primaryGroup, true);
} catch (ObjectAlreadyHasException ignored) {}
user.setPrimaryGroup(primaryGroup);
try {
user.unsetPermission("group.default");
} catch (ObjectLacksException ignored) {}
}
plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user);
}
@@ -20,18 +20,23 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.commands.migration.subcommands;
package me.lucko.luckperms.bukkit.migration;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import ru.tehkode.permissions.NativeInterface;
import ru.tehkode.permissions.PermissionGroup;
@@ -40,21 +45,20 @@ import ru.tehkode.permissions.PermissionUser;
import ru.tehkode.permissions.bukkit.PermissionsEx;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
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, Predicate.alwaysFalse(),
super("permissionsex", "Migration from PermissionsEx", Permission.MIGRATION, Predicates.alwaysFalse(),
Arg.list(Arg.create("world names...", false, "a list of worlds to migrate permissions from"))
);
}
@SuppressWarnings("deprecation")
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
final Logger log = plugin.getLog();
if (!plugin.isPluginLoaded("PermissionsEx")) {
log.severe("PermissionsEx Migration: Error -> PermissionsEx is not loaded.");
@@ -72,13 +76,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
.collect(Collectors.toList());
PermissionsEx pex = (PermissionsEx) plugin.getPlugin("PermissionsEx");
PermissionManager manager; // The compiler complains if you call the method directly, as Bukkit is not in this module.
try {
manager = (PermissionManager) PermissionsEx.class.getMethod("getPermissionsManager").invoke(pex);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
return CommandResult.FAILURE;
}
PermissionManager manager = pex.getPermissionsManager();
NativeInterface ni;
try {
@@ -102,7 +100,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
maxGroupWeight = Math.max(maxGroupWeight, groupWeight);
final String name = group.getName().toLowerCase();
plugin.getDatastore().createAndLoadGroup(name).getUnchecked();
plugin.getStorage().createAndLoadGroup(name).join();
Group lpGroup = plugin.getGroupManager().get(name);
try {
LogEntry.build()
@@ -226,7 +224,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
}
}
plugin.getDatastore().saveGroup(lpGroup);
plugin.getStorage().saveGroup(lpGroup);
}
@@ -254,7 +252,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
}
userCount++;
plugin.getDatastore().loadUser(u, "null").getUnchecked();
plugin.getStorage().loadUser(u, "null").join();
User lpUser = plugin.getUserManager().get(u);
try {
@@ -387,7 +385,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
}
plugin.getUserManager().cleanup(lpUser);
plugin.getDatastore().saveUser(lpUser);
plugin.getStorage().saveUser(lpUser);
}
log.info("PermissionsEx Migration: Migrated " + userCount + " users.");
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.commands.migration.subcommands;
package me.lucko.luckperms.bukkit.migration;
import com.github.cheesesoftware.PowerfulPermsAPI.*;
import com.google.common.util.concurrent.ListenableFuture;
@@ -28,13 +28,18 @@ import com.zaxxer.hikari.HikariDataSource;
import lombok.Cleanup;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.bukkit.migration.utils.LPResultRunnable;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.commands.migration.subcommands.utils.LPResultRunnable;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.lang.reflect.InvocationTargetException;
@@ -116,7 +121,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
public MigrationPowerfulPerms() {
super("powerfulperms", "Migration from PowerfulPerms", MIGRATION, Predicate.not(5),
super("powerfulperms", "Migration from PowerfulPerms", MIGRATION, Predicates.not(5),
Arg.list(
Arg.create("address", true, "the address of the PP database"),
Arg.create("database", true, "the name of the PP database"),
@@ -128,7 +133,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
try {
return run(plugin, args);
} catch (Throwable t) {
@@ -246,7 +251,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
log.info("PowerfulPerms Migration: Starting group migration.");
Map<Integer, Group> groups = pm.getGroups(); // All versions
for (Group g : groups.values()) {
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase()).getUnchecked();
plugin.getStorage().createAndLoadGroup(g.getName().toLowerCase()).join();
final me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
try {
LogEntry.build()
@@ -275,7 +280,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
}
}
plugin.getDatastore().saveGroup(group);
plugin.getStorage().saveGroup(group);
}
log.info("PowerfulPerms Migration: Group migration complete.");
@@ -288,7 +293,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
progress.put(uuid, new CountDownLatch(2));
// Create a LuckPerms user for the UUID
plugin.getDatastore().loadUser(uuid, "null").getUnchecked();
plugin.getStorage().loadUser(uuid, "null").join();
User user = plugin.getUserManager().get(uuid);
// Get a list of Permissions held by the user from the PP API.
@@ -299,7 +304,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
synchronized (progress) {
progress.get(uuid).countDown();
if (progress.get(uuid).getCount() == 0) {
plugin.getDatastore().saveUser(user);
plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user);
}
}
@@ -422,7 +427,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
synchronized (progress) {
progress.get(uuid).countDown();
if (progress.get(uuid).getCount() == 0) {
plugin.getDatastore().saveUser(user);
plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user);
}
}
@@ -20,18 +20,23 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.commands.migration.subcommands;
package me.lucko.luckperms.bukkit.migration;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.tracks.Track;
import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
@@ -40,19 +45,15 @@ import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* <3 <3 zPermissions <3 <3
* Finally a permissions plugin with a decent API. *sigh*
*/
public class MigrationZPermissions extends SubCommand<Object> {
public MigrationZPermissions() {
super("zpermissions", "Migration from zPermissions", Permission.MIGRATION, Predicate.alwaysFalse(),
super("zpermissions", "Migration from zPermissions", Permission.MIGRATION, Predicates.alwaysFalse(),
Arg.list(Arg.create("world names...", false, "a list of worlds to migrate permissions from"))
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
final Logger log = plugin.getLog();
if (!plugin.isPluginLoaded("zPermissions")) {
log.severe("zPermissions Migration: Error -> zPermissions is not loaded.");
@@ -72,7 +73,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
// Migrate all groups
log.info("zPermissions Migration: Starting group migration.");
for (String g : service.getAllGroups()) {
plugin.getDatastore().createAndLoadGroup(g.toLowerCase()).getUnchecked();
plugin.getStorage().createAndLoadGroup(g.toLowerCase()).join();
Group group = plugin.getGroupManager().get(g.toLowerCase());
try {
LogEntry.build()
@@ -115,13 +116,13 @@ public class MigrationZPermissions extends SubCommand<Object> {
}
}
plugin.getDatastore().saveGroup(group);
plugin.getStorage().saveGroup(group);
}
// Migrate all tracks
log.info("zPermissions Migration: Starting track migration.");
for (String t : service.getAllTracks()) {
plugin.getDatastore().createAndLoadTrack(t.toLowerCase()).getUnchecked();
plugin.getStorage().createAndLoadTrack(t.toLowerCase()).join();
Track track = plugin.getTrackManager().get(t.toLowerCase());
try {
LogEntry.build()
@@ -144,13 +145,13 @@ public class MigrationZPermissions extends SubCommand<Object> {
}
}
plugin.getDatastore().saveTrack(track);
plugin.getStorage().saveTrack(track);
}
// Migrate all users.
log.info("zPermissions Migration: Starting user migration.");
for (UUID u : service.getAllPlayersUUID()) {
plugin.getDatastore().loadUser(u, "null").getUnchecked();
plugin.getStorage().loadUser(u, "null").join();
User user = plugin.getUserManager().get(u);
for (Map.Entry<String, Boolean> e : service.getPlayerPermissions(null, null, u).entrySet()) {
@@ -243,7 +244,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
}
plugin.getUserManager().cleanup(user);
plugin.getDatastore().saveUser(user);
plugin.getStorage().saveUser(user);
}
log.info("zPermissions Migration: Success! Completed without any errors.");
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.commands.migration.subcommands.utils;
package me.lucko.luckperms.bukkit.migration.utils;
import com.github.cheesesoftware.PowerfulPermsAPI.ResultRunnable;
@@ -27,6 +27,7 @@ import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.caching.MetaData;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.core.NodeBuilder;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.users.User;
@@ -95,7 +96,7 @@ public class VaultChatHook extends Chat {
} catch (ObjectLacksException ignored) {}
});
Node.Builder metaNode = new me.lucko.luckperms.common.core.Node.Builder("meta." + k + "." + v).setValue(true);
Node.Builder metaNode = new NodeBuilder("meta." + k + "." + v).setValue(true);
if (!perms.getServer().equalsIgnoreCase("global")) {
metaNode.setServer(perms.getServer());
}
@@ -119,7 +120,7 @@ public class VaultChatHook extends Chat {
perms.log("Setting " + (prefix ? "prefix" : "suffix") + " for " + holder.getObjectName() + " on world " + world + ", server " + perms.getServer());
perms.getScheduler().scheduleTask(() -> {
Node.Builder node = new me.lucko.luckperms.common.core.Node.Builder(prefix ? "prefix" : "suffix" + ".1000." + escapeCharacters(value));
Node.Builder node = new NodeBuilder(prefix ? "prefix" : "suffix" + ".1000." + escapeCharacters(value));
node.setValue(true);
if (!perms.getServer().equalsIgnoreCase("global")) {
node.setServer(perms.getServer());
@@ -42,7 +42,11 @@ public class VaultHook {
permissionHook.setPlugin(plugin);
permissionHook.setServer(plugin.getConfiguration().getVaultServer());
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIncludingGlobal());
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIgnoreWorld());
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) {
@@ -22,11 +22,15 @@
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;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.caching.PermissionData;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.core.PermissionHolder;
@@ -43,33 +47,30 @@ import java.util.Map;
* The LuckPerms Vault Permission implementation
* Most lookups are cached.
*/
@Getter
@Setter
public class VaultPermissionHook extends Permission {
@Getter
@Setter
private LPBukkitPlugin plugin;
@Getter
@Setter(value = AccessLevel.NONE)
private VaultScheduler scheduler;
@Getter
@Setter
private String server = "global";
@Getter
@Setter
private boolean includeGlobal = true;
@Getter
@Setter
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);
}
public void log(String s) {
if (plugin.getConfiguration().isDebugPermissionChecks()) {
if (plugin.getConfiguration().isVaultDebug()) {
plugin.getLog().info("[VAULT] " + s);
}
}
@@ -81,7 +82,7 @@ public class VaultPermissionHook extends Permission {
@Override
public boolean isEnabled() {
return plugin.getDatastore().isAcceptingLogins();
return plugin.getStorage().isAcceptingLogins();
}
@Override
@@ -131,13 +132,12 @@ public class VaultPermissionHook extends Permission {
*/
void save(PermissionHolder holder) {
if (holder instanceof User) {
plugin.getDatastore().saveUser(((User) holder), b -> {
((User) holder).getRefreshBuffer().request();
});
plugin.getStorage().saveUser(((User) holder))
.thenRunAsync(() -> ((User) holder).getRefreshBuffer().request(), plugin.getAsyncExecutor());
}
if (holder instanceof Group) {
plugin.getDatastore().saveGroup(((Group) holder), b -> plugin.getUpdateTaskBuffer().request());
plugin.getStorage().saveGroup(((Group) holder))
.thenRunAsync(() -> plugin.getUpdateTaskBuffer().request(), plugin.getAsyncExecutor());
}
}
@@ -311,9 +311,81 @@ public class VaultPermissionHook extends Permission {
@Override
public String getPrimaryGroup(String world, @NonNull String player) {
world = ignoreWorld ? null : world; // Correct world value
log("Getting primary group of player: " + player);
final User user = plugin.getUserManager().get(player);
return (user == null) ? null : user.getPrimaryGroup();
if (user == null) {
return null;
}
if (!pgo) {
return user.getPrimaryGroup();
}
if (pgoCheckInherited) {
PermissionData data = user.getUserData().getPermissionData(createContext(server, world));
for (Map.Entry<String, Boolean> e : data.getImmutableBacking().entrySet()) {
if (!e.getValue()) {
continue;
}
if (!e.getKey().toLowerCase().startsWith("vault.primarygroup.")) {
continue;
}
String group = e.getKey().substring("vault.primarygroup.".length());
if (pgoCheckExists) {
if (!plugin.getGroupManager().isLoaded(group)) {
continue;
}
}
if (pgoCheckMemberOf) {
if (data.getPermissionValue("group." + group) != Tristate.TRUE) {
continue;
}
}
return group;
}
} else {
for (LocalizedNode node : user.getPermissions(true)) {
if (!node.getValue()) {
continue;
}
if (!node.getPermission().toLowerCase().startsWith("vault.primarygroup.")) {
continue;
}
if (!node.shouldApplyOnServer(server, isIncludeGlobal(), false)) {
continue;
}
if (!node.shouldApplyOnWorld(world, true, false)) {
continue;
}
String group = node.getPermission().substring("vault.primarygroup.".length());
if (pgoCheckExists) {
if (!plugin.getGroupManager().isLoaded(group)) {
continue;
}
}
if (pgoCheckMemberOf) {
if (!user.getLocalGroups(server, world, isIncludeGlobal()).contains(group.toLowerCase())) {
continue;
}
}
return group;
}
}
// Fallback
return user.getPrimaryGroup();
}
@Override
+34 -3
View File
@@ -46,9 +46,6 @@ online-mode: true
# If the plugin should send log notifications to users whenever permissions are modified.
log-notify: true
# If LuckPerms should print to console every time a plugin checks if a player has a permission
debug-permission-checks: false
@@ -70,6 +67,11 @@ apply-regex: true
# If set to true, LuckPerms will detect and expand shorthand node patterns.
apply-shorthand: true
# Define special group weights for this server.
# Default is just 0.
group-weight:
# admin: 10
@@ -112,6 +114,22 @@ vault-include-global: true
# If Vault operations should ignore any world arguments if supplied.
vault-ignore-world: false
# This block controls the Primary Group override feature
# See the wiki for more information.
vault-primary-groups-overrides:
# If the feature is enabled
enabled: false
# If the check should query the user's inherited permissions.
# (a value of false only checks the permissions they explicitly have)
check-inherited-permissions: false
# If LuckPerms should check if the group exists
check-group-exists: true
# If LuckPerms should check if the user is actually a member of the group
check-user-member-of: true
# If LuckPerms should print debugging info to console when a plugin uses a Vault function
vault-debug: false
# Mirrors world names. Whenever LuckPerms checks what world a user is in, if the world name is in this list, the value assigned
# will be sent forward for permission calculation instead.
world-rewrite:
@@ -155,6 +173,19 @@ data:
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
sync-minutes: 3
# Settings for Redis.
#
# If enabled and configured, LuckPerms will use the Redis PubSub system to inform other
# connected servers of changes. Use the command "/luckperms networksync" to push changes.
# Data is NOT stored on redis. It is only used as a messaging platform.
#
# 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.
redis:
enabled: false
address: localhost:6379
password: ''
+20 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version>
<version>2.14-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -69,6 +69,18 @@
<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>
</relocation>
</relocations>
</configuration>
</execution>
@@ -121,6 +133,13 @@
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
<!-- **************Migration Plugins************** -->
<dependency>
<groupId>net.alpenblock</groupId>
<artifactId>BungeePerms</artifactId>
<version>3.0-dev-52</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -22,30 +22,27 @@
package me.lucko.luckperms.bungee;
import com.google.common.collect.ImmutableList;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.common.calculators.*;
import me.lucko.luckperms.common.users.User;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@AllArgsConstructor
public class BungeeCalculatorFactory implements CalculatorFactory {
private final LPBungeePlugin plugin;
@Override
public PermissionCalculator build(Contexts contexts, User user, Map<String, Boolean> map) {
List<PermissionProcessor> processors = new ArrayList<>(3);
processors.add(new MapProcessor(map));
public PermissionCalculator build(Contexts contexts, User user) {
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
processors.add(new MapProcessor());
if (plugin.getConfiguration().isApplyingWildcards()) {
processors.add(new WildcardProcessor(map));
processors.add(new WildcardProcessor());
}
if (plugin.getConfiguration().isApplyingRegex()) {
processors.add(new RegexProcessor(map));
processors.add(new RegexProcessor());
}
return new PermissionCalculator(plugin, user.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors);
return new PermissionCalculator(plugin, user.getName(), processors.build());
}
}
@@ -26,7 +26,7 @@ import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.common.commands.CommandManager;
import me.lucko.luckperms.common.commands.Util;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Patterns;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
@@ -35,17 +35,19 @@ import net.md_5.bungee.api.plugin.TabExecutor;
import java.util.Arrays;
class BungeeCommand extends Command implements TabExecutor {
private final LPBungeePlugin plugin;
private final CommandManager manager;
BungeeCommand(CommandManager manager) {
BungeeCommand(LPBungeePlugin plugin, CommandManager manager) {
super("luckpermsbungee", null, "bperms", "lpb", "bpermissions", "bp", "bperm");
this.plugin = plugin;
this.manager = manager;
}
@Override
public void execute(CommandSender sender, String[] args) {
manager.onCommand(
BungeeSenderFactory.get(manager.getPlugin()).wrap(sender),
plugin.getSenderFactory().wrap(sender),
"bperms",
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
Callback.empty()
@@ -54,6 +56,6 @@ class BungeeCommand extends Command implements TabExecutor {
@Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
return manager.onTabComplete(BungeeSenderFactory.get(manager.getPlugin()).wrap(sender), Arrays.asList(args));
return manager.onTabComplete(plugin.getSenderFactory().wrap(sender), Arrays.asList(args));
}
}
@@ -23,7 +23,6 @@
package me.lucko.luckperms.bungee;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.api.event.events.UserFirstLoginEvent;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.core.UuidCache;
@@ -38,6 +37,7 @@ import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@@ -72,7 +72,7 @@ public class BungeeListener extends AbstractListener implements Listener {
}
Contexts contexts = new Contexts(
plugin.getContextManager().giveApplicableContext(player, MutableContextSet.empty()),
plugin.getContextManager().getApplicableContext(player),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
@@ -84,7 +84,7 @@ public class BungeeListener extends AbstractListener implements Listener {
e.setHasPermission(user.getUserData().getPermissionData(contexts).getPermissionValue(e.getPermission()).asBoolean());
}
@EventHandler
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerLogin(LoginEvent e) {
/* Delay the login here, as we want to cache UUID data before the player is connected to a backend bukkit server.
This means that a player will have the same UUID across the network, even if parts of the network are running in
@@ -96,28 +96,28 @@ public class BungeeListener extends AbstractListener implements Listener {
final PendingConnection c = e.getConnection();
if (!cache.isOnlineMode()) {
UUID uuid = plugin.getDatastore().getUUID(c.getName()).getUnchecked();
UUID uuid = plugin.getStorage().getUUID(c.getName()).join();
if (uuid != null) {
cache.addToCache(c.getUniqueId(), uuid);
} else {
// No previous data for this player
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName()));
cache.addToCache(c.getUniqueId(), c.getUniqueId());
plugin.getDatastore().force().saveUUIDData(c.getName(), c.getUniqueId()).getUnchecked();
plugin.getStorage().force().saveUUIDData(c.getName(), c.getUniqueId()).join();
}
} else {
UUID uuid = plugin.getDatastore().getUUID(c.getName()).getUnchecked();
UUID uuid = plugin.getStorage().getUUID(c.getName()).join();
if (uuid == null) {
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName()));
}
// Online mode, no cache needed. This is just for name -> uuid lookup.
plugin.getDatastore().force().saveUUIDData(c.getName(), c.getUniqueId()).getUnchecked();
plugin.getStorage().force().saveUUIDData(c.getName(), c.getUniqueId()).join();
}
// We have to make a new user on this thread whilst the connection is being held, or we get concurrency issues as the Bukkit server
// and the BungeeCord server try to make a new user at the same time.
plugin.getDatastore().force().loadUser(cache.getUUID(c.getUniqueId()), c.getName()).getUnchecked();
plugin.getStorage().force().loadUser(cache.getUUID(c.getUniqueId()), c.getName()).join();
User user = plugin.getUserManager().get(cache.getUUID(c.getUniqueId()));
if (user == null) {
plugin.getLog().warn("Failed to load user: " + c.getName());
@@ -23,7 +23,7 @@
package me.lucko.luckperms.bungee;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.SenderFactory;
import me.lucko.luckperms.common.commands.sender.SenderFactory;
import me.lucko.luckperms.common.constants.Constants;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
@@ -32,19 +32,10 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.UUID;
public class BungeeSenderFactory extends SenderFactory<CommandSender> {
private static BungeeSenderFactory instance = null;
private BungeeSenderFactory(LuckPermsPlugin plugin) {
public BungeeSenderFactory(LuckPermsPlugin plugin) {
super(plugin);
}
public static synchronized BungeeSenderFactory get(LuckPermsPlugin plugin) {
if (instance == null) {
instance = new BungeeSenderFactory(plugin);
}
return instance;
}
@Override
protected String getName(CommandSender sender) {
if (sender instanceof ProxiedPlayer) {
@@ -34,21 +34,22 @@ import me.lucko.luckperms.common.api.ApiProvider;
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;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.config.LPConfiguration;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.contexts.ContextManager;
import me.lucko.luckperms.common.contexts.ServerCalculator;
import me.lucko.luckperms.common.core.UuidCache;
import me.lucko.luckperms.common.data.Importer;
import me.lucko.luckperms.common.groups.GroupManager;
import me.lucko.luckperms.common.messaging.RedisMessaging;
import me.lucko.luckperms.common.runnables.ExpireTemporaryTask;
import me.lucko.luckperms.common.runnables.UpdateTask;
import me.lucko.luckperms.common.storage.Datastore;
import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.tracks.TrackManager;
import me.lucko.luckperms.common.users.UserManager;
import me.lucko.luckperms.common.utils.BufferedRequest;
import me.lucko.luckperms.common.utils.DebugHandler;
import me.lucko.luckperms.common.utils.LocaleManager;
import me.lucko.luckperms.common.utils.LogFactory;
import net.md_5.bungee.api.config.ServerInfo;
@@ -56,19 +57,26 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.File;
import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Getter
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
private Executor executor;
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
private LPConfiguration configuration;
private UserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
private Storage storage;
private RedisMessaging redisMessaging = null;
private UuidCache uuidCache;
private ApiProvider apiProvider;
private Logger log;
@@ -78,14 +86,48 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
private ContextManager<ProxiedPlayer> contextManager;
private CalculatorFactory calculatorFactory;
private BufferedRequest<Void> updateTaskBuffer;
private DebugHandler debugHandler;
private BungeeSenderFactory senderFactory;
@Override
public void onEnable() {
executor = r -> getProxy().getScheduler().runAsync(this, r);
log = LogFactory.wrap(getLogger());
debugHandler = new DebugHandler();
senderFactory = new BungeeSenderFactory(this);
getLog().info("Loading configuration...");
configuration = new BungeeConfig(this);
// register events
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
// initialise datastore
storage = StorageFactory.getInstance(this, "h2");
// initialise redis
if (getConfiguration().isRedisEnabled()) {
getLog().info("Loading redis...");
redisMessaging = new RedisMessaging(this);
try {
redisMessaging.init(getConfiguration().getRedisAddress(), getConfiguration().getRedisPassword());
getLog().info("Loaded redis successfully...");
} catch (Exception e) {
getLog().info("Couldn't load redis...");
e.printStackTrace();
}
}
// setup the update task buffer
updateTaskBuffer = new BufferedRequest<Void>(1000L, this::doAsync) {
@Override
protected Void perform() {
new UpdateTask(LPBungeePlugin.this).run();
return null;
}
};
// load locale
localeManager = new LocaleManager();
File locale = new File(getDataFolder(), "lang.yml");
if (locale.exists()) {
@@ -97,19 +139,15 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
}
}
// register events
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
// register commands
getLog().info("Registering commands...");
CommandManager commandManager = new CommandManager(this);
getProxy().getPluginManager().registerCommand(this, new BungeeCommand(commandManager));
getProxy().getPluginManager().registerCommand(this, new BungeeCommand(this, commandManager));
// disable the default Bungee /perms command so it gets handled by the Bukkit plugin
getProxy().getDisabledCommands().add("perms");
datastore = StorageFactory.getDatastore(this, "h2");
// load internal managers
getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().isOnlineMode());
userManager = new UserManager(this);
@@ -125,40 +163,36 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
contextManager.registerCalculator(serverCalculator);
contextManager.registerCalculator(new ServerCalculator<>(getConfiguration().getServer()));
final LPBungeePlugin i = this;
updateTaskBuffer = new BufferedRequest<Void>(6000L, this::doAsync) {
@Override
protected Void perform() {
doAsync(new UpdateTask(i));
return null;
}
};
// register with the LP API
getLog().info("Registering API...");
apiProvider = new ApiProvider(this);
ApiHandler.registerProvider(apiProvider);
// schedule update tasks
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
getProxy().getScheduler().schedule(this, new UpdateTask(this), mins, mins, TimeUnit.MINUTES);
}
// 20 times per second (once per "tick")
getProxy().getScheduler().schedule(this, BungeeSenderFactory.get(this), 50L, 50L, TimeUnit.MILLISECONDS);
// run an update instantly.
updateTaskBuffer.requestDirectly();
// register tasks
getProxy().getScheduler().schedule(this, new ExpireTemporaryTask(this), 3L, 3L, TimeUnit.SECONDS);
getProxy().getScheduler().schedule(this, consecutiveExecutor, 1L, 1L, TimeUnit.SECONDS);
getLog().info("Registering API...");
apiProvider = new ApiProvider(this);
ApiHandler.registerProvider(apiProvider);
// Run update task to refresh any online users
getLog().info("Scheduling Update Task to refresh any online users.");
updateTaskBuffer.request();
getLog().info("Successfully loaded.");
}
@Override
public void onDisable() {
getLog().info("Closing datastore...");
datastore.shutdown();
storage.shutdown();
if (redisMessaging != null) {
getLog().info("Closing redis...");
redisMessaging.shutdown();
}
getLog().info("Unregistering API...");
ApiHandler.unregisterProvider();
@@ -200,16 +234,15 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
}
@Override
public List<Sender> getNotifyListeners() {
public List<Sender> getSenders() {
return getProxy().getPlayers().stream()
.map(p -> BungeeSenderFactory.get(this).wrap(p, Collections.singleton(Permission.LOG_NOTIFY)))
.filter(Permission.LOG_NOTIFY::isAuthorized)
.map(p -> getSenderFactory().wrap(p))
.collect(Collectors.toList());
}
@Override
public Sender getConsoleSender() {
return BungeeSenderFactory.get(this).wrap(getProxy().getConsole());
return getSenderFactory().wrap(getProxy().getConsole());
}
@Override
@@ -271,7 +304,17 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
@Override
public void doSync(Runnable r) {
r.run();
doAsync(r);
}
@Override
public Executor getSyncExecutor() {
return executor;
}
@Override
public Executor getAsyncExecutor() {
return executor;
}
@Override
@@ -20,18 +20,19 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.commands.migration.subcommands;
package me.lucko.luckperms.bungee.migration;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import net.alpenblock.bungeeperms.*;
@@ -43,11 +44,11 @@ import java.util.Map;
*/
public class MigrationBungeePerms extends SubCommand<Object> {
public MigrationBungeePerms() {
super("bungeeperms", "Migration from BungeePerms", Permission.MIGRATION, Predicate.alwaysFalse(), null);
super("bungeeperms", "Migration from BungeePerms", Permission.MIGRATION, Predicates.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
final Logger log = plugin.getLog();
BungeePerms bp = BungeePerms.getInstance();
@@ -60,10 +61,10 @@ public class MigrationBungeePerms extends SubCommand<Object> {
log.info("BungeePerms Migration: Starting group migration.");
int groupCount = 0;
for (Group g : bp.getPermissionsManager().getBackEnd().loadGroups()) {
groupCount ++;
groupCount++;
// Make a LuckPerms group for the one being migrated
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase()).getUnchecked();
plugin.getStorage().createAndLoadGroup(g.getName().toLowerCase()).join();
me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
try {
LogEntry.build()
@@ -173,7 +174,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
}
}
plugin.getDatastore().saveGroup(group);
plugin.getStorage().saveGroup(group);
}
log.info("BungeePerms Migration: Migrated " + groupCount + " groups");
@@ -187,7 +188,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
userCount++;
// Make a LuckPerms user for the one being migrated.
plugin.getDatastore().loadUser(u.getUUID(), "null").getUnchecked();
plugin.getStorage().loadUser(u.getUUID(), "null").join();
me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(u.getUUID());
// Migrate global perms
@@ -288,7 +289,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
}
}
plugin.getDatastore().saveUser(user);
plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user);
}
+18 -3
View File
@@ -46,9 +46,6 @@ online-mode: true
# If the plugin should send log notifications to users whenever permissions are modified.
log-notify: true
# If LuckPerms should print to console every time a plugin checks if a player has a permission
debug-permission-checks: false
# Mirrors world names. Whenever LuckPerms checks what world a user is in, if the world name is in this list, the value assigned
# will be sent forward for permission calculation instead.
world-rewrite:
@@ -80,6 +77,11 @@ apply-regex: true
# If set to true, LuckPerms will detect and expand shorthand node patterns.
apply-shorthand: true
# Define special group weights for this server.
# Default is just 0.
group-weight:
# admin: 10
@@ -113,6 +115,19 @@ data:
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
sync-minutes: 3
# Settings for Redis.
#
# If enabled and configured, LuckPerms will use the Redis PubSub system to inform other
# connected servers of changes. Use the command "/luckpermsbungee networksync" to push changes.
# Data is NOT stored on redis. It is only used as a messaging platform.
#
# 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.
redis:
enabled: false
address: localhost:6379
password: ''
+8 -48
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version>
<version>2.14-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -39,6 +39,13 @@
<version>2.5.1</version>
<scope>compile</scope>
</dependency>
<!-- Jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
<scope>compile</scope>
</dependency>
<!-- SQLite -->
<dependency>
<groupId>org.xerial</groupId>
@@ -95,53 +102,6 @@
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
<!-- **************Migration Plugins************** -->
<dependency>
<groupId>org.tyrannyofheaven.bukkit</groupId>
<artifactId>zPermissions</artifactId>
<version>1.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ru.tehkode</groupId>
<artifactId>PermissionsEx</artifactId>
<version>1.23</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
</exclusion>
<exclusion>
<groupId>net.gravitydevelopment.updater</groupId>
<artifactId>updater</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.cheesesoftware</groupId>
<artifactId>PowerfulPermsAPI</artifactId>
<version>1.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.anjocaido</groupId>
<artifactId>GroupManager</artifactId>
<version>1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.alpenblock</groupId>
<artifactId>BungeePerms</artifactId>
<version>3.0-dev-52</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.bananaco</groupId>
<artifactId>bpermissions-api</artifactId>
<version>2.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -28,63 +28,167 @@ import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.common.api.ApiProvider;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.commands.ConsecutiveExecutor;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.config.LPConfiguration;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.contexts.ContextManager;
import me.lucko.luckperms.common.core.UuidCache;
import me.lucko.luckperms.common.data.Importer;
import me.lucko.luckperms.common.groups.GroupManager;
import me.lucko.luckperms.common.storage.Datastore;
import me.lucko.luckperms.common.messaging.RedisMessaging;
import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.tracks.TrackManager;
import me.lucko.luckperms.common.users.UserManager;
import me.lucko.luckperms.common.utils.BufferedRequest;
import me.lucko.luckperms.common.utils.DebugHandler;
import me.lucko.luckperms.common.utils.LocaleManager;
import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
/**
* Main internal interface for LuckPerms plugins, allowing the luckperms-common module to bind with the plugin instance.
* Main internal interface for LuckPerms plugins, providing the base for abstraction throughout the project.
*
* All plugin platforms implement this interface.
*/
public interface LuckPermsPlugin {
/*
* Access to all of the main internal manager classes
/**
* Gets the user manager instance for the platform
* @return the user manager
*/
UserManager getUserManager();
/**
* Gets the group manager instance for the platform
* @return the group manager
*/
GroupManager getGroupManager();
/**
* Gets the track manager instance for the platform
* @return the track manager
*/
TrackManager getTrackManager();
/**
* Gets the plugin's configuration
* @return the plugin config
*/
LPConfiguration getConfiguration();
Datastore getDatastore();
/**
* Gets the primary data storage instance. This is likely to be wrapped with extra layers for caching, etc.
* @return the storage handler instance
*/
Storage getStorage();
/**
* Gets the redis messaging instance if present. Could return null if redis is not enabled.
* @return the redis messaging service
*/
RedisMessaging getRedisMessaging();
/**
* Gets a wrapped logger instance for the platform.
* @return the plugin's logger
*/
Logger getLog();
/**
* Gets the UUID caching store for the platform
* @return the uuid cache
*/
UuidCache getUuidCache();
/**
* Returns the class implementing the LuckPermsAPI on this platform.
* @return the api
*/
ApiProvider getApiProvider();
/**
* Gets the importer instance
* @return the importer
*/
Importer getImporter();
/**
* Gets the consecutive command executor instance
* @return the consecutive executor
*/
ConsecutiveExecutor getConsecutiveExecutor();
/**
* Gets the instance providing locale translations for the plugin
* @return the locale manager
*/
LocaleManager getLocaleManager();
/**
* Gets the context manager.
* This object handles context accumulation for all players on the platform.
* @return the context manager
*/
ContextManager getContextManager();
/**
* Gets the class responsible for constructing PermissionCalculators on this platform.
* @return the permission calculator factory
*/
CalculatorFactory getCalculatorFactory();
/**
* Gets the verbose debug handler instance.
* @return the debug handler instance
*/
DebugHandler getDebugHandler();
/**
* Execute a runnable asynchronously
* @param r the task to run
*/
void doAsync(Runnable r);
/**
* Execute a runnable synchronously
* @param r the task to run
*/
void doSync(Runnable r);
Executor getSyncExecutor();
Executor getAsyncExecutor();
/**
* Execute a runnable asynchronously on a loop
* @param r the task to run
* @param interval the time between runs in ticks
*/
void doAsyncRepeating(Runnable r, long interval);
/**
* Gets a string of the plugin's version
* @return the version of the plugin
*/
String getVersion();
/**
* Gets the platform type this instance of LuckPerms is running on.
* @return the platform type
*/
PlatformType getType();
/**
* Gets the plugins main directory
* @return the main plugin directory
*/
File getMainDir();
/**
* Gets the plugins main data storage directory
* @return the platforms data folder
*/
File getDataFolder();
@@ -125,11 +229,13 @@ public interface LuckPermsPlugin {
boolean isOnline(UUID external);
/**
* Gets a list of online Senders on the platform
* @return a {@link List} of senders online on the platform
*/
List<Sender> getNotifyListeners();
List<Sender> getSenders();
/**
* Gets the console.
* @return the console sender of the instance
*/
Sender getConsoleSender();
@@ -143,7 +249,7 @@ public interface LuckPermsPlugin {
/**
* Gets a set of players ignoring logging output
* @return a {@link Set} of uuids
* @return a {@link Set} of {@link UUID}s
*/
Set<UUID> getIgnoringLogs();
@@ -162,7 +268,7 @@ public interface LuckPermsPlugin {
Object getService(Class clazz);
/**
* Used as a backup for migration
* Gets the UUID of a player. Used as a backup for migration
* @param playerName the players name
* @return a uuid if found, or null if not
*/
@@ -176,27 +282,9 @@ public interface LuckPermsPlugin {
boolean isPluginLoaded(String name);
/**
* Runs an update task
* Gets the update task buffer of the platform, used for scheduling and running update tasks.
* @return the update task buffer instance
*/
BufferedRequest<Void> getUpdateTaskBuffer();
/**
* Execute a runnable asynchronously
* @param r the task to run
*/
void doAsync(Runnable r);
/**
* Execute a runnable synchronously
* @param r the task to run
*/
void doSync(Runnable r);
/**
* Execute a runnable asynchronously on a loop
* @param r the task to run
* @param interval the time between runs in ticks
*/
void doAsyncRepeating(Runnable r, long interval);
}
@@ -31,6 +31,8 @@ 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.*;
import me.lucko.luckperms.common.core.NodeBuilder;
import me.lucko.luckperms.common.users.UserIdentifier;
import java.util.Optional;
@@ -69,7 +71,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public double getApiVersion() {
return 2.13;
return 2.14;
}
@Override
@@ -94,17 +96,28 @@ public class ApiProvider implements LuckPermsApi {
@Override
public LPConfiguration getConfiguration() {
return new me.lucko.luckperms.common.api.internal.LPConfigurationLink(plugin.getConfiguration());
return new LPConfigurationLink(plugin.getConfiguration());
}
@Override
public Storage getStorage() {
return new StorageLink(plugin, plugin.getStorage());
}
@SuppressWarnings("deprecation")
@Override
public Datastore getDatastore() {
return new me.lucko.luckperms.common.api.internal.DatastoreLink(plugin, plugin.getDatastore());
return new DatastoreLink(plugin, plugin.getStorage());
}
@Override
public Optional<MessagingService> getMessagingService() {
return Optional.ofNullable(plugin.getRedisMessaging());
}
@Override
public UuidCache getUuidCache() {
return new me.lucko.luckperms.common.api.internal.UuidCacheLink(plugin.getUuidCache());
return new UuidCacheLink(plugin.getUuidCache());
}
@Override
@@ -115,11 +128,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public User getUser(@NonNull UUID uuid) {
final me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(uuid);
if (user == null) {
return null;
}
return new me.lucko.luckperms.common.api.internal.UserLink(user);
return user == null ? null : new UserLink(user);
}
@Override
@@ -130,11 +139,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public User getUser(@NonNull String name) {
final me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(name);
if (user == null) {
return null;
}
return new me.lucko.luckperms.common.api.internal.UserLink(user);
return user == null ? null : new UserLink(user);
}
@Override
@@ -144,7 +149,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Set<User> getUsers() {
return plugin.getUserManager().getAll().values().stream().map(me.lucko.luckperms.common.api.internal.UserLink::new).collect(Collectors.toSet());
return plugin.getUserManager().getAll().values().stream().map(UserLink::new).collect(Collectors.toSet());
}
@Override
@@ -155,17 +160,13 @@ public class ApiProvider implements LuckPermsApi {
@Override
public void cleanupUser(@NonNull User user) {
me.lucko.luckperms.common.api.internal.Utils.checkUser(user);
plugin.getUserManager().cleanup(((me.lucko.luckperms.common.api.internal.UserLink) user).getMaster());
plugin.getUserManager().cleanup(((UserLink) user).getMaster());
}
@Override
public Group getGroup(@NonNull String name) {
final me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(name);
if (group == null) {
return null;
}
return new me.lucko.luckperms.common.api.internal.GroupLink(group);
return group == null ? null : new GroupLink(group);
}
@Override
@@ -175,7 +176,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Set<Group> getGroups() {
return plugin.getGroupManager().getAll().values().stream().map(me.lucko.luckperms.common.api.internal.GroupLink::new).collect(Collectors.toSet());
return plugin.getGroupManager().getAll().values().stream().map(GroupLink::new).collect(Collectors.toSet());
}
@Override
@@ -186,11 +187,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Track getTrack(@NonNull String name) {
final me.lucko.luckperms.common.tracks.Track track = plugin.getTrackManager().get(name);
if (track == null) {
return null;
}
return new me.lucko.luckperms.common.api.internal.TrackLink(track);
return track == null ? null : new TrackLink(track);
}
@Override
@@ -200,7 +197,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Set<Track> getTracks() {
return plugin.getTrackManager().getAll().values().stream().map(me.lucko.luckperms.common.api.internal.TrackLink::new).collect(Collectors.toSet());
return plugin.getTrackManager().getAll().values().stream().map(TrackLink::new).collect(Collectors.toSet());
}
@Override
@@ -210,7 +207,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Node.Builder buildNode(@NonNull String permission) throws IllegalArgumentException {
return new me.lucko.luckperms.common.core.Node.Builder(checkNode(permission));
return new NodeBuilder(checkNode(permission));
}
@SuppressWarnings("unchecked")
@@ -27,26 +27,29 @@ import lombok.NonNull;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.AbstractFuture;
import me.lucko.luckperms.common.storage.Storage;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import static me.lucko.luckperms.common.api.internal.Utils.*;
/**
* Provides a link between {@link Datastore} and {@link me.lucko.luckperms.common.storage.Datastore}
* 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"})
@SuppressWarnings({"unused", "WeakerAccess", "deprecation"})
public class DatastoreLink implements Datastore {
private final LuckPermsPlugin plugin;
private final me.lucko.luckperms.common.storage.Datastore master;
private final Storage master;
private final Async async;
private final Sync sync;
private final Future future;
public DatastoreLink(@NonNull LuckPermsPlugin plugin, @NonNull me.lucko.luckperms.common.storage.Datastore master) {
public DatastoreLink(@NonNull LuckPermsPlugin plugin, @NonNull Storage master) {
this.plugin = plugin;
this.master = master;
this.async = new Async(master);
@@ -54,12 +57,10 @@ public class DatastoreLink implements Datastore {
this.future = new Future(master);
}
private static <T> Callback<T> checkCallback(Callback<T> c) {
// If no callback was given, just send an empty one
if (c == null) {
c = Callback.empty();
private <T> void registerCallback(CompletableFuture<T> fut, Callback<T> c) {
if (c != null) {
fut.thenAcceptAsync(Callback.convertToConsumer(c), plugin.getSyncExecutor());
}
return c;
}
@Override
@@ -89,68 +90,68 @@ public class DatastoreLink implements Datastore {
@AllArgsConstructor
public class Async implements Datastore.Async {
private final me.lucko.luckperms.common.storage.Datastore master;
private final me.lucko.luckperms.common.storage.Storage master;
@Override
public void logAction(@NonNull LogEntry entry, Callback<Boolean> callback) {
master.logAction(entry, checkCallback(callback));
registerCallback(master.force().logAction(entry), callback);
}
@Override
public void getLog(Callback<Log> callback) {
master.getLog(log -> callback.onComplete(new LogLink(log)));
public void getLog(@NonNull Callback<Log> callback) {
master.force().getLog().thenAcceptAsync(log -> callback.onComplete(new LogLink(log)), plugin.getSyncExecutor());
}
@Override
public void loadOrCreateUser(@NonNull UUID uuid, @NonNull String username, Callback<Boolean> callback) {
master.loadUser(uuid, checkUsername(username), checkCallback(callback));
registerCallback(master.force().loadUser(uuid, checkUsername(username)) , callback);
}
@Override
public void loadUser(@NonNull UUID uuid, Callback<Boolean> callback) {
master.loadUser(uuid, "null", checkCallback(callback));
registerCallback(master.force().loadUser(uuid, "null"), callback);
}
@Override
public void loadUser(@NonNull UUID uuid, @NonNull String username, Callback<Boolean> callback) {
master.loadUser(uuid, checkUsername(username), checkCallback(callback));
registerCallback(master.force().loadUser(uuid, checkUsername(username)), callback);
}
@Override
public void saveUser(@NonNull User user, Callback<Boolean> callback) {
checkUser(user);
master.saveUser(((UserLink) user).getMaster(), checkCallback(callback));
registerCallback(master.force().saveUser(((UserLink) user).getMaster()), callback);
}
@Override
public void cleanupUsers(Callback<Boolean> callback) {
master.cleanupUsers(checkCallback(callback));
registerCallback(master.force().cleanupUsers(), callback);
}
@Override
public void getUniqueUsers(Callback<Set<UUID>> callback) {
master.getUniqueUsers(checkCallback(callback));
registerCallback(master.force().getUniqueUsers(), callback);
}
@Override
public void createAndLoadGroup(@NonNull String name, Callback<Boolean> callback) {
master.createAndLoadGroup(checkName(name), checkCallback(callback));
registerCallback(master.force().createAndLoadGroup(checkName(name)), callback);
}
@Override
public void loadGroup(@NonNull String name, Callback<Boolean> callback) {
master.loadGroup(checkName(name), checkCallback(callback));
registerCallback(master.force().loadGroup(checkName(name)), callback);
}
@Override
public void loadAllGroups(Callback<Boolean> callback) {
master.loadAllGroups(checkCallback(callback));
registerCallback(master.force().loadAllGroups(), callback);
}
@Override
public void saveGroup(@NonNull Group group, Callback<Boolean> callback) {
checkGroup(group);
master.saveGroup(((GroupLink) group).getMaster(), checkCallback(callback));
registerCallback(master.force().saveGroup(((GroupLink) group).getMaster()), callback);
}
@Override
@@ -159,59 +160,59 @@ public class DatastoreLink implements Datastore {
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
master.deleteGroup(((GroupLink) group).getMaster(), checkCallback(callback));
registerCallback(master.force().deleteGroup(((GroupLink) group).getMaster()), callback);
}
@Override
public void createAndLoadTrack(@NonNull String name, Callback<Boolean> callback) {
master.createAndLoadTrack(checkName(name), checkCallback(callback));
registerCallback(master.force().createAndLoadTrack(checkName(name)), callback);
}
@Override
public void loadTrack(@NonNull String name, Callback<Boolean> callback) {
master.loadTrack(checkName(name), checkCallback(callback));
registerCallback(master.force().loadTrack(checkName(name)), callback);
}
@Override
public void loadAllTracks(Callback<Boolean> callback) {
master.loadAllTracks(checkCallback(callback));
registerCallback(master.force().loadAllTracks(), callback);
}
@Override
public void saveTrack(@NonNull Track track, Callback<Boolean> callback) {
checkTrack(track);
master.saveTrack(((TrackLink) track).getMaster(), checkCallback(callback));
registerCallback(master.force().saveTrack(((TrackLink) track).getMaster()), callback);
}
@Override
public void deleteTrack(@NonNull Track track, Callback<Boolean> callback) {
checkTrack(track);
master.deleteTrack(((TrackLink) track).getMaster(), checkCallback(callback));
registerCallback(master.force().deleteTrack(((TrackLink) track).getMaster()), callback);
}
@Override
public void saveUUIDData(@NonNull String username, @NonNull UUID uuid, Callback<Boolean> callback) {
master.saveUUIDData(checkUsername(username), uuid, checkCallback(callback));
registerCallback(master.force().saveUUIDData(checkUsername(username), uuid), callback);
}
@Override
public void getUUID(@NonNull String username, Callback<UUID> callback) {
master.getUUID(checkUsername(username), checkCallback(callback));
registerCallback(master.force().getUUID(checkUsername(username)), callback);
}
}
@AllArgsConstructor
public class Sync implements Datastore.Sync {
private final me.lucko.luckperms.common.storage.Datastore master;
private final Storage master;
@Override
public boolean logAction(@NonNull LogEntry entry) {
return master.logAction(entry).getUnchecked();
return master.force().logAction(entry).join();
}
@Override
public Log getLog() {
me.lucko.luckperms.common.data.Log log = master.getLog().getUnchecked();
me.lucko.luckperms.common.data.Log log = master.force().getLog().join();
if (log == null) {
return null;
}
@@ -220,54 +221,54 @@ public class DatastoreLink implements Datastore {
@Override
public boolean loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) {
return master.loadUser(uuid, checkUsername(username)).getUnchecked();
return master.force().loadUser(uuid, checkUsername(username)).join();
}
@Override
public boolean loadUser(@NonNull UUID uuid) {
return master.loadUser(uuid, "null").getUnchecked();
return master.force().loadUser(uuid, "null").join();
}
@Override
public boolean loadUser(@NonNull UUID uuid, @NonNull String username) {
return master.loadUser(uuid, checkUsername(username)).getUnchecked();
return master.force().loadUser(uuid, checkUsername(username)).join();
}
@Override
public boolean saveUser(@NonNull User user) {
checkUser(user);
return master.saveUser(((UserLink) user).getMaster()).getUnchecked();
return master.force().saveUser(((UserLink) user).getMaster()).join();
}
@Override
public boolean cleanupUsers() {
return master.cleanupUsers().getUnchecked();
return master.force().cleanupUsers().join();
}
@Override
public Set<UUID> getUniqueUsers() {
return master.getUniqueUsers().getUnchecked();
return master.force().getUniqueUsers().join();
}
@Override
public boolean createAndLoadGroup(@NonNull String name) {
return master.createAndLoadGroup(checkName(name)).getUnchecked();
return master.force().createAndLoadGroup(checkName(name)).join();
}
@Override
public boolean loadGroup(@NonNull String name) {
return master.loadGroup(checkName(name)).getUnchecked();
return master.force().loadGroup(checkName(name)).join();
}
@Override
public boolean loadAllGroups() {
return master.loadAllGroups().getUnchecked();
return master.force().loadAllGroups().join();
}
@Override
public boolean saveGroup(@NonNull Group group) {
checkGroup(group);
return master.saveGroup(((GroupLink) group).getMaster()).getUnchecked();
return master.force().saveGroup(((GroupLink) group).getMaster()).join();
}
@Override
@@ -276,113 +277,111 @@ public class DatastoreLink implements Datastore {
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
return master.deleteGroup(((GroupLink) group).getMaster()).getUnchecked();
return master.force().deleteGroup(((GroupLink) group).getMaster()).join();
}
@Override
public boolean createAndLoadTrack(@NonNull String name) {
return master.createAndLoadTrack(checkName(name)).getUnchecked();
return master.force().createAndLoadTrack(checkName(name)).join();
}
@Override
public boolean loadTrack(@NonNull String name) {
return master.loadTrack(checkName(name)).getUnchecked();
return master.force().loadTrack(checkName(name)).join();
}
@Override
public boolean loadAllTracks() {
return master.loadAllTracks().getUnchecked();
return master.force().loadAllTracks().join();
}
@Override
public boolean saveTrack(@NonNull Track track) {
checkTrack(track);
return master.saveTrack(((TrackLink) track).getMaster()).getUnchecked();
return master.force().saveTrack(((TrackLink) track).getMaster()).join();
}
@Override
public boolean deleteTrack(@NonNull Track track) {
checkTrack(track);
return master.deleteTrack(((TrackLink) track).getMaster()).getUnchecked();
return master.force().deleteTrack(((TrackLink) track).getMaster()).join();
}
@Override
public boolean saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
return master.saveUUIDData(checkUsername(username), uuid).getUnchecked();
return master.force().saveUUIDData(checkUsername(username), uuid).join();
}
@Override
public UUID getUUID(@NonNull String username) {
return master.getUUID(checkUsername(username)).getUnchecked();
return master.force().getUUID(checkUsername(username)).join();
}
}
@AllArgsConstructor
public class Future implements Datastore.Future {
private final me.lucko.luckperms.common.storage.Datastore master;
private final Storage master;
@Override
public java.util.concurrent.Future<Boolean> logAction(@NonNull LogEntry entry) {
return master.logAction(entry);
return master.force().logAction(entry);
}
@Override
public java.util.concurrent.Future<Log> getLog() {
AbstractFuture<Log> fut = new AbstractFuture<>();
master.getLog(log -> fut.complete(new LogLink(log)));
return fut;
return master.force().getLog().thenApply(log -> log == null ? null : new LogLink(log));
}
@Override
public java.util.concurrent.Future<Boolean> loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) {
return master.loadUser(uuid, checkUsername(username));
return master.force().loadUser(uuid, checkUsername(username));
}
@Override
public java.util.concurrent.Future<Boolean> loadUser(@NonNull UUID uuid) {
return master.loadUser(uuid, "null");
return master.force().loadUser(uuid, "null");
}
@Override
public java.util.concurrent.Future<Boolean> loadUser(@NonNull UUID uuid, @NonNull String username) {
return master.loadUser(uuid, checkUsername(username));
return master.force().loadUser(uuid, checkUsername(username));
}
@Override
public java.util.concurrent.Future<Boolean> saveUser(@NonNull User user) {
checkUser(user);
return master.saveUser(((UserLink) user).getMaster());
return master.force().saveUser(((UserLink) user).getMaster());
}
@Override
public java.util.concurrent.Future<Boolean> cleanupUsers() {
return master.cleanupUsers();
return master.force().cleanupUsers();
}
@Override
public java.util.concurrent.Future<Set<UUID>> getUniqueUsers() {
return master.getUniqueUsers();
return master.force().getUniqueUsers();
}
@Override
public java.util.concurrent.Future<Boolean> createAndLoadGroup(@NonNull String name) {
return master.createAndLoadGroup(checkName(name));
return master.force().createAndLoadGroup(checkName(name));
}
@Override
public java.util.concurrent.Future<Boolean> loadGroup(@NonNull String name) {
return master.loadGroup(checkName(name));
return master.force().loadGroup(checkName(name));
}
@Override
public java.util.concurrent.Future<Boolean> loadAllGroups() {
return master.loadAllGroups();
return master.force().loadAllGroups();
}
@Override
public java.util.concurrent.Future<Boolean> saveGroup(@NonNull Group group) {
checkGroup(group);
return master.saveGroup(((GroupLink) group).getMaster());
return master.force().saveGroup(((GroupLink) group).getMaster());
}
@Override
@@ -391,44 +390,44 @@ public class DatastoreLink implements Datastore {
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
return master.deleteGroup(((GroupLink) group).getMaster());
return master.force().deleteGroup(((GroupLink) group).getMaster());
}
@Override
public java.util.concurrent.Future<Boolean> createAndLoadTrack(@NonNull String name) {
return master.createAndLoadTrack(checkName(name));
return master.force().createAndLoadTrack(checkName(name));
}
@Override
public java.util.concurrent.Future<Boolean> loadTrack(@NonNull String name) {
return master.loadTrack(checkName(name));
return master.force().loadTrack(checkName(name));
}
@Override
public java.util.concurrent.Future<Boolean> loadAllTracks() {
return master.loadAllTracks();
return master.force().loadAllTracks();
}
@Override
public java.util.concurrent.Future<Boolean> saveTrack(@NonNull Track track) {
checkTrack(track);
return master.saveTrack(((TrackLink) track).getMaster());
return master.force().saveTrack(((TrackLink) track).getMaster());
}
@Override
public java.util.concurrent.Future<Boolean> deleteTrack(@NonNull Track track) {
checkTrack(track);
return master.deleteTrack(((TrackLink) track).getMaster());
return master.force().deleteTrack(((TrackLink) track).getMaster());
}
@Override
public java.util.concurrent.Future<Boolean> saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
return master.saveUUIDData(checkUsername(username), uuid);
return master.force().saveUUIDData(checkUsername(username), uuid);
}
@Override
public java.util.concurrent.Future<UUID> getUUID(@NonNull String username) {
return master.getUUID(checkUsername(username));
return master.force().getUUID(checkUsername(username));
}
}
@@ -103,7 +103,7 @@ public class LPConfigurationLink implements LPConfiguration {
@Override
public boolean getDebugPermissionChecks() {
return master.isDebugPermissionChecks();
return false;
}
@Override
@@ -0,0 +1,162 @@
/*
* 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.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.common.LuckPermsPlugin;
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.*;
/**
* Provides a link between {@link Storage} and {@link me.lucko.luckperms.common.storage.Storage}
*/
@AllArgsConstructor
public class StorageLink implements Storage {
private final LuckPermsPlugin plugin;
private final me.lucko.luckperms.common.storage.Storage master;
@Override
public String getName() {
return master.getName();
}
@Override
public boolean isAcceptingLogins() {
return master.isAcceptingLogins();
}
@Override
public Executor getSyncExecutor() {
return plugin.getSyncExecutor();
}
@Override
public Executor getAsyncExecutor() {
return plugin.getAsyncExecutor();
}
@Override
public CompletableFuture<Boolean> logAction(@NonNull LogEntry entry) {
return master.force().logAction(entry);
}
@Override
public CompletableFuture<Log> getLog() {
return master.force().getLog().thenApply(log -> log == null ? null : new LogLink(log));
}
@Override
public CompletableFuture<Boolean> loadUser(UUID uuid, String username) {
return master.force().loadUser(uuid, checkUsername(username));
}
@Override
public CompletableFuture<Boolean> saveUser(User user) {
checkUser(user);
return master.force().saveUser(((UserLink) user).getMaster());
}
@Override
public CompletableFuture<Boolean> cleanupUsers() {
return master.force().cleanupUsers();
}
@Override
public CompletableFuture<Set<UUID>> getUniqueUsers() {
return master.force().getUniqueUsers();
}
@Override
public CompletableFuture<Boolean> createAndLoadGroup(String name) {
return master.force().createAndLoadGroup(checkName(name));
}
@Override
public CompletableFuture<Boolean> loadGroup(String name) {
return master.force().loadGroup(checkName(name));
}
@Override
public CompletableFuture<Boolean> loadAllGroups() {
return master.force().loadAllGroups();
}
@Override
public CompletableFuture<Boolean> saveGroup(Group group) {
checkGroup(group);
return master.force().saveGroup(((GroupLink) group).getMaster());
}
@Override
public CompletableFuture<Boolean> deleteGroup(Group group) {
checkGroup(group);
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
return master.force().deleteGroup(((GroupLink) group).getMaster());
}
@Override
public CompletableFuture<Boolean> createAndLoadTrack(String name) {
return master.force().createAndLoadTrack(checkName(name));
}
@Override
public CompletableFuture<Boolean> loadTrack(String name) {
return master.force().loadTrack(checkName(name));
}
@Override
public CompletableFuture<Boolean> loadAllTracks() {
return master.force().loadAllTracks();
}
@Override
public CompletableFuture<Boolean> saveTrack(Track track) {
checkTrack(track);
return master.force().saveTrack(((TrackLink) track).getMaster());
}
@Override
public CompletableFuture<Boolean> deleteTrack(Track track) {
checkTrack(track);
return master.force().deleteTrack(((TrackLink) track).getMaster());
}
@Override
public CompletableFuture<Boolean> saveUUIDData(String username, UUID uuid) {
return master.force().saveUUIDData(checkUsername(username), uuid);
}
@Override
public CompletableFuture<UUID> getUUID(String username) {
return master.force().getUUID(checkUsername(username));
}
}
@@ -22,6 +22,7 @@
package me.lucko.luckperms.common.api.internal;
import com.google.common.base.Preconditions;
import lombok.experimental.UtilityClass;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Track;
@@ -32,57 +33,51 @@ import me.lucko.luckperms.common.utils.ArgumentChecker;
public class Utils {
public static void checkUser(User user) {
if (!(user instanceof UserLink)) {
throw new IllegalStateException("User instance cannot be handled by this implementation.");
}
Preconditions.checkState(user instanceof UserLink, "User instance cannot be handled by this implementation.");
}
public static void checkGroup(Group group) {
if (!(group instanceof GroupLink)) {
throw new IllegalStateException("Group instance cannot be handled by this implementation.");
}
Preconditions.checkState(group instanceof GroupLink, "Group instance cannot be handled by this implementation.");
}
public static void checkTrack(Track track) {
if (!(track instanceof TrackLink)) {
throw new IllegalStateException("Track instance cannot be handled by this implementation.");
}
Preconditions.checkState(track instanceof TrackLink, "Track instance cannot be handled by this implementation.");
}
public static String checkUsername(String s) {
if (ArgumentChecker.checkUsername(s)) {
throw new IllegalArgumentException("Invalid username entry '" + s + "'. Usernames must be less than 16 chars" +
" and only contain 'a-z A-Z 1-9 _'.");
}
Preconditions.checkArgument(
!ArgumentChecker.checkUsername(s),
"Invalid username entry '" + s + "'. Usernames must be less than 16 chars and only contain 'a-z A-Z 1-9 _'."
);
return s;
}
public static String checkName(String s) {
if (ArgumentChecker.checkName(s)) {
throw new IllegalArgumentException("Invalid name entry '" + s + "'. Names must be less than 37 chars" +
" and only contain 'a-z A-Z 1-9'.");
}
Preconditions.checkArgument(
!ArgumentChecker.checkName(s),
"Invalid name entry '" + s + "'. Names must be less than 37 chars and only contain 'a-z A-Z 1-9'."
);
return s.toLowerCase();
}
public static String checkServer(String s) {
if (ArgumentChecker.checkServer(s)) {
throw new IllegalArgumentException("Invalid server entry '" + s + "'. Server names can only contain alphanumeric characters.");
}
Preconditions.checkArgument(
!ArgumentChecker.checkServer(s),
"Invalid server entry '" + s + "'. Server names can only contain alphanumeric characters."
);
return s;
}
public static String checkNode(String s) {
if (ArgumentChecker.checkNode(s)) {
throw new IllegalArgumentException("Invalid node entry '" + s + "'. Nodes cannot contain '/' or '$' characters.");
}
Preconditions.checkArgument(
!ArgumentChecker.checkNode(s),
"Invalid node entry '" + s + "'. Nodes cannot contain '/' or '$' characters."
);
return s;
}
public static long checkTime(long l) {
if (ArgumentChecker.checkTime(l)) {
throw new IllegalArgumentException("Unix time '" + l + "' is invalid, as it has already passed.");
}
Preconditions.checkArgument(!ArgumentChecker.checkTime(l), "Unix time '" + l + "' is invalid, as it has already passed.");
return l;
}
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.api.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.UuidCache;
import java.util.UUID;
@@ -35,12 +36,12 @@ public class UuidCacheLink implements UuidCache {
private final me.lucko.luckperms.common.core.UuidCache master;
@Override
public UUID getUUID(UUID external) {
public UUID getUUID(@NonNull UUID external) {
return master.getUUID(external);
}
@Override
public UUID getExternalUUID(UUID internal) {
public UUID getExternalUUID(@NonNull UUID internal) {
return master.getExternalUUID(internal);
}
}
@@ -24,143 +24,67 @@ package me.lucko.luckperms.common.caching;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node;
import lombok.Getter;
import lombok.NoArgsConstructor;
import me.lucko.luckperms.api.caching.MetaData;
import me.lucko.luckperms.api.context.MutableContextSet;
import java.util.*;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Holds a user's cached meta for a given context
*/
@RequiredArgsConstructor
@NoArgsConstructor
public class MetaCache implements MetaData {
private final Contexts contexts;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final SortedMap<Integer, String> prefixes = new TreeMap<>(Comparator.reverseOrder());
private final SortedMap<Integer, String> suffixes = new TreeMap<>(Comparator.reverseOrder());
@Getter
private Map<String, String> meta = ImmutableMap.of();
private final Map<String, String> meta = new HashMap<>();
@Getter
private SortedMap<Integer, String> prefixes = ImmutableSortedMap.of();
public void loadMeta(SortedSet<LocalizedNode> nodes) {
invalidateCache();
@Getter
private SortedMap<Integer, String> suffixes = ImmutableSortedMap.of();
MutableContextSet contexts = MutableContextSet.fromSet(this.contexts.getContexts());
String server = contexts.getValues("server").stream().findAny().orElse(null);
String world = contexts.getValues("world").stream().findAny().orElse(null);
contexts.removeAll("server");
contexts.removeAll("world");
for (LocalizedNode ln : nodes) {
Node n = ln.getNode();
if (!n.getValue()) {
continue;
}
if (!n.isMeta() && !n.isPrefix() && n.isSuffix()) {
continue;
}
if (!n.shouldApplyOnServer(server, this.contexts.isIncludeGlobal(), false)) {
continue;
}
if (!n.shouldApplyOnWorld(world, this.contexts.isIncludeGlobalWorld(), false)) {
continue;
}
if (!n.shouldApplyWithContext(contexts, false)) {
continue;
}
if (n.isPrefix()) {
Map.Entry<Integer, String> value = n.getPrefix();
synchronized (this.prefixes) {
if (!this.prefixes.containsKey(value.getKey())) {
this.prefixes.put(value.getKey(), value.getValue());
}
}
continue;
}
if (n.isSuffix()) {
Map.Entry<Integer, String> value = n.getSuffix();
synchronized (this.suffixes) {
if (!this.suffixes.containsKey(value.getKey())) {
this.suffixes.put(value.getKey(), value.getValue());
}
}
continue;
}
if (n.isMeta()) {
Map.Entry<String, String> meta = n.getMeta();
synchronized (this.meta) {
if (!this.meta.containsKey(meta.getKey())) {
this.meta.put(meta.getKey(), meta.getValue());
}
}
this.meta.put(meta.getKey(), meta.getValue());
}
}
}
private void invalidateCache() {
synchronized (meta) {
meta.clear();
}
synchronized (prefixes) {
prefixes.clear();
}
synchronized (suffixes) {
suffixes.clear();
}
}
@Override
public Map<String, String> getMeta() {
synchronized (meta) {
return ImmutableMap.copyOf(meta);
}
}
@Override
public SortedMap<Integer, String> getPrefixes() {
synchronized (prefixes) {
return ImmutableSortedMap.copyOfSorted(prefixes);
}
}
@Override
public SortedMap<Integer, String> getSuffixes() {
synchronized (suffixes) {
return ImmutableSortedMap.copyOfSorted(suffixes);
public void loadMeta(MetaHolder meta) {
lock.writeLock().lock();
try {
this.meta = ImmutableMap.copyOf(meta.getMeta());
this.prefixes = ImmutableSortedMap.copyOfSorted(meta.getPrefixes());
this.suffixes = ImmutableSortedMap.copyOfSorted(meta.getSuffixes());
} finally {
lock.writeLock().unlock();
}
}
@Override
public String getPrefix() {
synchronized (prefixes) {
lock.readLock().lock();
try {
if (prefixes.isEmpty()) {
return null;
}
return prefixes.get(prefixes.firstKey());
} finally {
lock.readLock().unlock();
}
}
@Override
public String getSuffix() {
synchronized (suffixes) {
lock.readLock().lock();
try {
if (suffixes.isEmpty()) {
return null;
}
return suffixes.get(suffixes.firstKey());
} finally {
lock.readLock().unlock();
}
}
@@ -0,0 +1,65 @@
/*
* 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;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.api.Node;
import java.util.*;
/**
* Holds temporary mutable meta whilst this object is passed up the inheritance tree to accumulate meta from parents
*/
@Getter
@ToString
public class MetaHolder {
private final Map<String, String> meta = new HashMap<>();
private final SortedMap<Integer, String> prefixes = new TreeMap<>(Comparator.reverseOrder());
private final SortedMap<Integer, String> suffixes = new TreeMap<>(Comparator.reverseOrder());
public void accumulateNode(Node n) {
if (n.isMeta()) {
Map.Entry<String, String> entry = n.getMeta();
if (!meta.containsKey(entry.getKey())) {
meta.put(entry.getKey(), entry.getValue());
}
}
if (n.isPrefix()) {
Map.Entry<Integer, String> value = n.getPrefix();
if (!prefixes.containsKey(value.getKey())) {
prefixes.put(value.getKey(), value.getValue());
}
}
if (n.isSuffix()) {
Map.Entry<Integer, String> value = n.getSuffix();
if (!suffixes.containsKey(value.getKey())) {
suffixes.put(value.getKey(), value.getValue());
}
}
}
}
@@ -53,7 +53,8 @@ public class PermissionCache implements PermissionData {
public PermissionCache(Contexts contexts, User user, CalculatorFactory calculatorFactory) {
permissions = new ConcurrentHashMap<>();
calculator = calculatorFactory.build(contexts, user, permissions);
calculator = calculatorFactory.build(contexts, user);
calculator.updateBacking(permissions); // Initial setup.
}
@Override
@@ -64,6 +65,7 @@ public class PermissionCache implements PermissionData {
public void setPermissions(Map<String, Boolean> permissions) {
this.permissions.clear();
this.permissions.putAll(permissions);
calculator.updateBacking(this.permissions);
invalidateCache();
}
@@ -78,7 +78,7 @@ public class UserCache implements UserData {
@Override
public ListenableFuture<MetaCache> reload(Contexts contexts, MetaCache oldData) {
oldData.loadMeta(user.getAllNodes(null, contexts));
oldData.loadMeta(user.accumulateMeta(null, null, contexts));
return Futures.immediateFuture(oldData);
}
});
@@ -102,8 +102,8 @@ public class UserCache implements UserData {
@Override
public MetaCache calculateMeta(@NonNull Contexts contexts) {
MetaCache data = new MetaCache(contexts);
data.loadMeta(user.getAllNodes(null, contexts));
MetaCache data = new MetaCache();
data.loadMeta(user.accumulateMeta(null, null, contexts));
return data;
}
@@ -25,13 +25,11 @@ package me.lucko.luckperms.common.calculators;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.common.users.User;
import java.util.Map;
/**
* Creates a calculator instance given a set of contexts
*/
public interface CalculatorFactory {
PermissionCalculator build(Contexts contexts, User user, Map<String, Boolean> map);
PermissionCalculator build(Contexts contexts, User user);
}
@@ -22,21 +22,23 @@
package me.lucko.luckperms.common.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.api.Tristate;
import java.util.Map;
@AllArgsConstructor
public class MapProcessor implements PermissionProcessor {
@Getter
private final Map<String, Boolean> map;
private Map<String, Boolean> map = null;
@Override
public Tristate hasPermission(String permission) {
Boolean b = map.get(permission);
return b == null ? Tristate.UNDEFINED : Tristate.fromBoolean(b);
}
@Override
public void updateBacking(Map<String, Boolean> map) {
if (this.map == null) {
this.map = map;
}
}
}
@@ -30,6 +30,7 @@ import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.LuckPermsPlugin;
import java.util.List;
import java.util.Map;
/**
* Calculates and caches permissions
@@ -38,7 +39,6 @@ import java.util.List;
public class PermissionCalculator {
private final LuckPermsPlugin plugin;
private final String objectName;
private final boolean debug;
private final List<PermissionProcessor> processors;
private final LoadingCache<String, Tristate> cache = CacheBuilder.newBuilder()
@@ -56,11 +56,7 @@ public class PermissionCalculator {
public Tristate getPermissionValue(String permission) {
permission = permission.toLowerCase();
Tristate t = cache.getUnchecked(permission);
if (debug) {
plugin.getLog().info("Checking if " + objectName + " has permission: " + permission + " - (" + t.toString() + ")");
}
plugin.getDebugHandler().printOutput(objectName, permission, t);
return t;
}
@@ -76,4 +72,10 @@ public class PermissionCalculator {
return Tristate.UNDEFINED;
}
public synchronized void updateBacking(Map<String, Boolean> map) {
for (PermissionProcessor processor : processors) {
processor.updateBacking(map);
}
}
}
@@ -24,8 +24,11 @@ package me.lucko.luckperms.common.calculators;
import me.lucko.luckperms.api.Tristate;
import java.util.Map;
public interface PermissionProcessor {
Tristate hasPermission(String permission);
void updateBacking(Map<String, Boolean> map);
}
@@ -22,35 +22,41 @@
package me.lucko.luckperms.common.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.constants.Patterns;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
@AllArgsConstructor
public class RegexProcessor implements PermissionProcessor {
@Getter
private final Map<String, Boolean> map;
private Map<String, Boolean> regexPermissions = new ConcurrentHashMap<>();
@Override
public Tristate hasPermission(String permission) {
for (Map.Entry<String, Boolean> e : map.entrySet()) {
if (e.getKey().toLowerCase().startsWith("r=")) {
Pattern p = Patterns.compile(e.getKey().substring(2));
if (p == null) {
continue;
}
for (Map.Entry<String, Boolean> e : regexPermissions.entrySet()) {
Pattern p = Patterns.compile(e.getKey());
if (p == null) {
continue;
}
if (p.matcher(permission).matches()) {
return Tristate.fromBoolean(e.getValue());
}
if (p.matcher(permission).matches()) {
return Tristate.fromBoolean(e.getValue());
}
}
return Tristate.UNDEFINED;
}
@Override
public void updateBacking(Map<String, Boolean> map) {
regexPermissions.clear();
for (Map.Entry<String, Boolean> e : map.entrySet()) {
if (!e.getKey().startsWith("r=") && !e.getKey().startsWith("R=")) {
continue;
}
regexPermissions.put(e.getKey().substring(2), e.getValue());
}
}
}
@@ -22,17 +22,12 @@
package me.lucko.luckperms.common.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.api.Tristate;
import java.util.Map;
@AllArgsConstructor
public class WildcardProcessor implements PermissionProcessor {
@Getter
private final Map<String, Boolean> map;
private Map<String, Boolean> map = null;
@Override
public Tristate hasPermission(String permission) {
@@ -65,4 +60,11 @@ public class WildcardProcessor implements PermissionProcessor {
return Tristate.UNDEFINED;
}
@Override
public void updateBacking(Map<String, Boolean> map) {
if (this.map == null) {
this.map = map;
}
}
}
@@ -43,11 +43,7 @@ public class Arg {
private final String description;
public String asPrettyString() {
if (required) {
return "&8<&7" + name + "&8>";
} else {
return "&8[&7" + name + "&8]";
}
return required ? "&8<&7" + name + "&8>" : "&8[&7" + name + "&8]";
}
}
@@ -22,20 +22,17 @@
package me.lucko.luckperms.common.commands;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.constants.Permission;
import java.util.UUID;
import java.util.List;
import java.util.function.Predicate;
/**
* Wrapper interface to represent a CommandSender/CommandSource within the luckperms-common command implementations.
*/
public interface Sender {
public abstract class BaseCommand<T, S> extends Command<T, S> {
LuckPermsPlugin getPlatform();
String getName();
UUID getUuid();
void sendMessage(String s);
boolean hasPermission(Permission permission);
public BaseCommand(String name, String description, Permission permission, Predicate<Integer> argumentCheck, List<Arg> args, List<Command<S, ?>> children) {
super(name, description, permission, argumentCheck, args, children);
}
public abstract String getUsage();
}
@@ -0,0 +1,98 @@
/*
* 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.commands;
import com.google.common.collect.ImmutableList;
import lombok.Getter;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Permission;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
public abstract class Command<T, S> {
@Getter
private final String name;
@Getter
private final String description;
// Could be null
private final Permission permission;
@Getter
private final Predicate<Integer> argumentCheck;
// Could be null
private final List<Arg> args;
// Could be null
private final List<Command<S, ?>> children;
public Command(String name, String description, Permission permission, Predicate<Integer> argumentCheck, List<Arg> args, List<Command<S, ?>> children) {
this.name = name;
this.description = description;
this.permission = permission;
this.argumentCheck = argumentCheck;
this.args = args == null ? null : ImmutableList.copyOf(args);
this.children = children == null ? null : ImmutableList.copyOf(children);
}
public Command(String name, String description, Permission permission, Predicate<Integer> argumentCheck, List<Arg> args) {
this(name, description, permission, argumentCheck, args, null);
}
public Command(String name, String description, Predicate<Integer> argumentCheck) {
this(name, description, null, argumentCheck, null, null);
}
public abstract CommandResult execute(LuckPermsPlugin plugin, Sender sender, T t, List<String> args, String label) throws CommandException;
public List<String> tabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
return Collections.emptyList();
}
public abstract void sendUsage(Sender sender, String label);
public abstract void sendDetailedUsage(Sender sender, String label);
public boolean isAuthorized(Sender sender) {
return permission == null || permission.isAuthorized(sender);
}
public Optional<Permission> getPermission() {
return Optional.ofNullable(permission);
}
public Optional<List<Arg>> getArgs() {
return Optional.ofNullable(args);
}
public Optional<List<Command<S, ?>>> getChildren() {
return Optional.ofNullable(children);
}
}
@@ -20,16 +20,11 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.utils;
package me.lucko.luckperms.common.commands;
import com.google.common.util.concurrent.Futures;
import java.util.concurrent.Future;
public interface LPFuture<T> extends Future<T> {
default T getUnchecked() {
return Futures.getUnchecked(this);
}
/**
* Exception to be thrown if there is an error processing a command
*/
public class CommandException extends Exception {
}
@@ -34,12 +34,16 @@ import me.lucko.luckperms.common.commands.group.ListGroups;
import me.lucko.luckperms.common.commands.log.LogMainCommand;
import me.lucko.luckperms.common.commands.migration.MigrationMainCommand;
import me.lucko.luckperms.common.commands.misc.*;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.track.CreateTrack;
import me.lucko.luckperms.common.commands.track.DeleteTrack;
import me.lucko.luckperms.common.commands.track.ListTracks;
import me.lucko.luckperms.common.commands.track.TrackMainCommand;
import me.lucko.luckperms.common.commands.user.UserMainCommand;
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 java.util.ArrayList;
import java.util.Collections;
@@ -53,14 +57,16 @@ public class CommandManager {
private final LuckPermsPlugin plugin;
@Getter
private final List<MainCommand> mainCommands = ImmutableList.<MainCommand>builder()
private final List<BaseCommand> mainCommands = ImmutableList.<BaseCommand>builder()
.add(new UserMainCommand())
.add(new GroupMainCommand())
.add(new TrackMainCommand())
.add(new LogMainCommand())
.add(new SyncCommand())
.add(new NetworkSyncCommand())
.add(new InfoCommand())
.add(new DebugCommand())
.add(new VerboseCommand())
.add(new ImportCommand())
.add(new ExportCommand())
.add(new QueueCommand())
@@ -74,7 +80,6 @@ public class CommandManager {
.add(new ListTracks())
.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
@@ -97,51 +102,93 @@ public class CommandManager {
* @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;
}
Optional<MainCommand> o = mainCommands.stream()
// 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;
}
final MainCommand main = o.get();
// 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;
}
if (main.getRequiredArgsLength() == 0) {
try {
return main.execute(plugin, sender, null, label);
} catch (Exception e) {
e.printStackTrace();
return CommandResult.FAILURE;
}
}
List<String> arguments = new ArrayList<>(args);
handleRewrites(arguments);
arguments.remove(0); // remove the main command arg.
if (args.size() == 1) {
// 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;
}
List<String> arguments = new ArrayList<>(args);
handleRewrites(arguments);
// Try to execute the command.
CommandResult result;
try {
return main.execute(plugin, sender, arguments.subList(1, arguments.size()), label);
result = main.execute(plugin, sender, null, arguments, label);
} catch (CommandException e) {
result = handleException(e, sender, label, main);
} catch (Exception e) {
e.printStackTrace();
return CommandResult.FAILURE;
result = CommandResult.FAILURE;
}
return result;
}
public static CommandResult handleException(CommandException e, Sender sender, String label, Command command) {
if (e instanceof ArgumentUtils.ArgumentException) {
if (e instanceof ArgumentUtils.DetailedUsageException) {
command.sendDetailedUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.UseInheritException) {
Message.USE_INHERIT_COMMAND.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidServerException) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.PastDateException) {
Message.PAST_DATE_ERROR.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidDateException) {
Message.ILLEGAL_DATE_ERROR.send(sender, ((ArgumentUtils.InvalidDateException) e).getInvalidDate());
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidPriorityException) {
Message.META_INVALID_PRIORITY.send(sender, ((ArgumentUtils.InvalidPriorityException) e).getInvalidPriority());
return CommandResult.INVALID_ARGS;
}
}
// Not something we can catch.
e.printStackTrace();
return CommandResult.FAILURE;
}
/**
@@ -152,24 +199,29 @@ public class CommandManager {
*/
@SuppressWarnings("unchecked")
public List<String> onTabComplete(Sender sender, List<String> args) {
final List<MainCommand> mains = mainCommands.stream()
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());
}
Optional<MainCommand> o = mains.stream()
// Find a main command matching the first arg
Optional<Command> o = mains.stream()
.filter(m -> m.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
@@ -178,7 +230,8 @@ public class CommandManager {
return Collections.emptyList();
}
return o.get().onTabComplete(sender, args.subList(1, args.size()), plugin);
// 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) {
@@ -194,7 +247,6 @@ public class CommandManager {
return;
}
String s = args.get(2).toLowerCase();
switch (s) {
// Provide aliases
@@ -204,6 +256,7 @@ public class CommandManager {
args.remove(2);
args.add(2, "permission");
break;
case "chat":
case "m":
args.remove(2);
args.add(2, "meta");
@@ -212,7 +265,10 @@ public class CommandManager {
case "inherit":
case "inheritances":
case "group":
case "groups":
case "rank":
case "ranks":
case "parents":
args.remove(2);
args.add(2, "parent");
break;
@@ -229,6 +285,16 @@ public class CommandManager {
case "unsettemp":
args.add(2, "permission");
break;
case "haspermission":
args.remove(2);
args.add(2, "permission");
args.add(3, "check");
break;
case "inheritspermission":
args.remove(2);
args.add(2, "permission");
args.add(3, "checkinherits");
break;
case "listgroups":
args.remove(2);
args.add(2, "parent");
@@ -240,6 +306,11 @@ public class CommandManager {
args.add(2, "parent");
args.add(3, "add");
break;
case "setgroup":
args.remove(2);
args.add(2, "parent");
args.add(3, "set");
break;
case "removegroup":
case "unsetinherit":
args.remove(2);
@@ -274,6 +345,20 @@ public class CommandManager {
args.add(2, "meta");
break;
}
// Provide lazy set rewrite
boolean lazySet = (
args.size() >= 6 &&
args.get(2).equalsIgnoreCase("permission") &&
args.get(3).toLowerCase().startsWith("set") &&
(args.get(5).equalsIgnoreCase("none") || args.get(5).equalsIgnoreCase("0"))
);
if (lazySet) {
args.remove(5);
args.remove(3);
args.add(3, "unset");
}
}
}
}
@@ -34,13 +34,13 @@ public enum CommandResult {
INVALID_ARGS(false),
NO_PERMISSION(false);
private boolean booleanValue;
private boolean value;
public boolean booleanValue() {
return booleanValue;
public boolean asBoolean() {
return value;
}
static CommandResult of(boolean b) {
public static CommandResult of(boolean b) {
return b ? SUCCESS : FAILURE;
}
@@ -25,6 +25,7 @@ package me.lucko.luckperms.common.commands;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.common.commands.sender.Sender;
import java.util.ArrayList;
import java.util.List;
@@ -22,11 +22,13 @@
package me.lucko.luckperms.common.commands;
import com.google.common.collect.ImmutableList;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.ArrayList;
import java.util.Collections;
@@ -34,50 +36,27 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Getter
@AllArgsConstructor
public abstract class MainCommand<T> {
public abstract class MainCommand<T> extends BaseCommand<Void, T> {
/**
* The name of the main command
*/
private final String name;
/**
* The command usage
*/
private final String usage;
/**
* How many arguments are required for the command to run
*/
private final int requiredArgsLength;
/**
* A list of the sub commands under this main command
*/
@Getter
private final List<SubCommand<T>> subCommands;
private final String usage;
private final int minArgs; // equals 1 if the command doesn't take a mid argument, e.g. /lp user <USER> sub-command....
MainCommand(String name, String usage, int requiredArgsLength) {
this(name, usage, requiredArgsLength, ImmutableList.of());
public MainCommand(String name, String description, String usage, int minArgs, @NonNull List<Command<T, ?>> children) {
super(name, description, null, Predicates.alwaysFalse(), null, children);
this.usage = usage;
this.minArgs = minArgs;
}
/**
* Called when this main command is ran
* @param plugin a link to the main plugin instance
* @param sender the sender to executed the command
* @param args the stripped arguments given
* @param label the command label used
*/
protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (args.size() < requiredArgsLength) {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Void v, List<String> args, String label) throws CommandException {
if (args.size() < minArgs) {
sendUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
Optional<SubCommand<T>> o = getSubCommands().stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(requiredArgsLength - 1)))
Optional<Command<T, ?>> o = getSubCommands().stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(minArgs - 1)))
.limit(1)
.findAny();
@@ -86,26 +65,33 @@ public abstract class MainCommand<T> {
return CommandResult.INVALID_ARGS;
}
final SubCommand<T> sub = o.get();
final Command<T, ?> sub = o.get();
if (!sub.isAuthorized(sender)) {
Message.COMMAND_NO_PERMISSION.send(sender);
return CommandResult.NO_PERMISSION;
}
List<String> strippedArgs = new ArrayList<>();
if (args.size() > requiredArgsLength) {
strippedArgs.addAll(args.subList(requiredArgsLength, args.size()));
if (args.size() > minArgs) {
strippedArgs.addAll(args.subList(minArgs, args.size()));
}
if (sub.getIsArgumentInvalid().test(strippedArgs.size())) {
sub.sendDetailedUsage(sender);
if (sub.getArgumentCheck().test(strippedArgs.size())) {
sub.sendDetailedUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
final String name = args.get(0).toLowerCase();
T t = getTarget(name, plugin, sender);
if (t != null) {
CommandResult result = sub.execute(plugin, sender, t, strippedArgs, label);
CommandResult result;
try {
result = sub.execute(plugin, sender, t, strippedArgs, label);
} catch (CommandException e) {
result = CommandManager.handleException(e, sender, label, sub);
}
cleanup(t, plugin);
return result;
}
@@ -113,61 +99,9 @@ public abstract class MainCommand<T> {
return CommandResult.LOADING_ERROR;
}
/**
* Gets the object the command is acting upon, and runs the callback if successful
* @param target the name of the object to be looked up
* @param plugin a link to the main plugin instance
* @param sender the user who send the command (used to send error messages if the lookup was unsuccessful)
*/
protected abstract T getTarget(String target, LuckPermsPlugin plugin, Sender sender);
protected abstract void cleanup(T t, LuckPermsPlugin plugin);
/**
* Get a list of {@link T} objects for tab completion
* @param plugin a link to the main plugin instance
* @return a list of strings
*/
protected abstract List<String> getObjects(LuckPermsPlugin plugin);
/**
* Send the command usage to a sender
* @param sender the sender to send the usage to
* @param label the command label used
*/
protected void sendUsage(Sender sender, String label) {
if (getSubCommands().isEmpty()) {
Util.sendPluginMessage(sender, "&3> &a" + String.format(getUsage(), label));
return;
}
List<SubCommand> subs = getSubCommands().stream()
.filter(s -> s.isAuthorized(sender))
.collect(Collectors.toList());
if (subs.size() > 0) {
Util.sendPluginMessage(sender, "&b" + getName() + " Sub Commands: &7(" + String.format(getUsage(), label) + " ...)");
for (SubCommand s : subs) {
s.sendUsage(sender);
}
} else {
Message.COMMAND_NO_PERMISSION.send(sender);
}
}
/**
* If a sender has permission to use this command
* @param sender the sender trying to use the command
* @return true if the sender can use the command
*/
protected boolean isAuthorized(Sender sender) {
return getSubCommands().stream().filter(sc -> sc.isAuthorized(sender)).count() != 0;
}
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
final List<String> objects = getObjects(plugin);
@Override
public List<String> tabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
final List<String> objects = getTargets(plugin);
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
@@ -179,7 +113,7 @@ public abstract class MainCommand<T> {
.collect(Collectors.toList());
}
final List<SubCommand<T>> subs = getSubCommands().stream()
final List<Command<T, ?>> subs = getSubCommands().stream()
.filter(s -> s.isAuthorized(sender))
.collect(Collectors.toList());
@@ -196,7 +130,7 @@ public abstract class MainCommand<T> {
.collect(Collectors.toList());
}
Optional<SubCommand<T>> o = subs.stream()
Optional<Command<T, ?>> o = subs.stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(1)))
.limit(1)
.findAny();
@@ -205,6 +139,56 @@ public abstract class MainCommand<T> {
return Collections.emptyList();
}
return o.get().onTabComplete(plugin, sender, args.subList(2, args.size()));
return o.get().tabComplete(plugin, sender, args.subList(2, args.size()));
}
protected abstract List<String> getTargets(LuckPermsPlugin plugin);
protected abstract T getTarget(String target, LuckPermsPlugin plugin, Sender sender);
protected abstract void cleanup(T t, LuckPermsPlugin plugin);
@Override
public void sendUsage(Sender sender, String label) {
/*
if (getSubCommands().isEmpty()) {
Util.sendPluginMessage(sender, "&3> &a" + String.format(getUsage(), label));
return;
*/
List<Command> subs = getSubCommands().stream()
.filter(s -> s.isAuthorized(sender))
.collect(Collectors.toList());
if (subs.size() > 0) {
Util.sendPluginMessage(sender, "&b" + getName() + " Sub Commands: &7(" + String.format(usage, label) + " ...)");
for (Command s : subs) {
s.sendUsage(sender, label);
}
} else {
Message.COMMAND_NO_PERMISSION.send(sender);
}
}
@Override
public void sendDetailedUsage(Sender sender, String label) {
}
@Override
public boolean isAuthorized(Sender sender) {
return getSubCommands().stream().filter(sc -> sc.isAuthorized(sender)).count() != 0;
}
@Deprecated
@Override
public Optional<List<Command<T, ?>>> getChildren() {
return super.getChildren();
}
@SuppressWarnings("deprecation")
public List<Command<T, ?>> getSubCommands() {
return getChildren().get();
}
}
@@ -1,134 +0,0 @@
/*
* 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.commands;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Factory class to make a thread-safe sender instance
* @param <T> the command sender type
*/
@RequiredArgsConstructor
public abstract class SenderFactory<T> implements Runnable {
private final LuckPermsPlugin plugin;
private final Map<T, List<String>> messages = new HashMap<>();
private final AtomicBoolean shouldSend = new AtomicBoolean(false);
private final SenderFactory<T> factory = this;
protected abstract String getName(T t);
protected abstract UUID getUuid(T t);
protected abstract void sendMessage(T t, String s);
protected abstract boolean hasPermission(T t, String node);
public final Sender wrap(T t) {
return new SenderImp(plugin, t, null);
}
public final Sender wrap(T t, Set<Permission> toCheck) {
return new SenderImp(plugin, t, toCheck);
}
@Override
public final void run() {
if (!shouldSend.getAndSet(false)) {
return;
}
synchronized (messages) {
for (Map.Entry<T, List<String>> e : messages.entrySet()) {
for (String s : e.getValue()) {
factory.sendMessage(e.getKey(), s);
}
}
messages.clear();
}
}
private class SenderImp implements Sender {
private final WeakReference<T> tRef;
// Cache these permissions, so they can be accessed async
private Map<Permission, Boolean> perms;
@Getter
private final String name;
@Getter
private final UUID uuid;
private final boolean console;
@Getter
private final LuckPermsPlugin platform;
private SenderImp(LuckPermsPlugin platform, T t, Set<Permission> toCheck) {
this.platform = platform;
this.tRef = new WeakReference<>(t);
this.name = factory.getName(t);
this.uuid = factory.getUuid(t);
this.console = this.uuid.equals(Constants.getConsoleUUID()) || this.uuid.equals(Constants.getImporterUUID());
if (!this.console) {
this.perms = ((toCheck == null || toCheck.isEmpty()) ? Arrays.stream(Permission.values()) : toCheck.stream())
.collect(ImmutableCollectors.toImmutableMap(p -> p, p -> {
for (String s : p.getNodes()) {
if (factory.hasPermission(t, s)) {
return true;
}
}
return false;
}));
}
}
@Override
public void sendMessage(String s) {
final T t = tRef.get();
if (t != null) {
synchronized (messages) {
if (!messages.containsKey(t)) {
messages.put(t, new ArrayList<>());
}
messages.get(t).add(s);
}
shouldSend.set(true);
}
}
@Override
public boolean hasPermission(Permission permission) {
return console || perms.get(permission);
}
}
}
@@ -0,0 +1,75 @@
/*
* 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.commands;
import lombok.Getter;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Permission;
import java.util.List;
import java.util.function.Predicate;
public abstract class SingleCommand extends BaseCommand<Void, Void> {
@Getter
private final String usage;
public SingleCommand(String name, String description, String usage, Permission permission, Predicate<Integer> argumentCheck, List<Arg> args) {
super(name, description, permission, argumentCheck, args, null);
this.usage = usage;
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Void v, List<String> args, String label) throws CommandException {
return execute(plugin, sender, args, label);
}
public abstract CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) throws CommandException;
@Override
public void sendUsage(Sender sender, String label) {
String usage = "";
if (getArgs().isPresent()) {
usage += "&3 - &7";
for (Arg arg : getArgs().get()) {
usage += arg.asPrettyString() + " ";
}
}
Util.sendPluginMessage(sender, "&3> &a" + getName().toLowerCase() + usage);
}
@Override
public void sendDetailedUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&3&lCommand Usage &3- &b" + getName());
Util.sendPluginMessage(sender, "&b> &7" + getDescription());
if (getArgs().isPresent()) {
Util.sendPluginMessage(sender, "&3Arguments:");
for (Arg arg : getArgs().get()) {
Util.sendPluginMessage(sender, "&b- " + arg.asPrettyString() + "&3 -> &7" + arg.getDescription());
}
}
}
}
@@ -1,77 +0,0 @@
/*
* 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.commands;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.constants.Permission;
import java.util.Collections;
import java.util.List;
/**
* An extension of {@link MainCommand} for implementations without any subcommands
*/
public class SingleMainCommand extends MainCommand<Object> {
private final Permission permission;
public SingleMainCommand(String name, String usage, int requiredArgsLength, Permission permission) {
super(name, usage, requiredArgsLength);
this.permission = permission;
}
@Override
protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
// Do nothing, allow the implementation to override this
return null;
}
@Override
protected Object getTarget(String target, LuckPermsPlugin plugin, Sender sender) {
return null;
}
@Override
protected void cleanup(Object o, LuckPermsPlugin plugin) {
// Do nothing
}
@Override
protected List<String> getObjects(LuckPermsPlugin plugin) {
return Collections.emptyList();
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
@Override
public List<SubCommand<Object>> getSubCommands() {
return Collections.emptyList();
}
@Override
protected boolean isAuthorized(Sender sender) {
return permission.isAuthorized(sender);
}
}
@@ -22,10 +22,10 @@
package me.lucko.luckperms.common.commands;
import com.google.common.collect.ImmutableList;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.groups.Group;
@@ -43,62 +43,22 @@ import java.util.stream.Collectors;
* Abstract SubCommand class
*/
@Getter
@AllArgsConstructor
public abstract class SubCommand<T> {
public abstract class SubCommand<T> extends Command<T, Void> {
/**
* The name of the sub command
*/
private final String name;
/**
* A brief description of what the sub command does
*/
private final String description;
/**
* The permission needed to use this command
*/
private final Permission permission;
/**
* Predicate to test if the argument length given is invalid
*/
private final Predicate<? super Integer> isArgumentInvalid;
private final ImmutableList<Arg> args;
/**
* Called when this sub command is ran
* @param plugin a link to the main plugin instance
* @param sender the sender to executed the command
* @param t the object the command is operating on
* @param args the stripped arguments given
* @param label the command label used
*/
public abstract CommandResult execute(LuckPermsPlugin plugin, Sender sender, T t, List<String> args, String label);
/**
* Returns a list of suggestions, which are empty by default. Sub classes that give tab complete suggestions override
* this method to give their own list.
* @param plugin the plugin instance
* @param sender who is tab completing
* @param args the arguments so far
* @return a list of suggestions
*/
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
return Collections.emptyList();
public SubCommand(String name, String description, Permission permission, Predicate<Integer> argumentCheck, List<Arg> args) {
super(name, description, permission, argumentCheck, args);
}
/**
* Send the command usage to a sender
* @param sender the sender to send the usage to
*/
public void sendUsage(Sender sender) {
@Override
public void sendUsage(Sender sender, String label) {
String usage = "";
if (args != null) {
if (getArgs().isPresent()) {
usage += "&3 - &7";
for (Arg arg : args) {
for (Arg arg : getArgs().get()) {
usage += arg.asPrettyString() + " ";
}
}
@@ -106,30 +66,22 @@ public abstract class SubCommand<T> {
Util.sendPluginMessage(sender, "&3> &a" + getName().toLowerCase() + usage);
}
public void sendDetailedUsage(Sender sender) {
@Override
public void sendDetailedUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&3&lCommand Usage &3- &b" + getName());
Util.sendPluginMessage(sender, "&b> &7" + getDescription());
if (args != null) {
if (getArgs().isPresent()) {
Util.sendPluginMessage(sender, "&3Arguments:");
for (Arg arg : args) {
for (Arg arg : getArgs().get()) {
Util.sendPluginMessage(sender, "&b- " + arg.asPrettyString() + "&3 -> &7" + arg.getDescription());
}
}
}
/**
* If a sender has permission to use this command
* @param sender the sender trying to use the command
* @return true if the sender can use the command
*/
public boolean isAuthorized(Sender sender) {
return permission.isAuthorized(sender);
}
/*
* ----------------------------------------------------------------------------------
* Utility methods used by #onTabComplete and #execute implementations in sub classes
* Utility methods used by #tabComplete and #execute implementations in sub classes
* ----------------------------------------------------------------------------------
*/
@@ -162,32 +114,35 @@ public abstract class SubCommand<T> {
}
public static void save(User user, Sender sender, LuckPermsPlugin plugin) {
if (plugin.getDatastore().saveUser(user).getUnchecked()) {
boolean success = plugin.getStorage().force().saveUser(user).join();
user.getRefreshBuffer().requestDirectly();
if (success) {
Message.USER_SAVE_SUCCESS.send(sender);
} else {
Message.USER_SAVE_ERROR.send(sender);
}
user.getRefreshBuffer().request().getUnchecked();
}
public static void save(Group group, Sender sender, LuckPermsPlugin plugin) {
if (plugin.getDatastore().saveGroup(group).getUnchecked()) {
boolean success = plugin.getStorage().force().saveGroup(group).join();
plugin.getUpdateTaskBuffer().requestDirectly();
if (success) {
Message.GROUP_SAVE_SUCCESS.send(sender);
} else {
Message.GROUP_SAVE_ERROR.send(sender);
}
plugin.getUpdateTaskBuffer().request();
}
public static void save(Track track, Sender sender, LuckPermsPlugin plugin) {
if (plugin.getDatastore().saveTrack(track).getUnchecked()) {
boolean success = plugin.getStorage().force().saveTrack(track).join();
plugin.getUpdateTaskBuffer().requestDirectly();
if (success) {
Message.TRACK_SAVE_SUCCESS.send(sender);
} else {
Message.TRACK_SAVE_ERROR.send(sender);
}
plugin.getUpdateTaskBuffer().request();
}
}
@@ -22,11 +22,16 @@
package me.lucko.luckperms.common.commands.generic;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
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.core.PermissionHolder;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.ArrayList;
import java.util.Collections;
@@ -34,29 +39,24 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class SecondaryMainCommand<T extends PermissionHolder> extends SubCommand<T> {
public class SharedMainCommand<T extends PermissionHolder> extends SubCommand<T> {
private boolean user;
private final List<SecondarySubCommand> secondaryCommands;
private final List<SharedSubCommand> secondaryCommands;
public SecondaryMainCommand(String name, String description, boolean user, List<SecondarySubCommand> secondaryCommands) {
super(name, description, null, Predicate.alwaysFalse(),
!name.equals("Meta") ? ImmutableList.copyOf(secondaryCommands.stream()
.map(s -> Arg.create(s.getName(), false, s.getDescription()))
.collect(Collectors.toList())
) : null
);
public SharedMainCommand(String name, String description, boolean user, List<SharedSubCommand> secondaryCommands) {
super(name, description, null, Predicates.alwaysFalse(), null);
this.secondaryCommands = secondaryCommands;
this.user = user;
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, T t, List<String> args, String label) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, T t, List<String> args, String label) throws CommandException {
if (args.size() == 0) {
sendUsageDetailed(sender, user, label);
return CommandResult.INVALID_ARGS;
}
Optional<SecondarySubCommand> o = secondaryCommands.stream()
Optional<SharedSubCommand> o = secondaryCommands.stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
@@ -66,7 +66,7 @@ public class SecondaryMainCommand<T extends PermissionHolder> extends SubCommand
return CommandResult.INVALID_ARGS;
}
final SecondarySubCommand sub = o.get();
final SharedSubCommand sub = o.get();
if (!sub.isAuthorized(sender, user)) {
Message.COMMAND_NO_PERMISSION.send(sender);
return CommandResult.NO_PERMISSION;
@@ -82,12 +82,56 @@ public class SecondaryMainCommand<T extends PermissionHolder> extends SubCommand
return CommandResult.INVALID_ARGS;
}
return sub.execute(plugin, sender, t, strippedArgs);
CommandResult result;
try {
result = sub.execute(plugin, sender, t, strippedArgs);
} catch (CommandException e) {
result = handleException(e, sender, sub);
}
return result;
}
private static CommandResult handleException(CommandException e, Sender sender, SharedSubCommand command) {
if (e instanceof ArgumentUtils.ArgumentException) {
if (e instanceof ArgumentUtils.DetailedUsageException) {
command.sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.UseInheritException) {
Message.USE_INHERIT_COMMAND.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidServerException) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.PastDateException) {
Message.PAST_DATE_ERROR.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidDateException) {
Message.ILLEGAL_DATE_ERROR.send(sender, ((ArgumentUtils.InvalidDateException) e).getInvalidDate());
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidPriorityException) {
Message.META_INVALID_PRIORITY.send(sender, ((ArgumentUtils.InvalidPriorityException) e).getInvalidPriority());
return CommandResult.INVALID_ARGS;
}
}
// Not something we can catch.
e.printStackTrace();
return CommandResult.FAILURE;
}
@Override
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
final List<SecondarySubCommand> subs = secondaryCommands.stream()
public List<String> tabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
final List<SharedSubCommand> subs = secondaryCommands.stream()
.filter(s -> s.isAuthorized(sender, user))
.collect(Collectors.toList());
@@ -104,7 +148,7 @@ public class SecondaryMainCommand<T extends PermissionHolder> extends SubCommand
.collect(Collectors.toList());
}
Optional<SecondarySubCommand> o = subs.stream()
Optional<SharedSubCommand> o = subs.stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
@@ -118,7 +162,7 @@ public class SecondaryMainCommand<T extends PermissionHolder> extends SubCommand
@Override
public boolean isAuthorized(Sender sender) {
for (SecondarySubCommand subCommand : secondaryCommands) {
for (SharedSubCommand subCommand : secondaryCommands) {
if (subCommand.isAuthorized(sender, user)) {
return true;
}
@@ -127,7 +171,7 @@ public class SecondaryMainCommand<T extends PermissionHolder> extends SubCommand
}
private void sendUsageDetailed(Sender sender, boolean user, String label) {
List<SecondarySubCommand> subs = secondaryCommands.stream()
List<SharedSubCommand> subs = secondaryCommands.stream()
.filter(s -> s.isAuthorized(sender, user))
.collect(Collectors.toList());
@@ -138,7 +182,7 @@ public class SecondaryMainCommand<T extends PermissionHolder> extends SubCommand
Util.sendPluginMessage(sender, "&b" + getName() + " Sub Commands: &7(" + String.format("/%s group <group> " + getName().toLowerCase() + " ...)", label));
}
for (SecondarySubCommand s : subs) {
for (SharedSubCommand s : subs) {
s.sendUsage(sender);
}
@@ -26,7 +26,12 @@ import com.google.common.collect.ImmutableList;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.groups.Group;
@@ -38,7 +43,7 @@ import java.util.function.Predicate;
@Getter
@AllArgsConstructor
public abstract class SecondarySubCommand {
public abstract class SharedSubCommand {
/**
* The name of the sub command
@@ -63,7 +68,7 @@ public abstract class SecondarySubCommand {
private final ImmutableList<Arg> args;
public abstract CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args);
public abstract CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException;
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
return Collections.emptyList();
@@ -23,13 +23,13 @@
package me.lucko.luckperms.common.commands.generic.meta;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.commands.generic.SecondaryMainCommand;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedMainCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.core.PermissionHolder;
public class CommandMeta<T extends PermissionHolder> extends SecondaryMainCommand<T> {
public class CommandMeta<T extends PermissionHolder> extends SharedMainCommand<T> {
public CommandMeta(boolean user) {
super("Meta", "Edit metadata values", user, ImmutableList.<SecondarySubCommand>builder()
super("Meta", "Edit metadata values", user, ImmutableList.<SharedSubCommand>builder()
.add(new MetaInfo())
.add(new MetaSet())
.add(new MetaUnset())
@@ -25,22 +25,26 @@ package me.lucko.luckperms.common.commands.generic.meta;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.List;
import java.util.stream.Collectors;
public class MetaAddPrefix extends SecondarySubCommand {
public class MetaAddPrefix extends SharedSubCommand {
public MetaAddPrefix() {
super("addprefix", "Adds a prefix", Permission.USER_META_ADDPREFIX, Permission.GROUP_META_ADDPREFIX, Predicate.notInRange(2, 4),
super("addprefix", "Adds a prefix", Permission.USER_META_ADDPREFIX, Permission.GROUP_META_ADDPREFIX,
Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
Arg.create("prefix", true, "the prefix string"),
@@ -51,51 +55,37 @@ public class MetaAddPrefix extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
final String prefix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String prefix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
final String node = "prefix." + priority + "." + MetaUtils.escapeCharacters(prefix);
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 3) {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.setPermission(node, true);
Message.ADDPREFIX_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority);
break;
case SERVER:
holder.setPermission(node, true, server);
Message.ADDPREFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server);
LogEntry.build().actor(sender).acted(holder)
.action("meta addprefix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
break;
case SERVER_AND_WORLD:
holder.setPermission(node, true, server, world);
Message.ADDPREFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server, world);
LogEntry.build().actor(sender).acted(holder)
.action("meta addprefix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
holder.setPermission(node, true);
Message.ADDPREFIX_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority);
LogEntry.build().actor(sender).acted(holder)
.action("meta addprefix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta addprefix " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_PREFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
@@ -25,22 +25,26 @@ package me.lucko.luckperms.common.commands.generic.meta;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.List;
import java.util.stream.Collectors;
public class MetaAddSuffix extends SecondarySubCommand {
public class MetaAddSuffix extends SharedSubCommand {
public MetaAddSuffix() {
super("addsuffix", "Adds a suffix", Permission.USER_META_ADDSUFFIX, Permission.GROUP_META_ADDSUFFIX, Predicate.notInRange(2, 4),
super("addsuffix", "Adds a suffix", Permission.USER_META_ADDSUFFIX, Permission.GROUP_META_ADDSUFFIX,
Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
Arg.create("suffix", true, "the suffix string"),
@@ -51,51 +55,37 @@ public class MetaAddSuffix extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
final String suffix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String suffix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
final String node = "suffix." + priority + "." + MetaUtils.escapeCharacters(suffix);
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 3) {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.setPermission(node, true);
Message.ADDSUFFIX_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority);
break;
case SERVER:
holder.setPermission(node, true, server);
Message.ADDSUFFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server);
LogEntry.build().actor(sender).acted(holder)
.action("meta addsuffix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
break;
case SERVER_AND_WORLD:
holder.setPermission(node, true, server, world);
Message.ADDSUFFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server, world);
LogEntry.build().actor(sender).acted(holder)
.action("meta addsuffix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
holder.setPermission(node, true);
Message.ADDSUFFIX_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority);
LogEntry.build().actor(sender).acted(holder)
.action("meta addsuffix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta addsuffix " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_SUFFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
@@ -25,23 +25,27 @@ package me.lucko.luckperms.common.commands.generic.meta;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.DateUtil;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.List;
import java.util.stream.Collectors;
public class MetaAddTempPrefix extends SecondarySubCommand {
public class MetaAddTempPrefix extends SharedSubCommand {
public MetaAddTempPrefix() {
super("addtempprefix", "Adds a prefix temporarily", Permission.USER_META_ADDTEMP_PREFIX, Permission.GROUP_META_ADDTEMP_PREFIX, Predicate.notInRange(3, 5),
super("addtempprefix", "Adds a prefix temporarily", Permission.USER_META_ADDTEMP_PREFIX,
Permission.GROUP_META_ADDTEMP_PREFIX, Predicates.notInRange(3, 5),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
Arg.create("prefix", true, "the prefix string"),
@@ -53,68 +57,44 @@ public class MetaAddTempPrefix extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
final String prefix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
long duration;
try {
duration = Long.parseLong(args.get(2));
} catch (NumberFormatException e) {
try {
duration = DateUtil.parseDateDiff(args.get(2), true);
} catch (DateUtil.IllegalDateException e1) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
return CommandResult.INVALID_ARGS;
}
}
if (DateUtil.shouldExpire(duration)) {
Message.PAST_DATE_ERROR.send(sender);
return CommandResult.INVALID_ARGS;
}
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String prefix = ArgumentUtils.handleNodeWithoutCheck(1, args);
long duration = ArgumentUtils.handleDuration(2, args);
String server = ArgumentUtils.handleServer(3, args);
String world = ArgumentUtils.handleWorld(4, args);
final String node = "prefix." + priority + "." + MetaUtils.escapeCharacters(prefix);
try {
if (args.size() >= 4) {
final String server = args.get(3).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 4) {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.setPermission(node, true, duration);
Message.ADD_TEMP_PREFIX_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority,
DateUtil.formatDateDiff(duration)
);
break;
case SERVER:
holder.setPermission(node, true, server, duration);
Message.ADD_TEMP_PREFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("meta addtempprefix " + priority + " " + args.get(1) + " " + duration + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(4).toLowerCase();
Message.ADD_TEMP_PREFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority,
server, DateUtil.formatDateDiff(duration)
);
break;
case SERVER_AND_WORLD:
holder.setPermission(node, true, server, world, duration);
Message.ADD_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server, world, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("meta addtempprefix " + priority + " " + args.get(1) + " " + duration + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
holder.setPermission(node, true, duration);
Message.ADD_TEMP_PREFIX_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("meta addtempprefix " + priority + " " + args.get(1) + " " + duration)
.build().submit(plugin, sender);
Message.ADD_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority,
server, world, DateUtil.formatDateDiff(duration)
);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta addtempprefix " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_PREFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
@@ -25,23 +25,27 @@ package me.lucko.luckperms.common.commands.generic.meta;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.DateUtil;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.List;
import java.util.stream.Collectors;
public class MetaAddTempSuffix extends SecondarySubCommand {
public class MetaAddTempSuffix extends SharedSubCommand {
public MetaAddTempSuffix() {
super("addtempsuffix", "Adds a suffix temporarily", Permission.USER_META_ADDTEMP_SUFFIX, Permission.GROUP_META_ADDTEMP_SUFFIX, Predicate.notInRange(3, 5),
super("addtempsuffix", "Adds a suffix temporarily", Permission.USER_META_ADDTEMP_SUFFIX,
Permission.GROUP_META_ADDTEMP_SUFFIX, Predicates.notInRange(3, 5),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
Arg.create("suffix", true, "the suffix string"),
@@ -53,68 +57,44 @@ public class MetaAddTempSuffix extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
final String suffix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
long duration;
try {
duration = Long.parseLong(args.get(2));
} catch (NumberFormatException e) {
try {
duration = DateUtil.parseDateDiff(args.get(2), true);
} catch (DateUtil.IllegalDateException e1) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
return CommandResult.INVALID_ARGS;
}
}
if (DateUtil.shouldExpire(duration)) {
Message.PAST_DATE_ERROR.send(sender);
return CommandResult.INVALID_ARGS;
}
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String suffix = ArgumentUtils.handleNodeWithoutCheck(1, args);
long duration = ArgumentUtils.handleDuration(2, args);
String server = ArgumentUtils.handleServer(3, args);
String world = ArgumentUtils.handleWorld(4, args);
final String node = "suffix." + priority + "." + MetaUtils.escapeCharacters(suffix);
try {
if (args.size() >= 4) {
final String server = args.get(3).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 4) {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.setPermission(node, true, duration);
Message.ADD_TEMP_SUFFIX_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority,
DateUtil.formatDateDiff(duration)
);
break;
case SERVER:
holder.setPermission(node, true, server, duration);
Message.ADD_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("meta addtempsuffix " + priority + " " + args.get(1) + " " + duration + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(4).toLowerCase();
Message.ADD_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority,
server, DateUtil.formatDateDiff(duration)
);
break;
case SERVER_AND_WORLD:
holder.setPermission(node, true, server, world, duration);
Message.ADD_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server, world, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("meta addtempsuffix " + priority + " " + args.get(1) + " " + duration + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
holder.setPermission(node, true, duration);
Message.ADD_TEMP_SUFFIX_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("meta addtempsuffix " + priority + " " + args.get(1) + " " + duration)
.build().submit(plugin, sender);
Message.ADD_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority,
server, world, DateUtil.formatDateDiff(duration)
);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta addtempsuffix " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_SUFFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
@@ -24,22 +24,24 @@ package me.lucko.luckperms.common.commands.generic.meta;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.List;
import java.util.stream.Collectors;
public class MetaClear extends SecondarySubCommand {
public class MetaClear extends SharedSubCommand {
public MetaClear() {
super("clear", "Clears all chat meta", Permission.USER_META_CLEAR, Permission.GROUP_META_CLEAR, Predicate.notInRange(0, 2),
super("clear", "Clears all chat meta", Permission.USER_META_CLEAR, Permission.GROUP_META_CLEAR, Predicates.notInRange(0, 2),
Arg.list(
Arg.create("server", false, "the server name to filter by"),
Arg.create("world", false, "the world name to filter by")
@@ -48,25 +50,22 @@ public class MetaClear extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
int before = holder.getNodes().size();
if (args.size() == 0) {
holder.clearMeta();
} else {
final String server = args.get(0);
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
String server = ArgumentUtils.handleServer(0, args);
String world = ArgumentUtils.handleWorld(1, args);
if (args.size() == 2) {
final String world = args.get(1);
holder.clearMeta(server, world);
} else {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.clearMeta();
break;
case SERVER:
holder.clearMeta(server);
}
break;
case SERVER_AND_WORLD:
holder.clearMeta(server, world);
break;
}
int changed = before - holder.getNodes().size();
@@ -76,7 +75,10 @@ public class MetaClear extends SecondarySubCommand {
Message.META_CLEAR_SUCCESS.send(sender, holder.getFriendlyName(), changed);
}
LogEntry.build().actor(sender).acted(holder).action("meta clear " + args.stream().collect(Collectors.joining(" "))).build().submit(plugin, sender);
LogEntry.build().actor(sender).acted(holder)
.action("meta clear " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
}
@@ -25,48 +25,41 @@ package me.lucko.luckperms.common.commands.generic.meta;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.Util;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.*;
public class MetaInfo extends SecondarySubCommand {
public class MetaInfo extends SharedSubCommand {
public MetaInfo() {
super("info", "Shows all chat meta", Permission.USER_META_INFO, Permission.GROUP_META_INFO, Predicate.alwaysFalse(), null);
super("info", "Shows all chat meta", Permission.USER_META_INFO, Permission.GROUP_META_INFO, Predicates.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
SortedSet<Map.Entry<Integer, String>> prefixes = new TreeSet<>(Util.getMetaComparator().reversed());
SortedSet<Map.Entry<Integer, String>> suffixes = new TreeSet<>(Util.getMetaComparator().reversed());
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
SortedSet<Map.Entry<Integer, Node>> prefixes = new TreeSet<>(Util.META_COMPARATOR.reversed());
SortedSet<Map.Entry<Integer, Node>> suffixes = new TreeSet<>(Util.META_COMPARATOR.reversed());
Set<Node> meta = new HashSet<>();
// Collect data
for (Node node : holder.getAllNodes(null, Contexts.allowAll())) {
if (!node.isSuffix() && !node.isPrefix()) {
if (!node.isSuffix() && !node.isPrefix() && !node.isMeta()) {
continue;
}
StringBuilder sb = new StringBuilder();
if (node.isServerSpecific()) {
if (node.isWorldSpecific()) {
sb.append("&6W=").append(node.getWorld().get()).append(" ");
}
sb.append("&6S=").append(node.getServer().get()).append(" ");
}
if (node.isPrefix()) {
sb.append(node.getPrefix().getValue());
prefixes.add(new AbstractMap.SimpleEntry<>(node.getPrefix().getKey(), sb.toString()));
}
if (node.isSuffix()) {
sb.append(node.getSuffix().getValue());
suffixes.add(new AbstractMap.SimpleEntry<>(node.getSuffix().getKey(), sb.toString()));
prefixes.add(new AbstractMap.SimpleEntry<>(node.getPrefix().getKey(), node));
} else if (node.isSuffix()) {
suffixes.add(new AbstractMap.SimpleEntry<>(node.getSuffix().getKey(), node));
} else if (node.isMeta()) {
meta.add(node);
}
}
@@ -74,8 +67,13 @@ public class MetaInfo extends SecondarySubCommand {
Message.CHAT_META_PREFIX_NONE.send(sender, holder.getFriendlyName());
} else {
Message.CHAT_META_PREFIX_HEADER.send(sender, holder.getFriendlyName());
for (Map.Entry<Integer, String> e : prefixes) {
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue());
for (Map.Entry<Integer, Node> e : prefixes) {
if (e.getValue().isServerSpecific() || e.getValue().isWorldSpecific() || !e.getValue().getContexts().isEmpty()) {
String context = Util.getNodeContextDescription(e.getValue());
Message.CHAT_META_ENTRY_WITH_CONTEXT.send(sender, e.getKey(), e.getValue().getPrefix().getValue(), context);
} else {
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue().getPrefix().getValue());
}
}
}
@@ -83,8 +81,27 @@ public class MetaInfo extends SecondarySubCommand {
Message.CHAT_META_SUFFIX_NONE.send(sender, holder.getFriendlyName());
} else {
Message.CHAT_META_SUFFIX_HEADER.send(sender, holder.getFriendlyName());
for (Map.Entry<Integer, String> e : suffixes) {
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue());
for (Map.Entry<Integer, Node> e : suffixes) {
if (e.getValue().isServerSpecific() || e.getValue().isWorldSpecific() || !e.getValue().getContexts().isEmpty()) {
String context = Util.getNodeContextDescription(e.getValue());
Message.CHAT_META_ENTRY_WITH_CONTEXT.send(sender, e.getKey(), e.getValue().getSuffix().getValue(), context);
} else {
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue().getSuffix().getValue());
}
}
}
if (meta.isEmpty()) {
Message.META_NONE.send(sender, holder.getFriendlyName());
} else {
Message.META_HEADER.send(sender, holder.getFriendlyName());
for (Node m : meta) {
if (m.isServerSpecific() || m.isWorldSpecific() || !m.getContexts().isEmpty()) {
String context = Util.getNodeContextDescription(m);
Message.META_ENTRY_WITH_CONTEXT.send(sender, m.getMeta().getKey(), m.getMeta().getValue(), context);
} else {
Message.META_ENTRY.send(sender, m.getMeta().getKey(), m.getMeta().getValue());
}
}
}
@@ -26,23 +26,27 @@ import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class MetaRemovePrefix extends SecondarySubCommand {
public class MetaRemovePrefix extends SharedSubCommand {
public MetaRemovePrefix() {
super("removeprefix", "Removes a prefix", Permission.USER_META_REMOVEPREFIX, Permission.GROUP_META_REMOVEPREFIX, Predicate.notInRange(2, 4),
super("removeprefix", "Removes a prefix", Permission.USER_META_REMOVEPREFIX, Permission.GROUP_META_REMOVEPREFIX,
Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
Arg.create("prefix", true, "the prefix string"),
@@ -53,32 +57,14 @@ public class MetaRemovePrefix extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
final String prefix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String prefix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
// Handle bulk removal
if (prefix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
if (args.size() >= 3) {
server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 3) {
world = args.get(3).toLowerCase();
}
}
List<Node> toRemove = new ArrayList<>();
for (Node node : holder.getNodes()) {
if (!node.isPrefix()) continue;
@@ -111,48 +97,36 @@ public class MetaRemovePrefix extends SecondarySubCommand {
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
save(holder, sender, plugin);
return CommandResult.SUCCESS;
}
} else {
final String node = "prefix." + priority + "." + MetaUtils.escapeCharacters(prefix);
final String node = "prefix." + priority + "." + MetaUtils.escapeCharacters(prefix);
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 3) {
holder.unsetPermission(node, server);
Message.REMOVEPREFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server);
LogEntry.build().actor(sender).acted(holder)
.action("meta removeprefix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
holder.unsetPermission(node, server, world);
Message.REMOVEPREFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server, world);
LogEntry.build().actor(sender).acted(holder)
.action("meta removeprefix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
try {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.unsetPermission(node);
Message.REMOVEPREFIX_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority);
LogEntry.build().actor(sender).acted(holder)
.action("meta removeprefix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_PREFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
break;
case SERVER:
holder.unsetPermission(node, server);
Message.REMOVEPREFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server);
break;
case SERVER_AND_WORLD:
holder.unsetPermission(node, server, world);
Message.REMOVEPREFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server, world);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta removeprefix " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_PREFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -26,23 +26,27 @@ import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class MetaRemoveSuffix extends SecondarySubCommand {
public class MetaRemoveSuffix extends SharedSubCommand {
public MetaRemoveSuffix() {
super("removesuffix", "Removes a suffix", Permission.USER_META_REMOVESUFFIX, Permission.GROUP_META_REMOVESUFFIX, Predicate.notInRange(2, 4),
super("removesuffix", "Removes a suffix", Permission.USER_META_REMOVESUFFIX, Permission.GROUP_META_REMOVESUFFIX,
Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
Arg.create("suffix", true, "the suffix string"),
@@ -53,32 +57,14 @@ public class MetaRemoveSuffix extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
final String suffix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String suffix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
// Handle bulk removal
if (suffix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
if (args.size() >= 3) {
server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 3) {
world = args.get(3).toLowerCase();
}
}
List<Node> toRemove = new ArrayList<>();
for (Node node : holder.getNodes()) {
if (!node.isSuffix()) continue;
@@ -111,48 +97,36 @@ public class MetaRemoveSuffix extends SecondarySubCommand {
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
save(holder, sender, plugin);
return CommandResult.SUCCESS;
}
} else {
final String node = "suffix." + priority + "." + MetaUtils.escapeCharacters(suffix);
final String node = "suffix." + priority + "." + MetaUtils.escapeCharacters(suffix);
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 3) {
holder.unsetPermission(node, server);
Message.REMOVESUFFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server);
LogEntry.build().actor(sender).acted(holder)
.action("meta removesuffix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
holder.unsetPermission(node, server, world);
Message.REMOVESUFFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server, world);
LogEntry.build().actor(sender).acted(holder)
.action("meta removesuffix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
try {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.unsetPermission(node);
Message.REMOVESUFFIX_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority);
LogEntry.build().actor(sender).acted(holder)
.action("meta removesuffix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_SUFFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
break;
case SERVER:
holder.unsetPermission(node, server);
Message.REMOVESUFFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server);
break;
case SERVER_AND_WORLD:
holder.unsetPermission(node, server, world);
Message.REMOVESUFFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server, world);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta removesuffix " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_SUFFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -26,23 +26,26 @@ import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class MetaRemoveTempPrefix extends SecondarySubCommand {
public class MetaRemoveTempPrefix extends SharedSubCommand {
public MetaRemoveTempPrefix() {
super("removetempprefix", "Removes a temporary prefix", Permission.USER_META_REMOVETEMP_PREFIX, Permission.GROUP_META_REMOVETEMP_PREFIX, Predicate.notInRange(2, 4),
super("removetempprefix", "Removes a temporary prefix", Permission.USER_META_REMOVETEMP_PREFIX, Permission.GROUP_META_REMOVETEMP_PREFIX, Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
Arg.create("prefix", true, "the prefix string"),
@@ -53,32 +56,14 @@ public class MetaRemoveTempPrefix extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
final String prefix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String prefix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
// Handle bulk removal
if (prefix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
if (args.size() >= 3) {
server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 3) {
world = args.get(3).toLowerCase();
}
}
List<Node> toRemove = new ArrayList<>();
for (Node node : holder.getNodes()) {
if (!node.isPrefix()) continue;
@@ -111,48 +96,36 @@ public class MetaRemoveTempPrefix extends SecondarySubCommand {
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
save(holder, sender, plugin);
return CommandResult.SUCCESS;
}
} else {
final String node = "prefix." + priority + "." + MetaUtils.escapeCharacters(prefix);
final String node = "prefix." + priority + "." + MetaUtils.escapeCharacters(prefix);
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 3) {
holder.unsetPermission(node, server, true);
Message.REMOVE_TEMP_PREFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server);
LogEntry.build().actor(sender).acted(holder)
.action("meta removetempprefix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
holder.unsetPermission(node, server, world, true);
Message.REMOVE_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server, world);
LogEntry.build().actor(sender).acted(holder)
.action("meta removetempprefix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
try {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.unsetPermission(node, true);
Message.REMOVE_TEMP_PREFIX_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority);
LogEntry.build().actor(sender).acted(holder)
.action("meta removetempprefix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_PREFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
break;
case SERVER:
holder.unsetPermission(node, server, true);
Message.REMOVE_TEMP_PREFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server);
break;
case SERVER_AND_WORLD:
holder.unsetPermission(node, server, world, true);
Message.REMOVE_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), prefix, priority, server, world);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta removetempprefix " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_PREFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -26,23 +26,26 @@ import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class MetaRemoveTempSuffix extends SecondarySubCommand {
public class MetaRemoveTempSuffix extends SharedSubCommand {
public MetaRemoveTempSuffix() {
super("removetempsuffix", "Removes a temporary suffix", Permission.USER_META_REMOVETEMP_SUFFIX, Permission.GROUP_META_REMOVETEMP_SUFFIX, Predicate.notInRange(2, 4),
super("removetempsuffix", "Removes a temporary suffix", Permission.USER_META_REMOVETEMP_SUFFIX, Permission.GROUP_META_REMOVETEMP_SUFFIX, Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
Arg.create("suffix", true, "the suffix string"),
@@ -53,32 +56,14 @@ public class MetaRemoveTempSuffix extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
final String suffix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
int priority = ArgumentUtils.handlePriority(0, args);
String suffix = ArgumentUtils.handleNodeWithoutCheck(1, args);
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
// Handle bulk removal
if (suffix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
if (args.size() >= 3) {
server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 3) {
world = args.get(3).toLowerCase();
}
}
List<Node> toRemove = new ArrayList<>();
for (Node node : holder.getNodes()) {
if (!node.isSuffix()) continue;
@@ -111,48 +96,36 @@ public class MetaRemoveTempSuffix extends SecondarySubCommand {
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
save(holder, sender, plugin);
return CommandResult.SUCCESS;
}
} else {
final String node = "suffix." + priority + "." + MetaUtils.escapeCharacters(suffix);
final String node = "suffix." + priority + "." + MetaUtils.escapeCharacters(suffix);
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 3) {
holder.unsetPermission(node, server, true);
Message.REMOVE_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server);
LogEntry.build().actor(sender).acted(holder)
.action("meta removetempsuffix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
holder.unsetPermission(node, server, world, true);
Message.REMOVE_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server, world);
LogEntry.build().actor(sender).acted(holder)
.action("meta removetempsuffix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
try {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.unsetPermission(node, true);
Message.REMOVE_TEMP_SUFFIX_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority);
LogEntry.build().actor(sender).acted(holder)
.action("meta removetempsuffix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_SUFFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
break;
case SERVER:
holder.unsetPermission(node, server, true);
Message.REMOVE_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server);
break;
case SERVER_AND_WORLD:
holder.unsetPermission(node, server, world, true);
Message.REMOVE_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), suffix, priority, server, world);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta removetempsuffix " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_SUFFIX.send(sender, holder.getFriendlyName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -23,25 +23,29 @@
package me.lucko.luckperms.common.commands.generic.meta;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.Node;
import me.lucko.luckperms.common.core.NodeBuilder;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.List;
import java.util.stream.Collectors;
public class MetaSet extends SecondarySubCommand {
public class MetaSet extends SharedSubCommand {
public MetaSet() {
super("set", "Sets a meta value", Permission.USER_META_SET, Permission.GROUP_META_SET, Predicate.notInRange(2, 4),
super("set", "Sets a meta value", Permission.USER_META_SET, Permission.GROUP_META_SET, Predicates.notInRange(2, 4),
Arg.list(
Arg.create("key", true, "the key to set"),
Arg.create("value", true, "the value to set"),
@@ -52,27 +56,15 @@ public class MetaSet extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
String key = MetaUtils.escapeCharacters(args.get(0));
String value = MetaUtils.escapeCharacters(args.get(1));
String node = "meta." + key + "." + value;
String server = null;
String world = null;
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
if (args.size() >= 3) {
server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 3) {
world = args.get(3).toLowerCase();
}
}
me.lucko.luckperms.api.Node n = new Node.Builder(node).setServer(server).setWorld(world).build();
Node n = new NodeBuilder(node).setServer(server).setWorld(world).build();
if (holder.hasPermission(n).asBoolean()) {
Message.ALREADY_HAS_META.send(sender, holder.getFriendlyName());
@@ -85,25 +77,22 @@ public class MetaSet extends SecondarySubCommand {
holder.setPermission(n);
} catch (ObjectAlreadyHasException ignored) {}
if (server == null) {
Message.SET_META_SUCCESS.send(sender, key, value, holder.getFriendlyName());
LogEntry.build().actor(sender).acted(holder)
.action("meta set " + key + " " + value)
.build().submit(plugin, sender);
} else {
if (world == null) {
switch (ContextHelper.determine(server, world)) {
case NONE:
Message.SET_META_SUCCESS.send(sender, key, value, holder.getFriendlyName());
break;
case SERVER:
Message.SET_META_SERVER_SUCCESS.send(sender, key, value, holder.getFriendlyName(), server);
LogEntry.build().actor(sender).acted(holder)
.action("meta set " + key + " " + value + " " + server)
.build().submit(plugin, sender);
} else {
break;
case SERVER_AND_WORLD:
Message.SET_META_SERVER_WORLD_SUCCESS.send(sender, key, value, holder.getFriendlyName(), server, world);
LogEntry.build().actor(sender).acted(holder)
.action("meta set " + key + " " + value + " " + server + " " + world)
.build().submit(plugin, sender);
}
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta set " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
}
@@ -23,26 +23,30 @@
package me.lucko.luckperms.common.commands.generic.meta;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.Node;
import me.lucko.luckperms.common.core.NodeBuilder;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.DateUtil;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.List;
import java.util.stream.Collectors;
public class MetaSetTemp extends SecondarySubCommand {
public class MetaSetTemp extends SharedSubCommand {
public MetaSetTemp() {
super("settemp", "Sets a meta value temporarily", Permission.USER_META_SETTEMP, Permission.GROUP_META_SETTEMP, Predicate.notInRange(3, 5),
super("settemp", "Sets a meta value temporarily", Permission.USER_META_SETTEMP, Permission.GROUP_META_SETTEMP, Predicates.notInRange(3, 5),
Arg.list(
Arg.create("key", true, "the key to set"),
Arg.create("value", true, "the value to set"),
@@ -54,44 +58,15 @@ public class MetaSetTemp extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
long duration;
try {
duration = Long.parseLong(args.get(2));
} catch (NumberFormatException e) {
try {
duration = DateUtil.parseDateDiff(args.get(2), true);
} catch (DateUtil.IllegalDateException e1) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
return CommandResult.INVALID_ARGS;
}
}
if (DateUtil.shouldExpire(duration)) {
Message.PAST_DATE_ERROR.send(sender);
return CommandResult.INVALID_ARGS;
}
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
String key = MetaUtils.escapeCharacters(args.get(0));
String value = MetaUtils.escapeCharacters(args.get(1));
long duration = ArgumentUtils.handleDuration(2, args);
String node = "meta." + key + "." + value;
String server = null;
String world = null;
String server = ArgumentUtils.handleServer(3, args);
String world = ArgumentUtils.handleWorld(4, args);
if (args.size() >= 3) {
server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 3) {
world = args.get(3).toLowerCase();
}
}
me.lucko.luckperms.api.Node n = new Node.Builder(node).setServer(server).setWorld(world).setExpiry(duration).build();
Node n = new NodeBuilder(node).setServer(server).setWorld(world).setExpiry(duration).build();
if (holder.hasPermission(n).asBoolean()) {
Message.ALREADY_HAS_META.send(sender, holder.getFriendlyName());
@@ -104,25 +79,22 @@ public class MetaSetTemp extends SecondarySubCommand {
holder.setPermission(n);
} catch (ObjectAlreadyHasException ignored) {}
if (server == null) {
Message.SET_META_TEMP_SUCCESS.send(sender, key, value, holder.getFriendlyName(), DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("meta settemp " + key + " " + value + " " + duration)
.build().submit(plugin, sender);
} else {
if (world == null) {
switch (ContextHelper.determine(server, world)) {
case NONE:
Message.SET_META_TEMP_SUCCESS.send(sender, key, value, holder.getFriendlyName(), DateUtil.formatDateDiff(duration));
break;
case SERVER:
Message.SET_META_TEMP_SERVER_SUCCESS.send(sender, key, value, holder.getFriendlyName(), server, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("meta settemp " + key + " " + value + " " + duration + " " + server)
.build().submit(plugin, sender);
} else {
break;
case SERVER_AND_WORLD:
Message.SET_META_TEMP_SERVER_WORLD_SUCCESS.send(sender, key, value, holder.getFriendlyName(), server, world, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("meta settemp " + key + " " + value + " " + duration + " " + server + " " + world)
.build().submit(plugin, sender);
}
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta settemp " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
}
@@ -25,22 +25,25 @@ package me.lucko.luckperms.common.commands.generic.meta;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.List;
import java.util.stream.Collectors;
public class MetaUnset extends SecondarySubCommand {
public class MetaUnset extends SharedSubCommand {
public MetaUnset() {
super("unset", "Unsets a meta value", Permission.USER_META_UNSET, Permission.GROUP_META_UNSET, Predicate.notInRange(1, 3),
super("unset", "Unsets a meta value", Permission.USER_META_UNSET, Permission.GROUP_META_UNSET,
Predicates.notInRange(1, 3),
Arg.list(
Arg.create("key", true, "the key to unset"),
Arg.create("server", false, "the server to remove the meta pair on"),
@@ -50,38 +53,27 @@ public class MetaUnset extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
String key = MetaUtils.escapeCharacters(args.get(0));
String server = null;
String world = null;
if (args.size() >= 2) {
server = args.get(1).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 2) {
world = args.get(2).toLowerCase();
}
}
String server = ArgumentUtils.handleServer(1, args);
String world = ArgumentUtils.handleWorld(2, args);
holder.clearMetaKeys(key, server, world, false);
if (server == null) {
Message.UNSET_META_SUCCESS.send(sender, key, holder.getFriendlyName());
} else {
if (world == null) {
switch (ContextHelper.determine(server, world)) {
case NONE:
Message.UNSET_META_SUCCESS.send(sender, key, holder.getFriendlyName());
break;
case SERVER:
Message.UNSET_META_SERVER_SUCCESS.send(sender, key, holder.getFriendlyName(), server);
} else {
break;
case SERVER_AND_WORLD:
Message.UNSET_META_SERVER_WORLD_SUCCESS.send(sender, key, holder.getFriendlyName(), server, world);
}
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta unset " + args.stream().collect(Collectors.joining(" ")))
.action("meta unset " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
@@ -25,22 +25,25 @@ package me.lucko.luckperms.common.commands.generic.meta;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.List;
import java.util.stream.Collectors;
public class MetaUnsetTemp extends SecondarySubCommand {
public class MetaUnsetTemp extends SharedSubCommand {
public MetaUnsetTemp() {
super("unsettemp", "Unsets a temporary meta value", Permission.USER_META_UNSETTEMP, Permission.GROUP_META_UNSETTEMP, Predicate.notInRange(1, 3),
super("unsettemp", "Unsets a temporary meta value", Permission.USER_META_UNSETTEMP, Permission.GROUP_META_UNSETTEMP,
Predicates.notInRange(1, 3),
Arg.list(
Arg.create("key", true, "the key to unset"),
Arg.create("server", false, "the server to remove the meta pair on"),
@@ -50,38 +53,27 @@ public class MetaUnsetTemp extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
String key = MetaUtils.escapeCharacters(args.get(0));
String server = null;
String world = null;
if (args.size() >= 2) {
server = args.get(1).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 2) {
world = args.get(2).toLowerCase();
}
}
String server = ArgumentUtils.handleServer(1, args);
String world = ArgumentUtils.handleWorld(2, args);
holder.clearMetaKeys(key, server, world, true);
if (server == null) {
Message.UNSET_META_TEMP_SUCCESS.send(sender, key, holder.getFriendlyName());
} else {
if (world == null) {
switch (ContextHelper.determine(server, world)) {
case NONE:
Message.UNSET_META_TEMP_SUCCESS.send(sender, key, holder.getFriendlyName());
break;
case SERVER:
Message.UNSET_META_TEMP_SERVER_SUCCESS.send(sender, key, holder.getFriendlyName(), server);
} else {
break;
case SERVER_AND_WORLD:
Message.UNSET_META_TEMP_SERVER_WORLD_SUCCESS.send(sender, key, holder.getFriendlyName(), server, world);
}
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("meta unsettemp " + args.stream().collect(Collectors.joining(" ")))
.action("meta unsettemp " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
@@ -0,0 +1,84 @@
/*
* 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.commands.generic.other;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class HolderShowTracks<T extends PermissionHolder> extends SubCommand<T> {
public HolderShowTracks(boolean user) {
super("showtracks", "Lists the tracks that the object is on",
user ? Permission.USER_SHOWTRACKS : Permission.GROUP_SHOWTRACKS, Predicates.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, T holder, List<String> args, String label) throws CommandException {
if (!plugin.getStorage().loadAllTracks().join()) {
Message.TRACKS_LOAD_ERROR.send(sender);
return CommandResult.LOADING_ERROR;
}
Set<Node> nodes = holder.getNodes().stream()
.filter(Node::isGroupNode)
.filter(Node::isPermanent)
.collect(Collectors.toSet());
StringBuilder sb = new StringBuilder();
for (Node node : nodes) {
String name = node.getGroupName();
plugin.getTrackManager().getAll().values().stream()
.filter(t -> t.containsGroup(name))
.forEach(t -> sb.append("&a")
.append(t.getName())
.append(": ")
.append(Util.listToArrowSep(t.getGroups(), name))
.append(Util.getNodeContextDescription(node))
.append("\n")
);
}
if (sb.length() == 0) {
Message.LIST_TRACKS_EMPTY.send(sender, holder.getFriendlyName());
return CommandResult.SUCCESS;
} else {
sb.deleteCharAt(sb.length() - 1);
Message.LIST_TRACKS.send(sender, holder.getFriendlyName(), sb.toString());
return CommandResult.SUCCESS;
}
}
}
@@ -23,14 +23,15 @@
package me.lucko.luckperms.common.commands.generic.parent;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.commands.generic.SecondaryMainCommand;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedMainCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.core.PermissionHolder;
public class CommandParent<T extends PermissionHolder> extends SecondaryMainCommand<T> {
public class CommandParent<T extends PermissionHolder> extends SharedMainCommand<T> {
public CommandParent(boolean user) {
super("Parent", "Edit inheritances", user, ImmutableList.<SecondarySubCommand>builder()
super("Parent", "Edit inheritances", user, ImmutableList.<SharedSubCommand>builder()
.add(new ParentInfo())
.add(new ParentSet())
.add(new ParentAdd())
.add(new ParentRemove())
.add(new ParentAddTemp())
@@ -24,26 +24,29 @@ package me.lucko.luckperms.common.commands.generic.parent;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.List;
import java.util.stream.Collectors;
import static me.lucko.luckperms.common.commands.SubCommand.getGroupTabComplete;
public class ParentAdd extends SecondarySubCommand {
public class ParentAdd extends SharedSubCommand {
public ParentAdd() {
super("add", "Sets another group for the object to inherit permissions from",
Permission.USER_PARENT_ADD, Permission.GROUP_PARENT_ADD, Predicate.notInRange(1, 3),
super("add", "Sets another group for the object to inherit permissions from", Permission.USER_PARENT_ADD,
Permission.GROUP_PARENT_ADD, Predicates.notInRange(1, 3),
Arg.list(
Arg.create("group", true, "the group to inherit from"),
Arg.create("server", false, "the server to inherit the group on"),
@@ -53,15 +56,12 @@ public class ParentAdd extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
String groupName = args.get(0).toLowerCase();
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
String groupName = ArgumentUtils.handleName(0, args);
String server = ArgumentUtils.handleServer(1, args);
String world = ArgumentUtils.handleWorld(2, args);
if (ArgumentChecker.checkNode(groupName)) {
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
if (!plugin.getDatastore().loadGroup(groupName).getUnchecked()) {
if (!plugin.getStorage().loadGroup(groupName).join()) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS;
}
@@ -73,38 +73,28 @@ public class ParentAdd extends SecondarySubCommand {
}
try {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 2) {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.setInheritGroup(group);
Message.SET_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName());
break;
case SERVER:
holder.setInheritGroup(group, server);
Message.SET_INHERIT_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), server);
LogEntry.build().actor(sender).acted(holder)
.action("parent add " + group.getName() + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(2).toLowerCase();
break;
case SERVER_AND_WORLD:
holder.setInheritGroup(group, server, world);
Message.SET_INHERIT_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), server, world);
LogEntry.build().actor(sender).acted(holder)
.action("parent add " + group.getName() + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
holder.setInheritGroup(group);
Message.SET_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName());
LogEntry.build().actor(sender).acted(holder)
.action("parent add " + group.getName())
.build().submit(plugin, sender);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("parent add " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_INHERITS.send(sender, holder.getFriendlyName(), group.getDisplayName());
return CommandResult.STATE_ERROR;
@@ -24,27 +24,30 @@ package me.lucko.luckperms.common.commands.generic.parent;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.DateUtil;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.List;
import java.util.stream.Collectors;
import static me.lucko.luckperms.common.commands.SubCommand.getGroupTabComplete;
public class ParentAddTemp extends SecondarySubCommand {
public class ParentAddTemp extends SharedSubCommand {
public ParentAddTemp() {
super("addtemp", "Sets another group for the object to inherit permissions from temporarily",
Permission.USER_PARENT_ADDTEMP, Permission.GROUP_PARENT_ADDTEMP, Predicate.notInRange(2, 4),
Permission.USER_PARENT_ADDTEMP, Permission.GROUP_PARENT_ADDTEMP, Predicates.notInRange(2, 4),
Arg.list(
Arg.create("group", true, "the group to inherit from"),
Arg.create("duration", true, "the duration of the group membership"),
@@ -55,32 +58,13 @@ public class ParentAddTemp extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
String groupName = args.get(0).toLowerCase();
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
String groupName = ArgumentUtils.handleName(0, args);
long duration = ArgumentUtils.handleDuration(1, args);
String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args);
if (ArgumentChecker.checkNode(groupName)) {
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
long duration;
try {
duration = Long.parseLong(args.get(1));
} catch (NumberFormatException e) {
try {
duration = DateUtil.parseDateDiff(args.get(1), true);
} catch (DateUtil.IllegalDateException e1) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(1));
return CommandResult.INVALID_ARGS;
}
}
if (DateUtil.shouldExpire(duration)) {
Message.PAST_DATE_ERROR.send(sender);
return CommandResult.INVALID_ARGS;
}
if (!plugin.getDatastore().loadGroup(groupName).getUnchecked()) {
if (!plugin.getStorage().loadGroup(groupName).join()) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS;
}
@@ -92,40 +76,34 @@ public class ParentAddTemp extends SecondarySubCommand {
}
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 3) {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.setInheritGroup(group, duration);
Message.SET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(),
DateUtil.formatDateDiff(duration)
);
break;
case SERVER:
holder.setInheritGroup(group, server, duration);
Message.SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), server,
DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("parent addtemp " + group.getName() + " " + duration + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
Message.SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(),
server, DateUtil.formatDateDiff(duration)
);
break;
case SERVER_AND_WORLD:
holder.setInheritGroup(group, server, world, duration);
Message.SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), server,
world, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("parent addtemp " + group.getName() + " " + duration + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
holder.setInheritGroup(group, duration);
Message.SET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(holder)
.action("parent addtemp " + group.getName() + " " + duration)
.build().submit(plugin, sender);
Message.SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(),
server, world, DateUtil.formatDateDiff(duration)
);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("parent addtemp " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_TEMP_INHERITS.send(sender, holder.getFriendlyName(), group.getDisplayName());
return CommandResult.STATE_ERROR;
@@ -23,25 +23,26 @@
package me.lucko.luckperms.common.commands.generic.parent;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.Util;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.List;
public class ParentInfo extends SecondarySubCommand {
public class ParentInfo extends SharedSubCommand {
public ParentInfo() {
super("info", "Lists the groups that this object inherits from",
Permission.USER_PARENT_INFO, Permission.GROUP_PARENT_INFO, Predicate.alwaysFalse(), null);
Permission.USER_PARENT_INFO, Permission.GROUP_PARENT_INFO, Predicates.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
Message.LISTPARENTS.send(sender, holder.getFriendlyName(), Util.permGroupsToString(holder.getPermissions(false)));
Message.LISTPARENTS_TEMP.send(sender, holder.getFriendlyName(), Util.tempGroupsToString(holder.getPermissions(false)));
return CommandResult.SUCCESS;
@@ -24,26 +24,29 @@ package me.lucko.luckperms.common.commands.generic.parent;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.stream.Collectors;
import static me.lucko.luckperms.common.commands.SubCommand.getGroupTabComplete;
public class ParentRemove extends SecondarySubCommand {
public class ParentRemove extends SharedSubCommand {
public ParentRemove() {
super("remove", "Removes a previously set inheritance rule", Permission.USER_PARENT_REMOVE, Permission.GROUP_PARENT_REMOVE,
Predicate.notInRange(1, 3),
super("remove", "Removes a previously set inheritance rule", Permission.USER_PARENT_REMOVE,
Permission.GROUP_PARENT_REMOVE, Predicates.notInRange(1, 3),
Arg.list(
Arg.create("group", true, "the group to remove"),
Arg.create("server", false, "the server to remove the group on"),
@@ -53,56 +56,49 @@ public class ParentRemove extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
String groupName = args.get(0).toLowerCase();
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
String groupName = ArgumentUtils.handleName(0, args);
String server = ArgumentUtils.handleServer(1, args);
String world = ArgumentUtils.handleWorld(2, args);
if (ArgumentChecker.checkNode(groupName)) {
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
ContextHelper.CommandContext context = ContextHelper.determine(server, world);
if (holder instanceof User) {
User user = (User) holder;
if ((args.size() == 1 || (args.size() == 2 && args.get(1).equalsIgnoreCase("global")))
&& user.getPrimaryGroup().equalsIgnoreCase(groupName)) {
boolean shouldPrevent = (context == ContextHelper.CommandContext.NONE ||
(context == ContextHelper.CommandContext.SERVER && server.equalsIgnoreCase("global"))) &&
user.getPrimaryGroup().equalsIgnoreCase(groupName);
if (shouldPrevent) {
Message.USER_REMOVEGROUP_ERROR_PRIMARY.send(sender);
return CommandResult.STATE_ERROR;
}
}
try {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 2) {
switch (context) {
case NONE:
holder.unsetPermission("group." + groupName);
Message.UNSET_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), groupName);
break;
case SERVER:
holder.unsetPermission("group." + groupName, server);
Message.UNSET_INHERIT_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), groupName, server);
LogEntry.build().actor(sender).acted(holder)
.action("parent remove " + groupName + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(2).toLowerCase();
break;
case SERVER_AND_WORLD:
holder.unsetPermission("group." + groupName, server, world);
Message.UNSET_INHERIT_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), groupName, server, world);
LogEntry.build().actor(sender).acted(holder)
.action("parent remove " + groupName + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
holder.unsetPermission("group." + groupName);
Message.UNSET_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), groupName);
LogEntry.build().actor(sender).acted(holder)
.action("parent remove " + groupName)
.build().submit(plugin, sender);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("parent remove " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_INHERIT.send(sender, holder.getFriendlyName(), groupName);
return CommandResult.STATE_ERROR;
@@ -24,25 +24,28 @@ package me.lucko.luckperms.common.commands.generic.parent;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.stream.Collectors;
import static me.lucko.luckperms.common.commands.SubCommand.getGroupTabComplete;
public class ParentRemoveTemp extends SecondarySubCommand {
public class ParentRemoveTemp extends SharedSubCommand {
public ParentRemoveTemp() {
super("removetemp", "Removes a previously set temporary inheritance rule",
Permission.USER_PARENT_REMOVETEMP, Permission.GROUP_PARENT_REMOVETEMP, Predicate.notInRange(1, 3),
Permission.USER_PARENT_REMOVETEMP, Permission.GROUP_PARENT_REMOVETEMP, Predicates.notInRange(1, 3),
Arg.list(
Arg.create("group", true, "the group to remove"),
Arg.create("server", false, "the server to remove the group on"),
@@ -52,47 +55,34 @@ public class ParentRemoveTemp extends SecondarySubCommand {
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) {
String groupName = args.get(0).toLowerCase();
if (ArgumentChecker.checkNode(groupName)) {
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
String groupName = ArgumentUtils.handleName(0, args);
String server = ArgumentUtils.handleServer(1, args);
String world = ArgumentUtils.handleWorld(2, args);
try {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 2) {
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.unsetPermission("group." + groupName, true);
Message.UNSET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), groupName);
break;
case SERVER:
holder.unsetPermission("group." + groupName, server, true);
Message.UNSET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), groupName, server);
LogEntry.build().actor(sender).acted(holder)
.action("parent removetemp " + groupName + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(2).toLowerCase();
break;
case SERVER_AND_WORLD:
holder.unsetPermission("group." + groupName, server, world, true);
Message.UNSET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), groupName, server, world);
LogEntry.build().actor(sender).acted(holder)
.action("parent removetemp " + groupName + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
holder.unsetPermission("group." + groupName, true);
Message.UNSET_TEMP_INHERIT_SUCCESS.send(sender, holder.getFriendlyName(), groupName);
LogEntry.build().actor(sender).acted(holder)
.action("parent removetemp " + groupName)
.build().submit(plugin, sender);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("parent removetemp " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_TEMP_INHERIT.send(sender, holder.getFriendlyName(), groupName);
return CommandResult.STATE_ERROR;
@@ -0,0 +1,126 @@
/*
* 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.commands.generic.parent;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.List;
import java.util.stream.Collectors;
import static me.lucko.luckperms.common.commands.SubCommand.getGroupTabComplete;
public class ParentSet extends SharedSubCommand {
public ParentSet() {
super("set", "Removes all other groups the object inherits already and adds them to the one given",
Permission.USER_PARENT_SET, Permission.GROUP_PARENT_SET, Predicates.notInRange(1, 3),
Arg.list(
Arg.create("group", true, "the group to set to"),
Arg.create("server", false, "the server to set the group on"),
Arg.create("world", false, "the world to set the group on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
String groupName = ArgumentUtils.handleName(0, args);
String server = ArgumentUtils.handleServer(1, args);
String world = ArgumentUtils.handleWorld(2, args);
if (!plugin.getStorage().loadGroup(groupName).join()) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS;
}
Group group = plugin.getGroupManager().get(groupName);
if (group == null) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
return CommandResult.LOADING_ERROR;
}
switch (ContextHelper.determine(server, world)) {
case NONE:
holder.clearParents(null, null);
try {
holder.setInheritGroup(group);
} catch (ObjectAlreadyHasException ignored) {}
if (holder instanceof User) {
((User) holder).setPrimaryGroup(group.getName());
}
Message.SET_PARENT_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName());
break;
case SERVER:
holder.clearParents(server, null);
try {
holder.setInheritGroup(group, server);
} catch (ObjectAlreadyHasException ignored) {}
if (server.equalsIgnoreCase("global") && holder instanceof User) {
((User) holder).setPrimaryGroup(group.getName());
}
Message.SET_PARENT_SERVER_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), server);
break;
case SERVER_AND_WORLD:
holder.clearParents(server, world);
try {
holder.setInheritGroup(group, server, world);
} catch (ObjectAlreadyHasException ignored) {}
Message.SET_PARENT_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), server, world);
break;
}
LogEntry.build().actor(sender).acted(holder)
.action("parent set " + args.stream().map(ArgumentUtils.WRAPPER).collect(Collectors.joining(" ")))
.build().submit(plugin, sender);
save(holder, sender, plugin);
return CommandResult.SUCCESS;
}
@Override
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
return getGroupTabComplete(args, plugin);
}
}
@@ -23,18 +23,20 @@
package me.lucko.luckperms.common.commands.generic.permission;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.commands.generic.SecondaryMainCommand;
import me.lucko.luckperms.common.commands.generic.SecondarySubCommand;
import me.lucko.luckperms.common.commands.generic.SharedMainCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.core.PermissionHolder;
public class CommandPermission<T extends PermissionHolder> extends SecondaryMainCommand<T> {
public class CommandPermission<T extends PermissionHolder> extends SharedMainCommand<T> {
public CommandPermission(boolean user) {
super("Permission", "Edit permissions", user, ImmutableList.<SecondarySubCommand>builder()
super("Permission", "Edit permissions", user, ImmutableList.<SharedSubCommand>builder()
.add(new PermissionInfo())
.add(new PermissionSet())
.add(new PermissionUnset())
.add(new PermissionSetTemp())
.add(new PermissionUnsetTemp())
.add(new PermissionCheck())
.add(new PermissionCheckInherits())
.build());
}
}
@@ -0,0 +1,73 @@
/*
* 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.commands.generic.permission;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.ArgumentUtils;
import me.lucko.luckperms.common.commands.utils.ContextHelper;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.NodeBuilder;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.List;
public class PermissionCheck extends SharedSubCommand {
public PermissionCheck() {
super("check", "Checks to see if the object has a certain permission node", Permission.USER_PERM_CHECK,
Permission.GROUP_PERM_CHECK, Predicates.notInRange(1, 3),
Arg.list(
Arg.create("node", true, "the permission node to check for"),
Arg.create("server", false, "the server to check on"),
Arg.create("world", false, "the world to check on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException {
String node = ArgumentUtils.handleNodeWithoutCheck(0, args);
String server = ArgumentUtils.handleServer(1, args);
String world = ArgumentUtils.handleWorld(2, args);
switch (ContextHelper.determine(server, world)) {
case NONE:
Util.sendTristate(sender, node, holder.hasPermission(new NodeBuilder(node).build()));
break;
case SERVER:
Util.sendTristate(sender, node, holder.hasPermission(new NodeBuilder(node).setServer(server).build()));
break;
case SERVER_AND_WORLD:
Util.sendTristate(sender, node, holder.hasPermission(new NodeBuilder(node).setServer(server).setWorld(world).build()));
break;
}
return CommandResult.SUCCESS;
}
}
Loaded 100 of 238 files, more files were not shown because too many files have changed in this diff. Show more