Compare commits

...
12 Commits
Author SHA1 Message Date
Luck a3604c7464 Bump version, and make future version changes easier 2016-07-25 21:05:09 +01:00
Luck 10574748ff Add inheritance methods to Group 2016-07-25 20:44:01 +01:00
Luck c7336dbcad Change Vault hook to use new per-world perms system 2016-07-25 20:20:51 +01:00
Luck ebeb69dd3a Per-world permissions 2016-07-25 18:19:36 +01:00
Luck 9ad40be210 Add complete offline-mode support 2016-07-25 11:18:35 +01:00
Luck df209f6515 Fix possible race condition 2016-07-23 22:34:42 +01:00
Luck d32d6b5474 Generics are cool 2016-07-23 21:57:19 +01:00
Luck 623b7b775c Fix readme markdown 2016-07-22 12:27:50 +01:00
Luck b3b687d9b7 Add Api 2016-07-21 21:40:24 +01:00
Luck a413c0a50a Cleanup & multiple small fixes 2016-07-21 14:15:14 +01:00
Luck 1870893fe1 Fix promotions/demotions 2016-07-19 17:10:40 +01:00
Luck f24562c642 Fix compile 2016-07-19 13:02:54 +01:00
91 changed files with 3750 additions and 969 deletions

No files matched your search

-142
View File
@@ -1,142 +0,0 @@
= LuckPerms
A (fairly bad) permissions implementation for Bukkit/BungeeCord.
== Features
* **Group inheritance** - users can be members of multiple groups, groups can inherit other groups
* **Temporary permissions** - users/groups can be given permissions that expire after a given time
* **Temporary groups** - users/groups can be added to/inherit other groups temporarily
* **Multi-server support** - data is synced across all servers/platforms
* **Per-server permissions/groups** - define user/group permissions that only apply on certain servers
* **Server-specific groups** - define groups that only apply on certain servers
* **Tracks / paths** - users can be promoted/demoted along multiple group tracks
* **Vault Support** - hooks into Vault to integrate with other plugins
* **Easy and simple setup and configuration using commands** - no editing yml files, yuck
* **Efficient/lightweight** - maybe? Who knows, it might be.
* **BungeeCord compatible** - permissions, users and groups are synced across Bukkit/BungeeCord instances
* **Support for MySQL, SQLite & Flatfile (JSON)** - other storage methods coming soon (maybe)
===== Possible Caveats
* Currently only supports MySQL, SQLite & Flatfile (JSON) (support for more methods might come in the future)
* Not at all tested and could produce unexpected/buggy results and errors
== Setup
All configuration options are in the **config.yml** file, which is generated automagically when the plugin first starts.
You can define the settings for per-server permissions, the storage method and credentials within this file.
== Info
=== Permission Calculation
Permissions are calculated based on a priority system as follows.
* Temporary permissions will override non-temporary permissions.
Example: if a user has a false permission set for "test.node", and a temporary true permission set for "test.node", the temporary permission will override the permanent one, and the user will be granted the true node.
* Server specific permissions will override generic/global permissions.
Example: if a user has a global "fly.use" permission, and then has a negated "fly.use" permission on the "factions" server, the server specific permission will override the globally defined one, and the user will be granted the negated node.
* Inherited permissions will be overridden by an objects own permissions.
Example: A user is a member of the default group, which grants "some.thing.perm", but the users own permissions has "some.thing.perm" set to false. The inherited permission will be overridden by the users own permissions, and the user will be granted the negative node.
=== Temporary Permissions
Temporary permissions are checked each time a user/group is loaded, and when the sync task runs. This means if you set a temporary permission to expire after 30 seconds, it won't actually be removed until the sync task runs.
The only way around this is to decrease the sync interval.
== Commands
Command usage is printed to the console/chat whenever invalid arguments are provided. Simply typing /perms will list all commands a user has permission to use.
=== Aliases
| Bukkit | /luckperms |
| | /perms |
| | /permissions |
| | /lp |
| | /perm |
| Bungee | /luckpermsbungee |
| | /bperms |
| | /bpermissions |
| | /lpb |
| | /bperm |
Arguments: <required> [optional]
Users with OP have access to all commands.
Additionally, you can use wildcards to grant users access to a selection of commands.
* **All commands** - luckperms.*
* **All user commands** - luckperms.user.*
* **All group commands** - luckperms.group.*
* **All track commands** - luckperms.track.*
| **Command** | **Description** | **Permission** |
| /perms | Sends plugin info and usage | N/A |
| /perms sync | Runs an update task and reloads the data of all online users | luckperms.sync |
| /perms info | Shows information about the plugin | luckperms.info |
| /perms debug | Shows some very brief debug info about the number of users/groups loaded | luckperms.debug |
| | | |
| | | |
| | | |
| /perms creategroup <group> | Creates a new group with the given name | luckperms.creategroup |
| /perms deletegroup <group> | Deletes an existing group | luckperms.deletegroup |
| /perms listgroups | Shows a list of the groups registered within the system | luckperms.listgroups |
| | | |
| | | |
| | | |
| /perms createtrack <track> | Creates a new track with the given name | luckperms.createtrack |
| /perms deletetrack <track> | Deletes an existing track | luckperms.deletetrack |
| /perms listtracks | Shows a list of the tracks registered within the system | luckperms.listtracks |
| | | |
| | | |
| | | |
| /perms user <user> info | Shows info about the user | luckperms.user.info |
| /perms user <user> getuuid | Shows the users Mojang UUID | luckperms.user.getuuid |
| /perms user <user> listnodes | Lists all of the permission nodes the user has | luckperms.user.listnodes |
| /perms user <user> haspermission <node> [server] | Checks if the user has a permission on a certain server | luckperms.user.haspermission |
| /perms user <user> inheritspermission <node> [server] | Checks if the user inherits a permission on a certain server. (This checks all parent groups unlike haspermission) | luckperms.user.inheritspermission |
| /perms user <user> set <node> <true/false> [server]| Sets a permission for the user | luckperms.user.setpermission |
| /perms user <user> unset <node> [server] | Unsets a permission for the user | luckperms.user.unsetpermission |
| /perms user <user> addgroup <group> [server] | Adds the user to a group | luckperms.user.addgroup |
| /perms user <user> removegroup <group> [server] | Removes the user from a group | luckperms.user.removegroup |
| /perms user <user> settemp <node> <true/false> <duration> [server]| Sets a temporary permission for the user | luckperms.user.settemppermission |
| /perms user <user> unsettemp <node> [server] | Unsets a temporary permission for the user | luckperms.user.unsettemppermission |
| /perms user <user> addtempgroup <group> <duration> [server] | Adds the user to a group temporarily | luckperms.user.addtempgroup |
| /perms user <user> removetempgroup <group> [server] | Removes the user from a temporary group | luckperms.user.removetempgroup |
| /perms user <user> setprimarygroup <group> | Sets the users primary group | luckperms.user.setprimarygroup |
| /perms user <user> showtracks | Shows a list of the tracks the user can be promoted/demoted on | luckperms.user.showtracks |
| /perms user <user> promote <track> | Promotes the user along a given track | luckperms.user.promote |
| /perms user <user> demote <track> | Demotes the user along a given track | luckperms.user.demote |
| /perms user <user> showpos <track> | Shows the users position on a given track | luckperms.user.showpos |
| /perms user <user> clear | Clears all permissions the user has | luckperms.user.clear |
| | | |
| | | |
| | | |
| /perms group <group> info | Shows info about the group | luckperms.group.info |
| /perms group <group> listnodes | Lists all of the permission nodes the group has | luckperms.group.listnodes |
| /perms group <group> haspermission <node> [server] | Checks if the group has a permission on a certain server | luckperms.group.haspermission |
| /perms group <group> inheritspermission <node> [server] | Checks if the group inherits a permission on a certain server. (This checks all parent groups unlike haspermission) | luckperms.group.inheritspermission |
| /perms group <group> set <node> <true/false> [server]| Sets a permission for the group | luckperms.group.setpermission |
| /perms group <group> unset <node> [server] | Unsets a permission for the group | luckperms.group.unsetpermission |
| /perms group <group> setinherit <group> [server]| Sets the group to inherit all permissions from another group | luckperms.group.setinherit |
| /perms group <group> unsetinherit <group> [server] | Unsets a previously defined inheritance rule | luckperms.group.unsetinherit |
| /perms group <group> settemp <node> <true/false> <duration> [server] | Sets a temporary permission for the group | luckperms.group.settemppermission |
| /perms group <group> unsettemp <node> [server] | Unsets a temporary permission for the group | luckperms.group.unsettemppermission |
| /perms group <group> settempinherit <group> <duration> [server] | Sets the group to inherit all permissions from another group temporarily | luckperms.group.settempinherit |
| /perms group <group> unsettempinherit <group> [server] | Unsets a previously defined temporary inheritance rule | luckperms.group.unsettempinherit |
| /perms group <group> showtracks | Shows a list of the tracks that the users in the group can be promoted/demoted on | luckperms.group.showtracks |
| /perms group <group> clear | Clears all permissions the group has | luckperms.group.clear |
| | | |
| | | |
| | | |
| /perms track <track> info | Shows info about the track | luckperms.track.info |
| /perms track <track> append <group> | Appends a group to the end of the track | luckperms.track.append |
| /perms track <track> insert <group> <position> | Inserts a group at the given position on the track | luckperms.track.insert |
| /perms track <track> remove <group> | Removes a group from the track | luckperms.track.remove |
| /perms track <track> clear | Clears all groups on the track | luckperms.track.clear |
== License
See LICENSE.md.
+150
View File
@@ -0,0 +1,150 @@
# LuckPerms
A permissions implementation for Bukkit/BungeeCord.
## Features
* **Group inheritance** - users can be members of multiple groups, groups can inherit other groups
* **Temporary permissions** - users/groups can be given permissions that expire after a given time
* **Temporary groups** - users/groups can be added to/inherit other groups temporarily
* **Multi-server support** - data is synced across all servers/platforms
* **Full offline-mode/mixed-mode support** - player permissions are synced properly over offline-mode or mixed online/offline-mode networks.
* **Per-server permissions/groups** - define user/group permissions that only apply on certain servers
* **Per-world permissions/groups** - define user/group permissions that only apply on certain worlds (on BungeeCord, a connected Bukkit/Spigot instance is treated as a world)
* **Tracks / paths / ladders** - users can be promoted/demoted along multiple group tracks
* **Vault Support** - hooks into Vault to integrate with other plugins
* **Developer API** - easily integrate LuckPerms into your own projects
* **Easy and simple setup and configuration using commands** - no editing yml files, yuck
* **Negated permissions and groups** - define special rules for certain users/groups
* **Full support for UUIDs, even in Offline Mode** - users can change their usernames without losing permissions. In offline mode, a single user has the same internal UUID across a network.
* **Permission data stored within MySQL in a json format** - easily integrate the LuckPerms backend into your other projects
* **Well documented** - API methods have comprehensive Java docs, it's clear what each method does.
* **Efficient/lightweight** - maybe? Who knows, it might be.
* **Open Sourced, Free...** - you shouldn't have to pay $10+ for a "powerful" permissions plugin.
* **BungeeCord compatible** - permissions, users and groups are synced across Bukkit/BungeeCord instances
* **Support for MySQL, SQLite & Flatfile (JSON)** - other storage methods coming soon (maybe)
## Setup
All configuration options are in the **config.yml** file, which is generated automagically when the plugin first starts.
You can define the settings for per-server permissions, the storage method and credentials within this file.
## Info
### Permission Calculation
Permissions are calculated based on a priority system as follows.
* Temporary permissions will override non-temporary permissions.
Example: if a user has a false permission set for "test.node", and a temporary true permission set for "test.node", the temporary permission will override the permanent one, and the user will be granted the true node.
* World specific permissions will override generic permissions.
Example: if a user has a global "fly.use" permission, and then has a negated "fly.use" permission in the "world_nether" world, the world specific permission will override the globally defined one, and the user will be granted the negated node (provided they're in that world, of course.).
* Server specific permissions will override generic/global permissions.
Example: if a user has a global "fly.use" permission, and then has a negated "fly.use" permission on the "factions" server, the server specific permission will override the globally defined one, and the user will be granted the negated node.
* Inherited permissions will be overridden by an objects own permissions.
Example: A user is a member of the default group, which grants "some.thing.perm", but the users own permissions has "some.thing.perm" set to false. The inherited permission will be overridden by the users own permissions, and the user will be granted the negative node (provided they're on that server).
### Temporary Permissions
Temporary permissions are checked each time a user/group is loaded, and when the sync task runs. This means if you set a temporary permission to expire after 30 seconds, it won't actually be removed until the sync task runs.
The only way around this is to decrease the sync interval.
## API
LuckPerms has an extensive API, allowing for easy integration with other projects. To use the Api, you need to obtain an instance of the `LuckPermsApi` interface. This can be done in two ways, (one way on BungeeCord).
```java
final LuckPermsApi api = LuckPerms.getApi();
final LuckPermsApi api = Bukkit.getServicesManager().getRegistration(LuckPermsApi.class).getProvider();
```
If you want to use LuckPerms in your onEnable method, you need to add the following to your plugins `plugin.yml`.
```yml
depend: [LuckPerms]
```
All of the available methods can be seen in the various interfaces in the `luckperms-api` module.
## Commands
Command usage is printed to the console/chat whenever invalid arguments are provided. Simply typing /perms will list all commands a user has permission to use.
### Aliases
| Bukkit | Bungee |
|------------------|------------------|
| /luckperms | /luckpermsbungee |
| /perms | /bperms |
| /permissions | /bpermissions |
| /lp | /lpb |
| /perm | /bperm |
Arguments: \<required\> [optional]
Users with OP have access to all commands.
Additionally, you can use wildcards to grant users access to a selection of commands.
* **All commands** - luckperms.*
* **All user commands** - luckperms.user.*
* **All group commands** - luckperms.group.*
* **All track commands** - luckperms.track.*
### General
* /perms - n/a
* /perms sync - luckperms.sync
* /perms info - luckperms.info
* /perms debug - luckperms.debug
* /perms creategroup \<group\> - luckperms.creategroup
* /perms deletegroup \<group\> - luckperms.deletegroup
* /perms listgroups - luckperms.listgroups
* /perms createtrack \<track\> - luckperms.createtrack
* /perms deletetrack \<track\> - luckperms.deletetrack
* /perms listtracks - luckperms.listtracks
### User
* /perms user \<user\> info - luckperms.user.info
* /perms user \<user\> getuuid - luckperms.user.getuuid
* /perms user \<user\> listnodes - luckperms.user.listnodes
* /perms user \<user\> haspermission \<node\> [server] [world] - luckperms.user.haspermission
* /perms user \<user\> inheritspermission \<node\> [server] [world] - luckperms.user.inheritspermission
* /perms user \<user\> set \<node\> \<true/false\> [server] [world] - luckperms.user.setpermission
* /perms user \<user\> unset \<node\> [server] [world] - luckperms.user.unsetpermission
* /perms user \<user\> addgroup \<group\> [server] [world] - luckperms.user.addgroup
* /perms user \<user\> removegroup \<group\> [server] [world] - luckperms.user.removegroup
* /perms user \<user\> settemp \<node\> \<true/false\> \<duration\> [server] [world] - luckperms.user.settemppermission
* /perms user \<user\> unsettemp \<node\> [server] [world] - luckperms.user.unsettemppermission
* /perms user \<user\> addtempgroup \<group\> \<duration\> [server] [world] - luckperms.user.addtempgroup
* /perms user \<user\> removetempgroup \<group\> [server] [world] - luckperms.user.removetempgroup
* /perms user \<user\> setprimarygroup \<group\> - luckperms.user.setprimarygroup
* /perms user \<user\> showtracks - luckperms.user.showtracks
* /perms user \<user\> promote \<track\> - luckperms.user.promote
* /perms user \<user\> demote \<track\> - luckperms.user.demote
* /perms user \<user\> showpos \<track\> - luckperms.user.showpos
* /perms user \<user\> clear - luckperms.user.clear
### Group
* /perms group \<group\> info - luckperms.group.info
* /perms group \<group\> listnodes - luckperms.group.listnodes
* /perms group \<group\> haspermission \<node\> [server] [world] - luckperms.group.haspermission
* /perms group \<group\> inheritspermission \<node\> [server] [world] - luckperms.group.inheritspermission
* /perms group \<group\> set \<node\> \<true/false\> [server] [world] - luckperms.group.setpermission
* /perms group \<group\> unset \<node\> [server] [world] - luckperms.group.unsetpermission
* /perms group \<group\> setinherit \<group\> [server] [world] - luckperms.group.setinherit
* /perms group \<group\> unsetinherit \<group\> [server] [world] - luckperms.group.unsetinherit
* /perms group \<group\> settemp \<node\> \<true/false\> \<duration\> [server] [world] - settemppermission
* /perms group \<group\> unsettemp \<node\> [server] [world] - luckperms.group.unsettemppermission
* /perms group \<group\> settempinherit \<group\> \<duration\> [server] [world] - luckperms.group.settempinherit
* /perms group \<group\> unsettempinherit \<group\> [server] [world] - luckperms.group.unsettempinherit
* /perms group \<group\> showtracks - luckperms.group.showtracks
* /perms group \<group\> clear - luckperms.group.clear
### Track
* /perms track \<track\> info - luckperms.track.info
* /perms track \<track\> append \<group\> - luckperms.track.append
* /perms track \<track\> insert \<group\> \<position\> - luckperms.track.insert
* /perms track \<track\> remove \<group\> - luckperms.track.remove
* /perms track \<track\> clear - luckperms.track.clear
## License
See LICENSE.md.
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko</groupId>
<version>${global.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-api</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,30 @@
package me.lucko.luckperms;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import me.lucko.luckperms.api.LuckPermsApi;
/**
* Static access to LuckPerms
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LuckPerms {
private static LuckPermsApi api = null;
public static LuckPermsApi getApi() {
if (api == null) {
throw new IllegalStateException("API is not loaded.");
}
return api;
}
static void registerProvider(LuckPermsApi luckPermsApi) {
api = luckPermsApi;
}
static void unregisterProvider() {
api = null;
}
}
@@ -0,0 +1,56 @@
package me.lucko.luckperms.api;
import me.lucko.luckperms.api.data.Callback;
import java.util.UUID;
/**
* Wrapper interface for the internal Datastore instance
* The implementations of this interface limit access to the datastore and add parameter checks to further prevent
* errors and ensure all API interactions to not damage the state of the plugin.
*/
@SuppressWarnings("unused")
public interface Datastore {
String getName();
boolean isAcceptingLogins();
Async async();
Sync sync();
interface Async {
void loadOrCreateUser(UUID uuid, String username, Callback<Boolean> callback);
void loadUser(UUID uuid, Callback<Boolean> callback);
void saveUser(User user, Callback<Boolean> callback);
void createAndLoadGroup(String name, Callback<Boolean> callback);
void loadGroup(String name, Callback<Boolean> callback);
void loadAllGroups(Callback<Boolean> callback);
void saveGroup(Group group, Callback<Boolean> callback);
void deleteGroup(Group group, Callback<Boolean> callback);
void createAndLoadTrack(String name, Callback<Boolean> callback);
void loadTrack(String name, Callback<Boolean> callback);
void loadAllTracks(Callback<Boolean> callback);
void saveTrack(Track track, Callback<Boolean> callback);
void deleteTrack(Track track, Callback<Boolean> callback);
void saveUUIDData(String username, UUID uuid, Callback<Boolean> callback);
void getUUID(String username, Callback<UUID> callback);
}
interface Sync {
boolean loadOrCreateUser(UUID uuid, String username);
boolean loadUser(UUID uuid);
boolean saveUser(User user);
boolean createAndLoadGroup(String name);
boolean loadGroup(String name);
boolean loadAllGroups();
boolean saveGroup(Group group);
boolean deleteGroup(Group group);
boolean createAndLoadTrack(String name);
boolean loadTrack(String name);
boolean loadAllTracks();
boolean saveTrack(Track track);
boolean deleteTrack(Track track);
boolean saveUUIDData(String username, UUID uuid);
UUID getUUID(String username);
}
}
@@ -0,0 +1,171 @@
package me.lucko.luckperms.api;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
/**
* Wrapper interface for internal Group instances
* The implementations of this interface limit access to the Group and add parameter checks to further prevent
* errors and ensure all API interactions to not damage the state of the group.
*/
@SuppressWarnings("unused")
public interface Group extends PermissionObject {
/**
* @return the name of the group
*/
String getName();
/**
* check to see if a group inherits a group
* @param group The group to check membership of
* @return true if the user is a member of the group
*/
boolean inheritsGroup(Group group);
/**
* check to see if the group inherits a group on a specific server
* @param group The group to check membership of
* @param server The server to check on
* @return true if the group inherits the group
*/
boolean inheritsGroup(Group group, String server);
/**
* check to see if the group inherits a group on a specific server
* @param group The group to check membership of
* @param server The server to check on
* @param world The world to check on
* @return true if the group inherits the group
*/
boolean inheritsGroup(Group group, String server, String world);
/**
* Make this group inherit another group
* @param group the group to be inherited
* @throws ObjectAlreadyHasException if the group already inherits the group
*/
void setInheritGroup(Group group) throws ObjectAlreadyHasException;
/**
* Make this group inherit another group on a specific server
* @param group the group to be inherited
* @param server The server to add the group on
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
*/
void setInheritGroup(Group group, String server) throws ObjectAlreadyHasException;
/**
* Make this group inherit another group on a specific server
* @param group the group to be inherited
* @param server The server to add the group on
* @param world The world to add the group on
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
*/
void setInheritGroup(Group group, String server, String world) throws ObjectAlreadyHasException;
/**
* Make this group inherit another group on a specific server
* @param group the group to be inherited
* @param expireAt when the group should expire
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
*/
void setInheritGroup(Group group, long expireAt) throws ObjectAlreadyHasException;
/**
* Make this group inherit another group on a specific server
* @param group the group to be inherited
* @param server The server to add the group on
* @param expireAt when the group should expire
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
*/
void setInheritGroup(Group group, String server, long expireAt) throws ObjectAlreadyHasException;
/**
* Make this group inherit another group on a specific server
* @param group the group to be inherited
* @param server The server to add the group on
* @param world The world to add the group on
* @param expireAt when the group should expire
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
*/
void setInheritGroup(Group group, String server, String world, long expireAt) throws ObjectAlreadyHasException;
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @throws ObjectLacksException if the group does not already inherit the group
*/
void unsetInheritGroup(Group group) throws ObjectLacksException;
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the group does not already inherit the group
*/
void unsetInheritGroup(Group group, boolean temporary) throws ObjectLacksException;
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @param server The server to remove the group on
* @throws ObjectLacksException if the group does not already inherit the group
*/
void unsetInheritGroup(Group group, String server) throws ObjectLacksException;
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @param server The server to remove the group on
* @param world The world to remove the group on
* @throws ObjectLacksException if the group does not already inherit the group
*/
void unsetInheritGroup(Group group, String server, String world) throws ObjectLacksException;
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @param server The server to remove the group on
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the group does not already inherit the group
*/
void unsetInheritGroup(Group group, String server, boolean temporary) throws ObjectLacksException;
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @param server The server to remove the group on
* @param world The world to remove the group on
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the group does not already inherit the group
*/
void unsetInheritGroup(Group group, String server, String world, boolean temporary) throws ObjectLacksException;
/**
* Clear all of the groups permission nodes
*/
void clearNodes();
/**
* Get a {@link List} of all of the groups the group inherits, on all servers
* @return a {@link List} of group names
*/
List<String> getGroupNames();
/**
* Get a {@link List} of the groups the group inherits on a specific server
* @param server the server to check
* @return a {@link List} of group names
*/
List<String> getLocalGroups(String server, String world);
/**
* Get a {@link List} of the groups the group inherits on a specific server
* @param server the server to check
* @return a {@link List} of group names
*/
List<String> getLocalGroups(String server);
}
@@ -0,0 +1,23 @@
package me.lucko.luckperms.api;
import java.util.UUID;
@SuppressWarnings("unused")
public interface LuckPermsApi {
void runUpdateTask();
String getVersion();
Datastore getDatastore();
User getUser(UUID uuid);
User getUser(String name);
boolean isUserLoaded(UUID uuid);
Group getGroup(String name);
boolean isGroupLoaded(String name);
Track getTrack(String name);
boolean isTrackLoaded(String name);
}
@@ -0,0 +1,277 @@
package me.lucko.luckperms.api;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.Map;
/**
* Wrapper interface for internal PermissionObject (user/group) instances
* The implementations of this interface limit access to the object and add parameter checks to further prevent
* errors and ensure all API interactions to not damage the state of the object.
*/
@SuppressWarnings("unused")
public interface PermissionObject {
String getObjectName();
Map<String, Boolean> getNodes();
/**
* Checks to see if the object has a certain permission
* @param node The permission node
* @param b If the node is true/false(negated)
* @return true if the user has the permission
*/
boolean hasPermission(String node, boolean b);
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @return true if the user has the permission
*/
boolean hasPermission(String node, boolean b, String server);
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @return true if the user has the permission
*/
boolean hasPermission(String node, boolean b, String server, String world);
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param temporary if the permission is temporary
* @return true if the user has the permission
*/
boolean hasPermission(String node, boolean b, boolean temporary);
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server to check on
* @param temporary if the permission is temporary
* @return true if the user has the permission
*/
boolean hasPermission(String node, boolean b, String server, boolean temporary);
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server to check on
* @param world The world to check on
* @param temporary if the permission is temporary
* @return true if the user has the permission
*/
boolean hasPermission(String node, boolean b, String server, String world, boolean temporary);
/**
* Checks to see if the object inherits a certain permission
* @param node The permission node
* @param b If the node is true/false(negated)
* @return true if the user inherits the permission
*/
boolean inheritsPermission(String node, boolean b);
/**
* Checks to see the the object inherits a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @return true if the user inherits the permission
*/
boolean inheritsPermission(String node, boolean b, String server);
/**
* Checks to see the the object inherits a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @return true if the user inherits the permission
*/
boolean inheritsPermission(String node, boolean b, String server, String world);
/**
* Checks to see if the object inherits a certain permission
* @param node The permission node
* @param b If the node is true/false(negated)
* @param temporary if the permission is temporary
* @return true if the user inherits the permission
*/
boolean inheritsPermission(String node, boolean b, boolean temporary);
/**
* Checks to see if the object inherits a certain permission
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param temporary if the permission is temporary
* @return true if the user inherits the permission
*/
boolean inheritsPermission(String node, boolean b, String server, boolean temporary);
/**
* Checks to see if the object inherits a certain permission
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @param temporary if the permission is temporary
* @return true if the user inherits the permission
*/
boolean inheritsPermission(String node, boolean b, String server, String world, boolean temporary);
/**
* Sets a permission for the object
* @param node The node to be set
* @param value What to set the node to - true/false(negated)
* @throws ObjectAlreadyHasException if the object already has the permission
*/
void setPermission(String node, boolean value) throws ObjectAlreadyHasException;
/**
* Sets a permission for the object
* @param node The node to set
* @param value What to set the node to - true/false(negated)
* @param server The server to set the permission on
* @throws ObjectAlreadyHasException if the object already has the permission
*/
void setPermission(String node, boolean value, String server) throws ObjectAlreadyHasException;
/**
* Sets a permission for the object
* @param node The node to set
* @param value What to set the node to - true/false(negated)
* @param server The server to set the permission on
* @param world The world to set the permission on
* @throws ObjectAlreadyHasException if the object already has the permission
*/
void setPermission(String node, boolean value, String server, String world) throws ObjectAlreadyHasException;
/**
* Sets a permission for the object
* @param node The node to set
* @param value What to set the node to - true/false(negated)
* @param expireAt The time in unixtime when the permission will expire
* @throws ObjectAlreadyHasException if the object already has the permission
*/
void setPermission(String node, boolean value, long expireAt) throws ObjectAlreadyHasException;
/**
* Sets a permission for the object
* @param node The node to set
* @param value What to set the node to - true/false(negated)
* @param server The server to set the permission on
* @param expireAt The time in unixtime when the permission will expire
* @throws ObjectAlreadyHasException if the object already has the permission
*/
void setPermission(String node, boolean value, String server, long expireAt) throws ObjectAlreadyHasException;
/**
* Sets a permission for the object
* @param node The node to set
* @param value What to set the node to - true/false(negated)
* @param server The server to set the permission on
* @param world The world to set the permission on
* @param expireAt The time in unixtime when the permission will expire
* @throws ObjectAlreadyHasException if the object already has the permission
*/
void setPermission(String node, boolean value, String server, String world, long expireAt) throws ObjectAlreadyHasException;
/**
* Unsets a permission for the object
* @param node The node to be unset
* @param temporary if the permission being removed is temporary
* @throws ObjectLacksException if the node wasn't already set
*/
void unsetPermission(String node, boolean temporary) throws ObjectLacksException;
/**
* Unsets a permission for the object
* @param node The node to be unset
* @throws ObjectLacksException if the node wasn't already set
*/
void unsetPermission(String node) throws ObjectLacksException;
/**
* Unsets a permission for the object
* @param node The node to be unset
* @param server The server to unset the node on
* @throws ObjectLacksException if the node wasn't already set
*/
void unsetPermission(String node, String server) throws ObjectLacksException;
/**
* Unsets a permission for the object
* @param node The node to be unset
* @param server The server to unset the node on
* @param world The world to unset the node on
* @throws ObjectLacksException if the node wasn't already set
*/
void unsetPermission(String node, String server, String world) throws ObjectLacksException;
/**
* Unsets a permission for the object
* @param node The node to be unset
* @param server The server to unset the node on
* @param temporary if the permission being unset is temporary
* @throws ObjectLacksException if the node wasn't already set
*/
void unsetPermission(String node, String server, boolean temporary) throws ObjectLacksException;
/**
* Unsets a permission for the object
* @param node The node to be unset
* @param server The server to unset the node on
* @param world The world to unset the node on
* @param temporary if the permission being unset is temporary
* @throws ObjectLacksException if the node wasn't already set
*/
void unsetPermission(String node, String server, String world, boolean temporary) throws ObjectLacksException;
/**
* Gets the permissions and inherited permissions that apply to a specific server
* @param server The server to get nodes for
* @param world The world to get nodes for
* @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues)
* @return a {@link Map} of the permissions
*/
Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups);
/**
* Gets the permissions and inherited permissions that apply to a specific server
* @param server The server to get nodes for (can be null)
* @param excludedGroups Groups that shouldn't be inherited, can be null (to prevent circular inheritance issues)
* @return a {@link Map} of the permissions
*/
Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups);
/**
* Processes the objects and returns the temporary ones.
* @return a map of temporary nodes
*/
Map<Map.Entry<String, Boolean>, Long> getTemporaryNodes();
/**
* Processes the objects and returns the non-temporary ones.
* @return a map of permanent nodes
*/
Map<String, Boolean> getPermanentNodes();
/**
* Removes temporary permissions that have expired
*/
void auditTemporaryPermissions();
}
@@ -0,0 +1,95 @@
package me.lucko.luckperms.api;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
/**
* Wrapper interface for internal Track instances
* The implementations of this interface limit access to the Track and add parameter checks to further prevent
* errors and ensure all API interactions to not damage the state of the track.
*/
@SuppressWarnings("unused")
public interface Track {
String getName();
/**
* Gets an ordered list of the groups on this track
* @return am ordered {@link List} of the groups on this track
*/
List<String> getGroups();
/**
* Gets the number of groups on this track
* @return the number of groups on this track
*/
int getSize();
/**
* Gets the next group on the track, after the one provided
* @param current the group before the group being requested
* @return the group name, or null if the end of the track has been reached
* @throws ObjectLacksException if the track does not contain the group given
*/
String getNext(Group current) throws ObjectLacksException;
/**
* Gets the group before the group provided
* @param current the group after the group being requested
* @return the group name, or null if the start of the track has been reached
* @throws ObjectLacksException if the track does not contain the group given
*/
String getPrevious(Group current) throws ObjectLacksException;
/**
* Appends a group to the end of this track
* @param group the group to append
* @throws ObjectAlreadyHasException if the group is already on this track somewhere
*/
void appendGroup(Group group) throws ObjectAlreadyHasException;
/**
* Inserts a group at a certain position on this track
* @param group the group to be inserted
* @param position the index position (a value of 0 inserts at the start)
* @throws ObjectAlreadyHasException if the group is already on this track somewhere
* @throws IndexOutOfBoundsException if the position is less than 0 or greater than the size of the track
*/
void insertGroup(Group group, int position) throws ObjectAlreadyHasException, IndexOutOfBoundsException;
/**
* Removes a group from this track
* @param group the group to remove
* @throws ObjectLacksException if the group is not on this track
*/
void removeGroup(Group group) throws ObjectLacksException;
/**
* Removes a group from this track
* @param group the group to remove
* @throws ObjectLacksException if the group is not on this track
*/
void removeGroup(String group) throws ObjectLacksException;
/**
* Checks if a group features on this track
* @param group the group to check
* @return true if the group is on this track
*/
boolean containsGroup(Group group);
/**
* Checks if a group features on this track
* @param group the group to check
* @return true if the group is on this track
*/
boolean containsGroup(String group);
/**
* Clear all of the groups within this track
*/
void clearGroups();
}
@@ -0,0 +1,196 @@
package me.lucko.luckperms.api;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.UUID;
/**
* Wrapper interface for internal User instances
* The implementations of this interface limit access to the User and add parameter checks to further prevent
* errors and ensure all API interactions to not damage the state of the user.
*/
@SuppressWarnings("unused")
public interface User extends PermissionObject {
/**
* @return the users Mojang assigned unique id
*/
UUID getUuid();
/**
* @return the Users Username
*/
String getName();
/**
* Gets the users primary group
* @return the users primary group
*/
String getPrimaryGroup();
/**
* Sets a users primary group
* @param s the new primary group
* @throws ObjectAlreadyHasException if the user already has this set as their primary group
*/
void setPrimaryGroup(String s) throws ObjectAlreadyHasException;
/**
* Refresh and re-assign the users permissions
*/
void refreshPermissions();
/**
* Check to see if the user is a member of a group
* @param group The group to check membership of
* @return true if the user is a member of the group
*/
boolean isInGroup(Group group);
/**
* Check to see if a user is a member of a group on a specific server
* @param group The group to check membership of
* @param server The server to check on
* @return true if the user is a member of the group
*/
boolean isInGroup(Group group, String server);
/**
* Check to see if a user is a member of a group on a specific server
* @param group The group to check membership of
* @param server The server to check on
* @param world The world to check on
* @return true if the user is a member of the group
*/
boolean isInGroup(Group group, String server, String world);
/**
* Add a user to a group
* @param group The group to add the user to
* @throws ObjectAlreadyHasException if the user is already a member of the group
*/
void addGroup(Group group) throws ObjectAlreadyHasException;
/**
* Add a user to a group on a specific server
* @param group The group to add the user to
* @param server The server to add the group on
* @throws ObjectAlreadyHasException if the user is already a member of the group on that server
*/
void addGroup(Group group, String server) throws ObjectAlreadyHasException;
/**
* Add a user to a group on a specific server
* @param group The group to add the user to
* @param server The server to add the group on
* @param world The world to add the group on
* @throws ObjectAlreadyHasException if the user is already a member of the group on that server
*/
void addGroup(Group group, String server, String world) throws ObjectAlreadyHasException;
/**
* Add a user to a group on a specific server
* @param group The group to add the user to
* @param expireAt when the group should expire
* @throws ObjectAlreadyHasException if the user is already a member of the group on that server
*/
void addGroup(Group group, long expireAt) throws ObjectAlreadyHasException;
/**
* Add a user to a group on a specific server
* @param group The group to add the user to
* @param server The server to add the group on
* @param expireAt when the group should expire
* @throws ObjectAlreadyHasException if the user is already a member of the group on that server
*/
void addGroup(Group group, String server, long expireAt) throws ObjectAlreadyHasException;
/**
* Add a user to a group on a specific server
* @param group The group to add the user to
* @param server The server to add the group on
* @param world The world to add the group on
* @param expireAt when the group should expire
* @throws ObjectAlreadyHasException if the user is already a member of the group on that server
*/
void addGroup(Group group, String server, String world, long expireAt) throws ObjectAlreadyHasException;
/**
* Remove the user from a group
* @param group the group to remove the user from
* @throws ObjectLacksException if the user isn't a member of the group
*/
void removeGroup(Group group) throws ObjectLacksException;
/**
* Remove the user from a group
* @param group the group to remove the user from
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the user isn't a member of the group
*/
void removeGroup(Group group, boolean temporary) throws ObjectLacksException;
/**
* Remove the user from a group
* @param group The group to remove the user from
* @param server The server to remove the group on
* @throws ObjectLacksException if the user isn't a member of the group
*/
void removeGroup(Group group, String server) throws ObjectLacksException;
/**
* Remove the user from a group
* @param group The group to remove the user from
* @param server The server to remove the group on
* @param world The world to remove the group on
* @throws ObjectLacksException if the user isn't a member of the group
*/
void removeGroup(Group group, String server, String world) throws ObjectLacksException;
/**
* Remove the user from a group
* @param group The group to remove the user from
* @param server The server to remove the group on
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the user isn't a member of the group
*/
void removeGroup(Group group, String server, boolean temporary) throws ObjectLacksException;
/**
* Remove the user from a group
* @param group The group to remove the user from
* @param server The server to remove the group on
* @param world The world to remove the group on
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the user isn't a member of the group
*/
void removeGroup(Group group, String server, String world, boolean temporary) throws ObjectLacksException;
/**
* Clear all of the users permission nodes
*/
void clearNodes();
/**
* Get a {@link List} of all of the groups the user is a member of, on all servers
* @return a {@link List} of group names
*/
List<String> getGroupNames();
/**
* Get a {@link List} of the groups the user is a member of on a specific server
* @param server the server to check
* @return a {@link List} of group names
*/
List<String> getLocalGroups(String server, String world);
/**
* Get a {@link List} of the groups the user is a member of on a specific server
* @param server the server to check
* @return a {@link List} of group names
*/
List<String> getLocalGroups(String server);
}
@@ -0,0 +1,7 @@
package me.lucko.luckperms.api.data;
public interface Callback<T> {
void onComplete(T t);
}
+8 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko</groupId>
<version>1.2</version>
<version>${global.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -75,5 +75,12 @@
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<!-- LuckPerms API -->
<dependency>
<groupId>me.lucko</groupId>
<artifactId>luckperms-api</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -7,66 +7,49 @@ import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
public class BukkitConfig implements LPConfiguration {
private final LPBukkitPlugin plugin;
class BukkitConfig extends LPConfiguration<LPBukkitPlugin> {
private YamlConfiguration configuration;
public BukkitConfig(LPBukkitPlugin plugin) {
this.plugin = plugin;
create();
BukkitConfig(LPBukkitPlugin plugin) {
super(plugin, "global", true, "sqlite");
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private void create() {
File configFile = new File(plugin.getDataFolder(), "config.yml");
@Override
protected void init() {
File configFile = new File(getPlugin().getDataFolder(), "config.yml");
if (!configFile.exists()) {
configFile.getParentFile().mkdirs();
plugin.saveResource("config.yml", false);
getPlugin().saveResource("config.yml", false);
}
configuration = new YamlConfiguration();
try {
configuration.load(configFile);
} catch (InvalidConfigurationException | IOException e) {
e.printStackTrace();
}
}
@Override
public String getServer() {
return configuration.getString("server", "global");
protected void set(String path, Object value) {
configuration.set(path, value);
}
@Override
public int getSyncTime() {
return configuration.getInt("sql.sync-minutes", 3);
protected String getString(String path, String def) {
return configuration.getString(path, def);
}
@Override
public String getDefaultGroupNode() {
return "group." + configuration.getString("default-group", "default");
protected int getInt(String path, int def) {
return configuration.getInt(path, def);
}
@Override
public String getDefaultGroupName() {
return configuration.getString("default-group", "default");
}
@Override
public boolean getIncludeGlobalPerms() {
return configuration.getBoolean("include-global", true);
}
@Override
public String getDatabaseValue(String value) {
return configuration.getString("sql." + value);
}
@Override
public String getStorageMethod() {
return configuration.getString("storage-method", "sqlite");
protected boolean getBoolean(String path, boolean def) {
return configuration.getBoolean(path, def);
}
}
@@ -1,6 +1,9 @@
package me.lucko.luckperms;
import lombok.Getter;
import me.lucko.luckperms.api.LuckPermsApi;
import me.lucko.luckperms.api.implementation.ApiProvider;
import me.lucko.luckperms.api.vault.VaultHook;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.data.MySQLConfiguration;
import me.lucko.luckperms.data.methods.FlatfileDatastore;
@@ -13,11 +16,12 @@ import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.BukkitUserManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import me.lucko.luckperms.vaulthooks.VaultHook;
import me.lucko.luckperms.utils.UuidCache;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
@@ -28,16 +32,16 @@ import java.util.stream.Collectors;
@Getter
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
public static final String VERSION = "v1.2";
private LPConfiguration configuration;
private UserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
private UuidCache uuidCache;
@Override
public void onEnable() {
getLogger().info("Loading configuration...");
configuration = new BukkitConfig(this);
// register events
@@ -45,14 +49,15 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
pm.registerEvents(new PlayerListener(this), this);
// register commands
getLogger().info("Registering commands...");
CommandManagerBukkit commandManager = new CommandManagerBukkit(this);
PluginCommand main = getServer().getPluginCommand("luckperms");
main.setExecutor(commandManager);
main.setTabCompleter(commandManager);
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
getLogger().info("Detecting storage method...");
final String storageMethod = configuration.getStorageMethod();
if (storageMethod.equalsIgnoreCase("mysql")) {
getLogger().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(this, new MySQLConfiguration(
@@ -68,18 +73,26 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
getLogger().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(this, getDataFolder());
} else {
getLogger().warning("Storage method '" + storageMethod + "' was not recognised. Using SQLite as fallback.");
getLogger().severe("Storage method '" + storageMethod + "' was not recognised. Using SQLite as fallback.");
datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite"));
}
getLogger().info("Initialising datastore...");
datastore.init();
getLogger().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
userManager = new BukkitUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager(this);
trackManager = new TrackManager();
// Run update task to refresh any online users
runUpdateTask();
getLogger().info("Scheduling Update Task to refresh any online users.");
try {
new UpdateTask(this).run();
} catch (Exception e) {
e.printStackTrace();
}
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
@@ -88,18 +101,35 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
}
// Provide vault support
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
VaultHook.hook(this);
getLogger().info("Registered Vault permission & chat hook.");
} else {
getLogger().info("Vault not found.");
getLogger().info("Attempting to hook into Vault...");
try {
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
VaultHook.hook(this);
getLogger().info("Registered Vault permission & chat hook.");
} else {
getLogger().info("Vault not found.");
}
} catch (Exception e) {
getLogger().severe("Error occurred whilst hooking into Vault.");
e.printStackTrace();
}
getLogger().info("Registering API...");
final ApiProvider provider = new ApiProvider(this);
LuckPerms.registerProvider(provider);
getServer().getServicesManager().register(LuckPermsApi.class, provider, this, ServicePriority.Normal);
getLogger().info("Successfully loaded.");
}
@Override
public void onDisable() {
getLogger().info("Closing datastore...");
datastore.shutdown();
getLogger().info("Unregistering API...");
LuckPerms.unregisterProvider();
getServer().getServicesManager().unregisterAll(this);
}
@Override
@@ -114,12 +144,12 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
@Override
public String getVersion() {
return VERSION;
return getDescription().getVersion();
}
@Override
public String getPlayerStatus(UUID uuid) {
return getServer().getPlayer(uuid) != null ? "&aOnline" : "&cOffline";
return getServer().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? "&aOnline" : "&cOffline";
}
@Override
@@ -1,4 +1,4 @@
package me.lucko.luckperms.vaulthooks;
package me.lucko.luckperms.api.vault;
import net.milkbowl.vault.chat.Chat;
import net.milkbowl.vault.permission.Permission;
@@ -1,4 +1,4 @@
package me.lucko.luckperms.vaulthooks;
package me.lucko.luckperms.api.vault;
import me.lucko.luckperms.LPBukkitPlugin;
import net.milkbowl.vault.chat.Chat;
@@ -0,0 +1,197 @@
package me.lucko.luckperms.api.vault;
import lombok.NonNull;
import lombok.Setter;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.PermissionObject;
import net.milkbowl.vault.permission.Permission;
/**
*
*/
class VaultPermissionHook extends Permission {
@Setter
private LPBukkitPlugin plugin;
@Override
public String getName() {
return "LuckPerms";
}
@Override
public boolean isEnabled() {
return plugin.getDatastore().isAcceptingLogins();
}
@Override
public boolean hasSuperPermsCompat() {
return true;
}
private boolean objectHas(String world, PermissionObject object, String permission) {
if (object == null) return false;
if (world != null && !world.equals("")) {
return object.hasPermission(permission, true, "global", world);
} else {
return object.hasPermission(permission, true);
}
}
private boolean objectAdd(String world, PermissionObject object, String permission) {
if (object == null) return false;
try {
if (world != null && !world.equals("")) {
object.setPermission(permission, true, "global", world);
} else {
object.setPermission(permission, true);
}
} catch (ObjectAlreadyHasException ignored) {}
objectSave(object);
return true;
}
private boolean objectRemove(String world, PermissionObject object, String permission) {
if (object == null) return false;
try {
if (world != null && !world.equals("")) {
object.unsetPermission(permission, "global", world);
} else {
object.unsetPermission(permission);
}
} catch (ObjectLacksException ignored) {}
objectSave(object);
return true;
}
private void objectSave(PermissionObject t) {
if (t instanceof User) {
((User) t).refreshPermissions();
plugin.getDatastore().saveUser(((User) t), aBoolean -> {});
}
if (t instanceof Group) {
plugin.getDatastore().saveGroup(((Group) t), aBoolean -> plugin.runUpdateTask());
}
}
@Override
public boolean playerHas(String world, @NonNull String player, @NonNull String permission) {
return objectHas(world, plugin.getUserManager().getUser(player), permission);
}
@Override
public boolean playerAdd(String world, @NonNull String player, @NonNull String permission) {
final User user = plugin.getUserManager().getUser(player);
return objectAdd(world, user, permission);
}
@Override
public boolean playerRemove(String world, @NonNull String player, @NonNull String permission) {
final User user = plugin.getUserManager().getUser(player);
return objectRemove(world, user, permission);
}
@Override
public boolean groupHas(String world, @NonNull String groupName, @NonNull String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
return objectHas(world, group, permission);
}
@Override
public boolean groupAdd(String world, @NonNull String groupName, @NonNull String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
return objectAdd(world, group, permission);
}
@Override
public boolean groupRemove(String world, @NonNull String groupName, @NonNull String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
return objectRemove(world, group, permission);
}
@Override
public boolean playerInGroup(String world, @NonNull String player, @NonNull String group) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
final Group group1 = plugin.getGroupManager().getGroup(group);
if (group1 == null) return false;
if (world != null && !world.equals("")) {
return user.isInGroup(group1, "global", world);
} else {
return user.isInGroup(group1);
}
}
@Override
public boolean playerAddGroup(String world, @NonNull String player, @NonNull String groupName) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
if (world != null && !world.equals("")) {
user.addGroup(group, "global", world);
} else {
user.addGroup(group);
}
} catch (ObjectAlreadyHasException ignored) {}
objectSave(user);
return true;
}
@Override
public boolean playerRemoveGroup(String world, @NonNull String player, @NonNull String groupName) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
if (world != null && !world.equals("")) {
user.removeGroup(group, "global", world);
} else {
user.removeGroup(group);
}
} catch (ObjectLacksException ignored) {}
objectSave(user);
return true;
}
@Override
public String[] getPlayerGroups(String world, @NonNull String player) {
final User user = plugin.getUserManager().getUser(player);
return (user == null) ? new String[0] :
world != null && !world.equals("") ? user.getLocalGroups("global", world).toArray(new String[0]) :
user.getGroupNames().toArray(new String[0]);
}
@Override
public String getPrimaryGroup(String world, @NonNull String player) {
final User user = plugin.getUserManager().getUser(player);
return (user == null) ? null : user.getPrimaryGroup();
}
@Override
public String[] getGroups() {
return plugin.getGroupManager().getGroups().keySet().toArray(new String[0]);
}
@Override
public boolean hasGroupSupport() {
return true;
}
}
@@ -6,36 +6,52 @@ import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.users.BukkitUser;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.UuidCache;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.*;
import java.util.UUID;
@AllArgsConstructor
public class PlayerListener implements Listener {
private static final String KICK_MESSAGE = Util.color(Message.PREFIX + "User data could not be loaded. Please contact an administrator.");
private final LPBukkitPlugin plugin;
@EventHandler
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
if (!plugin.getDatastore().isAcceptingLogins()) {
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER,
Util.color(Message.PREFIX + "Error whilst validating login with the network. \nPlease contact an administrator."));
// Datastore is disabled, prevent players from joining the server
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, KICK_MESSAGE);
return;
}
plugin.getDatastore().loadOrCreateUser(e.getUniqueId(), e.getName());
final UuidCache cache = plugin.getUuidCache();
if (!cache.isOnlineMode()) {
UUID uuid = plugin.getDatastore().getUUID(e.getName());
if (uuid != null) {
cache.addToCache(e.getUniqueId(), uuid);
} else {
// No previous data for this player
cache.addToCache(e.getUniqueId(), e.getUniqueId());
plugin.getDatastore().saveUUIDData(e.getName(), e.getUniqueId(), b -> {});
}
} else {
// Online mode, no cache needed. This is just for name -> uuid lookup.
plugin.getDatastore().saveUUIDData(e.getName(), e.getUniqueId(), b -> {});
}
plugin.getDatastore().loadOrCreateUser(cache.getUUID(e.getUniqueId()), e.getName());
}
@EventHandler
public void onPlayerLogin(PlayerLoginEvent e) {
Player player = e.getPlayer();
User user = plugin.getUserManager().getUser(player.getUniqueId());
final Player player = e.getPlayer();
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
if (user == null) {
e.disallow(PlayerLoginEvent.Result.KICK_OTHER,
Util.color(Message.PREFIX + "User data could not be loaded. Please contact an administrator."));
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, KICK_MESSAGE);
return;
}
@@ -49,24 +65,32 @@ public class PlayerListener implements Listener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
// Save UUID data for the player
plugin.getDatastore().saveUUIDData(e.getPlayer().getName(), e.getPlayer().getUniqueId(), success -> {});
User user = plugin.getUserManager().getUser(e.getPlayer().getUniqueId());
if (user != null) {
// Refresh permissions again
user.refreshPermissions();
}
// Refresh permissions again
refreshPlayer(e.getPlayer());
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
Player player = e.getPlayer();
final Player player = e.getPlayer();
final UuidCache cache = plugin.getUuidCache();
// Unload the user from memory when they disconnect
User user = plugin.getUserManager().getUser(player.getUniqueId());
// Unload the user from memory when they disconnect;
cache.clearCache(player.getUniqueId());
final User user = plugin.getUserManager().getUser(cache.getUUID(player.getUniqueId()));
plugin.getUserManager().unloadUser(user);
}
@EventHandler
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
refreshPlayer(e.getPlayer());
}
private void refreshPlayer(Player p) {
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(p.getUniqueId()));
if (user != null) {
user.refreshPermissions();
}
}
}
@@ -3,7 +3,6 @@ package me.lucko.luckperms.users;
import lombok.Getter;
import lombok.Setter;
import me.lucko.luckperms.LPBukkitPlugin;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionAttachment;
@@ -31,7 +30,7 @@ public class BukkitUser extends User {
@Override
public void refreshPermissions() {
plugin.doSync(() -> {
Player player = Bukkit.getPlayer(getUuid());
final Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid()));
if (player == null) return;
if (attachment == null) {
@@ -43,7 +42,7 @@ public class BukkitUser extends User {
attachment.getPermissions().keySet().forEach(p -> attachment.setPermission(p, false));
// Re-add all defined permissions for the user
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null);
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), player.getWorld().getName(), null);
local.entrySet().forEach(e -> attachment.setPermission(e.getKey(), e.getValue()));
});
}
@@ -1,10 +1,11 @@
package me.lucko.luckperms.users;
import me.lucko.luckperms.LPBukkitPlugin;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class BukkitUserManager extends UserManager {
private final LPBukkitPlugin plugin;
@@ -22,7 +23,7 @@ public class BukkitUserManager extends UserManager {
BukkitUser u = (BukkitUser) user;
if (u.getAttachment() != null) {
Player player = Bukkit.getPlayer(u.getUuid());
Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid()));
if (player != null) {
player.removeAttachment(u.getAttachment());
@@ -37,7 +38,7 @@ public class BukkitUserManager extends UserManager {
@Override
public void cleanupUser(User user) {
if (Bukkit.getPlayer(user.getUuid()) == null) {
if (plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) {
unloadUser(user);
}
}
@@ -54,6 +55,12 @@ public class BukkitUserManager extends UserManager {
@Override
public void updateAllUsers() {
plugin.getServer().getOnlinePlayers().stream().map(Player::getUniqueId).forEach(u -> plugin.getDatastore().loadUser(u));
// Sometimes called async, so we need to get the players on the Bukkit thread.
plugin.doSync(() -> {
Set<UUID> players = plugin.getServer().getOnlinePlayers().stream()
.map(p -> plugin.getUuidCache().getUUID(p.getUniqueId()))
.collect(Collectors.toSet());
plugin.doAsync(() -> players.forEach(u -> plugin.getDatastore().loadUser(u)));
});
}
}
@@ -1,152 +0,0 @@
package me.lucko.luckperms.vaulthooks;
import lombok.Setter;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import net.milkbowl.vault.permission.Permission;
class VaultPermissionHook extends Permission {
@Setter
private LPBukkitPlugin plugin;
@Override
public String getName() {
return "LuckPerms";
}
@Override
public boolean isEnabled() {
return plugin.getDatastore().isAcceptingLogins();
}
@Override
public boolean hasSuperPermsCompat() {
// Idk???
return true;
}
@Override
public boolean playerHas(String world, String player, String permission) {
final User user = plugin.getUserManager().getUser(player);
return user != null && user.hasPermission(permission, true);
}
@Override
public boolean playerAdd(String world, String player, String permission) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
try {
user.setPermission(permission, true);
} catch (ObjectAlreadyHasException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public boolean playerRemove(String world, String player, String permission) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
try {
user.unsetPermission(permission);
} catch (ObjectLacksException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public boolean groupHas(String world, String groupName, String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
return group != null && group.hasPermission(permission, true);
}
@Override
public boolean groupAdd(String world, String groupName, String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
group.setPermission(permission, true);
} catch (ObjectAlreadyHasException ignored) {}
plugin.runUpdateTask();
return true;
}
@Override
public boolean groupRemove(String world, String groupName, String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
group.unsetPermission(permission);
} catch (ObjectLacksException ignored) {}
plugin.runUpdateTask();
return true;
}
@Override
public boolean playerInGroup(String world, String player, String group) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
final Group group1 = plugin.getGroupManager().getGroup(group);
return group1 != null && user.isInGroup(group1);
}
@Override
public boolean playerAddGroup(String world, String player, String groupName) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
user.addGroup(group);
} catch (ObjectAlreadyHasException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public boolean playerRemoveGroup(String world, String player, String groupName) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
user.removeGroup(group);
} catch (ObjectLacksException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public String[] getPlayerGroups(String world, String player) {
final User user = plugin.getUserManager().getUser(player);
return (user == null) ? new String[0] : user.getGroupNames().toArray(new String[0]);
}
@Override
public String getPrimaryGroup(String world, String player) {
final User user = plugin.getUserManager().getUser(player);
return (user == null) ? null : user.getPrimaryGroup();
}
@Override
public String[] getGroups() {
return plugin.getGroupManager().getGroups().keySet().toArray(new String[0]);
}
@Override
public boolean hasGroupSupport() {
return true;
}
}
+13
View File
@@ -9,6 +9,19 @@ default-group: default
# If users on this server should have their global permissions/groups applied.
include-global: true
# If this server is in offline or online mode.
# This setting allows a player to have the same UUID across a network of offline mode/mixed servers.
# You should generally reflect the setting in server.properties here. Except when...
# 1. You have Spigot servers connected to a BungeeCord proxy, with online-mode set to false, but 'bungeecord' set to true in the spigot.yml
# AND 'ip-forward' set to true in the BungeeCord config.yml
# In this case, set online-mode in LuckPerms to true, dispite the server being in offline mode.
# 2. You are only running one server instance using LuckPerms, (not a network)
# In this case, set online-mode to true no matter what is set in server.properties. (we can just fallback to the servers uuid cache)
online-mode: true
# Which storage method the plugin should use.
# Currently supported: mysql, sqlite, flatfile
# Fill out connection info below if you're using MySQL
+1 -1
View File
@@ -1,6 +1,6 @@
name: LuckPerms
author: Luck
version: 1.2
version: ${global.version}
main: me.lucko.luckperms.LPBukkitPlugin
softdepend: [Vault]
description: A permissions plugin
+8 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko</groupId>
<version>1.2</version>
<version>${global.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -68,6 +68,13 @@
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<!-- LuckPerms API -->
<dependency>
<groupId>me.lucko</groupId>
<artifactId>luckperms-api</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -10,30 +10,20 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
public class BungeeConfig implements LPConfiguration {
private final LPBungeePlugin plugin;
class BungeeConfig extends LPConfiguration<LPBungeePlugin> {
private Configuration configuration;
public BungeeConfig(LPBungeePlugin plugin) {
this.plugin = plugin;
reload();
}
private void reload() {
try {
configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(makeFile("config.yml"));
} catch (IOException e) {
e.printStackTrace();
}
BungeeConfig(LPBungeePlugin plugin) {
super(plugin, "bungee", false, "flatfile");
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private File makeFile(String file) throws IOException {
File cfg = new File(plugin.getDataFolder(), file);
File cfg = new File(getPlugin().getDataFolder(), file);
if (!cfg.exists()) {
plugin.getDataFolder().mkdir();
try (InputStream is = plugin.getResourceAsStream(file)) {
getPlugin().getDataFolder().mkdir();
try (InputStream is = getPlugin().getResourceAsStream(file)) {
Files.copy(is, cfg.toPath());
}
}
@@ -42,37 +32,31 @@ public class BungeeConfig implements LPConfiguration {
}
@Override
public String getServer() {
return configuration.getString("server", "bungee");
protected void init() {
try {
configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(makeFile("config.yml"));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public int getSyncTime() {
return configuration.getInt("sql.sync-minutes", 3);
protected void set(String path, Object value) {
configuration.set(path, value);
}
@Override
public String getDefaultGroupNode() {
return "group." + configuration.getString("default-group", "default");
protected String getString(String path, String def) {
return configuration.getString(path, def);
}
@Override
public String getDefaultGroupName() {
return configuration.getString("default-group", "default");
protected int getInt(String path, int def) {
return configuration.getInt(path, def);
}
@Override
public boolean getIncludeGlobalPerms() {
return configuration.getBoolean("include-global", false);
}
@Override
public String getDatabaseValue(String value) {
return configuration.getString("sql." + value);
}
@Override
public String getStorageMethod() {
return configuration.getString("storage-method", "sqlite");
protected boolean getBoolean(String path, boolean def) {
return configuration.getBoolean(path, def);
}
}
@@ -1,6 +1,7 @@
package me.lucko.luckperms;
import lombok.Getter;
import me.lucko.luckperms.api.implementation.ApiProvider;
import me.lucko.luckperms.commands.CommandManager;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.data.MySQLConfiguration;
@@ -13,6 +14,7 @@ import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.BungeeUserManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import me.lucko.luckperms.utils.UuidCache;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
@@ -23,29 +25,30 @@ import java.util.stream.Collectors;
@Getter
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
public static final String VERSION = "v1.2";
private LPConfiguration configuration;
private UserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
private UuidCache uuidCache;
@Override
public void onEnable() {
getLogger().info("Loading configuration...");
configuration = new BungeeConfig(this);
// register events
getProxy().getPluginManager().registerListener(this, new PlayerListener(this));
// register commands
getLogger().info("Registering commands...");
getProxy().getPluginManager().registerCommand(this, new MainCommand(new CommandManager(this)));
// disable the default Bungee /perms command so it gets handled by the Bukkit plugin
getProxy().getDisabledCommands().add("perms");
getLogger().info("Detecting storage method...");
final String storageMethod = configuration.getStorageMethod();
if (storageMethod.equalsIgnoreCase("mysql")) {
getLogger().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(this, new MySQLConfiguration(
@@ -58,35 +61,55 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
getLogger().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(this, getDataFolder());
} else {
getLogger().warning("Storage method '" + storageMethod + "' was not recognised. Using Flatfile as fallback.");
getLogger().severe("Storage method '" + storageMethod + "' was not recognised. Using Flatfile as fallback.");
datastore = new FlatfileDatastore(this, getDataFolder());
}
getLogger().info("Initialising datastore...");
datastore.init();
getLogger().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
userManager = new BungeeUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager(this);
trackManager = new TrackManager();
// Run update task to refresh any online users
getLogger().info("Scheduling Update Task to refresh any online users.");
try {
new UpdateTask(this).run();
} catch (Exception e) {
e.printStackTrace();
}
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
getProxy().getScheduler().schedule(this, new UpdateTask(this), mins, mins, TimeUnit.MINUTES);
}
getLogger().info("Registering API...");
LuckPerms.registerProvider(new ApiProvider(this));
getLogger().info("Successfully loaded.");
}
@Override
public void onDisable() {
getLogger().info("Closing datastore...");
datastore.shutdown();
getLogger().info("Unregistering API...");
LuckPerms.unregisterProvider();
}
@Override
public String getVersion() {
return VERSION;
return getDescription().getVersion();
}
@Override
public String getPlayerStatus(UUID uuid) {
return getProxy().getPlayer(uuid) != null ? "&aOnline" : "&cOffline";
return getProxy().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? "&aOnline" : "&cOffline";
}
@Override
@@ -16,7 +16,6 @@ class MainCommand extends Command implements TabExecutor {
public MainCommand(CommandManager manager) {
super("luckpermsbungee", null, "bperms", "lpb", "bpermissions", "bp", "bperm");
this.manager = manager;
}
@Override
@@ -5,53 +5,94 @@ import me.lucko.luckperms.LPBungeePlugin;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.UuidCache;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.event.ServerSwitchEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import java.lang.ref.WeakReference;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@AllArgsConstructor
public class PlayerListener implements Listener {
private static final TextComponent WARN_MESSAGE = new TextComponent(Util.color(
Message.PREFIX + "Permissions data could not be loaded. Please contact an administrator.")
);
private final LPBungeePlugin plugin;
@EventHandler
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
Offline mode. */
e.registerIntent(plugin);
plugin.doAsync(() -> {
final UuidCache cache = plugin.getUuidCache();
final PendingConnection c = e.getConnection();
if (!cache.isOnlineMode()) {
UUID uuid = plugin.getDatastore().getUUID(c.getName());
if (uuid != null) {
cache.addToCache(c.getUniqueId(), uuid);
} else {
// No previous data for this player
cache.addToCache(c.getUniqueId(), c.getUniqueId());
plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId());
}
} else {
// Online mode, no cache needed. This is just for name -> uuid lookup.
plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId());
}
// 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().loadOrCreateUser(cache.getUUID(c.getUniqueId()), c.getName());
e.completeIntent(plugin);
});
}
@EventHandler
public void onPlayerPostLogin(PostLoginEvent e) {
final ProxiedPlayer player = e.getPlayer();
final WeakReference<ProxiedPlayer> p = new WeakReference<>(player);
plugin.getDatastore().loadOrCreateUser(player.getUniqueId(), player.getName(), success -> {
if (!success) {
plugin.getProxy().getScheduler().schedule(plugin, () -> {
final ProxiedPlayer pl = p.get();
if (pl != null) {
pl.sendMessage(new TextComponent(Util.color(Message.PREFIX + "Permissions data could not be loaded. Please contact an administrator.")));
}
}, 3, TimeUnit.SECONDS);
} else {
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
if (user == null) {
plugin.getProxy().getScheduler().schedule(plugin, () -> {
final ProxiedPlayer pl = p.get();
if (pl != null) {
final User user = plugin.getUserManager().getUser(pl.getUniqueId());
user.refreshPermissions();
pl.sendMessage(WARN_MESSAGE);
}
}
});
plugin.getDatastore().saveUUIDData(player.getName(), player.getUniqueId(), success -> {});
}, 3, TimeUnit.SECONDS);
} else {
user.refreshPermissions();
}
}
@EventHandler
public void onPlayerQuit(PlayerDisconnectEvent e) {
ProxiedPlayer player = e.getPlayer();
final ProxiedPlayer player = e.getPlayer();
final UuidCache cache = plugin.getUuidCache();
// Unload the user from memory when they disconnect
User user = plugin.getUserManager().getUser(player.getUniqueId());
// Unload the user from memory when they disconnect;
cache.clearCache(player.getUniqueId());
final User user = plugin.getUserManager().getUser(cache.getUUID(player.getUniqueId()));
plugin.getUserManager().unloadUser(user);
}
@EventHandler
public void onPlayerServerSwitch(ServerSwitchEvent e) {
final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
if (user != null) {
user.refreshPermissions();
}
}
}
@@ -24,7 +24,7 @@ public class BungeeUser extends User {
@Override
public void refreshPermissions() {
ProxiedPlayer player = plugin.getProxy().getPlayer(getUuid());
ProxiedPlayer player = plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid()));
if (player == null) return;
// Clear existing permissions
@@ -32,7 +32,8 @@ public class BungeeUser extends User {
perms.forEach(p -> player.setPermission(p, false));
// Re-add all defined permissions for the user
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null);
final String server = player.getServer() == null ? null : (player.getServer().getInfo() == null ? null : player.getServer().getInfo().getName());
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), server, null);
local.entrySet().forEach(e -> player.setPermission(e.getKey(), e.getValue()));
}
}
@@ -1,7 +1,6 @@
package me.lucko.luckperms.users;
import me.lucko.luckperms.LPBungeePlugin;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.UUID;
@@ -24,7 +23,7 @@ public class BungeeUserManager extends UserManager {
@Override
public void cleanupUser(User user) {
if (plugin.getProxy().getPlayer(user.getUuid()) == null) {
if (plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) {
unloadUser(user);
}
}
@@ -41,6 +40,8 @@ public class BungeeUserManager extends UserManager {
@Override
public void updateAllUsers() {
plugin.getProxy().getPlayers().stream().map(ProxiedPlayer::getUniqueId).forEach(u -> plugin.getDatastore().loadUser(u));
plugin.getProxy().getPlayers().stream()
.map(p -> plugin.getUuidCache().getUUID(p.getUniqueId()))
.forEach(u -> plugin.getDatastore().loadUser(u));
}
}
+13
View File
@@ -9,6 +9,19 @@ default-group: default
# If users on this server should have their global permissions/groups applied.
include-global: false
# If this server is in offline or online mode.
# This setting allows a player to have the same UUID across a network of offline mode/mixed servers.
# You should generally reflect the setting in server.properties here. Except when...
# 1. You have Spigot servers connected to a BungeeCord proxy, with online-mode set to false, but 'bungeecord' set to true in the spigot.yml
# AND 'ip-forward' set to true in the BungeeCord config.yml
# In this case, set online-mode in LuckPerms to true, dispite the server being in offline mode.
# 2. You are only running one server instance using LuckPerms, (not a network)
# In this case, set online-mode to true no matter what is set in server.properties. (we can just fallback to the servers uuid cache)
online-mode: true
# Which storage method the plugin should use.
# Currently supported: mysql & flatfile
# Fill out connection info below if you're using MySQL
+1 -1
View File
@@ -1,5 +1,5 @@
name: LuckPerms
author: Luck
version: 1.2
version: ${global.version}
main: me.lucko.luckperms.LPBungeePlugin
description: A permissions plugin
+12 -2
View File
@@ -5,12 +5,11 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko</groupId>
<version>1.2</version>
<version>${global.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-common</artifactId>
<version>$(project.parent.version)</version>
<build>
<plugins>
<plugin>
@@ -24,4 +23,15 @@
</plugin>
</plugins>
</build>
<dependencies>
<!-- LuckPerms API -->
<dependency>
<groupId>me.lucko</groupId>
<artifactId>luckperms-api</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -5,6 +5,7 @@ import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import me.lucko.luckperms.utils.UuidCache;
import java.util.List;
import java.util.UUID;
@@ -48,6 +49,12 @@ public interface LuckPermsPlugin {
*/
Logger getLogger();
/**
* Retrieves the {@link UuidCache} for the plugin
* @return the plugin's {@link UuidCache}
*/
UuidCache getUuidCache();
/**
* @return the version of the plugin
*/
@@ -0,0 +1,90 @@
package me.lucko.luckperms.api.implementation;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.implementation.internal.DatastoreLink;
import me.lucko.luckperms.api.implementation.internal.GroupLink;
import me.lucko.luckperms.api.implementation.internal.TrackLink;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import java.util.UUID;
/**
* Provides static access to LuckPerms
*/
@AllArgsConstructor
public class ApiProvider implements LuckPermsApi {
private final LuckPermsPlugin plugin;
@Override
public void runUpdateTask() {
plugin.runUpdateTask();
}
@Override
public String getVersion() {
return plugin.getVersion();
}
@Override
public Datastore getDatastore() {
return new DatastoreLink(plugin.getDatastore());
}
@Override
public User getUser(@NonNull UUID uuid) {
final me.lucko.luckperms.users.User user = plugin.getUserManager().getUser(uuid);
if (user == null) {
return null;
}
return new UserLink(user);
}
@Override
public User getUser(@NonNull String name) {
final me.lucko.luckperms.users.User user = plugin.getUserManager().getUser(name);
if (user == null) {
return null;
}
return new UserLink(user);
}
@Override
public boolean isUserLoaded(@NonNull UUID uuid) {
return plugin.getUserManager().isLoaded(uuid);
}
@Override
public Group getGroup(@NonNull String name) {
final me.lucko.luckperms.groups.Group group = plugin.getGroupManager().getGroup(name);
if (group == null) {
return null;
}
return new GroupLink(group);
}
@Override
public boolean isGroupLoaded(@NonNull String name) {
return plugin.getGroupManager().isLoaded(name);
}
@Override
public Track getTrack(@NonNull String name) {
final me.lucko.luckperms.tracks.Track track = plugin.getTrackManager().getTrack(name);
if (track == null) {
return null;
}
return new TrackLink(track);
}
@Override
public boolean isTrackLoaded(@NonNull String name) {
return plugin.getTrackManager().isLoaded(name);
}
}
@@ -0,0 +1,244 @@
package me.lucko.luckperms.api.implementation.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.Datastore;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.utils.Patterns;
import java.util.UUID;
/**
* Provides a link between {@link Datastore} and {@link me.lucko.luckperms.data.Datastore}
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public class DatastoreLink implements Datastore {
private final me.lucko.luckperms.data.Datastore master;
private final Async async;
private final Sync sync;
public DatastoreLink(@NonNull me.lucko.luckperms.data.Datastore master) {
this.master = master;
this.async = new Async(master);
this.sync = new Sync(master);
}
private static String checkUsername(String s) {
if (s.length() > 16 || Patterns.NON_USERNAME.matcher(s).find()) {
throw new IllegalArgumentException("Invalid username entry '" + s + "'. Usernames must be less than 16 chars" +
" and only contain 'a-z A-Z 1-9 _'.");
}
return s;
}
private static String checkName(String s) {
if (s.length() > 36 || Patterns.NON_ALPHA_NUMERIC.matcher(s).find()) {
throw new IllegalArgumentException("Invalid name entry '" + s + "'. Names must be less than 37 chars" +
" and only contain 'a-z A-Z 1-9'.");
}
return s.toLowerCase();
}
private static <T> Callback<T> checkCallback(Callback<T> c) {
// If no callback was given, just send an empty one
if (c == null) {
c = t -> {};
}
return c;
}
@Override
public String getName() {
return master.getName();
}
@Override
public boolean isAcceptingLogins() {
return master.isAcceptingLogins();
}
@Override
public Async async() {
return async;
}
@Override
public Sync sync() {
return sync;
}
@AllArgsConstructor
public class Async implements Datastore.Async {
private final me.lucko.luckperms.data.Datastore master;
@Override
public void loadOrCreateUser(@NonNull UUID uuid, @NonNull String username, Callback<Boolean> callback) {
master.loadOrCreateUser(uuid, checkUsername(username), checkCallback(callback));
}
@Override
public void loadUser(@NonNull UUID uuid, Callback<Boolean> callback) {
master.loadUser(uuid, checkCallback(callback));
}
@Override
public void saveUser(@NonNull User user, Callback<Boolean> callback) {
Utils.checkUser(user);
master.saveUser(((UserLink) user).getMaster(), checkCallback(callback));
}
@Override
public void createAndLoadGroup(@NonNull String name, Callback<Boolean> callback) {
master.createAndLoadGroup(checkName(name), checkCallback(callback));
}
@Override
public void loadGroup(@NonNull String name, Callback<Boolean> callback) {
master.loadGroup(checkName(name), checkCallback(callback));
}
@Override
public void loadAllGroups(Callback<Boolean> callback) {
master.loadAllGroups(checkCallback(callback));
}
@Override
public void saveGroup(@NonNull Group group, Callback<Boolean> callback) {
Utils.checkGroup(group);
master.saveGroup(((GroupLink) group).getMaster(), checkCallback(callback));
}
@Override
public void deleteGroup(@NonNull Group group, Callback<Boolean> callback) {
Utils.checkGroup(group);
master.deleteGroup(((GroupLink) group).getMaster(), checkCallback(callback));
}
@Override
public void createAndLoadTrack(@NonNull String name, Callback<Boolean> callback) {
master.createAndLoadTrack(checkName(name), checkCallback(callback));
}
@Override
public void loadTrack(@NonNull String name, Callback<Boolean> callback) {
master.loadTrack(checkName(name), checkCallback(callback));
}
@Override
public void loadAllTracks(Callback<Boolean> callback) {
master.loadAllTracks(checkCallback(callback));
}
@Override
public void saveTrack(@NonNull Track track, Callback<Boolean> callback) {
Utils.checkTrack(track);
master.saveTrack(((TrackLink) track).getMaster(), checkCallback(callback));
}
@Override
public void deleteTrack(@NonNull Track track, Callback<Boolean> callback) {
Utils.checkTrack(track);
master.deleteTrack(((TrackLink) track).getMaster(), checkCallback(callback));
}
@Override
public void saveUUIDData(@NonNull String username, @NonNull UUID uuid, Callback<Boolean> callback) {
master.saveUUIDData(checkUsername(username), uuid, checkCallback(callback));
}
@Override
public void getUUID(@NonNull String username, Callback<UUID> callback) {
master.getUUID(checkUsername(username), checkCallback(callback));
}
}
@AllArgsConstructor
public class Sync implements Datastore.Sync {
private final me.lucko.luckperms.data.Datastore master;
@Override
public boolean loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) {
return master.loadOrCreateUser(uuid, checkUsername(username));
}
@Override
public boolean loadUser(@NonNull UUID uuid) {
return master.loadUser(uuid);
}
@Override
public boolean saveUser(@NonNull User user) {
Utils.checkUser(user);
return master.saveUser(((UserLink) user).getMaster());
}
@Override
public boolean createAndLoadGroup(@NonNull String name) {
return master.createAndLoadGroup(checkName(name));
}
@Override
public boolean loadGroup(@NonNull String name) {
return master.loadGroup(checkName(name));
}
@Override
public boolean loadAllGroups() {
return master.loadAllGroups();
}
@Override
public boolean saveGroup(@NonNull Group group) {
Utils.checkGroup(group);
return master.saveGroup(((GroupLink) group).getMaster());
}
@Override
public boolean deleteGroup(@NonNull Group group) {
Utils.checkGroup(group);
return master.deleteGroup(((GroupLink) group).getMaster());
}
@Override
public boolean createAndLoadTrack(@NonNull String name) {
return master.createAndLoadTrack(checkName(name));
}
@Override
public boolean loadTrack(@NonNull String name) {
return master.loadTrack(checkName(name));
}
@Override
public boolean loadAllTracks() {
return master.loadAllTracks();
}
@Override
public boolean saveTrack(@NonNull Track track) {
Utils.checkTrack(track);
return master.saveTrack(((TrackLink) track).getMaster());
}
@Override
public boolean deleteTrack(@NonNull Track track) {
Utils.checkTrack(track);
return master.deleteTrack(((TrackLink) track).getMaster());
}
@Override
public boolean saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
return master.saveUUIDData(checkUsername(username), uuid);
}
@Override
public UUID getUUID(@NonNull String username) {
return master.getUUID(checkUsername(username));
}
}
}
@@ -0,0 +1,140 @@
package me.lucko.luckperms.api.implementation.internal;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
/**
* Provides a link between {@link Group} and {@link me.lucko.luckperms.groups.Group}
*/
@SuppressWarnings("unused")
public class GroupLink extends PermissionObjectLink implements Group {
@Getter(AccessLevel.PACKAGE)
private final me.lucko.luckperms.groups.Group master;
public GroupLink(@NonNull me.lucko.luckperms.groups.Group master) {
super(master);
this.master = master;
}
@Override
public String getName() {
return master.getName();
}
@Override
public boolean inheritsGroup(@NonNull Group group) {
Utils.checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster());
}
@Override
public boolean inheritsGroup(@NonNull Group group, @NonNull String server) {
Utils.checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster(), server);
}
@Override
public boolean inheritsGroup(@NonNull Group group, @NonNull String server, @NonNull String world) {
Utils.checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster(), server, world);
}
@Override
public void setInheritGroup(@NonNull Group group) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster());
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server));
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world);
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull long expireAt) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkTime(expireAt));
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server, @NonNull long expireAt) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), checkTime(expireAt));
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull long expireAt) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world, checkTime(expireAt));
}
@Override
public void unsetInheritGroup(@NonNull Group group) throws ObjectLacksException {
Utils.checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster());
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull boolean temporary) throws ObjectLacksException {
Utils.checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), temporary);
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server) throws ObjectLacksException {
Utils.checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server));
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectLacksException {
Utils.checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world);
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server, @NonNull boolean temporary) throws ObjectLacksException {
Utils.checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), temporary);
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull boolean temporary) throws ObjectLacksException {
Utils.checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world, temporary);
}
@Override
public void clearNodes() {
master.clearNodes();
}
@Override
public List<String> getGroupNames() {
return master.getGroupNames();
}
@Override
public List<String> getLocalGroups(@NonNull String server, @NonNull String world) {
return master.getLocalGroups(checkServer(server), world);
}
@Override
public List<String> getLocalGroups(@NonNull String server) {
return master.getLocalGroups(checkServer(server));
}
}
@@ -0,0 +1,202 @@
package me.lucko.luckperms.api.implementation.internal;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.PermissionObject;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.utils.DateUtil;
import me.lucko.luckperms.utils.Patterns;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Provides a link between {@link PermissionObject} and {@link me.lucko.luckperms.utils.PermissionObject}
*/
@SuppressWarnings("unused")
@AllArgsConstructor(access = AccessLevel.PACKAGE)
class PermissionObjectLink implements PermissionObject {
@NonNull
private final me.lucko.luckperms.utils.PermissionObject master;
static String checkServer(String s) {
if (Patterns.NON_ALPHA_NUMERIC.matcher(s).find()) {
throw new IllegalArgumentException("Invalid server entry '" + s + "'. Server names can only contain alphanumeric characters.");
}
return s;
}
private static String checkNode(String s) {
if (s.contains("/") || s.contains("$")) {
throw new IllegalArgumentException("Invalid node entry '" + s + "'. Nodes cannot contain '/' or '$' characters.");
}
return s;
}
static long checkTime(long l) {
if (DateUtil.shouldExpire(l)) {
throw new IllegalArgumentException("Unix time '" + l + "' is invalid, as it has already passed.");
}
return l;
}
@Override
public String getObjectName() {
return master.getObjectName();
}
@Override
public Map<String, Boolean> getNodes() {
return Collections.unmodifiableMap(master.getNodes());
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b) {
return master.hasPermission(node, b);
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server) {
return master.hasPermission(node, b, checkServer(server));
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world) {
return master.hasPermission(node, b, checkServer(server), world);
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull boolean temporary) {
return master.hasPermission(node, b, temporary);
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull boolean temporary) {
return master.hasPermission(node, b, checkServer(server), temporary);
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world, @NonNull boolean temporary) {
return master.hasPermission(node, b, checkServer(server), world, temporary);
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b) {
return master.inheritsPermission(node, b);
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server) {
return master.inheritsPermission(node, b, checkServer(server));
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world) {
return master.inheritsPermission(node, b, checkServer(server), world);
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull boolean temporary) {
return master.inheritsPermission(node, b, temporary);
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull boolean temporary) {
return master.inheritsPermission(node, b, checkServer(server), temporary);
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world, @NonNull boolean temporary) {
return master.inheritsPermission(node, b, checkServer(server), world, temporary);
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value);
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull String server) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value, checkServer(server));
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull String server, @NonNull String world) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value, checkServer(server), world);
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull long expireAt) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value, checkTime(expireAt));
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull String server, @NonNull long expireAt) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value, checkServer(server), checkTime(expireAt));
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull String server, @NonNull String world, @NonNull long expireAt) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value, checkServer(server), world, checkTime(expireAt));
}
@Override
public void unsetPermission(@NonNull String node, @NonNull boolean temporary) throws ObjectLacksException {
master.unsetPermission(checkNode(node), temporary);
}
@Override
public void unsetPermission(@NonNull String node) throws ObjectLacksException {
master.unsetPermission(checkNode(node));
}
@Override
public void unsetPermission(@NonNull String node, @NonNull String server) throws ObjectLacksException {
master.unsetPermission(checkNode(node), checkServer(server));
}
@Override
public void unsetPermission(@NonNull String node, @NonNull String server, @NonNull String world) throws ObjectLacksException {
master.unsetPermission(checkNode(node), checkServer(server), world);
}
@Override
public void unsetPermission(@NonNull String node, @NonNull String server, @NonNull boolean temporary) throws ObjectLacksException {
master.unsetPermission(checkNode(node), checkServer(server), temporary);
}
@Override
public void unsetPermission(@NonNull String node, @NonNull String server, @NonNull String world, @NonNull boolean temporary) throws ObjectLacksException {
master.unsetPermission(checkNode(node), checkServer(server), world, temporary);
}
@Override
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups) {
return master.getLocalPermissions(server, world, excludedGroups);
}
@Override
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups) {
return master.getLocalPermissions(server, excludedGroups);
}
@Override
public Map<Map.Entry<String, Boolean>, Long> getTemporaryNodes() {
return master.getTemporaryNodes();
}
@Override
public Map<String, Boolean> getPermanentNodes() {
return master.getPermanentNodes();
}
@Override
public void auditTemporaryPermissions() {
master.auditTemporaryPermissions();
}
}
@@ -0,0 +1,90 @@
package me.lucko.luckperms.api.implementation.internal;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
/**
* Provides a link between {@link Track} and {@link me.lucko.luckperms.tracks.Track}
*/
@SuppressWarnings("unused")
@AllArgsConstructor
public class TrackLink implements Track {
@NonNull
@Getter(AccessLevel.PACKAGE)
private final me.lucko.luckperms.tracks.Track master;
@Override
public String getName() {
return master.getName();
}
@Override
public List<String> getGroups() {
return master.getGroups();
}
@Override
public int getSize() {
return master.getSize();
}
@Override
public String getNext(@NonNull Group current) throws ObjectLacksException {
Utils.checkGroup(current);
return master.getNext(((GroupLink) current).getMaster());
}
@Override
public String getPrevious(@NonNull Group current) throws ObjectLacksException {
Utils.checkGroup(current);
return master.getPrevious(((GroupLink) current).getMaster());
}
@Override
public void appendGroup(@NonNull Group group) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.appendGroup(((GroupLink) group).getMaster());
}
@Override
public void insertGroup(@NonNull Group group, @NonNull int position) throws ObjectAlreadyHasException, IndexOutOfBoundsException {
Utils.checkGroup(group);
master.insertGroup(((GroupLink) group).getMaster(), position);
}
@Override
public void removeGroup(@NonNull Group group) throws ObjectLacksException {
Utils.checkGroup(group);
master.removeGroup(((GroupLink) group).getMaster());
}
@Override
public void removeGroup(@NonNull String group) throws ObjectLacksException {
master.removeGroup(group);
}
@Override
public boolean containsGroup(@NonNull Group group) {
Utils.checkGroup(group);
return master.containsGroup(((GroupLink) group).getMaster());
}
@Override
public boolean containsGroup(@NonNull String group) {
return master.containsGroup(group);
}
@Override
public void clearGroups() {
master.clearGroups();
}
}
@@ -0,0 +1,171 @@
package me.lucko.luckperms.api.implementation.internal;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.UUID;
/**
* Provides a link between {@link User} and {@link me.lucko.luckperms.users.User}
*/
@SuppressWarnings("unused")
public class UserLink extends PermissionObjectLink implements User {
@Getter(AccessLevel.PACKAGE)
private final me.lucko.luckperms.users.User master;
public UserLink(@NonNull me.lucko.luckperms.users.User master) {
super(master);
this.master = master;
}
@Override
public UUID getUuid() {
return master.getUuid();
}
@Override
public String getName() {
return master.getName();
}
@Override
public String getPrimaryGroup() {
return master.getPrimaryGroup();
}
@Override
public void setPrimaryGroup(String s) throws ObjectAlreadyHasException {
if (getPrimaryGroup().equalsIgnoreCase(s)) {
throw new ObjectAlreadyHasException();
}
if (!getGroupNames().contains(s.toLowerCase())) {
throw new IllegalStateException("User is not a member of that group.");
}
master.setPrimaryGroup(s.toLowerCase());
}
@Override
public void refreshPermissions() {
master.refreshPermissions();
}
@Override
public boolean isInGroup(@NonNull Group group) {
Utils.checkGroup(group);
return master.isInGroup(((GroupLink) group).getMaster());
}
@Override
public boolean isInGroup(@NonNull Group group, @NonNull String server) {
Utils.checkGroup(group);
return master.isInGroup(((GroupLink) group).getMaster(), server);
}
@Override
public boolean isInGroup(@NonNull Group group, @NonNull String server, @NonNull String world) {
Utils.checkGroup(group);
return master.isInGroup(((GroupLink) group).getMaster(), server, world);
}
@Override
public void addGroup(@NonNull Group group) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.addGroup(((GroupLink) group).getMaster());
}
@Override
public void addGroup(@NonNull Group group, @NonNull String server) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.addGroup(((GroupLink) group).getMaster(), checkServer(server));
}
@Override
public void addGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.addGroup(((GroupLink) group).getMaster(), checkServer(server), world);
}
@Override
public void addGroup(@NonNull Group group, @NonNull long expireAt) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.addGroup(((GroupLink) group).getMaster(), checkTime(expireAt));
}
@Override
public void addGroup(@NonNull Group group, @NonNull String server, @NonNull long expireAt) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.addGroup(((GroupLink) group).getMaster(), checkServer(server), checkTime(expireAt));
}
@Override
public void addGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull long expireAt) throws ObjectAlreadyHasException {
Utils.checkGroup(group);
master.addGroup(((GroupLink) group).getMaster(), checkServer(server), world, checkTime(expireAt));
}
@Override
public void removeGroup(@NonNull Group group) throws ObjectLacksException {
Utils.checkGroup(group);
master.removeGroup(((GroupLink) group).getMaster());
}
@Override
public void removeGroup(@NonNull Group group, @NonNull boolean temporary) throws ObjectLacksException {
Utils.checkGroup(group);
master.removeGroup(((GroupLink) group).getMaster(), temporary);
}
@Override
public void removeGroup(@NonNull Group group, @NonNull String server) throws ObjectLacksException {
Utils.checkGroup(group);
master.removeGroup(((GroupLink) group).getMaster(), checkServer(server));
}
@Override
public void removeGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectLacksException {
Utils.checkGroup(group);
master.removeGroup(((GroupLink) group).getMaster(), checkServer(server), world);
}
@Override
public void removeGroup(@NonNull Group group, @NonNull String server, @NonNull boolean temporary) throws ObjectLacksException {
Utils.checkGroup(group);
master.removeGroup(((GroupLink) group).getMaster(), checkServer(server), temporary);
}
@Override
public void removeGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull boolean temporary) throws ObjectLacksException {
Utils.checkGroup(group);
master.removeGroup(((GroupLink) group).getMaster(), checkServer(server), world, temporary);
}
@Override
public void clearNodes() {
master.clearNodes();
}
@Override
public List<String> getGroupNames() {
return master.getGroupNames();
}
@Override
public List<String> getLocalGroups(@NonNull String server, @NonNull String world) {
return master.getLocalGroups(checkServer(server), world);
}
@Override
public List<String> getLocalGroups(@NonNull String server) {
return master.getLocalGroups(checkServer(server));
}
}
@@ -0,0 +1,27 @@
package me.lucko.luckperms.api.implementation.internal;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
class Utils {
static void checkUser(User user) {
if (!(user instanceof UserLink)) {
throw new IllegalArgumentException("User instance cannot be handled by this implementation.");
}
}
static void checkGroup(Group group) {
if (!(group instanceof GroupLink)) {
throw new IllegalArgumentException("Group instance cannot be handled by this implementation.");
}
}
static void checkTrack(Track track) {
if (!(track instanceof TrackLink)) {
throw new IllegalArgumentException("Track instance cannot be handled by this implementation.");
}
}
}
@@ -147,7 +147,8 @@ public class CommandManager {
return mains.stream().map(MainCommand::getName).map(String::toLowerCase).collect(Collectors.toList());
}
return mains.stream().map(MainCommand::getName).map(String::toLowerCase).filter(s -> s.startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
return mains.stream().map(MainCommand::getName).map(String::toLowerCase)
.filter(s -> s.startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
}
Optional<MainCommand> o = mains.stream().filter(m -> m.getName().equalsIgnoreCase(args.get(0))).limit(1).findAny();
@@ -1,5 +1,8 @@
package me.lucko.luckperms.commands;
/**
* Wrapper class to represent a CommandSender in Bukkit/Bungee within the luckperms-common command implementations.
*/
public interface Sender {
void sendMessage(String s);
@@ -4,6 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import java.util.ArrayList;
import java.util.Arrays;
@@ -11,6 +12,13 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* Abstract SubCommand class
* Doesn't declare any abstract onCommand methods, as sub classes declare their own with parameters unique to the sub command type.
* For example, see: {@link me.lucko.luckperms.commands.user.UserSubCommand#execute(LuckPermsPlugin, Sender, User, List, String)}
*
* SubCommand #execute methods are always called from the {@link MainCommand} class related to them, so abstraction is not needed.
*/
@Getter
@AllArgsConstructor
public abstract class SubCommand {
@@ -19,6 +27,25 @@ public abstract class SubCommand {
private final String usage;
private final Permission permission;
public abstract boolean isArgLengthInvalid(int argLength);
public boolean isAuthorized(Sender sender) {
return permission.isAuthorized(sender);
}
public void sendUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&e-> &d" + String.format(getUsage(), 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.
*/
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
/* Utility methods used by #onTabComplete implementations in sub classes */
protected static List<String> getGroupTabComplete(List<String> args, LuckPermsPlugin plugin) {
return getTabComplete(new ArrayList<>(plugin.getGroupManager().getGroups().keySet()), args);
}
@@ -27,6 +54,14 @@ public abstract class SubCommand {
return getTabComplete(new ArrayList<>(plugin.getTrackManager().getTracks().keySet()), args);
}
protected static List<String> getBoolTabComplete(List<String> args) {
if (args.size() == 2) {
return Arrays.asList("true", "false");
} else {
return Collections.emptyList();
}
}
private static List<String> getTabComplete(List<String> options, List<String> args) {
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
@@ -38,26 +73,4 @@ public abstract class SubCommand {
return Collections.emptyList();
}
protected static List<String> getBoolTabComplete(List<String> args) {
if (args.size() == 2) {
return Arrays.asList("true", "false");
} else {
return Collections.emptyList();
}
}
public boolean isAuthorized(Sender sender) {
return permission.isAuthorized(sender);
}
public void sendUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&e-> &d" + String.format(getUsage(), label));
}
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
public abstract boolean isArgLengthInvalid(int argLength);
}
@@ -1,5 +1,6 @@
package me.lucko.luckperms.commands;
import lombok.experimental.UtilityClass;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.utils.DateUtil;
@@ -7,10 +8,9 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
@UtilityClass
public class Util {
private Util() {}
public static void sendPluginMessage(Sender sender, String message) {
sender.sendMessage(color(Message.PREFIX + message));
}
@@ -7,6 +7,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import java.util.ArrayList;
import java.util.Collections;
@@ -32,6 +33,11 @@ public class DeleteGroup extends MainCommand {
return;
}
if (Patterns.NON_ALPHA_NUMERIC.matcher(groupName).find()) {
Message.GROUP_INVALID_ENTRY.send(sender);
return;
}
plugin.getDatastore().loadGroup(groupName, success -> {
if (!success) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
@@ -6,6 +6,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import java.util.ArrayList;
import java.util.List;
@@ -51,6 +52,12 @@ public class GroupMainCommand extends MainCommand {
}
final String groupName = args.get(0).toLowerCase();
if (Patterns.NON_ALPHA_NUMERIC.matcher(groupName).find()) {
Message.GROUP_INVALID_ENTRY.send(sender);
return;
}
plugin.getDatastore().loadGroup(groupName, success -> {
if (!success) {
Message.GROUP_NOT_FOUND.send(sender);
@@ -4,21 +4,33 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class GroupHasPerm extends GroupSubCommand {
public GroupHasPerm() {
super("haspermission", "Checks to see if a group has a certain permission node",
"/%s group <group> haspermission <node> [server]", Permission.GROUP_HASPERMISSION);
"/%s group <group> haspermission <node> [server] [world]", Permission.GROUP_HASPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
if (args.size() == 2) {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1).toLowerCase()));
if (args.size() >= 2) {
if (Patterns.NON_ALPHA_NUMERIC.matcher(args.get(1)).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1)));
} else {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1), args.get(2)));
}
} else {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, "global"));
}
@@ -26,6 +38,6 @@ public class GroupHasPerm extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -4,21 +4,33 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class GroupInheritsPerm extends GroupSubCommand {
public GroupInheritsPerm() {
super("inheritspermission", "Checks to see if a group inherits a certain permission node",
"/%s group <group> inheritspermission <node> [server]", Permission.GROUP_INHERITSPERMISSION);
"/%s group <group> inheritspermission <node> [server] [world]", Permission.GROUP_INHERITSPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
if (args.size() == 2) {
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1).toLowerCase()));
if (args.size() >= 2) {
if (Patterns.NON_ALPHA_NUMERIC.matcher(args.get(1)).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1)));
} else {
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1), args.get(2)));
}
} else {
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true));
}
@@ -26,6 +38,6 @@ public class GroupInheritsPerm extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -7,13 +7,14 @@ import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class GroupSetInherit extends GroupSubCommand {
public GroupSetInherit() {
super("setinherit", "Sets another group for this group to inherit permissions from",
"/%s group <group> setinherit <group> [server]", Permission.GROUP_SETINHERIT);
"/%s group <group> setinherit <group> [server] [world]", Permission.GROUP_SETINHERIT);
}
@Override
@@ -30,10 +31,22 @@ public class GroupSetInherit extends GroupSubCommand {
Message.GROUP_LOAD_ERROR.send(sender);
} else {
try {
if (args.size() == 2) {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
group.setPermission("group." + groupName, true, server);
Message.GROUP_SETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
group.setPermission("group." + groupName, true, server);
Message.GROUP_SETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
} else {
final String world = args.get(2).toLowerCase();
group.setPermission("group." + groupName, true, server, world);
Message.GROUP_SETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world);
}
} else {
group.setPermission("group." + groupName, true);
Message.GROUP_SETINHERIT_SUCCESS.send(sender, group.getName(), groupName);
@@ -54,6 +67,6 @@ public class GroupSetInherit extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -13,7 +13,7 @@ import java.util.List;
public class GroupSetPermission extends GroupSubCommand {
public GroupSetPermission() {
super("set", "Sets a permission for a group", "/%s group <group> set <node> <true|false> [server]",
super("set", "Sets a permission for a group", "/%s group <group> set <node> <true|false> [server] [world]",
Permission.GROUP_SETPERMISSION);
}
@@ -40,10 +40,22 @@ public class GroupSetPermission extends GroupSubCommand {
boolean b = Boolean.parseBoolean(bool);
try {
if (args.size() == 3) {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
group.setPermission(node, b, server);
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 3) {
group.setPermission(node, b, server);
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server);
} else {
final String world = args.get(3).toLowerCase();
group.setPermission(node, b, server, world);
Message.SETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, bool, group.getName(), server, world);
}
} else {
group.setPermission(node, b);
Message.SETPERMISSION_SUCCESS.send(sender, node, bool, group.getName());
@@ -62,6 +74,6 @@ public class GroupSetPermission extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 2 && argLength != 3;
return argLength != 2 && argLength != 3 && argLength != 4;
}
}
@@ -8,13 +8,14 @@ import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.DateUtil;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class GroupSetTempInherit extends GroupSubCommand {
public GroupSetTempInherit() {
super("settempinherit", "Sets another group for this group to inherit permissions from temporarily",
"/%s group <group> settempinherit <group> <duration> [server]", Permission.GROUP_SET_TEMP_INHERIT);
"/%s group <group> settempinherit <group> <duration> [server] [world]", Permission.GROUP_SET_TEMP_INHERIT);
}
@Override
@@ -44,11 +45,24 @@ public class GroupSetTempInherit extends GroupSubCommand {
Message.GROUP_LOAD_ERROR.send(sender);
} else {
try {
if (args.size() == 3) {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
group.setPermission("group." + groupName, true, server, duration);
Message.GROUP_SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server,
DateUtil.formatDateDiff(duration));
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 3) {
group.setPermission("group." + groupName, true, server, duration);
Message.GROUP_SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server,
DateUtil.formatDateDiff(duration));
} else {
final String world = args.get(3).toLowerCase();
group.setPermission("group." + groupName, true, server, world, duration);
Message.GROUP_SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server,
world, DateUtil.formatDateDiff(duration));
}
} else {
group.setPermission("group." + groupName, true, duration);
Message.GROUP_SET_TEMP_INHERIT_SUCCESS.send(sender, group.getName(), groupName, DateUtil.formatDateDiff(duration));
@@ -69,6 +83,6 @@ public class GroupSetTempInherit extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 2 && argLength != 3;
return argLength != 2 && argLength != 3 && argLength != 4;
}
}
@@ -14,8 +14,8 @@ import java.util.List;
public class GroupSetTempPermission extends GroupSubCommand {
public GroupSetTempPermission() {
super("settemp", "Sets a temporary permission for a group", "/%s group <group> settemp <node> <true|false> <duration> [server]",
Permission.GROUP_SET_TEMP_PERMISSION);
super("settemp", "Sets a temporary permission for a group",
"/%s group <group> settemp <node> <true|false> <duration> [server] [world]", Permission.GROUP_SET_TEMP_PERMISSION);
}
@Override
@@ -54,10 +54,24 @@ public class GroupSetTempPermission extends GroupSubCommand {
}
try {
if (args.size() == 4) {
if (args.size() >= 4) {
final String server = args.get(3).toLowerCase();
group.setPermission(node, b, server, duration);
Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server, DateUtil.formatDateDiff(duration));
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 4) {
group.setPermission(node, b, server, duration);
Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server,
DateUtil.formatDateDiff(duration));
} else {
final String world = args.get(4).toLowerCase();
group.setPermission(node, b, server, world, duration);
Message.SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS.send(sender, node, bool, group.getName(), server,
world, DateUtil.formatDateDiff(duration));
}
} else {
group.setPermission(node, b, duration);
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, bool, group.getName(), DateUtil.formatDateDiff(duration));
@@ -76,6 +90,6 @@ public class GroupSetTempPermission extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 3 && argLength != 4;
return argLength != 3 && argLength != 4 && argLength != 5;
}
}
@@ -14,7 +14,7 @@ import java.util.List;
public class GroupUnSetPermission extends GroupSubCommand {
public GroupUnSetPermission() {
super("unset", "Unsets a permission for a group",
"/%s group <group> unset <node> [server]", Permission.GROUP_UNSETPERMISSION);
"/%s group <group> unset <node> [server] [world]", Permission.GROUP_UNSETPERMISSION);
}
@Override
@@ -32,10 +32,22 @@ public class GroupUnSetPermission extends GroupSubCommand {
}
try {
if (args.size() == 2) {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
group.unsetPermission(node, server);
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
group.unsetPermission(node, server);
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission(node, server, world);
Message.UNSETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, group.getName(), server, world);
}
} else {
group.unsetPermission(node);
Message.UNSETPERMISSION_SUCCESS.send(sender, node, group.getName());
@@ -49,6 +61,6 @@ public class GroupUnSetPermission extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -7,13 +7,14 @@ import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class GroupUnsetInherit extends GroupSubCommand {
public GroupUnsetInherit() {
super("unsetinherit", "Unsets another group for this group to inherit permissions from",
"/%s group <group> unsetinherit <group> [server]", Permission.GROUP_UNSETINHERIT);
"/%s group <group> unsetinherit <group> [server] [world]", Permission.GROUP_UNSETINHERIT);
}
@Override
@@ -26,10 +27,22 @@ public class GroupUnsetInherit extends GroupSubCommand {
}
try {
if (args.size() == 2) {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
group.unsetPermission("group." + groupName, server);
Message.GROUP_UNSETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
group.unsetPermission("group." + groupName, server);
Message.GROUP_UNSETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission("group." + groupName, server, world);
Message.GROUP_UNSETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world);
}
} else {
group.unsetPermission("group." + groupName);
Message.GROUP_UNSETINHERIT_SUCCESS.send(sender, group.getName(), groupName);
@@ -48,6 +61,6 @@ public class GroupUnsetInherit extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -7,13 +7,14 @@ import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class GroupUnsetTempInherit extends GroupSubCommand {
public GroupUnsetTempInherit() {
super("unsettempinherit", "Unsets another group for this group to inherit permissions from",
"/%s group <group> unsettempinherit <group> [server]", Permission.GROUP_UNSET_TEMP_INHERIT);
"/%s group <group> unsettempinherit <group> [server] [world]", Permission.GROUP_UNSET_TEMP_INHERIT);
}
@Override
@@ -26,10 +27,22 @@ public class GroupUnsetTempInherit extends GroupSubCommand {
}
try {
if (args.size() == 2) {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
group.unsetPermission("group." + groupName, server, true);
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
group.unsetPermission("group." + groupName, server, true);
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission("group." + groupName, server, world, true);
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world);
}
} else {
group.unsetPermission("group." + groupName, true);
Message.GROUP_UNSET_TEMP_INHERIT_SUCCESS.send(sender, group.getName(), groupName);
@@ -48,6 +61,6 @@ public class GroupUnsetTempInherit extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -14,7 +14,7 @@ import java.util.List;
public class GroupUnsetTempPermission extends GroupSubCommand {
public GroupUnsetTempPermission() {
super("unsettemp", "Unsets a temporary permission for a group",
"/%s group <group> unsettemp <node> [server]", Permission.GROUP_UNSET_TEMP_PERMISSION);
"/%s group <group> unsettemp <node> [server] [world]", Permission.GROUP_UNSET_TEMP_PERMISSION);
}
@Override
@@ -32,10 +32,22 @@ public class GroupUnsetTempPermission extends GroupSubCommand {
}
try {
if (args.size() == 2) {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
group.unsetPermission(node, server);
Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server, true);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
group.unsetPermission(node, server);
Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission(node, server, world);
Message.UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, group.getName(), server, world);
}
} else {
group.unsetPermission(node, true);
Message.UNSET_TEMP_PERMISSION_SUCCESS.send(sender, node, group.getName());
@@ -49,6 +61,6 @@ public class GroupUnsetTempPermission extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -6,6 +6,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.utils.LPConfiguration;
import java.util.Collections;
import java.util.List;
@@ -17,7 +18,9 @@ public class InfoCommand extends MainCommand {
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
Message.INFO.send(sender, plugin.getVersion(), plugin.getDatastore().getName());
final LPConfiguration c = plugin.getConfiguration();
Message.INFO.send(sender, plugin.getVersion(), plugin.getDatastore().getName(), c.getServer(),
c.getDefaultGroupName(), c.getSyncTime(), c.getIncludeGlobalPerms(), c.getOnlineMode());
}
@Override
@@ -7,6 +7,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.utils.Patterns;
import java.util.ArrayList;
import java.util.Collections;
@@ -27,6 +28,11 @@ public class DeleteTrack extends MainCommand {
String trackName = args.get(0).toLowerCase();
if (Patterns.NON_ALPHA_NUMERIC.matcher(trackName).find()) {
Message.TRACK_INVALID_ENTRY.send(sender);
return;
}
plugin.getDatastore().loadTrack(trackName, success -> {
if (!success) {
Message.TRACK_DOES_NOT_EXIST.send(sender);
@@ -6,6 +6,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.utils.Patterns;
import java.util.ArrayList;
import java.util.List;
@@ -51,6 +52,12 @@ public class TrackMainCommand extends MainCommand {
}
final String trackName = args.get(0).toLowerCase();
if (Patterns.NON_ALPHA_NUMERIC.matcher(trackName).find()) {
Message.TRACK_INVALID_ENTRY.send(sender);
return;
}
plugin.getDatastore().loadTrack(trackName, success -> {
if (!success) {
Message.TRACK_NOT_FOUND.send(sender);
@@ -7,6 +7,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Patterns;
import java.util.ArrayList;
import java.util.List;
@@ -54,6 +55,12 @@ public class UserMainCommand extends MainCommand {
}
final String user = args.get(0);
if (Patterns.NON_USERNAME.matcher(user).find()) {
Message.USER_INVALID_ENTRY.send(sender, user);
return;
}
UUID u = Util.parseUuid(user);
if (u != null) {
runSub(plugin, sender, u, sub, strippedArgs, label);
@@ -8,12 +8,13 @@ import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class UserAddGroup extends UserSubCommand {
public UserAddGroup() {
super("addgroup", "Adds the user to a group", "/%s user <user> addgroup <group> [server]", Permission.USER_ADDGROUP);
super("addgroup", "Adds the user to a group", "/%s user <user> addgroup <group> [server] [world]", Permission.USER_ADDGROUP);
}
@Override
@@ -36,10 +37,22 @@ public class UserAddGroup extends UserSubCommand {
}
try {
if (args.size() == 2) {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
user.addGroup(group, server);
Message.USER_ADDGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
user.addGroup(group, server);
Message.USER_ADDGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
} else {
final String world = args.get(2).toLowerCase();
user.addGroup(group, server, world);
Message.USER_ADDGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world);
}
} else {
user.addGroup(group);
Message.USER_ADDGROUP_SUCCESS.send(sender, user.getName(), groupName);
@@ -60,6 +73,6 @@ public class UserAddGroup extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return (argLength != 1 && argLength != 2);
return (argLength != 1 && argLength != 2 && argLength != 3);
}
}
@@ -9,13 +9,14 @@ import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.DateUtil;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class UserAddTempGroup extends UserSubCommand {
public UserAddTempGroup() {
super("addtempgroup", "Adds the user to a group temporarily", "/%s user <user> addtempgroup <group> <duration> [server]",
Permission.USER_ADDTEMPGROUP);
super("addtempgroup", "Adds the user to a group temporarily",
"/%s user <user> addtempgroup <group> <duration> [server] [world]", Permission.USER_ADDTEMPGROUP);
}
@Override
@@ -51,11 +52,24 @@ public class UserAddTempGroup extends UserSubCommand {
}
try {
if (args.size() == 3) {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
user.addGroup(group, server, duration);
Message.USER_ADDTEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server,
DateUtil.formatDateDiff(duration));
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 3) {
user.addGroup(group, server, duration);
Message.USER_ADDTEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server,
DateUtil.formatDateDiff(duration));
} else {
final String world = args.get(3).toLowerCase();
user.addGroup(group, server, world, duration);
Message.USER_ADDTEMPGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server,
world, DateUtil.formatDateDiff(duration));
}
} else {
user.addGroup(group, duration);
Message.USER_ADDTEMPGROUP_SUCCESS.send(sender, user.getName(), groupName, DateUtil.formatDateDiff(duration));
@@ -76,6 +90,6 @@ public class UserAddTempGroup extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return (argLength != 2 && argLength != 3);
return (argLength != 2 && argLength != 3 && argLength != 4);
}
}
@@ -65,9 +65,11 @@ public class UserDemote extends UserSubCommand {
try {
user.unsetPermission("group." + old);
} catch (ObjectLacksException ignored) {}
try {
user.addGroup(previousGroup);
user.setPrimaryGroup(previousGroup.getName());
} catch (ObjectLacksException | ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {}
user.setPrimaryGroup(previousGroup.getName());
Message.USER_DEMOTE_SUCCESS_PROMOTE.send(sender, track.getName(), old, previousGroup.getName());
Message.USER_DEMOTE_SUCCESS_REMOVE.send(sender, user.getName(), old, previousGroup.getName(), previousGroup.getName());
@@ -4,21 +4,33 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class UserHasPerm extends UserSubCommand {
public UserHasPerm() {
super("haspermission", "Checks to see if a user has a certain permission node",
"/%s user <user> haspermission <node> [server]", Permission.USER_HASPERMISSION);
"/%s user <user> haspermission <node> [server] [world]", Permission.USER_HASPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
if (args.size() >= 2) {
Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, args.get(1)));
if (Patterns.NON_ALPHA_NUMERIC.matcher(args.get(1)).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, args.get(1)));
} else {
Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, args.get(1), args.get(2)));
}
} else {
Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, "global"));
}
@@ -26,6 +38,6 @@ public class UserHasPerm extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -4,21 +4,33 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class UserInheritsPerm extends UserSubCommand {
public UserInheritsPerm() {
super("inheritspermission", "Checks to see if a user inherits a certain permission node",
"/%s user <user> inheritspermission <node> [server]", Permission.USER_INHERITSPERMISSION);
"/%s user <user> inheritspermission <node> [server] [world]", Permission.USER_INHERITSPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
if (args.size() >= 2) {
Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true, args.get(1)));
if (Patterns.NON_ALPHA_NUMERIC.matcher(args.get(1)).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true, args.get(1)));
} else {
Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true, args.get(1), args.get(2)));
}
} else {
Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true));
}
@@ -26,6 +38,6 @@ public class UserInheritsPerm extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -65,9 +65,11 @@ public class UserPromote extends UserSubCommand {
try {
user.unsetPermission("group." + old);
} catch (ObjectLacksException ignored) {}
try {
user.addGroup(nextGroup);
user.setPrimaryGroup(nextGroup.getName());
} catch (ObjectLacksException | ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {}
user.setPrimaryGroup(nextGroup.getName());
Message.USER_PROMOTE_SUCCESS_PROMOTE.send(sender, track.getName(), old, nextGroup.getName());
Message.USER_PROMOTE_SUCCESS_REMOVE.send(sender, user.getName(), old, nextGroup.getName(), nextGroup.getName());
@@ -7,12 +7,13 @@ import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class UserRemoveGroup extends UserSubCommand {
public UserRemoveGroup() {
super("removegroup", "Removes a user from a group", "/%s user <user> removegroup <group> [server]", Permission.USER_REMOVEGROUP);
super("removegroup", "Removes a user from a group", "/%s user <user> removegroup <group> [server] [world]", Permission.USER_REMOVEGROUP);
}
@Override
@@ -31,10 +32,22 @@ public class UserRemoveGroup extends UserSubCommand {
}
try {
if (args.size() == 2) {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
user.unsetPermission("group." + groupName, server);
Message.USER_REMOVEGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
user.unsetPermission("group." + groupName, server);
Message.USER_REMOVEGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
} else {
final String world = args.get(2).toLowerCase();
user.unsetPermission("group." + groupName, server, world);
Message.USER_REMOVEGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world);
}
} else {
user.unsetPermission("group." + groupName);
Message.USER_REMOVEGROUP_SUCCESS.send(sender, user.getName(), groupName);
@@ -53,6 +66,6 @@ public class UserRemoveGroup extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return (argLength != 1 && argLength != 2);
return (argLength != 1 && argLength != 2 && argLength != 3);
}
}
@@ -7,12 +7,14 @@ import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class UserRemoveTempGroup extends UserSubCommand {
public UserRemoveTempGroup() {
super("removetempgroup", "Removes a user from a temporary group", "/%s user <user> removetempgroup <group> [server]", Permission.USER_REMOVETEMPGROUP);
super("removetempgroup", "Removes a user from a temporary group",
"/%s user <user> removetempgroup <group> [server] [world]", Permission.USER_REMOVETEMPGROUP);
}
@Override
@@ -25,10 +27,22 @@ public class UserRemoveTempGroup extends UserSubCommand {
}
try {
if (args.size() == 2) {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
user.unsetPermission("group." + groupName, server, true);
Message.USER_REMOVETEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
user.unsetPermission("group." + groupName, server, true);
Message.USER_REMOVETEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
} else {
final String world = args.get(2).toLowerCase();
user.unsetPermission("group." + groupName, server, world, true);
Message.USER_REMOVETEMPGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world);
}
} else {
user.unsetPermission("group." + groupName, true);
Message.USER_REMOVETEMPGROUP_SUCCESS.send(sender, user.getName(), groupName);
@@ -47,6 +61,6 @@ public class UserRemoveTempGroup extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return (argLength != 1 && argLength != 2);
return (argLength != 1 && argLength != 2 && argLength != 3);
}
}
@@ -14,7 +14,7 @@ import java.util.List;
public class UserSetPermission extends UserSubCommand {
public UserSetPermission() {
super("set", "Sets a permission for a user",
"/%s user <user> set <node> <true|false> [server]", Permission.USER_SETPERMISSION);
"/%s user <user> set <node> <true|false> [server] [world]", Permission.USER_SETPERMISSION);
}
@Override
@@ -40,10 +40,22 @@ public class UserSetPermission extends UserSubCommand {
boolean b = Boolean.parseBoolean(bool);
try {
if (args.size() == 3) {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
user.setPermission(node, b, server);
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 3) {
user.setPermission(node, b, server);
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server);
} else {
final String world = args.get(3).toLowerCase();
user.setPermission(node, b, server, world);
Message.SETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, bool, user.getName(), server, world);
}
} else {
user.setPermission(node, b);
Message.SETPERMISSION_SUCCESS.send(sender, node, bool, user.getName());
@@ -62,6 +74,6 @@ public class UserSetPermission extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 2 && argLength != 3;
return argLength != 2 && argLength != 3 && argLength != 4;
}
}
@@ -15,7 +15,7 @@ import java.util.List;
public class UserSetTempPermission extends UserSubCommand {
public UserSetTempPermission() {
super("settemp", "Sets a temporary permission for a user",
"/%s user <user> settemp <node> <true|false> <duration> [server]", Permission.USER_SET_TEMP_PERMISSION);
"/%s user <user> settemp <node> <true|false> <duration> [server] [world]", Permission.USER_SET_TEMP_PERMISSION);
}
@Override
@@ -54,10 +54,22 @@ public class UserSetTempPermission extends UserSubCommand {
}
try {
if (args.size() == 4) {
if (args.size() >= 4) {
final String server = args.get(3).toLowerCase();
user.setPermission(node, b, server, duration);
Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server, DateUtil.formatDateDiff(duration));
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 4) {
user.setPermission(node, b, server, duration);
Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server, DateUtil.formatDateDiff(duration));
} else {
final String world = args.get(4).toLowerCase();
user.setPermission(node, b, server, world, duration);
Message.SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS.send(sender, node, bool, user.getName(), server, world, DateUtil.formatDateDiff(duration));
}
} else {
user.setPermission(node, b, duration);
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, bool, user.getName(), DateUtil.formatDateDiff(duration));
@@ -76,6 +88,6 @@ public class UserSetTempPermission extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 3 && argLength != 4;
return argLength != 3 && argLength != 4 && argLength != 5;
}
}
@@ -14,7 +14,7 @@ import java.util.List;
public class UserUnSetPermission extends UserSubCommand {
public UserUnSetPermission() {
super("unset", "Unsets a permission for a user",
"/%s user <user> unset <node> [server]", Permission.USER_UNSETPERMISSION);
"/%s user <user> unset <node> [server] [world]", Permission.USER_UNSETPERMISSION);
}
@Override
@@ -32,10 +32,22 @@ public class UserUnSetPermission extends UserSubCommand {
}
try {
if (args.size() == 2) {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
user.unsetPermission(node, server);
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
user.unsetPermission(node, server);
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server);
} else {
final String world = args.get(2).toLowerCase();
user.unsetPermission(node, server, world);
Message.UNSETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, user.getName(), server, world);
}
} else {
user.unsetPermission(node);
Message.UNSETPERMISSION_SUCCESS.send(sender, node, user.getName());
@@ -49,6 +61,6 @@ public class UserUnSetPermission extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -14,7 +14,7 @@ import java.util.List;
public class UserUnsetTempPermission extends UserSubCommand {
public UserUnsetTempPermission() {
super("unsettemp", "Unsets a temporary permission for a user",
"/%s user <user> unsettemp <node> [server]", Permission.USER_UNSET_TEMP_PERMISSION);
"/%s user <user> unsettemp <node> [server] [world]", Permission.USER_UNSET_TEMP_PERMISSION);
}
@Override
@@ -32,10 +32,22 @@ public class UserUnsetTempPermission extends UserSubCommand {
}
try {
if (args.size() == 2) {
if (args.size() >= 2) {
final String server = args.get(1).toLowerCase();
user.unsetPermission(node, server, true);
Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server);
if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) {
Message.SERVER_INVALID_ENTRY.send(sender);
return;
}
if (args.size() == 2) {
user.unsetPermission(node, server, true);
Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server);
} else {
final String world = args.get(2).toLowerCase();
user.unsetPermission(node, server, world, true);
Message.UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, user.getName(), server, world);
}
} else {
user.unsetPermission(node, true);
Message.UNSET_TEMP_PERMISSION_SUCCESS.send(sender, node, user.getName());
@@ -49,6 +61,6 @@ public class UserUnsetTempPermission extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
return argLength != 1 && argLength != 2 && argLength != 3;
}
}
@@ -1,11 +1,9 @@
package me.lucko.luckperms.constants;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
@SuppressWarnings("SpellCheckingInspection")
@AllArgsConstructor
public enum Message {
/**
@@ -52,9 +50,11 @@ public enum Message {
GROUP_USE_INHERIT("Use the setinherit command instead of specifying the node.", true),
GROUP_USE_UNINHERIT("Use the unsetinherit command instead of specifying the node.", true),
GROUP_INVALID_ENTRY("Group names can only contain alphanumeric charcters.", true),
GROUP_INVALID_ENTRY("Group names can only contain alphanumeric characters.", true),
TRACK_INVALID_ENTRY("Track names can only contain alphanumeric charcters.", true),
TRACK_INVALID_ENTRY("Track names can only contain alphanumeric characters.", true),
SERVER_INVALID_ENTRY("Server names can only contain alphanumeric characters.", true),
/**
@@ -93,7 +93,12 @@ public enum Message {
INFO(
PREFIX + "&6Running &bLuckPerms %s&6." + "\n" +
PREFIX + "&eAuthor: &6Luck" + "\n" +
PREFIX + "&eStorage Method: &6%s",
PREFIX + "&eStorage Method: &6%s" + "\n" +
PREFIX + "&eServer Name: &6%s" + "\n" +
PREFIX + "&eDefault Group: &6%s" + "\n" +
PREFIX + "&eSync Interval: &6%s minutes" + "\n" +
PREFIX + "&eInclude Global Perms: &6%s" + "\n" +
PREFIX + "&eOnline Mode: &6%s",
false
),
DEBUG(
@@ -118,12 +123,16 @@ public enum Message {
LISTNODES_TEMP("&e%s's Temporary Nodes:" + "\n" + "%s", true),
SETPERMISSION_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a.", true),
SETPERMISSION_SERVER_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a.", true),
SETPERMISSION_SERVER_WORLD_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a, world &b%s&a.", true),
SETPERMISSION_TEMP_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a for a duration of &b%s&a.", true),
SETPERMISSION_TEMP_SERVER_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a for a duration of &b%s&a.", true),
SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a, world &b%s&a, for a duration of &b%s&a.", true),
UNSETPERMISSION_SUCCESS("&aUnset &b%s&a for &b%s&a.", true),
UNSETPERMISSION_SERVER_SUCCESS("&aUnset &b%s&a for &b%s&a on server &b%$s&a.", true),
UNSETPERMISSION_SERVER_WORLD_SUCCESS("&aUnset &b%s&a for &b%s&a on server &b%$s&a, world &b%$s&a.", true),
UNSET_TEMP_PERMISSION_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a.", true),
UNSET_TEMP_PERMISSION_SERVER_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a on server &b%$s&a.", true),
UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a on server &b%$s&a, world &b%$s&a.", true),
CLEAR_SUCCESS("&b%s&a's permissions were cleared.", true),
ILLEGAL_DATE_ERROR("Could not parse date '%s'.", true),
PAST_DATE_ERROR("You cannot set a date in the past!", true),
@@ -142,12 +151,16 @@ public enum Message {
USER_GETUUID("&bThe UUID of &e%s&b is &e%s&b.", true),
USER_ADDGROUP_SUCCESS("&b%s&a successfully added to group &b%s&a.", true),
USER_ADDGROUP_SERVER_SUCCESS("&b%s&a successfully added to group &b%s&a on server &b%s&a.", true),
USER_ADDGROUP_SERVER_WORLD_SUCCESS("&b%s&a successfully added to group &b%s&a on server &b%s&a, world &b%s&a.", true),
USER_ADDTEMPGROUP_SUCCESS("&b%s&a successfully added to group &b%s&a for a duration of &b%s&a.", true),
USER_ADDTEMPGROUP_SERVER_SUCCESS("&b%s&a successfully added to group &b%s&a on server &b%s&a for a duration of &b%s&a.", true),
USER_ADDTEMPGROUP_SERVER_WORLD_SUCCESS("&b%s&a successfully added to group &b%s&a on server &b%s&a, world &b%s&a, for a duration of &b%s&a.", true),
USER_REMOVEGROUP_SUCCESS("&b%s&a was removed from group &b%s&a.", true),
USER_REMOVEGROUP_SERVER_SUCCESS("&b%s&a was removed from group &b%s&a on server &b%s&a.", true),
USER_REMOVEGROUP_SERVER_WORLD_SUCCESS("&b%s&a was removed from group &b%s&a on server &b%s&a, world &b%s&a.", true),
USER_REMOVETEMPGROUP_SUCCESS("&b%s&a was removed from temproary group &b%s&a.", true),
USER_REMOVETEMPGROUP_SERVER_SUCCESS("&b%s&a was removed from temporary group &b%s&a on server &b%s&a.", true),
USER_REMOVETEMPGROUP_SERVER_WORLD_SUCCESS("&b%s&a was removed from temporary group &b%s&a on server &b%s&a, world &b%s&a.", true),
USER_REMOVEGROUP_ERROR_PRIMARY("You cannot remove a user from their primary group.", true),
USER_PRIMARYGROUP_SUCCESS("&b%s&a's primary group was set to &b%s&a.", true),
USER_PRIMARYGROUP_ERROR_ALREADYHAS("The user already has this group set as their primary group.", true),
@@ -182,12 +195,16 @@ public enum Message {
),
GROUP_SETINHERIT_SUCCESS("&b%s&a now inherits permissions from &b%s&a.", true),
GROUP_SETINHERIT_SERVER_SUCCESS("&b%s&a now inherits permissions from &b%s&a on server &b%s&a.", true),
GROUP_SETINHERIT_SERVER_WORLD_SUCCESS("&b%s&a now inherits permissions from &b%s&a on server &b%s&a, world &b%s&a.", true),
GROUP_SET_TEMP_INHERIT_SUCCESS("&b%s&a now inherits permissions from &b%s&a for a duration of &b%s&a.", true),
GROUP_SET_TEMP_INHERIT_SERVER_SUCCESS("&b%s&a now inherits permissions from &b%s&a on server &b%s&a for a duration of &b%s&a.", true),
GROUP_SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS("&b%s&a now inherits permissions from &b%s&a on server &b%s&a, world &b%s&a, for a duration of &b%s&a.", true),
GROUP_UNSETINHERIT_SUCCESS("&b%s&a no longer inherits permissions from &b%s&a.", true),
GROUP_UNSETINHERIT_SERVER_SUCCESS("&b%s&a no longer inherits permissions from &b%s&a on server &b%s&a.", true),
GROUP_UNSETINHERIT_SERVER_WORLD_SUCCESS("&b%s&a no longer inherits permissions from &b%s&a on server &b%s&a, world &b%s&a.", true),
GROUP_UNSET_TEMP_INHERIT_SUCCESS("&b%s&a no longer temporarily inherits permissions from &b%s&a.", true),
GROUP_UNSET_TEMP_INHERIT_SERVER_SUCCESS("&b%s&a no longer temporarily inherits permissions from &b%s&a on server &b%s&a.", true),
GROUP_UNSET_TEMP_INHERIT_SERVER_WORLD_SUCCESS("&b%s&a no longer temporarily inherits permissions from &b%s&a on server &b%s&a, world &b%s&a.", true),
TRACK_INFO(
PREFIX + "&d-> &eTrack: &6%s" + "\n" +
@@ -204,6 +221,11 @@ public enum Message {
private String message;
private boolean showPrefix;
Message(String message, boolean showPrefix) {
this.message = Util.color(message);
this.showPrefix = showPrefix;
}
@Override
public String toString() {
return message;
@@ -211,9 +233,9 @@ public enum Message {
public void send(Sender sender, Object... objects) {
if (showPrefix) {
sender.sendMessage(Util.color(PREFIX + String.format(message, objects)));
sender.sendMessage(PREFIX + String.format(message, objects));
} else {
sender.sendMessage(Util.color(String.format(message, objects)));
sender.sendMessage(String.format(message, objects));
}
}
}
@@ -1,14 +1,18 @@
package me.lucko.luckperms.data;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.util.UUID;
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public abstract class Datastore {
protected final LuckPermsPlugin plugin;
@@ -17,13 +21,7 @@ public abstract class Datastore {
@Getter
@Setter
private boolean acceptingLogins;
protected Datastore(LuckPermsPlugin plugin, String name) {
this.plugin = plugin;
this.name = name;
this.acceptingLogins = false;
}
private boolean acceptingLogins = false;
/**
* Execute a runnable asynchronously
@@ -41,8 +39,8 @@ public abstract class Datastore {
plugin.doSync(r);
}
private void runCallback(boolean result, Callback callback) {
doSync(() -> callback.onComplete(result));
private <T> void runCallback(T t, Callback<T> callback) {
doSync(() -> callback.onComplete(t));
}
/*
@@ -72,71 +70,63 @@ public abstract class Datastore {
These methods will schedule the operation to run async. The callback will be ran when the task is complete.
Callbacks are ran on the main Bukkit server thread (if applicable)
*/
public void loadOrCreateUser(UUID uuid, String username, Callback callback) {
public void loadOrCreateUser(UUID uuid, String username, Callback<Boolean> callback) {
doAsync(() -> runCallback(loadOrCreateUser(uuid, username), callback));
}
public void loadUser(UUID uuid, Callback callback) {
public void loadUser(UUID uuid, Callback<Boolean> callback) {
doAsync(() -> runCallback(loadUser(uuid), callback));
}
public void saveUser(User user, Callback callback) {
public void saveUser(User user, Callback<Boolean> callback) {
doAsync(() -> runCallback(saveUser(user), callback));
}
public void createAndLoadGroup(String name, Callback callback) {
public void createAndLoadGroup(String name, Callback<Boolean> callback) {
doAsync(() -> runCallback(createAndLoadGroup(name), callback));
}
public void loadGroup(String name, Callback callback) {
public void loadGroup(String name, Callback<Boolean> callback) {
doAsync(() -> runCallback(loadGroup(name), callback));
}
public void loadAllGroups(Callback callback) {
public void loadAllGroups(Callback<Boolean> callback) {
doAsync(() -> runCallback(loadAllGroups(), callback));
}
public void saveGroup(Group group, Callback callback) {
public void saveGroup(Group group, Callback<Boolean> callback) {
doAsync(() -> runCallback(saveGroup(group), callback));
}
public void deleteGroup(Group group, Callback callback) {
public void deleteGroup(Group group, Callback<Boolean> callback) {
doAsync(() -> runCallback(deleteGroup(group), callback));
}
public void createAndLoadTrack(String name, Callback callback) {
public void createAndLoadTrack(String name, Callback<Boolean> callback) {
doAsync(() -> runCallback(createAndLoadTrack(name), callback));
}
public void loadTrack(String name, Callback callback) {
public void loadTrack(String name, Callback<Boolean> callback) {
doAsync(() -> runCallback(loadTrack(name), callback));
}
public void loadAllTracks(Callback callback) {
public void loadAllTracks(Callback<Boolean> callback) {
doAsync(() -> runCallback(loadAllTracks(), callback));
}
public void saveTrack(Track track, Callback callback) {
public void saveTrack(Track track, Callback<Boolean> callback) {
doAsync(() -> runCallback(saveTrack(track), callback));
}
public void deleteTrack(Track track, Callback callback) {
public void deleteTrack(Track track, Callback<Boolean> callback) {
doAsync(() -> runCallback(deleteTrack(track), callback));
}
public void saveUUIDData(String username, UUID uuid, Callback callback) {
public void saveUUIDData(String username, UUID uuid, Callback<Boolean> callback) {
doAsync(() -> runCallback(saveUUIDData(username, uuid), callback));
}
public void getUUID(String username, GetUUIDCallback callback) {
doAsync(() -> doSync(() -> callback.onComplete(getUUID(username))));
}
public interface Callback {
void onComplete(boolean success);
}
public interface GetUUIDCallback {
void onComplete(UUID uuid);
public void getUUID(String username, Callback<UUID> callback) {
doAsync(() -> runCallback(getUUID(username), callback));
}
}
@@ -2,6 +2,7 @@ package me.lucko.luckperms.data.methods;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import lombok.Cleanup;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.groups.Group;
@@ -31,61 +32,32 @@ public class FlatfileDatastore extends Datastore {
private boolean doWrite(File file, WriteOperation writeOperation) {
boolean success = false;
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;
JsonWriter jsonWriter = null;
try {
fileWriter = new FileWriter(file);
bufferedWriter = new BufferedWriter(fileWriter);
jsonWriter = new JsonWriter(bufferedWriter);
@Cleanup FileWriter fileWriter = new FileWriter(file);
@Cleanup BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
@Cleanup JsonWriter jsonWriter = new JsonWriter(bufferedWriter);
jsonWriter.setIndent(" ");
success = writeOperation.onRun(jsonWriter);
jsonWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(jsonWriter);
close(bufferedWriter);
close(fileWriter);
}
return success;
}
private boolean doRead(File file, ReadOperation readOperation) {
boolean success = false;
FileReader fileReader = null;
BufferedReader bufferedReader = null;
JsonReader jsonReader = null;
try {
fileReader = new FileReader(file);
bufferedReader = new BufferedReader(fileReader);
jsonReader = new JsonReader(bufferedReader);
@Cleanup FileReader fileReader = new FileReader(file);
@Cleanup BufferedReader bufferedReader = new BufferedReader(fileReader);
@Cleanup JsonReader jsonReader = new JsonReader(bufferedReader);
success = readOperation.onRun(jsonReader);
} catch (IOException e) {
e.printStackTrace();
} finally {
close(jsonReader);
close(bufferedReader);
close(fileReader);
}
return success;
}
private static void close(AutoCloseable closeable) {
if (closeable == null) return;
try {
closeable.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void init() {
try {
@@ -499,12 +471,9 @@ public class FlatfileDatastore extends Datastore {
private Map<String, String> getUUIDCache() {
Map<String, String> cache = new HashMap<>();
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
fileReader = new FileReader(uuidData);
bufferedReader = new BufferedReader(fileReader);
@Cleanup FileReader fileReader = new FileReader(uuidData);
@Cleanup BufferedReader bufferedReader = new BufferedReader(fileReader);
Properties props = new Properties();
props.load(bufferedReader);
@@ -514,21 +483,14 @@ public class FlatfileDatastore extends Datastore {
} catch (IOException e) {
e.printStackTrace();
} finally {
close(bufferedReader);
close(fileReader);
}
return cache;
}
private void saveUUIDCache(Map<String, String> cache) {
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;
try {
fileWriter = new FileWriter(uuidData);
bufferedWriter = new BufferedWriter(fileWriter);
@Cleanup FileWriter fileWriter = new FileWriter(uuidData);
@Cleanup BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
Properties properties = new Properties();
properties.putAll(cache);
@@ -536,9 +498,6 @@ public class FlatfileDatastore extends Datastore {
} catch (IOException e) {
e.printStackTrace();
} finally {
close(bufferedWriter);
close(fileWriter);
}
}
@@ -3,6 +3,7 @@ package me.lucko.luckperms.data.methods;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.AllArgsConstructor;
import lombok.Cleanup;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.Datastore;
@@ -57,66 +58,40 @@ abstract class SQLDatastore extends Datastore {
abstract Connection getConnection() throws SQLException;
private static void close(AutoCloseable closeable) {
if (closeable == null) return;
try {
closeable.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean runQuery(QueryPS queryPS) {
boolean success = false;
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = getConnection();
@Cleanup Connection connection = getConnection();
if (connection == null) {
throw new IllegalStateException("SQL connection is null");
}
preparedStatement = connection.prepareStatement(queryPS.getQuery());
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
queryPS.onRun(preparedStatement);
preparedStatement.execute();
success = true;
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(preparedStatement);
close(connection);
}
return success;
}
private boolean runQuery(QueryRS queryRS) {
boolean success = false;
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = getConnection();
@Cleanup Connection connection = getConnection();
if (connection == null) {
throw new IllegalStateException("SQL connection is null");
}
preparedStatement = connection.prepareStatement(queryRS.getQuery());
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
queryRS.onRun(preparedStatement);
preparedStatement.execute();
resultSet = preparedStatement.executeQuery();
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
success = queryRS.onResult(resultSet);
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(resultSet);
close(preparedStatement);
close(connection);
}
return success;
}
@@ -414,6 +389,8 @@ abstract class SQLDatastore extends Datastore {
preparedStatement.setString(1, track.getName());
}
});
if (success) plugin.getTrackManager().unloadTrack(track);
return success;
}
@@ -1,9 +1,20 @@
package me.lucko.luckperms.groups;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.utils.Patterns;
import me.lucko.luckperms.utils.PermissionObject;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ToString(of = {"name"})
@EqualsAndHashCode(of = {"name"}, callSuper = false)
public class Group extends PermissionObject {
/**
@@ -13,10 +24,198 @@ public class Group extends PermissionObject {
private final String name;
Group(String name, LuckPermsPlugin plugin) {
super(plugin, name);
super(name, plugin);
this.name = name;
}
/**
* check to see if a group inherits a group
* @param group The group to check membership of
* @return true if the user is a member of the group
*/
public boolean inheritsGroup(Group group) {
return inheritsGroup(group, "global");
}
/**
* check to see if the group inherits a group on a specific server
* @param group The group to check membership of
* @param server The server to check on
* @return true if the group inherits the group
*/
public boolean inheritsGroup(Group group, String server) {
return hasPermission("group." + group.getName(), true, server);
}
/**
* check to see if the group inherits a group on a specific server
* @param group The group to check membership of
* @param server The server to check on
* @param world The world to check on
* @return true if the group inherits the group
*/
public boolean inheritsGroup(Group group, String server, String world) {
return hasPermission("group." + group.getName(), true, server, world);
}
/**
* Make this group inherit another group
* @param group the group to be inherited
* @throws ObjectAlreadyHasException if the group already inherits the group
*/
public void setInheritGroup(Group group) throws ObjectAlreadyHasException {
setInheritGroup(group, "global");
}
/**
* Make this group inherit another group on a specific server
* @param group the group to be inherited
* @param server The server to add the group on
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
*/
public void setInheritGroup(Group group, String server) throws ObjectAlreadyHasException {
if (server == null) {
server = "global";
}
setPermission("group." + group.getName(), true, server);
}
/**
* Make this group inherit another group on a specific server
* @param group the group to be inherited
* @param server The server to add the group on
* @param world The world to add the group on
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
*/
public void setInheritGroup(Group group, String server, String world) throws ObjectAlreadyHasException {
if (server == null) {
server = "global";
}
setPermission("group." + group.getName(), true, server, world);
}
/**
* Make this group inherit another group on a specific server
* @param group the group to be inherited
* @param expireAt when the group should expire
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
*/
public void setInheritGroup(Group group, long expireAt) throws ObjectAlreadyHasException {
setPermission("group." + group.getName(), true, expireAt);
}
/**
* Make this group inherit another group on a specific server
* @param group the group to be inherited
* @param server The server to add the group on
* @param expireAt when the group should expire
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
*/
public void setInheritGroup(Group group, String server, long expireAt) throws ObjectAlreadyHasException {
if (server == null) {
server = "global";
}
setPermission("group." + group.getName(), true, server, expireAt);
}
/**
* Make this group inherit another group on a specific server
* @param group the group to be inherited
* @param server The server to add the group on
* @param world The world to add the group on
* @param expireAt when the group should expire
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
*/
public void setInheritGroup(Group group, String server, String world, long expireAt) throws ObjectAlreadyHasException {
if (server == null) {
server = "global";
}
setPermission("group." + group.getName(), true, server, world, expireAt);
}
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @throws ObjectLacksException if the group does not already inherit the group
*/
public void unsetInheritGroup(Group group) throws ObjectLacksException {
unsetInheritGroup(group, "global");
}
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the group does not already inherit the group
*/
public void unsetInheritGroup(Group group, boolean temporary) throws ObjectLacksException {
unsetInheritGroup(group, "global", temporary);
}
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @param server The server to remove the group on
* @throws ObjectLacksException if the group does not already inherit the group
*/
public void unsetInheritGroup(Group group, String server) throws ObjectLacksException {
if (server == null) {
server = "global";
}
unsetPermission("group." + group.getName(), server);
}
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @param server The server to remove the group on
* @param world The world to remove the group on
* @throws ObjectLacksException if the group does not already inherit the group
*/
public void unsetInheritGroup(Group group, String server, String world) throws ObjectLacksException {
if (server == null) {
server = "global";
}
unsetPermission("group." + group.getName(), server, world);
}
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @param server The server to remove the group on
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the group does not already inherit the group
*/
public void unsetInheritGroup(Group group, String server, boolean temporary) throws ObjectLacksException {
if (server == null) {
server = "global";
}
unsetPermission("group." + group.getName(), server, temporary);
}
/**
* Remove a previously set inheritance
* @param group the group to uninherit
* @param server The server to remove the group on
* @param world The world to remove the group on
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the group does not already inherit the group
*/
public void unsetInheritGroup(Group group, String server, String world, boolean temporary) throws ObjectLacksException {
if (server == null) {
server = "global";
}
unsetPermission("group." + group.getName(), server, world, temporary);
}
/**
* Clear all of the groups permission nodes
*/
@@ -24,8 +223,46 @@ public class Group extends PermissionObject {
getNodes().clear();
}
@Override
public String toString() {
return getName();
/**
* Get a {@link List} of all of the groups the group inherits, on all servers
* @return a {@link List} of group names
*/
public List<String> getGroupNames() {
return getGroups(null, null, true);
}
/**
* Get a {@link List} of the groups the group inherits on a specific server
* @param server the server to check
* @return a {@link List} of group names
*/
public List<String> getLocalGroups(String server, String world) {
return getGroups(server, world, false);
}
/**
* Get a {@link List} of the groups the group inherits on a specific server
* @param server the server to check
* @return a {@link List} of group names
*/
public List<String> getLocalGroups(String server) {
return getLocalGroups(server, null);
}
/**
* Get a {@link List} of the groups the group inherits on a specific server with the option to include global
* groups or all groups
* @param server Which server to check on
* @param world Which world to check on
* @param includeGlobal Whether to include global groups
* @return a {@link List} of group names
*/
private List<String> getGroups(String server, String world, boolean includeGlobal) {
// Call super #getPermissions method, and just sort through those
Map<String, Boolean> perms = getPermissions(server, world, null, includeGlobal);
return perms.keySet().stream()
.filter(s -> Patterns.GROUP_MATCH.matcher(s).matches())
.map(s -> Patterns.DOT_SPLIT.split(s, 2)[1])
.collect(Collectors.toList());
}
}
@@ -1,11 +1,13 @@
package me.lucko.luckperms.groups;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@RequiredArgsConstructor
public class GroupManager {
private final LuckPermsPlugin plugin;
@@ -15,10 +17,6 @@ public class GroupManager {
@Getter
private final Map<String, Group> groups = new ConcurrentHashMap<>();
public GroupManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
}
/**
* Get a group object by name
* @param name The name to search by
@@ -75,19 +73,6 @@ public class GroupManager {
groups.clear();
}
/**
* Load all groups from the datastore
*/
public void loadAllGroups() {
plugin.getDatastore().loadAllGroups(success -> {
String defaultGroup = plugin.getConfiguration().getDefaultGroupName();
if (!groups.keySet().contains(defaultGroup)) {
plugin.getDatastore().createAndLoadGroup(defaultGroup, success1 -> {});
}
});
}
/**
* Makes a new group object
* @param name The name of the group
@@ -1,6 +1,9 @@
package me.lucko.luckperms.tracks;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
@@ -9,6 +12,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ToString(of = {"name"})
@EqualsAndHashCode(of = {"name"}, callSuper = false)
@RequiredArgsConstructor
public class Track {
/**
@@ -20,11 +26,7 @@ public class Track {
/**
* The groups within this track
*/
private List<String> groups = new ArrayList<>();
Track(String name) {
this.name = name;
}
private List<String> groups = Collections.synchronizedList(new ArrayList<>());
/**
* Gets an ordered list of the groups on this track
@@ -165,12 +167,6 @@ public class Track {
groups.clear();
}
private void assertContains(Group g) throws ObjectLacksException {
if (!containsGroup(g)) {
throw new ObjectLacksException();
}
}
private void assertNotContains(Group g) throws ObjectAlreadyHasException {
if (containsGroup(g)) {
throw new ObjectAlreadyHasException();
@@ -182,16 +178,4 @@ public class Track {
throw new ObjectLacksException();
}
}
private void assertNotContains(String g) throws ObjectAlreadyHasException {
if (containsGroup(g)) {
throw new ObjectAlreadyHasException();
}
}
@Override
public String toString() {
return name;
}
}
@@ -1,7 +1,6 @@
package me.lucko.luckperms.tracks;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import java.util.Map;
import java.util.Set;
@@ -9,7 +8,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
public class TrackManager {
private final LuckPermsPlugin plugin;
/**
* A {@link Map} containing all loaded tracks
@@ -17,10 +15,6 @@ public class TrackManager {
@Getter
private final Map<String, Track> tracks = new ConcurrentHashMap<>();
public TrackManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
}
/**
* Get a track object by name
* @param name the name to search by
@@ -86,13 +80,6 @@ public class TrackManager {
tracks.clear();
}
/**
* Load all tracks from the datastore
*/
public void loadAllTracks() {
plugin.getDatastore().loadAllTracks(success -> {});
}
/**
* Makes a new track object
* @param name The name of the track
@@ -1,7 +1,9 @@
package me.lucko.luckperms.users;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
@@ -9,9 +11,13 @@ import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import me.lucko.luckperms.utils.PermissionObject;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@ToString(of = {"uuid"})
@EqualsAndHashCode(of = {"uuid"}, callSuper = false)
public abstract class User extends PermissionObject {
/**
@@ -35,13 +41,13 @@ public abstract class User extends PermissionObject {
private String primaryGroup = null;
User(UUID uuid, LuckPermsPlugin plugin) {
super(plugin, uuid.toString());
super(uuid.toString(), plugin);
this.uuid = uuid;
this.name = null;
}
User(UUID uuid, String name, LuckPermsPlugin plugin) {
super(plugin, uuid.toString());
super(uuid.toString(), plugin);
this.uuid = uuid;
this.name = name;
}
@@ -70,6 +76,17 @@ public abstract class User extends PermissionObject {
return hasPermission("group." + group.getName(), true, server);
}
/**
* Check to see if a user is a member of a group on a specific server
* @param group The group to check membership of
* @param server The server to check on
* @param world The world to check on
* @return true if the user is a member of the group
*/
public boolean isInGroup(Group group, String server, String world) {
return hasPermission("group." + group.getName(), true, server, world);
}
/**
* Add a user to a group
* @param group The group to add the user to
@@ -93,6 +110,21 @@ public abstract class User extends PermissionObject {
setPermission("group." + group.getName(), true, server);
}
/**
* Add a user to a group on a specific server
* @param group The group to add the user to
* @param server The server to add the group on
* @param world The world to add the group on
* @throws ObjectAlreadyHasException if the user is already a member of the group on that server
*/
public void addGroup(Group group, String server, String world) throws ObjectAlreadyHasException {
if (server == null) {
server = "global";
}
setPermission("group." + group.getName(), true, server, world);
}
/**
* Add a user to a group on a specific server
* @param group The group to add the user to
@@ -118,6 +150,22 @@ public abstract class User extends PermissionObject {
setPermission("group." + group.getName(), true, server, expireAt);
}
/**
* Add a user to a group on a specific server
* @param group The group to add the user to
* @param server The server to add the group on
* @param world The world to add the group on
* @param expireAt when the group should expire
* @throws ObjectAlreadyHasException if the user is already a member of the group on that server
*/
public void addGroup(Group group, String server, String world, long expireAt) throws ObjectAlreadyHasException {
if (server == null) {
server = "global";
}
setPermission("group." + group.getName(), true, server, world, expireAt);
}
/**
* Remove the user from a group
* @param group the group to remove the user from
@@ -151,6 +199,21 @@ public abstract class User extends PermissionObject {
unsetPermission("group." + group.getName(), server);
}
/**
* Remove the user from a group
* @param group The group to remove the user from
* @param server The server to remove the group on
* @param world The world to remove the group on
* @throws ObjectLacksException if the user isn't a member of the group
*/
public void removeGroup(Group group, String server, String world) throws ObjectLacksException {
if (server == null) {
server = "global";
}
unsetPermission("group." + group.getName(), server, world);
}
/**
* Remove the user from a group
* @param group The group to remove the user from
@@ -166,6 +229,22 @@ public abstract class User extends PermissionObject {
unsetPermission("group." + group.getName(), server, temporary);
}
/**
* Remove the user from a group
* @param group The group to remove the user from
* @param server The server to remove the group on
* @param world The world to remove the group on
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the user isn't a member of the group
*/
public void removeGroup(Group group, String server, String world, boolean temporary) throws ObjectLacksException {
if (server == null) {
server = "global";
}
unsetPermission("group." + group.getName(), server, world, temporary);
}
/**
* Clear all of the users permission nodes
*/
@@ -188,95 +267,33 @@ public abstract class User extends PermissionObject {
* @param server the server to check
* @return a {@link List} of group names
*/
public List<String> getLocalGroups(String server) {
return getGroups(server, null, false);
public List<String> getLocalGroups(String server, String world) {
return getGroups(server, world, false);
}
/**
* Get a {@link List} of the groups the user is a member of on a specific server with the option to include global groups or all groups
* Get a {@link List} of the groups the user is a member of on a specific server
* @param server the server to check
* @return a {@link List} of group names
*/
public List<String> getLocalGroups(String server) {
return getLocalGroups(server, null);
}
/**
* Get a {@link List} of the groups the user is a member of on a specific server with the option to include global
* groups or all groups
* @param server Which server to check on
* @param excludedGroups groups to exclude (prevents circular inheritance issues)
* @param world Which world to check on
* @param includeGlobal Whether to include global groups
* @return a {@link List} of group names
*/
private List<String> getGroups(String server, List<String> excludedGroups, boolean includeGlobal) {
if (excludedGroups == null) {
excludedGroups = new ArrayList<>();
}
excludedGroups.add(getObjectName());
List<String> groups = new ArrayList<>();
if (server == null || server.equals("")) {
server = "global";
}
/*
Priority:
1. server specific group nodes
2. group nodes
*/
final Map<String, Boolean> serverSpecificGroups = new HashMap<>();
final Map<String, Boolean> groupNodes = new HashMap<>();
// Sorts the permissions and puts them into a priority order
for (Map.Entry<String, Boolean> node : convertTemporaryPerms().entrySet()) {
serverSpecific:
if (node.getKey().contains("/")) {
String[] parts = Patterns.SERVER_SPLIT.split(node.getKey(), 2);
if (parts[0].equalsIgnoreCase("global")) {
// REGULAR
break serverSpecific;
}
if (!parts[0].equalsIgnoreCase(server)) {
// SERVER SPECIFIC BUT DOES NOT APPLY
continue;
}
if (Patterns.GROUP_MATCH.matcher(parts[1]).matches()) {
// SERVER SPECIFIC AND GROUP
serverSpecificGroups.put(node.getKey(), node.getValue());
continue;
}
continue;
}
// Skip adding global permissions if they are not requested
if (!includeGlobal) continue;
if (Patterns.GROUP_MATCH.matcher(node.getKey()).matches()) {
// GROUP
groupNodes.put(node.getKey(), node.getValue());
}
}
// If a group is negated at a higher priority, the group should not then be applied at a lower priority
serverSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
groupNodes.remove(node.getKey());
groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
});
groups.addAll(serverSpecificGroups.entrySet().stream()
.filter(Map.Entry::getValue)
.map(e -> Patterns.DOT_SPLIT.split(e.getKey(), 2)[1])
.collect(Collectors.toList())
);
groups.addAll(groupNodes.entrySet().stream()
.filter(Map.Entry::getValue)
.map(e -> Patterns.DOT_SPLIT.split(e.getKey(), 2)[1])
.collect(Collectors.toList())
);
return groups;
}
@Override
public String toString() {
return getUuid().toString();
private List<String> getGroups(String server, String world, boolean includeGlobal) {
// Call super #getPermissions method, and just sort through those
Map<String, Boolean> perms = getPermissions(server, world, null, includeGlobal);
return perms.keySet().stream()
.filter(s -> Patterns.GROUP_MATCH.matcher(s).matches())
.map(s -> Patterns.DOT_SPLIT.split(s, 2)[1])
.collect(Collectors.toList());
}
}
@@ -1,8 +1,8 @@
package me.lucko.luckperms.users;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.Map;
@@ -10,6 +10,7 @@ import java.util.NoSuchElementException;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@RequiredArgsConstructor
public abstract class UserManager {
/**
@@ -23,10 +24,6 @@ public abstract class UserManager {
*/
private final LuckPermsPlugin plugin;
public UserManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
}
/**
* Get a user object by UUID
* @param uuid The uuid to search by
@@ -76,16 +73,6 @@ public abstract class UserManager {
}
}
/**
* Saves a user object in the datastore
* @param user the user to save
* @param datastore the datastore
*/
public void saveUser(User user, Datastore datastore) {
user.refreshPermissions();
datastore.saveUser(user, success -> {});
}
/**
* Set a user to the default group
* @param user the user to give to
@@ -1,5 +1,7 @@
package me.lucko.luckperms.utils;
import lombok.experimental.UtilityClass;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.regex.Matcher;
@@ -10,12 +12,11 @@ import java.util.regex.Pattern;
* https://github.com/drtshock/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/utils/DateUtil.java
* https://github.com/essentials/Essentials/blob/2.x/Essentials/src/com/earth2me/essentials/utils/DateUtil.java
*/
@UtilityClass
public class DateUtil {
private static final Pattern TIME_PATTERN = Pattern.compile("(?:([0-9]+)\\s*y[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*mo[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*w[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*d[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*h[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*m[a-z]*[,\\s]*)?" + "(?:([0-9]+)\\s*(?:s[a-z]*)?)?", Pattern.CASE_INSENSITIVE);
private static final int MAX_YEARS = 100000;
private DateUtil() {}
public static boolean shouldExpire(long unixTime) {
return unixTime < (System.currentTimeMillis() / 1000);
}
@@ -1,13 +1,75 @@
package me.lucko.luckperms.utils;
public interface LPConfiguration {
import lombok.AccessLevel;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
String getServer();
int getSyncTime();
String getDefaultGroupNode();
String getDefaultGroupName();
boolean getIncludeGlobalPerms();
String getDatabaseValue(String value);
String getStorageMethod();
public abstract class LPConfiguration<T extends LuckPermsPlugin> {
@Getter(AccessLevel.PROTECTED)
private final T plugin;
private final String defaultServerName;
private final boolean defaultIncludeGlobal;
private final String defaultStorage;
public LPConfiguration(T plugin, String defaultServerName, boolean defaultIncludeGlobal, String defaultStorage) {
this.plugin = plugin;
this.defaultServerName = defaultServerName;
this.defaultIncludeGlobal = defaultIncludeGlobal;
this.defaultStorage = defaultStorage;
init();
if (Patterns.NON_ALPHA_NUMERIC.matcher(getServer()).find()) {
plugin.getLogger().severe("Server name defined in config.yml contains invalid characters. Server names can " +
"only contain alphanumeric characters.\nDefined server name '" + getServer() + "' will be replaced with '" +
defaultServerName + "' (the default)");
set("server", defaultServerName);
}
if (Patterns.NON_ALPHA_NUMERIC.matcher(getDefaultGroupName()).find()) {
plugin.getLogger().severe("Default group defined in config.yml contains invalid characters. Group names can " +
"only contain alphanumeric characters.\nDefined default group name '" + getDefaultGroupName() +
"' will be replaced with 'default' (the default)");
set("default-group", "default");
}
}
protected abstract void init();
protected abstract void set(String path, Object value);
protected abstract String getString(String path, String def);
protected abstract int getInt(String path, int def);
protected abstract boolean getBoolean(String path, boolean def);
public String getServer() {
return getString("server", defaultServerName);
}
public int getSyncTime() {
return getInt("sql.sync-minutes", 3);
}
public String getDefaultGroupNode() {
return "group." + getDefaultGroupName();
}
public String getDefaultGroupName() {
return getString("default-group", "default");
}
public boolean getIncludeGlobalPerms() {
return getBoolean("include-global", defaultIncludeGlobal);
}
public boolean getOnlineMode() {
return getBoolean("online-mode", true);
}
public String getDatabaseValue(String value) {
return getString("sql." + value, null);
}
public String getStorageMethod() {
return getString("storage-method", defaultStorage);
}
}
@@ -1,15 +1,17 @@
package me.lucko.luckperms.utils;
import lombok.experimental.UtilityClass;
import java.util.regex.Pattern;
@UtilityClass
public class Patterns {
public static final Pattern SERVER_SPLIT = Pattern.compile("\\/");
public static final Pattern WORLD_SPLIT = Pattern.compile("\\-");
public static final Pattern TEMP_SPLIT = Pattern.compile("\\$");
public static final Pattern DOT_SPLIT = Pattern.compile("\\.");
public static final Pattern GROUP_MATCH = Pattern.compile("group\\..*");
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[^A-Za-z0-9]");
private Patterns() {}
public static final Pattern NON_USERNAME = Pattern.compile("[^A-Za-z0-9_]");
}
@@ -1,52 +1,46 @@
package me.lucko.luckperms.utils;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* Represents an object that can hold permissions
* For example a User or a Group
*/
@Getter
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public abstract class PermissionObject {
/**
* The UUID of the user / name of the group.
* Used to prevent circular inheritance issues
*/
@Getter
private final String objectName;
/**
* Reference to the main plugin instance
*/
@Getter(AccessLevel.PROTECTED)
private final LuckPermsPlugin plugin;
/**
* If false, only permissions specific to the server are applied
*/
@Setter
private boolean includeGlobalPermissions;
/**
* The user/group's permissions
*/
private Map<String, Boolean> nodes = new HashMap<>();
protected PermissionObject(LuckPermsPlugin plugin, String objectName) {
this.objectName = objectName;
this.plugin = plugin;
this.includeGlobalPermissions = plugin.getConfiguration().getIncludeGlobalPerms();
}
@Getter
private Map<String, Boolean> nodes = new ConcurrentHashMap<>();
public void setNodes(Map<String, Boolean> nodes) {
this.nodes = nodes;
this.nodes.clear();
this.nodes.putAll(nodes);
auditTemporaryPermissions();
}
@@ -81,7 +75,7 @@ public abstract class PermissionObject {
*/
public boolean hasPermission(String node, boolean b) {
if (node.startsWith("global/")) node = node.replace("global/", "");
return hasPermission(getNodes(), node, b);
return hasPermission(this.nodes, node, b);
}
/**
@@ -95,6 +89,18 @@ public abstract class PermissionObject {
return hasPermission(server + "/" + node, b);
}
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @return true if the user has the permission
*/
public boolean hasPermission(String node, boolean b, String server, String world) {
return hasPermission(server + "-" + world + "/" + node, b);
}
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
@@ -106,6 +112,31 @@ public abstract class PermissionObject {
return hasPermission(node + (temporary ? "$a" : ""), b);
}
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server to check on
* @param temporary if the permission is temporary
* @return true if the user has the permission
*/
public boolean hasPermission(String node, boolean b, String server, boolean temporary) {
return hasPermission(server + "/" + node + (temporary ? "$a" : ""), b);
}
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server to check on
* @param world The world to check on
* @param temporary if the permission is temporary
* @return true if the user has the permission
*/
public boolean hasPermission(String node, boolean b, String server, String world, boolean temporary) {
return hasPermission(server + "-" + world + "/" + node + (temporary ? "$a" : ""), b);
}
/**
* Checks to see if the object inherits a certain permission
* @param node The permission node
@@ -130,10 +161,29 @@ public abstract class PermissionObject {
* @return true if the user inherits the permission
*/
public boolean inheritsPermission(String node, boolean b, String server) {
if (server.contains("-")) {
// Use other method
final String[] parts = Patterns.WORLD_SPLIT.split(server, 2);
return inheritsPermission(node, b, parts[0], parts[1]);
}
final Map<String, Boolean> local = getLocalPermissions(server, null);
return hasPermission(local, node, b);
}
/**
* Checks to see the the object inherits a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @return true if the user inherits the permission
*/
public boolean inheritsPermission(String node, boolean b, String server, String world) {
final Map<String, Boolean> local = getLocalPermissions(server, world, null);
return hasPermission(local, node, b);
}
/**
* Checks to see if the object inherits a certain permission
* @param node The permission node
@@ -145,6 +195,31 @@ public abstract class PermissionObject {
return inheritsPermission(node + (temporary ? "$a" : ""), b);
}
/**
* Checks to see if the object inherits a certain permission
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param temporary if the permission is temporary
* @return true if the user inherits the permission
*/
public boolean inheritsPermission(String node, boolean b, String server, boolean temporary) {
return inheritsPermission(server + "/" + node + (temporary ? "$a" : ""), b);
}
/**
* Checks to see if the object inherits a certain permission
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @param world The world
* @param temporary if the permission is temporary
* @return true if the user inherits the permission
*/
public boolean inheritsPermission(String node, boolean b, String server, String world, boolean temporary) {
return inheritsPermission(server + "-" + world + "/" + node + (temporary ? "$a" : ""), b);
}
/**
* Sets a permission for the object
* @param node The node to be set
@@ -156,7 +231,7 @@ public abstract class PermissionObject {
if (hasPermission(node, value)) {
throw new ObjectAlreadyHasException();
}
getNodes().put(node, value);
this.nodes.put(node, value);
}
/**
@@ -170,6 +245,18 @@ public abstract class PermissionObject {
setPermission(server + "/" + node, value);
}
/**
* Sets a permission for the object
* @param node The node to set
* @param value What to set the node to - true/false(negated)
* @param server The server to set the permission on
* @param world The world to set the permission on
* @throws ObjectAlreadyHasException if the object already has the permission
*/
public void setPermission(String node, boolean value, String server, String world) throws ObjectAlreadyHasException {
setPermission(server + "-" + world + "/" + node, value);
}
/**
* Sets a permission for the object
* @param node The node to set
@@ -193,6 +280,19 @@ public abstract class PermissionObject {
setPermission(node + "$" + expireAt, value, server);
}
/**
* Sets a permission for the object
* @param node The node to set
* @param value What to set the node to - true/false(negated)
* @param server The server to set the permission on
* @param world The world to set the permission on
* @param expireAt The time in unixtime when the permission will expire
* @throws ObjectAlreadyHasException if the object already has the permission
*/
public void setPermission(String node, boolean value, String server, String world, long expireAt) throws ObjectAlreadyHasException {
setPermission(node + "$" + expireAt, value, server, world);
}
/**
* Unsets a permission for the object
* @param node The node to be unset
@@ -201,26 +301,21 @@ public abstract class PermissionObject {
*/
public void unsetPermission(String node, boolean temporary) throws ObjectLacksException {
if (node.startsWith("global/")) node = node.replace("global/", "");
String match = null;
final String fNode = node;
Optional<String> match = Optional.empty();
if (!temporary) {
if (getNodes().containsKey(node)) {
match = node;
}
if (temporary) {
match = this.nodes.keySet().stream()
.filter(n -> n.contains("$")).filter(n -> Patterns.TEMP_SPLIT.split(n)[0].equalsIgnoreCase(fNode))
.findFirst();
} else {
for (String n : getNodes().keySet()) {
if (n.contains("$")) {
String[] parts = Patterns.TEMP_SPLIT.split(n);
if (parts[0].equalsIgnoreCase(node)) {
match = n;
break;
}
}
if (this.nodes.containsKey(fNode)) {
match = Optional.of(fNode);
}
}
if (match != null) {
getNodes().remove(match);
if (match.isPresent()) {
this.nodes.remove(match.get());
} else {
throw new ObjectLacksException();
}
@@ -245,6 +340,17 @@ public abstract class PermissionObject {
unsetPermission(server + "/" + node);
}
/**
* Unsets a permission for the object
* @param node The node to be unset
* @param server The server to unset the node on
* @param world The world to unset the node on
* @throws ObjectLacksException if the node wasn't already set
*/
public void unsetPermission(String node, String server, String world) throws ObjectLacksException {
unsetPermission(server + "-" + world + "/" + node);
}
/**
* Unsets a permission for the object
* @param node The node to be unset
@@ -256,6 +362,29 @@ public abstract class PermissionObject {
unsetPermission(server + "/" + node, temporary);
}
/**
* Unsets a permission for the object
* @param node The node to be unset
* @param server The server to unset the node on
* @param world The world to unset the node on
* @param temporary if the permission being unset is temporary
* @throws ObjectLacksException if the node wasn't already set
*/
public void unsetPermission(String node, String server, String world, boolean temporary) throws ObjectLacksException {
unsetPermission(server + "-" + world + "/" + node, temporary);
}
/**
* Gets the permissions and inherited permissions that apply to a specific server
* @param server The server to get nodes for
* @param world The world to get nodes for
* @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues)
* @return a {@link Map} of the permissions
*/
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups) {
return getPermissions(server, world, excludedGroups, plugin.getConfiguration().getIncludeGlobalPerms());
}
/**
* Gets the permissions and inherited permissions that apply to a specific server
* @param server The server to get nodes for
@@ -263,7 +392,7 @@ public abstract class PermissionObject {
* @return a {@link Map} of the permissions
*/
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups) {
return getPermissions(server, excludedGroups, includeGlobalPermissions);
return getLocalPermissions(server, null, excludedGroups);
}
/**
@@ -271,19 +400,12 @@ public abstract class PermissionObject {
* @return a map of temporary nodes
*/
public Map<Map.Entry<String, Boolean>, Long> getTemporaryNodes() {
Map<Map.Entry<String, Boolean>, Long> temps = new HashMap<>();
for (Map.Entry<String, Boolean> e : getNodes().entrySet()) {
if (!e.getKey().contains("$")) {
continue;
}
String[] parts = Patterns.TEMP_SPLIT.split(e.getKey());
return this.nodes.entrySet().stream().filter(e -> e.getKey().contains("$")).map(e -> {
final String[] parts = Patterns.TEMP_SPLIT.split(e.getKey());
final long expiry = Long.parseLong(parts[1]);
temps.put(new AbstractMap.SimpleEntry<>(parts[0], e.getValue()), expiry);
}
return new AbstractMap.SimpleEntry<Map.Entry<String, Boolean>, Long>(new AbstractMap.SimpleEntry<>(parts[0], e.getValue()), expiry);
return temps;
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
/**
@@ -291,46 +413,27 @@ public abstract class PermissionObject {
* @return a map of permanent nodes
*/
public Map<String, Boolean> getPermanentNodes() {
Map<String, Boolean> permas = new HashMap<>();
for (Map.Entry<String, Boolean> e : getNodes().entrySet()) {
if (e.getKey().contains("$")) {
continue;
}
permas.put(e.getKey(), e.getValue());
}
return permas;
return this.nodes.entrySet().stream().filter(e -> !e.getKey().contains("$"))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
/**
* Removes temporary permissions that have expired
* @return true if permissions had expired and had to be removed
*/
public boolean auditTemporaryPermissions() {
Set<String> toRemove = getNodes().keySet().stream()
public void auditTemporaryPermissions() {
this.nodes.keySet().stream()
.filter(s -> s.contains("$"))
.filter(s -> DateUtil.shouldExpire(Long.parseLong(Patterns.TEMP_SPLIT.split(s)[1])))
.collect(Collectors.toSet());
toRemove.forEach(s -> getNodes().remove(s));
return !toRemove.isEmpty();
.forEach(s -> this.nodes.remove(s));
}
private String stripTime(String s) {
if (s.contains("$")) {
return Patterns.TEMP_SPLIT.split(s)[0];
}
return s;
}
protected Map<String, Boolean> convertTemporaryPerms() {
private Map<String, Boolean> convertTemporaryPerms() {
auditTemporaryPermissions();
Map<String, Boolean> nodes = new HashMap<>();
Map<String, Boolean> tempNodes = new HashMap<>();
for (Map.Entry<String, Boolean> e : getNodes().entrySet()) {
for (Map.Entry<String, Boolean> e : this.nodes.entrySet()) {
if (e.getKey().contains("$")) {
tempNodes.put(e.getKey(), e.getValue());
} else {
@@ -343,7 +446,7 @@ public abstract class PermissionObject {
return nodes;
}
private Map<String, Boolean> getPermissions(String server, List<String> excludedGroups, boolean includeGlobal) {
protected Map<String, Boolean> getPermissions(String server, String world, List<String> excludedGroups, boolean includeGlobal) {
if (excludedGroups == null) {
excludedGroups = new ArrayList<>();
}
@@ -355,17 +458,25 @@ public abstract class PermissionObject {
server = "global";
}
if (world != null && world.equalsIgnoreCase("")) {
world = null;
}
/*
Priority:
1. server specific nodes
2. user nodes
3. server specific group nodes
4. group nodes
1. server+world specific nodes
2. server specific nodes
3. user nodes
4. server+world specific group nodes
5. server specific group nodes
6. group nodes
*/
final Map<String, Boolean> serverWorldSpecificNodes = new HashMap<>();
final Map<String, Boolean> serverSpecificNodes = new HashMap<>();
final Map<String, Boolean> userNodes = new HashMap<>();
final Map<String, Boolean> serverWorldSpecificGroups = new HashMap<>();
final Map<String, Boolean> serverSpecificGroups = new HashMap<>();
final Map<String, Boolean> groupNodes = new HashMap<>();
@@ -374,6 +485,33 @@ public abstract class PermissionObject {
serverSpecific:
if (node.getKey().contains("/")) {
String[] parts = Patterns.SERVER_SPLIT.split(node.getKey(), 2);
// 0=server(+world) 1=node
// WORLD SPECIFIC
if (parts[0].contains("-")) {
String[] serverParts = Patterns.WORLD_SPLIT.split(parts[0], 2);
// 0=server 1=world
if ((!serverParts[0].equalsIgnoreCase("global") || !includeGlobal) && (!serverParts[0].equalsIgnoreCase(server))) {
// GLOBAL AND UNWANTED OR SERVER SPECIFIC BUT DOES NOT APPLY :(((
continue;
}
if (world != null && !serverParts[1].equalsIgnoreCase(world)) {
// WORLD SPECIFIC BUT DOES NOT APPLY
continue;
}
if (Patterns.GROUP_MATCH.matcher(parts[1]).matches()) {
// SERVER+WORLD SPECIFIC AND GROUP
serverWorldSpecificGroups.put(node.getKey(), node.getValue());
continue;
}
// SERVER+WORLD SPECIFIC
serverWorldSpecificNodes.put(node.getKey(), node.getValue());
continue;
}
if (parts[0].equalsIgnoreCase("global")) {
// REGULAR
@@ -399,17 +537,30 @@ public abstract class PermissionObject {
// Skip adding global permissions if they are not requested
if (!includeGlobal) continue;
if (Patterns.GROUP_MATCH.matcher(node.getKey()).matches()) {
// Could be here if the server was set to global.
String n = node.getKey();
if (n.contains("/")) {
n = Patterns.SERVER_SPLIT.split(n, 2)[0];
}
if (Patterns.GROUP_MATCH.matcher(n).matches()) {
// GROUP
groupNodes.put(node.getKey(), node.getValue());
groupNodes.put(n, node.getValue());
continue;
}
// JUST NORMAL
userNodes.put(node.getKey(), node.getValue());
userNodes.put(n, node.getValue());
}
// If a group is negated at a higher priority, the group should not then be applied at a lower priority
serverWorldSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
groupNodes.remove(node.getKey());
groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
serverSpecificGroups.remove(node.getKey());
serverSpecificGroups.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
serverSpecificGroups.remove(Patterns.WORLD_SPLIT.split(node.getKey(), 2)[0] + "/" + Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
});
serverSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
groupNodes.remove(node.getKey());
groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
@@ -436,24 +587,26 @@ public abstract class PermissionObject {
}
}
// Apply next priority: serverSpecificGroups
for (Map.Entry<String, Boolean> groupNode : serverSpecificGroups.entrySet()) {
final String rawNode = Patterns.SERVER_SPLIT.split(groupNode.getKey())[1];
// Apply next priorities: serverSpecificGroups and then serverWorldSpecificGroups
for (Map<String, Boolean> m : Arrays.asList(serverSpecificGroups, serverWorldSpecificGroups)) {
for (Map.Entry<String, Boolean> groupNode : m.entrySet()) {
final String rawNode = Patterns.SERVER_SPLIT.split(groupNode.getKey())[1];
// Add the actual group perm node, so other plugins can hook
perms.put(rawNode, groupNode.getValue());
// Add the actual group perm node, so other plugins can hook
perms.put(rawNode, groupNode.getValue());
// Don't add negated groups
if (!groupNode.getValue()) continue;
// Don't add negated groups
if (!groupNode.getValue()) continue;
String groupName = Patterns.DOT_SPLIT.split(rawNode, 2)[1];
if (!excludedGroups.contains(groupName)) {
Group group = plugin.getGroupManager().getGroup(groupName);
if (group != null) {
perms.putAll(group.getLocalPermissions(server, excludedGroups));
} else {
plugin.getLogger().warning("Error whilst refreshing the permissions of '" + objectName + "'." +
"\n The group '" + groupName + "' is not loaded.");
String groupName = Patterns.DOT_SPLIT.split(rawNode, 2)[1];
if (!excludedGroups.contains(groupName)) {
Group group = plugin.getGroupManager().getGroup(groupName);
if (group != null) {
perms.putAll(group.getLocalPermissions(server, excludedGroups));
} else {
plugin.getLogger().warning("Error whilst refreshing the permissions of '" + objectName + "'." +
"\n The group '" + groupName + "' is not loaded.");
}
}
}
}
@@ -461,12 +614,21 @@ public abstract class PermissionObject {
// Apply next priority: userNodes
perms.putAll(userNodes);
// Apply highest priority: serverSpecificNodes
for (Map.Entry<String, Boolean> node : serverSpecificNodes.entrySet()) {
final String rawNode = Patterns.SERVER_SPLIT.split(node.getKey())[1];
perms.put(rawNode, node.getValue());
// Apply final priorities: serverSpecificNodes and then serverWorldSpecificNodes
for (Map<String, Boolean> m : Arrays.asList(serverSpecificNodes, serverWorldSpecificNodes)) {
for (Map.Entry<String, Boolean> node : m.entrySet()) {
final String rawNode = Patterns.SERVER_SPLIT.split(node.getKey())[1];
perms.put(rawNode, node.getValue());
}
}
return perms;
}
private static String stripTime(String s) {
if (s.contains("$")) {
return Patterns.TEMP_SPLIT.split(s)[0];
}
return s;
}
}
@@ -0,0 +1,47 @@
package me.lucko.luckperms.utils;
import lombok.Getter;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class UuidCache {
// External UUID --> Internal UUID
private Map<UUID, UUID> cache;
@Getter
private final boolean onlineMode;
public UuidCache(boolean onlineMode) {
this.onlineMode = onlineMode;
if (!onlineMode) {
cache = new ConcurrentHashMap<>();
}
}
public UUID getUUID(UUID external) {
return onlineMode ? external : (cache.containsKey(external) ? cache.get(external) : external);
}
public UUID getExternalUUID(UUID internal) {
if (onlineMode) return internal;
Optional<UUID> external = cache.entrySet().stream().filter(e -> e.getValue().equals(internal)).map(Map.Entry::getKey).findFirst();
return external.isPresent() ? external.get() : internal;
}
public void addToCache(UUID external, UUID internal) {
if (onlineMode) return;
cache.put(external, internal);
}
public void clearCache(UUID external) {
if (onlineMode) return;
cache.remove(external);
}
}
+7 -2
View File
@@ -7,14 +7,19 @@
<groupId>me.lucko</groupId>
<artifactId>luckperms</artifactId>
<version>1.2</version>
<version>${global.version}</version>
<modules>
<module>bukkit</module>
<module>common</module>
<module>bungee</module>
<module>api</module>
</modules>
<packaging>pom</packaging>
<properties>
<global.version>1.4</global.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
@@ -61,4 +66,4 @@
<scope>provided</scope>
</dependency>
</dependencies>
</project>
</project>