Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
563dd4683d | ||
|
|
e9131f729a | ||
|
|
c4ea626e33 | ||
|
|
fefba7976b | ||
|
|
2ce8555692 | ||
|
|
9fe9c386bb | ||
|
|
e8cd2c7548 | ||
|
|
158d8b086a | ||
|
|
1c534d7475 | ||
|
|
90f8dbe243 | ||
|
|
0c33b26fa9 | ||
|
|
d320679f69 | ||
|
|
8d5398b5a3 | ||
|
|
6cd8593fa5 | ||
|
|
5ebbc178a5 | ||
|
|
4f6e229943 | ||
|
|
3e846d9527 | ||
|
|
981d745b74 | ||
|
|
2dd0858960 | ||
|
|
f72819a664 | ||
|
|
5361b1e87b | ||
|
|
e15d03ed4e | ||
|
|
6c9041ce40 | ||
|
|
8da96e6e48 | ||
|
|
385aa6d438 | ||
|
|
79f24a5944 | ||
|
|
80570717f9 | ||
|
|
ebab79c4ca | ||
|
|
42882ebe11 | ||
|
|
d2de26f765 | ||
|
|
e2cebfbd16 | ||
|
|
a58cc6bdf3 | ||
|
|
36bc1553c0 | ||
|
|
17b06c39e9 | ||
|
|
ba2f6eb7be | ||
|
|
b93145f26d | ||
|
|
e88ea9c13d | ||
|
|
1275d0023d | ||
|
|
27f6f225c9 | ||
|
|
41362aa34a | ||
|
|
a99609e016 | ||
|
|
c0ea2d8ec3 | ||
|
|
bb6b31d715 | ||
|
|
21695dd2cb | ||
|
|
531835c948 | ||
|
|
77e3b351fd | ||
|
|
66f756575a | ||
|
|
7acc8bc7ed | ||
|
|
0a4d337a53 | ||
|
|
0198068a13 | ||
|
|
1c15f8462f | ||
|
|
3929ce0dfc | ||
|
|
7deeaf305d | ||
|
|
0f04c06e13 | ||
|
|
d1863fa714 | ||
|
|
46b122a167 | ||
|
|
ee3db1e5c5 | ||
|
|
bd830617c9 | ||
|
|
a9b6493091 | ||
|
|
9894e45516 | ||
|
|
2cfc82f3aa | ||
|
|
bb9eab0989 | ||
|
|
dc87ec1c82 | ||
|
|
98b7b65ce7 | ||
|
|
9f8f32b33e | ||
|
|
a80ec6d893 | ||
|
|
4d85930f5a | ||
|
|
f722f4112d | ||
|
|
383276f47a | ||
|
|
33c78e4a17 | ||
|
|
55a0de7899 | ||
|
|
6b3aab66bf | ||
|
|
77e70ef8d3 | ||
|
|
9b92143501 | ||
|
|
87f94f6b8f | ||
|
|
5d955e77b6 | ||
|
|
270a276b98 | ||
|
|
be7d914e39 | ||
|
|
37fc00cce8 | ||
|
|
0d515abadb | ||
|
|
daef01194e | ||
|
|
258bf1cc41 | ||
|
|
ce3d7829d7 | ||
|
|
c66a01c1a6 | ||
|
|
d113a92ce5 | ||
|
|
7b655d12df | ||
|
|
a4c872f1e8 | ||
|
|
0e7d9bf9c1 | ||
|
|
6252a5bc75 | ||
|
|
e4e80c9c31 | ||
|
|
165c5610c3 | ||
|
|
13fbc7dd39 | ||
|
|
02a75fc32a | ||
|
|
699c4d107b | ||
|
|
e4810302e1 | ||
|
|
73f10cad66 | ||
|
|
f1d670dc46 | ||
|
|
045539c752 | ||
|
|
782c09b686 | ||
|
|
6109718c67 | ||
|
|
cd758d7e48 | ||
|
|
fcb0fcadeb | ||
|
|
26fb506560 | ||
|
|
b6c4239322 | ||
|
|
74f9283f18 | ||
|
|
60e6ae6e23 | ||
|
|
83d9229295 | ||
|
|
e079b0f3ed | ||
|
|
d433a5461d | ||
|
|
2c43f6bf21 | ||
|
|
ac57509a29 | ||
|
|
c5ce655cf6 | ||
|
|
9fe05efb4e | ||
|
|
dcf207f5e5 | ||
|
|
11facab71c | ||
|
|
5b4975f34c | ||
|
|
069e535f1a | ||
|
|
1eb053447e | ||
|
|
93c7c06b2d | ||
|
|
b0085bc1e1 | ||
|
|
9133951446 | ||
|
|
7853d4686a | ||
|
|
ed5892eb56 | ||
|
|
687804de2c | ||
|
|
9d166041ab | ||
|
|
924041bff4 | ||
|
|
e9216d3e0f | ||
|
|
db8f1bca66 | ||
|
|
2429831153 | ||
|
|
80d2246634 | ||
|
|
56df2477ca | ||
|
|
9b4384dc33 | ||
|
|
bc65857831 | ||
|
|
de462d2385 | ||
|
|
90150428be | ||
|
|
2a7f951f4f | ||
|
|
82789328c1 | ||
|
|
13bccd1d3f | ||
|
|
43c514132d | ||
|
|
9e0fdcbfee | ||
|
|
008dc3fc52 | ||
|
|
9fde237d9b | ||
|
|
d626c08b4c | ||
|
|
58e223e74b | ||
|
|
1da1df156e | ||
|
|
3442372281 | ||
|
|
1b3b50c113 | ||
|
|
18e126b781 | ||
|
|
c88600adda | ||
|
|
4787361e66 | ||
|
|
b5ece8b5bd | ||
|
|
7ee3116f29 | ||
|
|
1fc0d77971 | ||
|
|
a32ab4bf7f | ||
|
|
2d8083bf18 | ||
|
|
63b9be9845 | ||
|
|
85a83d8c71 | ||
|
|
71b33a296c | ||
|
|
becdfd6f03 | ||
|
|
41744f9416 | ||
|
|
cb89a92ba9 | ||
|
|
93d54373c6 | ||
|
|
385addfe08 | ||
|
|
4c21957b04 | ||
|
|
ab6b011225 | ||
|
|
e72d91503c | ||
|
|
b9ee206908 | ||
|
|
4c9abba5fa | ||
|
|
3424b0542a | ||
|
|
fec90b8958 | ||
|
|
4da7fe4ff9 | ||
|
|
c53623dd67 | ||
|
|
6540ffa4dd | ||
|
|
5ee6db02ff | ||
|
|
d8221f466a | ||
|
|
462bea2a09 | ||
|
|
f452a97278 | ||
|
|
eb9d2be587 | ||
|
|
df1e747861 | ||
|
|
f48595b1ff | ||
|
|
12cd4e19cb | ||
|
|
a195e94522 | ||
|
|
02abb39dc2 | ||
|
|
f7a0b1ef78 | ||
|
|
7678f25879 | ||
|
|
fa9324bda8 | ||
|
|
1e72f9d8fe | ||
|
|
50fd954599 | ||
|
|
b1e34b55f8 | ||
|
|
cff1b8a411 | ||
|
|
6ffa6720be | ||
|
|
f52a106165 | ||
|
|
bf247b71e1 | ||
|
|
66818e4c82 | ||
|
|
23d53d39b4 | ||
|
|
30ea5a5b69 | ||
|
|
e7a210dc06 | ||
|
|
497de9824a | ||
|
|
be74b50762 | ||
|
|
f2e06b56e7 | ||
|
|
f6aa20c300 | ||
|
|
5e16134f6f | ||
|
|
6165fcbb21 | ||
|
|
831e882db0 | ||
|
|
feb8bf4bd3 | ||
|
|
ce3ee866ca | ||
|
|
d29dd35689 | ||
|
|
3a0a89853f | ||
|
|
e7ca79d251 | ||
|
|
22426bab33 | ||
|
|
116094ea96 | ||
|
|
9df39a9545 | ||
|
|
b8f44df723 | ||
|
|
74f275eb69 | ||
|
|
1142cbcb2c | ||
|
|
37749e5829 | ||
|
|
f9025c7a51 | ||
|
|
c7bfc38477 | ||
|
|
7ca394d7b9 | ||
|
|
31884ea59d | ||
|
|
e79b7c7023 | ||
|
|
1fdb4e8ade | ||
|
|
53db8c5928 | ||
|
|
07514000a4 | ||
|
|
f28721e55a | ||
|
|
fc230291d3 | ||
|
|
89ff4cfa40 | ||
|
|
d786b6abb2 | ||
|
|
fb0e694155 | ||
|
|
cd6cac1fb6 | ||
|
|
ea07f05097 | ||
|
|
d84767af68 | ||
|
|
aab73a8d81 | ||
|
|
995fc2ccd8 | ||
|
|
60bcd5f643 | ||
|
|
ba04fb320b | ||
|
|
770b7dc282 | ||
|
|
ed85eee36c | ||
|
|
23df8a2df8 | ||
|
|
36cd388607 | ||
|
|
4d48ef1939 | ||
|
|
7970e2a1c6 | ||
|
|
cee96d7daa | ||
|
|
861c1ddd69 | ||
|
|
5dec5a54cb | ||
|
|
5c760aabd4 | ||
|
|
1a2fa5d8c3 | ||
|
|
ef0c53da82 | ||
|
|
3fd62a80e2 | ||
|
|
5c19dd8b15 | ||
|
|
1fc88e147f | ||
|
|
9b4bbe0500 | ||
|
|
b37fdd3619 | ||
|
|
ab00c41452 | ||
|
|
c15727377b | ||
|
|
1e6f32bdc4 | ||
|
|
42e69c98a7 | ||
|
|
a217727bb4 | ||
|
|
ba10b1c06e | ||
|
|
075ba33e8b | ||
|
|
19dbc7d90a | ||
|
|
ade70bb7ba | ||
|
|
4b67913eee | ||
|
|
75858c1555 | ||
|
|
659baaf5fb | ||
|
|
3c83c578eb | ||
|
|
3ddbf1da87 | ||
|
|
35cb5b81dc | ||
|
|
02d9b996a7 | ||
|
|
d4cf6a5ad7 | ||
|
|
9fdb4fa25f | ||
|
|
d5bc1cdf5d | ||
|
|
f5995c0afa | ||
|
|
2cc65160b4 | ||
|
|
57f5a7c4cd | ||
|
|
6aea3b53f3 | ||
|
|
9f5e194a6e | ||
|
|
0831585a27 | ||
|
|
b2cf6dce2d | ||
|
|
a3ebf86f6b | ||
|
|
2a305b1c55 | ||
|
|
2ea9b36c77 | ||
|
|
edaf174ebf | ||
|
|
c4497db06c | ||
|
|
9873415303 | ||
|
|
2b71476cfe | ||
|
|
44d14001e1 | ||
|
|
de5fda6a18 | ||
|
|
8b83a1d9a2 | ||
|
|
c0a0239eeb | ||
|
|
84f377451e | ||
|
|
21d0c9ab0e | ||
|
|
f9c1cdb4bd | ||
|
|
e89444141b | ||
|
|
9cd4e01d8e | ||
|
|
f7fa08d5e9 | ||
|
|
7a4135319f | ||
|
|
41fca40a36 | ||
|
|
9dbfa76b26 | ||
|
|
20eeade06f | ||
|
|
cd9f18ffdb | ||
|
|
f7baf67985 | ||
|
|
692bf30cf5 | ||
|
|
41b33fbd7a | ||
|
|
5dc551c05d | ||
|
|
dd7aee9d15 | ||
|
|
bbeed1e4ed | ||
|
|
471084a9ef | ||
|
|
6fc00976a0 |
No files matched your search
+151
-24
@@ -1,31 +1,27 @@
|
||||
# built application files
|
||||
*.jar
|
||||
# Created by https://www.gitignore.io/
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
### Intellij ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
logs/
|
||||
|
||||
# Eclipse project files
|
||||
.classpath
|
||||
.project
|
||||
|
||||
# Intellij project files
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
# User-specific stuff:
|
||||
.idea/
|
||||
*.iws
|
||||
/out/
|
||||
*.iml
|
||||
.idea_modules/
|
||||
|
||||
# Gradle
|
||||
.gradletasknamecache
|
||||
.gradle/
|
||||
build/
|
||||
bin/
|
||||
gradle/
|
||||
gradlew*
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Maven
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
|
||||
### Maven ###
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
@@ -34,4 +30,135 @@ pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
.mvn/timing.properties
|
||||
|
||||
|
||||
### Eclipse ###
|
||||
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
.recommenders
|
||||
|
||||
# Eclipse Core
|
||||
.project
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# PyDev specific (Python IDE for Eclipse)
|
||||
*.pydevproject
|
||||
|
||||
# CDT-specific (C/C++ Development Tooling)
|
||||
.cproject
|
||||
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
# Java annotation processor (APT)
|
||||
.factorypath
|
||||
|
||||
# PDT-specific (PHP Development Tools)
|
||||
.buildpath
|
||||
|
||||
# sbteclipse plugin
|
||||
.target
|
||||
|
||||
# Tern plugin
|
||||
.tern-project
|
||||
|
||||
# TeXlipse plugin
|
||||
.texlipse
|
||||
|
||||
# STS (Spring Tool Suite)
|
||||
.springBeans
|
||||
|
||||
# Code Recommenders
|
||||
.recommenders/
|
||||
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
|
||||
### macOS ###
|
||||
*.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
# Thumbnails
|
||||
._*
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
|
||||
### Windows ###
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
|
||||
### Java ###
|
||||
*.class
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
@@ -1,292 +1,29 @@
|
||||

|
||||
# LuckPerms [](https://ci.lucko.me/job/LuckPerms/)
|
||||
A permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
|
||||
An advanced permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
|
||||
|
||||
## Links
|
||||
* **Development Builds** - <https://ci.lucko.me/job/LuckPerms>
|
||||
* **Javadocs** - <https://jd.lucko.me/LuckPerms>
|
||||
* **Wiki** - <https://github.com/lucko/LuckPerms/wiki>
|
||||
|
||||
## Why LuckPerms?
|
||||
_Features checked on 19th Aug 2016. If you find any inaccuracies, please do let me know. I tried to be as fair as possible, and copy all major features from the respective plugin pages._
|
||||
## Description
|
||||
LuckPerms is an advanced permissions implementation aiming to be a flexible, performant and reliable alternative to other permission systems, providing all the features you could ever possibly need in a permissions plugin, along with an extensive and well documented API for developers.
|
||||
|
||||

|
||||
|
||||
## 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
|
||||
* **Wildcard permissions** - users/groups can be given wildcard permissions (e.g. "minecraft.command.*"), even when plugins haven't implemented their own wildcards.
|
||||
* **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
|
||||
* **Advanced action logging** - keep track of permission changes over time
|
||||
* **Easily switch between storage systems** - export a log file from one datastore and import it into another
|
||||
* **Easy and simple setup and configuration using commands** - no editing yml files, yuck
|
||||
* **Negated permissions and groups** - define special rules for certain users/groups
|
||||
* **Regex permissions** - define special permissions using regex
|
||||
* **Shorthand nodes** - add nodes using the LuckPerms shorthand system
|
||||
* **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 all LuckPerms instances
|
||||
* **Sponge compatible** - permissions, users and groups are synced across all LuckPerms instances (bukkit --> sponge, for example)
|
||||
* **Support for MySQL, MongoDB, SQLite, H2 & Flatfile (JSON)** - other storage methods coming soon (maybe)
|
||||
|
||||
## Setup
|
||||
All configuration options are in the **config.yml/luckperms.conf** 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.
|
||||
|
||||
* **Non wildcard/regex permissions will be overridden by normal permissions**
|
||||
|
||||
Example: if a user has a true permission set for "luckperms.\*", and a false permission set for "luckperms.something", the non-wildcard permission will override the wildcard, and "luckperms.something" will be set to false, despite the wildcard.
|
||||
|
||||
* **More specific wildcards override less specific ones**
|
||||
|
||||
Example: if a user has "luckperms.\*" set to true, but "luckperms.user.\*" set to false, all of the user permissions will be set to false, despite the more generic wildcard for "luckperms.*".
|
||||
|
||||
* **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 (provided they're on that server).
|
||||
|
||||
* **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 audited once every 3 seconds, to check if they have expired. This check happens regardless of the sync interval setting. This means that you can safely set temporary permissions to expire after a matter of seconds, and they will be removed on-time.
|
||||
|
||||
### Shorthand Permissions
|
||||
LuckPerms has it's own system (although it's quite similar to PermissionsEx :P) that allows you to set permissions in a shorthand format.
|
||||
|
||||
Using the LuckPerms permission nodes as an example, say for instance, you wanted to let a user set and unset permissions for both groups and users.
|
||||
|
||||
Without shorthand, you would have to apply 4 nodes.
|
||||
```
|
||||
luckperms.user.setpermission
|
||||
luckperms.user.unsetpermission
|
||||
luckperms.group.setpermission
|
||||
luckperms.group.unsetpermission
|
||||
```
|
||||
However, with shorthand, you can just apply the following node:
|
||||
|
||||
`luckperms.(user|group).(setpermission|unsetpermission)`
|
||||
|
||||
You use brackets to define part of a node as a shorthand group, and then use the vertical bar `|` to separate entries.
|
||||
|
||||
There are some limitations, firstly, you cannot use shorthand in the first part of the node. (The "luckperms" part in the example above)
|
||||
|
||||
Additionally, you cannot combine shorthand and normal text in the same part of the node.
|
||||
For example, `luckperms.(user|group).(set|unset)permission` would not work.
|
||||
|
||||
### Regex
|
||||
LuckPerms has support for regex when defining permission nodes and server/world names.
|
||||
|
||||
Whenever regex is used, it MUST be prefixed with "R=", so LuckPerms knows to treat it as regex, and not as a normal string.
|
||||
|
||||
For example, if you wanted to give all members of the default group, the `essentials.fly` permission on all of your hub servers, where the hub server names are hub1, hub2, hub3, etc.
|
||||
You would use the command `/perms group default set essentials.fly true R=hub\d+`.
|
||||
|
||||
You can also use regex in permission nodes.
|
||||
Once again using LuckPerms permissions as an example, if you wanted a user to be able to create both groups and tracks, you would normally just add the two permission nodes. However with regex, you can just add one. `luckperms\.create.*` Remember to escape any characters, specifically dots, as the entire node will be parsed.
|
||||
|
||||
## 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 a number of ways.
|
||||
|
||||
```java
|
||||
// On all platforms (throws IllegalStateException if the API is not loaded)
|
||||
final LuckPermsApi api = LuckPerms.getApi();
|
||||
|
||||
// Or with Optional
|
||||
Optional<LuckPermsApi> provider = LuckPerms.getApiSafe();
|
||||
if (provider.isPresent()) {
|
||||
final LuckPermsApi api = provider.get();
|
||||
}
|
||||
|
||||
// On Bukkit/Spigot
|
||||
ServicesManager manager = Bukkit.getServicesManager();
|
||||
if (manager.isProvidedFor(LuckPermsApi.class)) {
|
||||
final LuckPermsApi api = manager.getRegistration(LuckPermsApi.class).getProvider();
|
||||
}
|
||||
|
||||
// On Sponge
|
||||
Optional<LuckPermsApi> provider = Sponge.getServiceManager().provide(LuckPermsApi.class);
|
||||
if (provider.isPresent()) {
|
||||
final LuckPermsApi api = provider.get();
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
You can add LuckPerms as a Maven dependency by adding the following to your projects `pom.xml`.
|
||||
````xml
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>luck-repo</id>
|
||||
<url>https://repo.lucko.me/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-api</artifactId>
|
||||
<version>2.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
````
|
||||
|
||||
### Events
|
||||
LuckPerms exposes a full read/write API, as well as an event listening system. Due to the multi-platform nature of the project, an internal Event system is used, as opposed to the systems already in place on each platform. (the Bukkit Event api, for example). This means that simply registering your listener with the platform is not sufficient.
|
||||
|
||||
All events are *fired asynchronously*. This means you should not interact with or call any non-thread safe methods from within listeners.
|
||||
|
||||
To listen to an event, you need to first make a class that implements `LPListener`. Then within this class, you can define all of your listener methods.
|
||||
|
||||
Each listener method must be annotated with `@Subscribe`. For example...
|
||||
|
||||
```java
|
||||
package me.lucko.test;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import me.lucko.luckperms.api.event.LPListener;
|
||||
import me.lucko.luckperms.api.event.events.PermissionSetEvent;
|
||||
|
||||
public class TestListener implements LPListener {
|
||||
|
||||
@Subscribe
|
||||
public void onPermissionSet(PermissionSetEvent event) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
You also need to register your new Listener with the API.
|
||||
```java
|
||||
@Override
|
||||
public void onEnable() {
|
||||
LuckPermsApi api;
|
||||
api.registerListener(new TestListener());
|
||||
}
|
||||
```
|
||||
|
||||
## Versioning
|
||||
As of version 2.0, LuckPerms roughly follows the standards set out in Semantic Versioning.
|
||||
|
||||
The only difference is that the patch number is not included anywhere within the pom, and is calculated each build, based upon how may commits have been made since the last tag. (A new tag is made every minor version)
|
||||
|
||||
This means that API versions do not have a patch number (as no API changes are made in patches). API versions will be x.y, and each individual build of LuckPerms will follow x.y.z.
|
||||
|
||||
## 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.*
|
||||
* **All log commands** - luckperms.log.*
|
||||
|
||||
### General
|
||||
* /perms - n/a
|
||||
* /perms sync - luckperms.sync
|
||||
* /perms info - luckperms.info
|
||||
* /perms debug - luckperms.debug
|
||||
* /perms import \<file\> - luckperms.import
|
||||
* /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
|
||||
|
||||
### Log
|
||||
* /perms log recent [user] [page] - luckperms.log.recent
|
||||
* /perms log search \<query\> [page] - luckperms.log.search
|
||||
* /perms log notify [on|off] - luckperms.log.notify
|
||||
* /perms log export \<file\> - luckperms.log.export
|
||||
* /perms log userhistory \<user\> [page] - luckperms.log.userhistory
|
||||
* /perms log grouphistory \<group\> [page] - luckperms.log.grouphistory
|
||||
* /perms log trackhistory \<track\> [page] - luckperms.log.trackhistory
|
||||
* [Spigot Plugin Page](https://www.spigotmc.org/resources/luckperms-an-advanced-permissions-system.28140/ "Spigot Plugin Page")
|
||||
* [Sponge Plugin Page](https://forums.spongepowered.org/t/luckperms-an-advanced-permissions-system/14274 "Sponge Plugin Page")
|
||||
|
||||
## LuckPerms vs Other Plugins
|
||||
### Bukkit
|
||||

|
||||
_Features checked on 23rd Aug 2016. If you find any inaccuracies, please do let me know. I tried to be as fair as possible, and copy all major features from the respective plugin pages._
|
||||
### Sponge
|
||||

|
||||
_Features checked on 8th Oct 2016. If you find any inaccuracies, please do let me know. I tried to be as fair as possible, and copy all major features from the respective plugin pages._
|
||||
## License
|
||||
See LICENSE.md.
|
||||
LuckPerms is licensed under the permissive MIT license. See LICENSE.md for more info.
|
||||
|
||||
## Thanks to:
|
||||
[](http://www.ej-technologies.com/products/jprofiler/overview.html)
|
||||
|
||||
Thanks to ej-technologies for granting LuckPerms an open source licence to their [Java Profiling Software](http://www.ej-technologies.com/products/jprofiler/overview.html "Java Profiler").
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.5-SNAPSHOT</version>
|
||||
<version>2.14-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents the context and options for a permission lookup.
|
||||
* All values are immutable.
|
||||
* @since 2.11
|
||||
*/
|
||||
public class Contexts {
|
||||
public static final String SERVER_KEY = "server";
|
||||
public static final String WORLD_KEY = "world";
|
||||
|
||||
/**
|
||||
* Gets a context that will allow all nodes
|
||||
* @return a context that will not apply any filters
|
||||
*/
|
||||
public static Contexts allowAll() {
|
||||
return new Contexts(ContextSet.empty(), true, true, true, true, true, true);
|
||||
}
|
||||
|
||||
public static Contexts of(ContextSet context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
|
||||
return new Contexts(context, includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups, op);
|
||||
}
|
||||
|
||||
public Contexts(ContextSet context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
|
||||
if (context == null) {
|
||||
throw new NullPointerException("context");
|
||||
}
|
||||
|
||||
this.context = context.makeImmutable();
|
||||
this.includeGlobal = includeGlobal;
|
||||
this.includeGlobalWorld = includeGlobalWorld;
|
||||
this.applyGroups = applyGroups;
|
||||
this.applyGlobalGroups = applyGlobalGroups;
|
||||
this.applyGlobalWorldGroups = applyGlobalWorldGroups;
|
||||
this.op = op;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
public static Contexts of(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups) {
|
||||
return new Contexts(context, includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
public static Contexts of(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
|
||||
return new Contexts(context, includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups, op);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Contexts(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
|
||||
this(context == null ? null : ContextSet.fromMap(context), includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups, op);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
public Contexts(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups) {
|
||||
this(context, includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The contexts that apply for this lookup
|
||||
* The keys for servers and worlds are defined as static values.
|
||||
*/
|
||||
private final ContextSet context;
|
||||
|
||||
/**
|
||||
* The mode to parse defaults on Bukkit
|
||||
* @since 2.12
|
||||
*/
|
||||
private final boolean op;
|
||||
|
||||
/**
|
||||
* If global or non server specific nodes should be applied
|
||||
*/
|
||||
private final boolean includeGlobal;
|
||||
|
||||
/**
|
||||
* If global or non world specific nodes should be applied
|
||||
*/
|
||||
private final boolean includeGlobalWorld;
|
||||
|
||||
/**
|
||||
* If parent groups should be applied
|
||||
*/
|
||||
private final boolean applyGroups;
|
||||
|
||||
/**
|
||||
* If global or non server specific group memberships should be applied
|
||||
*/
|
||||
private final boolean applyGlobalGroups;
|
||||
|
||||
/**
|
||||
* If global or non world specific group memberships should be applied
|
||||
*/
|
||||
private final boolean applyGlobalWorldGroups;
|
||||
|
||||
/**
|
||||
* Gets the contexts that apply for this lookup
|
||||
* @return an immutable set of context key value pairs
|
||||
* @since 2.13
|
||||
*/
|
||||
public ContextSet getContexts() {
|
||||
return this.context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the contexts that apply for this lookup
|
||||
* @return an immutable map of context key value pairs
|
||||
* @deprecated in favour of {@link #getContexts()}
|
||||
*/
|
||||
@Deprecated
|
||||
public Map<String, String> getContext() {
|
||||
return this.context.toMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if OP defaults should be included
|
||||
* @return true if op defaults should be included
|
||||
*/
|
||||
public boolean isOp() {
|
||||
return this.op;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non server specific nodes should be applied
|
||||
* @return true if global or non server specific nodes should be applied
|
||||
*/
|
||||
public boolean isIncludeGlobal() {
|
||||
return this.includeGlobal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non world specific nodes should be applied
|
||||
* @return true if global or non world specific nodes should be applied
|
||||
*/
|
||||
public boolean isIncludeGlobalWorld() {
|
||||
return this.includeGlobalWorld;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if parent groups should be applied
|
||||
* @return true if parent groups should be applied
|
||||
*/
|
||||
public boolean isApplyGroups() {
|
||||
return this.applyGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non server specific group memberships should be applied
|
||||
* @return true if global or non server specific group memberships should be applied
|
||||
*/
|
||||
public boolean isApplyGlobalGroups() {
|
||||
return this.applyGlobalGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non world specific group memberships should be applied
|
||||
* @return true if global or non world specific group memberships should be applied
|
||||
*/
|
||||
public boolean isApplyGlobalWorldGroups() {
|
||||
return this.applyGlobalWorldGroups;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Contexts(" +
|
||||
"context=" + this.getContexts() + ", " +
|
||||
"op=" + this.isOp() + ", " +
|
||||
"includeGlobal=" + this.isIncludeGlobal() + ", " +
|
||||
"includeGlobalWorld=" + this.isIncludeGlobalWorld() + ", " +
|
||||
"applyGroups=" + this.isApplyGroups() + ", " +
|
||||
"applyGlobalGroups=" + this.isApplyGlobalGroups() + ", " +
|
||||
"applyGlobalWorldGroups=" + this.isApplyGlobalWorldGroups() +
|
||||
")";
|
||||
}
|
||||
|
||||
/*
|
||||
* Ugly auto-generated lombok code
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check for equality
|
||||
* @param o the other
|
||||
* @return true if equal
|
||||
* @since 2.12
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof Contexts)) return false;
|
||||
final Contexts other = (Contexts) o;
|
||||
final Object this$context = this.getContexts();
|
||||
final Object other$context = other.getContexts();
|
||||
if (this$context == null ? other$context != null : !this$context.equals(other$context)) return false;
|
||||
if (this.isOp() != other.isOp()) return false;
|
||||
if (this.isIncludeGlobal() != other.isIncludeGlobal()) return false;
|
||||
if (this.isIncludeGlobalWorld() != other.isIncludeGlobalWorld()) return false;
|
||||
if (this.isApplyGroups() != other.isApplyGroups()) return false;
|
||||
if (this.isApplyGlobalGroups() != other.isApplyGlobalGroups()) return false;
|
||||
if (this.isApplyGlobalWorldGroups() != other.isApplyGlobalWorldGroups()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hashcode
|
||||
* @return the hashcode
|
||||
* @since 2.12
|
||||
*/
|
||||
public int hashCode() {
|
||||
final int PRIME = 59;
|
||||
int result = 1;
|
||||
final Object $context = this.getContexts();
|
||||
result = result * PRIME + ($context == null ? 43 : $context.hashCode());
|
||||
result = result * PRIME + (this.isOp() ? 79 : 97);
|
||||
result = result * PRIME + (this.isIncludeGlobal() ? 79 : 97);
|
||||
result = result * PRIME + (this.isIncludeGlobalWorld() ? 79 : 97);
|
||||
result = result * PRIME + (this.isApplyGroups() ? 79 : 97);
|
||||
result = result * PRIME + (this.isApplyGlobalGroups() ? 79 : 97);
|
||||
result = result * PRIME + (this.isApplyGlobalWorldGroups() ? 79 : 97);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,50 +24,40 @@ package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Wrapper interface for the internal Datastore instance
|
||||
*
|
||||
* <p> 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.
|
||||
* Interface for the internal Datastore instance
|
||||
* @deprecated as of version 2.14 in favour of {@link Storage}.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated
|
||||
public interface Datastore {
|
||||
|
||||
String getName();
|
||||
boolean isAcceptingLogins();
|
||||
|
||||
Async async();
|
||||
@Deprecated
|
||||
Sync sync();
|
||||
|
||||
@Deprecated
|
||||
Async async();
|
||||
|
||||
@Deprecated
|
||||
Future future();
|
||||
|
||||
interface Async {
|
||||
void logAction(LogEntry entry, Callback<Boolean> callback);
|
||||
void getLog(Callback<Log> callback);
|
||||
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);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
interface Sync {
|
||||
boolean logAction(LogEntry entry);
|
||||
Log getLog();
|
||||
@Deprecated
|
||||
boolean loadOrCreateUser(UUID uuid, String username);
|
||||
@Deprecated
|
||||
boolean loadUser(UUID uuid);
|
||||
boolean loadUser(UUID uuid, String username);
|
||||
boolean saveUser(User user);
|
||||
boolean cleanupUsers();
|
||||
Set<UUID> getUniqueUsers();
|
||||
boolean createAndLoadGroup(String name);
|
||||
boolean loadGroup(String name);
|
||||
boolean loadAllGroups();
|
||||
@@ -82,12 +72,44 @@ public interface Datastore {
|
||||
UUID getUUID(String username);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
interface Async {
|
||||
void logAction(LogEntry entry, Callback<Boolean> callback);
|
||||
void getLog(Callback<Log> callback);
|
||||
@Deprecated
|
||||
void loadOrCreateUser(UUID uuid, String username, Callback<Boolean> callback);
|
||||
@Deprecated
|
||||
void loadUser(UUID uuid, Callback<Boolean> callback);
|
||||
void loadUser(UUID uuid, String username, Callback<Boolean> callback);
|
||||
void saveUser(User user, Callback<Boolean> callback);
|
||||
void cleanupUsers(Callback<Boolean> callback);
|
||||
void getUniqueUsers(Callback<Set<UUID>> 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);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
interface Future {
|
||||
java.util.concurrent.Future<Boolean> logAction(LogEntry entry);
|
||||
java.util.concurrent.Future<Log> getLog();
|
||||
@Deprecated
|
||||
java.util.concurrent.Future<Boolean> loadOrCreateUser(UUID uuid, String username);
|
||||
@Deprecated
|
||||
java.util.concurrent.Future<Boolean> loadUser(UUID uuid);
|
||||
java.util.concurrent.Future<Boolean> loadUser(UUID uuid, String username);
|
||||
java.util.concurrent.Future<Boolean> saveUser(User user);
|
||||
java.util.concurrent.Future<Boolean> cleanupUsers();
|
||||
java.util.concurrent.Future<Set<UUID>> getUniqueUsers();
|
||||
java.util.concurrent.Future<Boolean> createAndLoadGroup(String name);
|
||||
java.util.concurrent.Future<Boolean> loadGroup(String name);
|
||||
java.util.concurrent.Future<Boolean> loadAllGroups();
|
||||
|
||||
@@ -28,10 +28,7 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal Group instances
|
||||
*
|
||||
* <p> 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.
|
||||
* Interface for internal Group instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Group extends PermissionHolder {
|
||||
@@ -42,26 +39,34 @@ public interface Group extends PermissionHolder {
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* check to see if a group inherits a group
|
||||
* 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
|
||||
* @return true if the group inherits the other group
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
boolean inheritsGroup(Group group);
|
||||
|
||||
/**
|
||||
* check to see if the group inherits a group on a specific 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
|
||||
* @return true if the group inherits the group
|
||||
* @return true if the group inherits the group on the server
|
||||
* @throws NullPointerException if the group or server is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the server is invalid
|
||||
*/
|
||||
boolean inheritsGroup(Group group, String server);
|
||||
|
||||
/**
|
||||
* check to see if the group inherits a group on a specific server
|
||||
* Check to see if the group inherits a group on a specific server and world
|
||||
* @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
|
||||
* @return true if the group inherits the group on the server and world
|
||||
* @throws NullPointerException if the group, server or world is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the server or world is invalid
|
||||
*/
|
||||
boolean inheritsGroup(Group group, String server, String world);
|
||||
|
||||
@@ -69,101 +74,134 @@ public interface Group extends PermissionHolder {
|
||||
* Make this group inherit another group
|
||||
* @param group the group to be inherited
|
||||
* @throws ObjectAlreadyHasException if the group already inherits the group
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
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
|
||||
* @param server The server to inherit the group on
|
||||
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
|
||||
* @throws NullPointerException if the group or server is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the server is invalid
|
||||
*/
|
||||
void setInheritGroup(Group group, String server) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Make this group inherit another group on a specific server
|
||||
* Make this group inherit another group on a specific server and world
|
||||
* @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
|
||||
* @param server The server to inherit the group on
|
||||
* @param world The world to inherit the group on
|
||||
* @throws ObjectAlreadyHasException if the group already inherits the group on that server and world
|
||||
* @throws NullPointerException if the group, server or world is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the server or world is invalid
|
||||
*/
|
||||
void setInheritGroup(Group group, String server, String world) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Make this group inherit another group on a specific server
|
||||
* Make this group inherit another group temporarily
|
||||
* @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
|
||||
* @param expireAt the unix time when the group should expire
|
||||
* @throws ObjectAlreadyHasException if the group already inherits the group temporarily
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the expiry time is in the past
|
||||
*/
|
||||
void setInheritGroup(Group group, long expireAt) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Make this group inherit another group on a specific server
|
||||
* Make this group inherit another group on a specific server temporarily
|
||||
* @param group the group to be inherited
|
||||
* @param server The server to add the group on
|
||||
* @param server The server inherit add the group on
|
||||
* @param expireAt when the group should expire
|
||||
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
|
||||
* @throws ObjectAlreadyHasException if the group already inherits the group on that server temporarily
|
||||
* @throws NullPointerException if the group or server is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the expiry time is in the past or the server is invalid
|
||||
*/
|
||||
void setInheritGroup(Group group, String server, long expireAt) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Make this group inherit another group on a specific server
|
||||
* Make this group inherit another group on a specific server and world temporarily
|
||||
* @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 server The server to inherit the group on
|
||||
* @param world The world to inherit the group on
|
||||
* @param expireAt when the group should expire
|
||||
* @throws ObjectAlreadyHasException if the group already inherits the group on that server
|
||||
* @throws ObjectAlreadyHasException if the group already inherits the group on that server and world temporarily
|
||||
* @throws NullPointerException if the group, server or world is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the expiry time is in the past or the server/world is invalid
|
||||
*/
|
||||
void setInheritGroup(Group group, String server, String world, long expireAt) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Remove a previously set inheritance
|
||||
* Remove a previously set inheritance rule
|
||||
* @param group the group to uninherit
|
||||
* @throws ObjectLacksException if the group does not already inherit the group
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
void unsetInheritGroup(Group group) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Remove a previously set inheritance
|
||||
* Remove a previously set inheritance rule
|
||||
* @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
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
void unsetInheritGroup(Group group, boolean temporary) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Remove a previously set inheritance
|
||||
* Remove a previously set inheritance rule on a specific server
|
||||
* @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
|
||||
* @throws ObjectLacksException if the group does not already inherit the group on that server
|
||||
* @throws NullPointerException if the group or server is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the server is invalid
|
||||
*/
|
||||
void unsetInheritGroup(Group group, String server) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Remove a previously set inheritance
|
||||
* Remove a previously set inheritance rule on a specific server and world
|
||||
* @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
|
||||
* @throws NullPointerException if the group, server or world is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the server or world is invalid
|
||||
*/
|
||||
void unsetInheritGroup(Group group, String server, String world) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Remove a previously set inheritance
|
||||
* Remove a previously set inheritance rule on a specific server
|
||||
* @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
|
||||
* @throws NullPointerException if the group or server is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the expiry time is in the past or the server is invalid
|
||||
*/
|
||||
void unsetInheritGroup(Group group, String server, boolean temporary) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Remove a previously set inheritance
|
||||
* Remove a previously set inheritance rule on a specific server and world
|
||||
* @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
|
||||
* @param temporary if the group being removed was set temporarily
|
||||
* @throws ObjectLacksException if the group does not already inherit the group
|
||||
* @throws NullPointerException if the group, server or world is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the expiry time is in the past or the server/world is invalid
|
||||
*/
|
||||
void unsetInheritGroup(Group group, String server, String world, boolean temporary) throws ObjectLacksException;
|
||||
|
||||
@@ -183,6 +221,8 @@ public interface Group extends PermissionHolder {
|
||||
* @param server the server to check
|
||||
* @param world the world to check
|
||||
* @return a {@link List} of group names
|
||||
* @throws NullPointerException if the server or world is null
|
||||
* @throws IllegalArgumentException if the server or world is invalid
|
||||
*/
|
||||
List<String> getLocalGroups(String server, String world);
|
||||
|
||||
@@ -190,6 +230,8 @@ public interface Group extends PermissionHolder {
|
||||
* Get a {@link List} of the groups the group inherits on a specific server
|
||||
* @param server the server to check
|
||||
* @return a {@link List} of group names
|
||||
* @throws NullPointerException if the server is null
|
||||
* @throws IllegalArgumentException if the server is invalid
|
||||
*/
|
||||
List<String> getLocalGroups(String server);
|
||||
}
|
||||
@@ -25,9 +25,12 @@ package me.lucko.luckperms.api;
|
||||
import me.lucko.luckperms.api.data.DatastoreConfiguration;
|
||||
import me.lucko.luckperms.api.data.MySQLConfiguration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A wrapper interface for the internal LuckPerms configuration, providing read only access.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface LPConfiguration {
|
||||
|
||||
/**
|
||||
@@ -42,12 +45,16 @@ public interface LPConfiguration {
|
||||
|
||||
/**
|
||||
* @return the default group, in a node representation
|
||||
* @deprecated as of 2.6, the default group is always "default"
|
||||
*/
|
||||
@Deprecated
|
||||
String getDefaultGroupNode();
|
||||
|
||||
/**
|
||||
* @return the name of the default group
|
||||
* @deprecated as of 2.6, the default group is always "default"
|
||||
*/
|
||||
@Deprecated
|
||||
String getDefaultGroupName();
|
||||
|
||||
/**
|
||||
@@ -55,6 +62,24 @@ public interface LPConfiguration {
|
||||
*/
|
||||
boolean getIncludeGlobalPerms();
|
||||
|
||||
/**
|
||||
* @return if the users on this server will have their global world permissions applied
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getIncludeGlobalWorldPerms();
|
||||
|
||||
/**
|
||||
* @return true if the platform is applying global groups
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getApplyGlobalGroups();
|
||||
|
||||
/**
|
||||
* @return true if the platform is applying global world groups
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getApplyGlobalWorldGroups();
|
||||
|
||||
/**
|
||||
* @return the online mode setting in the config
|
||||
*/
|
||||
@@ -75,6 +100,50 @@ public interface LPConfiguration {
|
||||
*/
|
||||
boolean getApplyShorthand();
|
||||
|
||||
/**
|
||||
* @return if LuckPerms will send notifications to users when permissions are modified
|
||||
* @since 2.7
|
||||
*/
|
||||
boolean getLogNotify();
|
||||
|
||||
/**
|
||||
* @return true if permission checks are being recorded / debugged
|
||||
* @since 2.9
|
||||
* @deprecated as this value is now always false. Functionality was replaced by the verbose command.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean getDebugPermissionChecks();
|
||||
|
||||
/**
|
||||
* @return true if the vanilla op system is enabled
|
||||
* @since 2.8
|
||||
*/
|
||||
boolean getEnableOps();
|
||||
|
||||
/**
|
||||
* @return true if opped players are allowed to use LuckPerms commands
|
||||
* @since 2.8
|
||||
*/
|
||||
boolean getCommandsAllowOp();
|
||||
|
||||
/**
|
||||
* @return true if auto op is enabled
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getAutoOp();
|
||||
|
||||
/**
|
||||
* @return the name of the server used within Vault operations
|
||||
* @since 2.7
|
||||
*/
|
||||
String getVaultServer();
|
||||
|
||||
/**
|
||||
* @return true if global permissions should be considered when retrieving meta or player groups
|
||||
* @since 2.7
|
||||
*/
|
||||
boolean getVaultIncludeGlobal();
|
||||
|
||||
/**
|
||||
* @return the database values set in the configuration
|
||||
* @deprecated use {@link #getDatastoreConfig()}
|
||||
@@ -93,4 +162,17 @@ public interface LPConfiguration {
|
||||
*/
|
||||
String getStorageMethod();
|
||||
|
||||
/**
|
||||
* @return true if split storage is enabled
|
||||
* @since 2.7
|
||||
*/
|
||||
boolean getSplitStorage();
|
||||
|
||||
/**
|
||||
* @return a map of split storage options, where the key is the storage section, and the value is the storage method.
|
||||
* For example: key = user, value = json
|
||||
* @since 2.7
|
||||
*/
|
||||
Map<String, String> getSplitStorageOptions();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
/**
|
||||
* Represents a Node and where it was inherited from.
|
||||
* @since 2.11
|
||||
*/
|
||||
public interface LocalizedNode extends Node {
|
||||
|
||||
/**
|
||||
* Gets the node
|
||||
* @return the node this instance is representing
|
||||
*/
|
||||
Node getNode();
|
||||
|
||||
/**
|
||||
* Gets the location where the {@link Node} is inherited from
|
||||
* @return where the node was inherited from. Will not return null.
|
||||
* @see PermissionHolder#getObjectName()
|
||||
*/
|
||||
String getLocation();
|
||||
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents the internal LuckPerms log.
|
||||
* All content is immutable. You can add to the log using the {@link Datastore}, and then request an updated copy.
|
||||
* All content internally is immutable. You can add to the log using the {@link Datastore}, and then request an updated copy.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Log {
|
||||
@@ -38,27 +38,124 @@ public interface Log {
|
||||
*/
|
||||
SortedSet<LogEntry> getContent();
|
||||
|
||||
/**
|
||||
* @return all content in this log
|
||||
*/
|
||||
SortedSet<LogEntry> getRecent();
|
||||
|
||||
/**
|
||||
* Gets the recent content separated by page
|
||||
* @param pageNo the page number
|
||||
* @return the page content
|
||||
*/
|
||||
SortedMap<Integer, LogEntry> getRecent(int pageNo);
|
||||
|
||||
/**
|
||||
* @return the max page number allowed in the {@link #getRecent(int)} method
|
||||
*/
|
||||
int getRecentMaxPages();
|
||||
|
||||
|
||||
/**
|
||||
* @param actor the uuid of the actor to filter by
|
||||
* @return all content in this log where is actor = uuid
|
||||
*/
|
||||
SortedSet<LogEntry> getRecent(UUID actor);
|
||||
|
||||
/**
|
||||
* Gets the recent content for the uuid, separated into pages
|
||||
* @param pageNo the page number
|
||||
* @param actor the uuid of the actor to filter by
|
||||
* @return the page content
|
||||
*/
|
||||
SortedMap<Integer, LogEntry> getRecent(int pageNo, UUID actor);
|
||||
|
||||
/**
|
||||
* @param actor the actor to filter by
|
||||
* @return the max page number allowed in the {@link #getRecent(int, UUID)} method
|
||||
*/
|
||||
int getRecentMaxPages(UUID actor);
|
||||
|
||||
|
||||
/**
|
||||
* @param uuid the uuid to filter by
|
||||
* @return all content in this log where the user = uuid
|
||||
*/
|
||||
SortedSet<LogEntry> getUserHistory(UUID uuid);
|
||||
|
||||
/**
|
||||
* Gets the user history content, separated by pages
|
||||
* @param pageNo the page number
|
||||
* @param uuid the uuid of the acted user to filter by
|
||||
* @return the page content
|
||||
*/
|
||||
SortedMap<Integer, LogEntry> getUserHistory(int pageNo, UUID uuid);
|
||||
|
||||
/**
|
||||
* @param uuid the uuid to filter by
|
||||
* @return the max page number allowed in the {@link #getUserHistory(int, UUID)} method
|
||||
*/
|
||||
int getUserHistoryMaxPages(UUID uuid);
|
||||
|
||||
|
||||
/**
|
||||
* @param name the name to filter by
|
||||
* @return all content in this log where the group = name
|
||||
*/
|
||||
SortedSet<LogEntry> getGroupHistory(String name);
|
||||
|
||||
/**
|
||||
* Gets the group history content, separated by pages
|
||||
* @param pageNo the page number
|
||||
* @param name the name of the acted group to filter by
|
||||
* @return the page content
|
||||
*/
|
||||
SortedMap<Integer, LogEntry> getGroupHistory(int pageNo, String name);
|
||||
|
||||
/**
|
||||
* @param name the name to filter by
|
||||
* @return the max page number allowed in the {@link #getGroupHistory(int, String)} method
|
||||
*/
|
||||
int getGroupHistoryMaxPages(String name);
|
||||
|
||||
|
||||
/**
|
||||
* @param name the name to filter by
|
||||
* @return all content in this log where the track = name
|
||||
*/
|
||||
SortedSet<LogEntry> getTrackHistory(String name);
|
||||
|
||||
/**
|
||||
* Gets the track history content, separated by pages
|
||||
* @param pageNo the page number
|
||||
* @param name the name of the acted track to filter by
|
||||
* @return the page content
|
||||
*/
|
||||
SortedMap<Integer, LogEntry> getTrackHistory(int pageNo, String name);
|
||||
|
||||
/**
|
||||
* @param name the name to filter by
|
||||
* @return the max page number allowed in the {@link #getTrackHistory(int, String)} method
|
||||
*/
|
||||
int getTrackHistoryMaxPages(String name);
|
||||
|
||||
/**
|
||||
* @param query the query to filter by
|
||||
* @return all content in this log where the content matches query
|
||||
*/
|
||||
SortedSet<LogEntry> getSearch(String query);
|
||||
|
||||
/**
|
||||
* Gets the search content, separated by pages
|
||||
* @param pageNo the page number
|
||||
* @param query the query to filter by
|
||||
* @return the page content
|
||||
*/
|
||||
SortedMap<Integer, LogEntry> getSearch(int pageNo, String query);
|
||||
|
||||
/**
|
||||
* @param query the query to filter by
|
||||
* @return the max page number allowed in the {@link #getSearch(int, String)} method
|
||||
*/
|
||||
int getSearchMaxPages(String query);
|
||||
}
|
||||
@@ -24,6 +24,10 @@ package me.lucko.luckperms.api;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents a single entry in a log
|
||||
*/
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
public class LogEntry implements Comparable<LogEntry> {
|
||||
public static LogEntryBuilder builder() {
|
||||
return new LogEntryBuilder();
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
/**
|
||||
* A wrapper class for platform logger instances.
|
||||
* A wrapper interface for platform logger instances.
|
||||
*
|
||||
* <p> Bukkit/Bungee both use java.util.logging, and Sponge uses org.slf4j. This class wraps those classes so the commons
|
||||
* module can access a logger.
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextListener;
|
||||
import me.lucko.luckperms.api.context.IContextCalculator;
|
||||
import me.lucko.luckperms.api.event.LPListener;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -29,7 +31,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* The root Api interface in LuckPerms
|
||||
* The root API interface in LuckPerms
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface LuckPermsApi {
|
||||
@@ -39,20 +41,34 @@ public interface LuckPermsApi {
|
||||
*/
|
||||
void runUpdateTask();
|
||||
|
||||
/**
|
||||
* @return the version of the API running on the platform
|
||||
* @since 2.6
|
||||
*/
|
||||
double getApiVersion();
|
||||
|
||||
/**
|
||||
* @return the version of the plugin running on the platform
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* @return the platform LuckPerms is running on
|
||||
* @since 2.7
|
||||
*/
|
||||
PlatformType getPlatformType();
|
||||
|
||||
/**
|
||||
* Registers a listener to be sent LuckPerms events
|
||||
* @param listener the listener instance
|
||||
* @throws NullPointerException if the listener is null
|
||||
*/
|
||||
void registerListener(LPListener listener);
|
||||
|
||||
/**
|
||||
* Unregisters a previously registered listener from the EventBus
|
||||
* @param listener the listener instance to unregister
|
||||
* @throws NullPointerException if the listener is null
|
||||
*/
|
||||
void unregisterListener(LPListener listener);
|
||||
|
||||
@@ -63,11 +79,27 @@ public interface LuckPermsApi {
|
||||
LPConfiguration getConfiguration();
|
||||
|
||||
/**
|
||||
* Gets a wrapped {@link Datastore} instance, with somewhat limited access
|
||||
* @return a datastore instance
|
||||
* Gets a wrapped {@link Storage} instance.
|
||||
* @return a storage instance
|
||||
* @since 2.14
|
||||
*/
|
||||
Storage getStorage();
|
||||
|
||||
/**
|
||||
* Gets a wrapped Datastore instance.
|
||||
* @return a datastore instance
|
||||
* @deprecated in favour of {@link #getStorage()}
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
Datastore getDatastore();
|
||||
|
||||
/**
|
||||
* Gets the messaging service in use on the platform, if present.
|
||||
* @return an optional that may contain a messaging service instance.
|
||||
*/
|
||||
Optional<MessagingService> getMessagingService();
|
||||
|
||||
/**
|
||||
* Gets the {@link Logger} wrapping used by the platform
|
||||
* @return the logger instance
|
||||
@@ -76,7 +108,7 @@ public interface LuckPermsApi {
|
||||
|
||||
/**
|
||||
* Gets a wrapped {@link UuidCache} instance, providing read access to the LuckPerms internal uuid caching system
|
||||
* @return a uuidcache instance
|
||||
* @return a uuid cache instance
|
||||
*/
|
||||
UuidCache getUuidCache();
|
||||
|
||||
@@ -84,6 +116,7 @@ public interface LuckPermsApi {
|
||||
* Gets a wrapped user object from the user storage
|
||||
* @param uuid the uuid of the user to get
|
||||
* @return a {@link User} object, if one matching the uuid is loaded, or null if not
|
||||
* @throws NullPointerException if the uuid is null
|
||||
*/
|
||||
User getUser(UUID uuid);
|
||||
|
||||
@@ -91,6 +124,7 @@ public interface LuckPermsApi {
|
||||
* Gets a wrapped user object from the user storage. This method does not return null, unlike {@link #getUser(UUID)}
|
||||
* @param uuid the uuid of the user to get
|
||||
* @return an optional {@link User} object
|
||||
* @throws NullPointerException if the uuid is null
|
||||
*/
|
||||
Optional<User> getUserSafe(UUID uuid);
|
||||
|
||||
@@ -98,6 +132,7 @@ public interface LuckPermsApi {
|
||||
* Gets a wrapped user object from the user storage
|
||||
* @param name the username of the user to get
|
||||
* @return a {@link User} object, if one matching the uuid is loaded, or null if not
|
||||
* @throws NullPointerException if the name is null
|
||||
*/
|
||||
User getUser(String name);
|
||||
|
||||
@@ -105,6 +140,7 @@ public interface LuckPermsApi {
|
||||
* Gets a wrapped user object from the user storage. This method does not return null, unlike {@link #getUser(String)}
|
||||
* @param name the username of the user to get
|
||||
* @return an optional {@link User} object
|
||||
* @throws NullPointerException if the name is null
|
||||
*/
|
||||
Optional<User> getUserSafe(String name);
|
||||
|
||||
@@ -118,13 +154,23 @@ public interface LuckPermsApi {
|
||||
* Check if a user is loaded in memory
|
||||
* @param uuid the uuid to check for
|
||||
* @return true if the user is loaded
|
||||
* @throws NullPointerException if the uuid is null
|
||||
*/
|
||||
boolean isUserLoaded(UUID uuid);
|
||||
|
||||
/**
|
||||
* Unload a user from the internal storage, if they're not currently online.
|
||||
* @param user the user to unload
|
||||
* @throws NullPointerException if the user is null
|
||||
* @since 2.6
|
||||
*/
|
||||
void cleanupUser(User user);
|
||||
|
||||
/**
|
||||
* Gets a wrapped group object from the group storage
|
||||
* @param name the name of the group to get
|
||||
* @return a {@link Group} object, if one matching the name exists, or null if not
|
||||
* @throws NullPointerException if the name is null
|
||||
*/
|
||||
Group getGroup(String name);
|
||||
|
||||
@@ -132,6 +178,7 @@ public interface LuckPermsApi {
|
||||
* Gets a wrapped group object from the group storage. This method does not return null, unlike {@link #getGroup}
|
||||
* @param name the name of the group to get
|
||||
* @return an optional {@link Group} object
|
||||
* @throws NullPointerException if the name is null
|
||||
*/
|
||||
Optional<Group> getGroupSafe(String name);
|
||||
|
||||
@@ -145,6 +192,7 @@ public interface LuckPermsApi {
|
||||
* Check if a group is loaded in memory
|
||||
* @param name the name to check for
|
||||
* @return true if the group is loaded
|
||||
* @throws NullPointerException if the name is null
|
||||
*/
|
||||
boolean isGroupLoaded(String name);
|
||||
|
||||
@@ -152,13 +200,15 @@ public interface LuckPermsApi {
|
||||
* Gets a wrapped track object from the track storage
|
||||
* @param name the name of the track to get
|
||||
* @return a {@link Track} object, if one matching the name exists, or null if not
|
||||
* @throws NullPointerException if the name is null
|
||||
*/
|
||||
Track getTrack(String name);
|
||||
|
||||
/**
|
||||
* Gets a wrapped tracj object from the track storage. This method does not return null, unlike {@link #getTrack}
|
||||
* Gets a wrapped track object from the track storage. This method does not return null, unlike {@link #getTrack}
|
||||
* @param name the name of the track to get
|
||||
* @return an optional {@link Track} object
|
||||
* @throws NullPointerException if the name is null
|
||||
*/
|
||||
Optional<Track> getTrackSafe(String name);
|
||||
|
||||
@@ -172,7 +222,32 @@ public interface LuckPermsApi {
|
||||
* Check if a track is loaded in memory
|
||||
* @param name the name to check for
|
||||
* @return true if the track is loaded
|
||||
* @throws NullPointerException if the name is null
|
||||
*/
|
||||
boolean isTrackLoaded(String name);
|
||||
|
||||
/**
|
||||
* Returns a permission builder instance
|
||||
* @param permission the main permission node to build
|
||||
* @return a {@link Node.Builder} instance
|
||||
* @throws IllegalArgumentException if the permission is invalid
|
||||
* @throws NullPointerException if the permission is null
|
||||
* @since 2.6
|
||||
*/
|
||||
Node.Builder buildNode(String permission) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Register a custom context calculator to the server
|
||||
* @param contextCalculator the context calculator to register. The type MUST be the player class of the platform.
|
||||
* @throws ClassCastException if the type is not the player class of the platform.
|
||||
*/
|
||||
void registerContextCalculator(IContextCalculator<?> contextCalculator);
|
||||
|
||||
/**
|
||||
* Registers a custom context listener to the server,
|
||||
* @param contextListener the context listener to register. The type MUST be the player class of the platform.
|
||||
* @throws ClassCastException if the type is not the player class of the platform.
|
||||
*/
|
||||
void registerContextListener(ContextListener<?> contextListener);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
/**
|
||||
* Exposes any networking provider being used on the platform. e.g. Redis
|
||||
* @since 2.14
|
||||
*/
|
||||
public interface MessagingService {
|
||||
|
||||
/**
|
||||
* Uses the messaging service to inform other servers about changes.
|
||||
* This will push the update asynchronously, and this method will return almost immediately.
|
||||
*/
|
||||
void pushUpdate();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.LuckPerms;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A collection of utilities to help retrieve meta values for {@link PermissionHolder}s
|
||||
* @since 2.7
|
||||
*/
|
||||
public class MetaUtils {
|
||||
|
||||
private MetaUtils(){}
|
||||
|
||||
/**
|
||||
* Escapes special characters used within LuckPerms, so the string can be saved without issues
|
||||
* @param s the string to escape
|
||||
* @return an escaped string
|
||||
* @throws NullPointerException if the string is null
|
||||
*/
|
||||
public static String escapeCharacters(String s) {
|
||||
if (s == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
s = s.replace(".", "{SEP}");
|
||||
s = s.replace("/", "{FSEP}");
|
||||
s = s.replace("$", "{DSEP}");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescapes special characters used within LuckPerms, the inverse of {@link #escapeCharacters(String)}
|
||||
* @param s the string to unescape
|
||||
* @return an unescaped string
|
||||
* @throws NullPointerException if the string is null
|
||||
*/
|
||||
public static String unescapeCharacters(String s) {
|
||||
if (s == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
s = s.replace("{SEP}", ".");
|
||||
s = s.replace("{FSEP}", "/");
|
||||
s = s.replace("{DSEP}", "$");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a meta value on a holder
|
||||
* @param holder the holder to apply the meta node to
|
||||
* @param server the server to apply the meta on, can be null
|
||||
* @param world the world to apply the meta on, can be null
|
||||
* @param node the meta node
|
||||
* @param value the meta value
|
||||
* @throws NullPointerException if the holder, node or value is null
|
||||
* @throws IllegalArgumentException if the node or value is empty
|
||||
*/
|
||||
public static void setMeta(PermissionHolder holder, String server, String world, String node, String value) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
|
||||
if (node == null) {
|
||||
throw new NullPointerException("node");
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
if (node.equals("")) {
|
||||
throw new IllegalArgumentException("node is empty");
|
||||
}
|
||||
|
||||
if (value.equals("")) {
|
||||
throw new IllegalArgumentException("value is empty");
|
||||
}
|
||||
|
||||
if (server == null || server.equals("")) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
node = escapeCharacters(node);
|
||||
value = escapeCharacters(value);
|
||||
|
||||
Set<Node> toRemove = new HashSet<>();
|
||||
for (Node n : holder.getEnduringPermissions()) {
|
||||
if (n.isMeta() && n.getMeta().getKey().equals(node)) {
|
||||
toRemove.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
for (Node n : toRemove) {
|
||||
try {
|
||||
holder.unsetPermission(n);
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
}
|
||||
|
||||
Node.Builder metaNode = LuckPerms.getApi().buildNode("meta." + node + "." + value).setValue(true);
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
metaNode.setServer(server);
|
||||
}
|
||||
if (world != null && !world.equals("")) {
|
||||
metaNode.setServer(server).setWorld(world);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(metaNode.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a meta value for the holder
|
||||
* @param holder the holder to get the meta from
|
||||
* @param server the server to retrieve the meta on, can be null
|
||||
* @param world the world to retrieve the meta on, can be null
|
||||
* @param node the node to get
|
||||
* @param defaultValue the default value to return if the node is not set
|
||||
* @param includeGlobal if global nodes should be considered when retrieving the meta
|
||||
* @return a meta string, or the default value if the user does not have the meta node
|
||||
* @throws NullPointerException if the holder or node is null
|
||||
* @throws IllegalArgumentException if the node is empty
|
||||
*/
|
||||
public static String getMeta(PermissionHolder holder, String server, String world, String node, String defaultValue, boolean includeGlobal) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
|
||||
if (server == null || server.equals("")) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
if (node == null) {
|
||||
throw new NullPointerException("node");
|
||||
}
|
||||
|
||||
if (node.equals("")) {
|
||||
throw new IllegalArgumentException("node is empty");
|
||||
}
|
||||
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
if (!n.shouldApplyOnServer(server, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
return unescapeCharacters(meta.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static void setChatMeta(boolean prefix, PermissionHolder holder, String value, int priority, String server, String world) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
|
||||
if (value == null || value.equals("")) {
|
||||
throw new IllegalArgumentException("value is null/empty");
|
||||
}
|
||||
|
||||
Node.Builder node = LuckPerms.getApi().buildNode(prefix ? "prefix" : "suffix" + "." + priority + "." + escapeCharacters(value));
|
||||
node.setValue(true);
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
node.setServer(server);
|
||||
}
|
||||
if (world != null && !world.equals("")) {
|
||||
node.setServer(server).setWorld(world);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(node.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a prefix to a holder on a specific server and world
|
||||
* @param holder the holder to set the prefix for
|
||||
* @param prefix the prefix value
|
||||
* @param priority the priority to set the prefix at
|
||||
* @param server the server to set the prefix on, can be null
|
||||
* @param world the world to set the prefix on, can be null
|
||||
* @throws NullPointerException if the holder is null
|
||||
* @throws IllegalArgumentException if the prefix is null or empty
|
||||
*/
|
||||
public static void setPrefix(PermissionHolder holder, String prefix, int priority, String server, String world) {
|
||||
setChatMeta(true, holder, prefix, priority, server, world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a suffix to a holder on a specific server and world
|
||||
* @param holder the holder to set the suffix for
|
||||
* @param suffix the suffix value
|
||||
* @param priority the priority to set the suffix at
|
||||
* @param server the server to set the suffix on, can be null
|
||||
* @param world the world to set the suffix on, can be null
|
||||
* @throws NullPointerException if the holder is null
|
||||
* @throws IllegalArgumentException if the suffix is null or empty
|
||||
*/
|
||||
public static void setSuffix(PermissionHolder holder, String suffix, int priority, String server, String world) {
|
||||
setChatMeta(false, holder, suffix, priority, server, world);
|
||||
}
|
||||
|
||||
private static String getChatMeta(boolean prefix, PermissionHolder holder, String server, String world, boolean includeGlobal) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
if (server == null) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
int priority = Integer.MIN_VALUE;
|
||||
String meta = null;
|
||||
for (Node n : holder.getAllNodes(Contexts.allowAll())) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
if (!n.shouldApplyOnServer(server, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix ? !n.isPrefix() : !n.isSuffix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> value = prefix ? n.getPrefix() : n.getSuffix();
|
||||
if (value.getKey() > priority) {
|
||||
meta = value.getValue();
|
||||
priority = value.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return meta == null ? "" : unescapeCharacters(meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a holders highest priority prefix, if they have one
|
||||
* @param holder the holder
|
||||
* @param server the server to retrieve the prefix on
|
||||
* @param world the world to retrieve the prefix on
|
||||
* @param includeGlobal if global nodes should be considered when retrieving the prefix
|
||||
* @return a prefix string, if the holder has one, or an empty string if not.
|
||||
* @throws NullPointerException if the holder is null
|
||||
*/
|
||||
public static String getPrefix(PermissionHolder holder, String server, String world, boolean includeGlobal) {
|
||||
return getChatMeta(true, holder, server, world, includeGlobal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a holders highest priority suffix, if they have one
|
||||
* @param holder the holder
|
||||
* @param server the server to retrieve the suffix on
|
||||
* @param world the world to retrieve the suffix on
|
||||
* @param includeGlobal if global nodes should be considered when retrieving the suffix
|
||||
* @return a suffix string, if the holder has one, or an empty string if not.
|
||||
* @throws NullPointerException if the holder is null
|
||||
*/
|
||||
public static String getSuffix(PermissionHolder holder, String server, String world, boolean includeGlobal) {
|
||||
return getChatMeta(false, holder, server, world, includeGlobal);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Represents an immutable node object
|
||||
* <p> Use {@link LuckPermsApi#buildNode(String)} to get an instance.
|
||||
* @since 2.6
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Node extends Map.Entry<String, Boolean> {
|
||||
|
||||
/**
|
||||
* @return the actual permission node
|
||||
*/
|
||||
String getPermission();
|
||||
|
||||
/**
|
||||
* Get what value the permission is set to. A negated node would return <code>false</code>.
|
||||
* @return the permission's value
|
||||
*/
|
||||
@Override
|
||||
Boolean getValue();
|
||||
|
||||
/**
|
||||
* @return the value of this node as a Tristate
|
||||
*/
|
||||
Tristate getTristate();
|
||||
|
||||
/**
|
||||
* @return true if the node is negated
|
||||
*/
|
||||
boolean isNegated();
|
||||
|
||||
/**
|
||||
* If this node is set to override explicitly.
|
||||
* This value does not persist across saves, and is therefore only useful for transient nodes
|
||||
* @return true if this node is set to override explicitly
|
||||
*/
|
||||
boolean isOverride();
|
||||
|
||||
/**
|
||||
* Gets the server this node applies on, if the node is server specific
|
||||
* @return an {@link Optional} containing the server, if one is defined
|
||||
*/
|
||||
Optional<String> getServer();
|
||||
|
||||
/**
|
||||
* Gets the world this node applies on, if the node is world specific
|
||||
* @return an {@link Optional} containing the world, if one is defined
|
||||
*/
|
||||
Optional<String> getWorld();
|
||||
|
||||
/**
|
||||
* @return true if this node is server specific
|
||||
*/
|
||||
boolean isServerSpecific();
|
||||
|
||||
/**
|
||||
* @return true if this node is server specific
|
||||
*/
|
||||
boolean isWorldSpecific();
|
||||
|
||||
/**
|
||||
* If this node should apply on a specific server
|
||||
* @param server the name of the server
|
||||
* @param includeGlobal if global permissions should apply
|
||||
* @param applyRegex if regex should be applied
|
||||
* @return true if the node should apply
|
||||
*/
|
||||
boolean shouldApplyOnServer(String server, boolean includeGlobal, boolean applyRegex);
|
||||
|
||||
/**
|
||||
* If this node should apply on a specific world
|
||||
* @param world the name of the world
|
||||
* @param includeGlobal if global permissions should apply
|
||||
* @param applyRegex if regex should be applied
|
||||
* @return true if the node should apply
|
||||
*/
|
||||
boolean shouldApplyOnWorld(String world, boolean includeGlobal, boolean applyRegex);
|
||||
|
||||
/**
|
||||
* If this node should apply in the given context
|
||||
* @param context the context key value pairs
|
||||
* @param worldAndServer if world and server contexts should be checked
|
||||
* @return true if the node should apply
|
||||
* @since 2.13
|
||||
*/
|
||||
boolean shouldApplyWithContext(ContextSet context, boolean worldAndServer);
|
||||
|
||||
/**
|
||||
* If this node should apply in the given context
|
||||
* @param context the context key value pairs
|
||||
* @return true if the node should apply
|
||||
* @since 2.13
|
||||
*/
|
||||
boolean shouldApplyWithContext(ContextSet context);
|
||||
|
||||
/**
|
||||
* If this node should apply in the given context
|
||||
* @param context the context key value pairs
|
||||
* @param worldAndServer if world and server contexts should be checked
|
||||
* @return true if the node should apply
|
||||
* @deprecated in favour of {@link #shouldApplyWithContext(ContextSet, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean shouldApplyWithContext(Map<String, String> context, boolean worldAndServer) {
|
||||
return shouldApplyWithContext(ContextSet.fromMap(context), worldAndServer);
|
||||
}
|
||||
|
||||
/**
|
||||
* If this node should apply in the given context
|
||||
* @param context the context key value pairs
|
||||
* @return true if the node should apply
|
||||
* @deprecated in favour of {@link #shouldApplyWithContext(ContextSet)}
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean shouldApplyWithContext(Map<String, String> context) {
|
||||
return shouldApplyWithContext(ContextSet.fromMap(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link #shouldApplyOnServer(String, boolean, boolean)}, except this method accepts a List
|
||||
* @param servers the list of servers
|
||||
* @param includeGlobal if global permissions should apply
|
||||
* @return true if the node should apply
|
||||
*/
|
||||
boolean shouldApplyOnAnyServers(List<String> servers, boolean includeGlobal);
|
||||
|
||||
/**
|
||||
* Similar to {@link #shouldApplyOnWorld(String, boolean, boolean)}, except this method accepts a List
|
||||
* @param worlds the list of world
|
||||
* @param includeGlobal if global permissions should apply
|
||||
* @return true if the node should apply
|
||||
*/
|
||||
boolean shouldApplyOnAnyWorlds(List<String> worlds, boolean includeGlobal);
|
||||
|
||||
/**
|
||||
* Resolves a list of wildcards that match this node
|
||||
* @param possibleNodes a list of possible permission nodes
|
||||
* @return a list of permissions that match this wildcard
|
||||
*/
|
||||
List<String> resolveWildcard(List<String> possibleNodes);
|
||||
|
||||
/**
|
||||
* Resolves any shorthand parts of this node and returns the full list
|
||||
* @return a list of full nodes
|
||||
*/
|
||||
List<String> resolveShorthand();
|
||||
|
||||
/**
|
||||
* @return true if this node will expire in the future
|
||||
*/
|
||||
boolean isTemporary();
|
||||
|
||||
/**
|
||||
* @return true if this node will not expire
|
||||
*/
|
||||
boolean isPermanent();
|
||||
|
||||
/**
|
||||
* @return the time in Unix time when this node will expire
|
||||
* @throws IllegalStateException if the node is not temporary
|
||||
*/
|
||||
long getExpiryUnixTime();
|
||||
|
||||
/**
|
||||
* @return the {@link Date} when this node will expire
|
||||
* @throws IllegalStateException if the node is not temporary
|
||||
*/
|
||||
Date getExpiry();
|
||||
|
||||
/**
|
||||
* @return the number of seconds until this permission will expire
|
||||
* @throws IllegalStateException if the node is not temporary
|
||||
*/
|
||||
long getSecondsTilExpiry();
|
||||
|
||||
/**
|
||||
* Return true if the node has expired.
|
||||
* This also returns false if the node is not temporary
|
||||
*
|
||||
* @return true if this node has expired
|
||||
*/
|
||||
boolean hasExpired();
|
||||
|
||||
/**
|
||||
* @return the extra contexts required for this node to apply
|
||||
* @deprecated in favour of {@link #getContexts()}
|
||||
*/
|
||||
@Deprecated
|
||||
default Map<String, String> getExtraContexts() {
|
||||
return getContexts().toMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the extra contexts required for this node to apply
|
||||
* @since 2.13
|
||||
*/
|
||||
ContextSet getContexts();
|
||||
|
||||
/**
|
||||
* Converts this node into a serialized form
|
||||
* @return a serialized node string
|
||||
*/
|
||||
String toSerializedNode();
|
||||
|
||||
/**
|
||||
* @return true if this is a group node
|
||||
*/
|
||||
boolean isGroupNode();
|
||||
|
||||
/**
|
||||
* @return the name of the group
|
||||
* @throws IllegalStateException if this is not a group node. See {@link #isGroupNode()}
|
||||
*/
|
||||
String getGroupName();
|
||||
|
||||
/**
|
||||
* @return true is this node is a wildcard node
|
||||
*/
|
||||
boolean isWildcard();
|
||||
|
||||
/**
|
||||
* Gets the level of this wildcard, higher is more specific
|
||||
* @return the wildcard level
|
||||
* @throws IllegalStateException if this is not a wildcard
|
||||
*/
|
||||
int getWildcardLevel();
|
||||
|
||||
/**
|
||||
* @return true if this node is a meta node
|
||||
*/
|
||||
boolean isMeta();
|
||||
|
||||
/**
|
||||
* Gets the meta value from this node
|
||||
* @return the meta value
|
||||
* @throws IllegalStateException if this node is not a meta node
|
||||
*/
|
||||
Map.Entry<String, String> getMeta();
|
||||
|
||||
/**
|
||||
* @return true if this node is a prefix node
|
||||
*/
|
||||
boolean isPrefix();
|
||||
|
||||
/**
|
||||
* Gets the prefix value from this node
|
||||
* @return the prefix value
|
||||
* @throws IllegalStateException if this node is a not a prefix node
|
||||
*/
|
||||
Map.Entry<Integer, String> getPrefix();
|
||||
|
||||
/**
|
||||
* @return true if this node is a suffix node
|
||||
*/
|
||||
boolean isSuffix();
|
||||
|
||||
/**
|
||||
* Gets the suffix value from this node
|
||||
* @return the suffix value
|
||||
* @throws IllegalStateException if this node is a not a suffix node
|
||||
*/
|
||||
Map.Entry<Integer, String> getSuffix();
|
||||
|
||||
/**
|
||||
* Checks if this Node is equal to another node
|
||||
* @param obj the other node
|
||||
* @return true if this node is equal to the other provided
|
||||
* @see #equalsIgnoringValue(Node) for a less strict implementation of this method
|
||||
*/
|
||||
boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the value
|
||||
* @param other the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
*/
|
||||
boolean equalsIgnoringValue(Node other);
|
||||
|
||||
/**
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the expiry time or value
|
||||
* @param other the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
*/
|
||||
boolean almostEquals(Node other);
|
||||
|
||||
/**
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the value or if the node is temporary
|
||||
* @param other the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
* @since 2.8
|
||||
*/
|
||||
boolean equalsIgnoringValueOrTemp(Node other);
|
||||
|
||||
/**
|
||||
* Builds a Node instance
|
||||
*/
|
||||
interface Builder {
|
||||
Builder setNegated(boolean negated);
|
||||
Builder setValue(boolean value);
|
||||
|
||||
/**
|
||||
* Warning: this value does not persist, and disappears when the holder is re-loaded.
|
||||
* It is therefore only useful for transient nodes.
|
||||
*/
|
||||
Builder setOverride(boolean override);
|
||||
|
||||
Builder setExpiry(long expireAt);
|
||||
Builder setWorld(String world);
|
||||
Builder setServer(String server) throws IllegalArgumentException;
|
||||
Builder withExtraContext(String key, String value);
|
||||
Builder withExtraContext(Map<String, String> map);
|
||||
Builder withExtraContext(Set<Map.Entry<String, String>> context);
|
||||
Builder withExtraContext(Map.Entry<String, String> entry);
|
||||
Builder withExtraContext(ContextSet set);
|
||||
Node build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,25 +27,108 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal PermissionHolder (user/group) instances
|
||||
*
|
||||
* <p> 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.
|
||||
* Interface for internal PermissionHolder (user/group) instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface PermissionHolder {
|
||||
|
||||
/**
|
||||
* @return the identifier for this object. either a uuid string or name
|
||||
* However, you should really just use {@link User#getUuid()}, {@link User#getName()} or {@link Group#getName()}
|
||||
*/
|
||||
String getObjectName();
|
||||
|
||||
/**
|
||||
* Gets an immutable Set of the objects permission nodes
|
||||
* @return an immutable set of permissions in priority order
|
||||
* @since 2.6
|
||||
*/
|
||||
SortedSet<? extends Node> getPermissions();
|
||||
|
||||
/**
|
||||
* Similar to {@link #getPermissions()}, except excluding transient permissions
|
||||
* @return a set of nodes
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getEnduringPermissions();
|
||||
|
||||
/**
|
||||
* Similar to {@link #getPermissions()}, except excluding non-transient permissions
|
||||
* @return a set of nodes
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getTransientPermissions();
|
||||
|
||||
|
||||
/**
|
||||
* Gets an immutable set of the nodes that this object has and inherits
|
||||
* @return an immutable set of permissions
|
||||
* @since 2.6
|
||||
* @deprecated in favour of {@link #getAllNodes(Contexts)}
|
||||
*/
|
||||
@Deprecated
|
||||
Set<Node> getAllNodes();
|
||||
|
||||
/**
|
||||
* Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context
|
||||
* Unlike {@link #getAllNodesFiltered(Contexts)}, this method will not filter individual nodes. The context is only
|
||||
* used to determine which groups should apply.
|
||||
* Nodes are sorted into priority order.
|
||||
* @param contexts the context for the lookup,
|
||||
* @return a mutable sorted set of permissions
|
||||
* @throws NullPointerException if the context is null
|
||||
* @since 2.11
|
||||
*/
|
||||
SortedSet<LocalizedNode> getAllNodes(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Gets a mutable set of the nodes that is objects has and inherits, filtered by context.
|
||||
* Unlike {@link #getAllNodes(Contexts)}, this method WILL filter individual nodes, and only return ones that fully
|
||||
* meet the context provided.
|
||||
* @param contexts the context for the lookup
|
||||
* @return a mutable set of permissions
|
||||
* @throws NullPointerException if the context is null
|
||||
* @since 2.11
|
||||
*/
|
||||
Set<LocalizedNode> getAllNodesFiltered(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Gets an immutable Map of the objects permission nodes
|
||||
* @return an immutable map of permissions
|
||||
* @deprecated in favour of {@link #getPermissions()}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, Boolean> getNodes();
|
||||
|
||||
/**
|
||||
* Checks to see if the object has a certain permission
|
||||
* @param node the node to check for
|
||||
* @return a Tristate for the holders permission status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 2.6
|
||||
*/
|
||||
Tristate hasPermission(Node node);
|
||||
|
||||
/**
|
||||
* Checks to see if the object has a certain permission
|
||||
* @param node the node to check for
|
||||
* @return a Tristate for the holders permission status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 2.6
|
||||
*/
|
||||
Tristate hasTransientPermission(Node node);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
*/
|
||||
boolean hasPermission(String node, boolean b);
|
||||
|
||||
@@ -54,26 +137,32 @@ public interface PermissionHolder {
|
||||
* @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
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
*/
|
||||
boolean hasPermission(String node, boolean b, String server);
|
||||
|
||||
/**
|
||||
* Checks to see the the object has a permission on a certain server
|
||||
* Checks to see the the object has a permission on a certain server and world
|
||||
* @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
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node, server or world is invalid
|
||||
*/
|
||||
boolean hasPermission(String node, boolean b, String server, String world);
|
||||
|
||||
/**
|
||||
* Checks to see the the object has a permission on a certain server
|
||||
* Checks to see the the object has a 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 has the permission
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
*/
|
||||
boolean hasPermission(String node, boolean b, boolean temporary);
|
||||
|
||||
@@ -83,26 +172,41 @@ public interface PermissionHolder {
|
||||
* @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
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
*/
|
||||
boolean hasPermission(String node, boolean b, String server, boolean temporary);
|
||||
|
||||
/**
|
||||
* Checks to see the the object has a permission on a certain server
|
||||
* Checks to see the the object has a permission on a certain server and world
|
||||
* @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
|
||||
* @return true if the object has the permission
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node, server or world is invalid
|
||||
*/
|
||||
boolean hasPermission(String node, boolean b, String server, String world, boolean temporary);
|
||||
|
||||
/**
|
||||
* Cheks to see if the object inherits a certain permission
|
||||
* @param node the node to check for
|
||||
* @return a Tristate for the holders inheritance status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 2.6
|
||||
*/
|
||||
Tristate inheritsPermission(Node node);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
*/
|
||||
boolean inheritsPermission(String node, boolean b);
|
||||
|
||||
@@ -111,175 +215,282 @@ public interface PermissionHolder {
|
||||
* @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
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
*/
|
||||
boolean inheritsPermission(String node, boolean b, String server);
|
||||
|
||||
/**
|
||||
* Checks to see the the object inherits a permission on a certain server
|
||||
* Checks to see the the object inherits a permission on a certain server and world
|
||||
* @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
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node server or world is invalid
|
||||
*/
|
||||
boolean inheritsPermission(String node, boolean b, String server, String world);
|
||||
|
||||
/**
|
||||
* Checks to see if the object inherits a certain permission
|
||||
* Checks to see if the object inherits a 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
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
*/
|
||||
boolean inheritsPermission(String node, boolean b, boolean temporary);
|
||||
|
||||
/**
|
||||
* Checks to see if the object inherits a certain permission
|
||||
* Checks to see if 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 temporary if the permission is temporary
|
||||
* @return true if the user inherits the permission
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
*/
|
||||
boolean inheritsPermission(String node, boolean b, String server, boolean temporary);
|
||||
|
||||
/**
|
||||
* Checks to see if the object inherits a certain permission
|
||||
* Checks to see if the object inherits a permission on a certain server and world
|
||||
* @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
|
||||
* @return true if the object inherits the permission
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node, server or world if invalid
|
||||
*/
|
||||
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
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 2.6
|
||||
*/
|
||||
void setPermission(Node node) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Sets a transient permission for the object
|
||||
*
|
||||
* <p> A transient node is a permission that does not persist.
|
||||
* Whenever a user logs out of the server, or the server restarts, this permission will disappear.
|
||||
* It is never saved to the datastore, and therefore will not apply on other servers.
|
||||
*
|
||||
* <p> This is useful if you want to temporarily set a permission for a user while they're online, but don't
|
||||
* want it to persist, and have to worry about removing it when they log out.
|
||||
*
|
||||
* <p> For unsetting a transient permission, see {@link #unsetTransientPermission(Node)}
|
||||
* @param node The node to be set
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 2.6
|
||||
*/
|
||||
void setTransientPermission(Node node) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
* @deprecated in favour of {@link #setPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
void setPermission(String node, boolean value) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* Sets a permission for the object on a specific server
|
||||
* @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
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
* @deprecated in favour of {@link #setPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
void setPermission(String node, boolean value, String server) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* Sets a permission for the object on a specific server and world
|
||||
* @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
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node, server or world is invalid
|
||||
* @deprecated in favour of {@link #setPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
void setPermission(String node, boolean value, String server, String world) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* Sets a temporary 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
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid or if the expiry time is in the past
|
||||
* @deprecated in favour of {@link #setPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
void setPermission(String node, boolean value, long expireAt) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* Sets a temporary permission for the object on a specific server
|
||||
* @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
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node/server is invalid or if the expiry time is in the past
|
||||
* @deprecated in favour of {@link #setPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
void setPermission(String node, boolean value, String server, long expireAt) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Sets a permission for the object
|
||||
* Sets a temporary permission for the object on a specific server and world
|
||||
* @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
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node/server/world is invalid, or if the expiry time is in the past
|
||||
* @deprecated in favour of {@link #setPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
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
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 2.6
|
||||
*/
|
||||
void unsetPermission(Node node) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Unsets a transient permission for the object
|
||||
* @param node The node to be unset
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 2.6
|
||||
*/
|
||||
void unsetTransientPermission(Node node) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
* @deprecated in favour of {@link #unsetPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
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
|
||||
* @throws NullPointerException if the node is null
|
||||
* @throws IllegalArgumentException if the node is invalid
|
||||
* @deprecated in favour of {@link #unsetPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
void unsetPermission(String node) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* Unsets a permission for the object on a specific server
|
||||
* @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
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
* @deprecated in favour of {@link #unsetPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
void unsetPermission(String node, String server) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* Unsets a permission for the object on a specific server and world
|
||||
* @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
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node, server or world is invalid
|
||||
* @deprecated in favour of {@link #unsetPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
void unsetPermission(String node, String server, String world) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* Unsets a permission for the object on a specific server
|
||||
* @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
|
||||
* @throws NullPointerException if the node or server is null
|
||||
* @throws IllegalArgumentException if the node or server is invalid
|
||||
* @deprecated in favour of {@link #unsetPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
void unsetPermission(String node, String server, boolean temporary) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Unsets a permission for the object
|
||||
* Unsets a permission for the object on a specific server and world
|
||||
* @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
|
||||
* @throws NullPointerException if the node, server or world is null
|
||||
* @throws IllegalArgumentException if the node, server or world is invalid
|
||||
* @deprecated in favour of {@link #unsetPermission(Node)}
|
||||
*/
|
||||
@Deprecated
|
||||
void unsetPermission(String node, String server, String world, boolean temporary) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Gets the permissions and inherited permissions that apply to a specific server
|
||||
* Gets the permissions and inherited permissions that apply to a specific server and world
|
||||
* @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)
|
||||
* @param possibleNodes A list of possible permission nodes for wildcard permission handling
|
||||
* @return a {@link Map} of the permissions
|
||||
* @deprecated in favour of {@link #getPermissions(String, String, Map, boolean, List, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups, List<String> possibleNodes);
|
||||
|
||||
/**
|
||||
* Gets the permissions and inherited permissions that apply to a specific server
|
||||
* Gets the permissions and inherited permissions that apply to a specific server and world
|
||||
* @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
|
||||
* @deprecated in favour of {@link #getPermissions(String, String, Map, boolean, List, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups);
|
||||
|
||||
/**
|
||||
@@ -288,7 +499,9 @@ public interface PermissionHolder {
|
||||
* @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues)
|
||||
* @param possibleNodes A list of possible permission nodes for wildcard permission handling
|
||||
* @return a {@link Map} of the permissions
|
||||
* @deprecated in favour of {@link #getPermissions(String, String, Map, boolean, List, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups, List<String> possibleNodes);
|
||||
|
||||
/**
|
||||
@@ -296,21 +509,56 @@ public interface PermissionHolder {
|
||||
* @param server The server to get nodes for
|
||||
* @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues)
|
||||
* @return a {@link Map} of the permissions
|
||||
* @deprecated in favour of {@link #getPermissions(String, String, Map, boolean, List, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups);
|
||||
|
||||
/**
|
||||
* Processes the objects and returns the temporary ones.
|
||||
* @return a map of temporary nodes
|
||||
* Convert the holders nodes into a Map of permissions to be applied on the platform
|
||||
* @param server the server
|
||||
* @param world the world
|
||||
* @param extraContext any extra context to filter by
|
||||
* @param includeGlobal whether to include global nodes
|
||||
* @param possibleNodes a list of possible permissions for resolving wildcards
|
||||
* @param applyGroups if inherited group permissions should be included
|
||||
* @return a map of permissions
|
||||
* @since 2.6
|
||||
* @deprecated in favour of {@link #getAllNodesFiltered(Contexts)}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, Boolean> getPermissions(String server, String world, Map<String, String> extraContext, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups);
|
||||
|
||||
/**
|
||||
* Processes the nodes and returns the temporary ones.
|
||||
* @return a map of temporary nodes
|
||||
* @deprecated in favour of {@link #getTemporaryPermissionNodes()}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<Map.Entry<String, Boolean>, Long> getTemporaryNodes();
|
||||
|
||||
/**
|
||||
* Processes the objects and returns the non-temporary ones.
|
||||
* @return a map of permanent nodes
|
||||
* Processes the nodes and returns the temporary ones.
|
||||
* @return a set of temporary nodes
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getTemporaryPermissionNodes();
|
||||
|
||||
/**
|
||||
* Processes the nodes and returns the non-temporary ones.
|
||||
* @return a map of permanent nodes
|
||||
* @deprecated in favour of {@link #getPermanentPermissionNodes()}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, Boolean> getPermanentNodes();
|
||||
|
||||
/**
|
||||
* Processes the nodes and returns the non-temporary ones.
|
||||
* @return a set of permanent nodes
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getPermanentPermissionNodes();
|
||||
|
||||
/**
|
||||
* Removes temporary permissions that have expired
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
/**
|
||||
* Represents the platform type that LuckPerms is running on
|
||||
* @since 2.7
|
||||
*/
|
||||
public enum PlatformType {
|
||||
|
||||
BUKKIT("Bukkit"),
|
||||
BUNGEE("Bungee"),
|
||||
SPONGE("Sponge"),
|
||||
|
||||
/**
|
||||
* @since 2.9
|
||||
*/
|
||||
STANDALONE("Standalone");
|
||||
|
||||
private final String friendlyName;
|
||||
|
||||
PlatformType(String friendlyName) {
|
||||
this.friendlyName = friendlyName;
|
||||
}
|
||||
|
||||
public String getFriendlyName() {
|
||||
return friendlyName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Interface for the internal Storage instance
|
||||
*
|
||||
* All methods return {@link CompletableFuture}s, which will be populated with the result once the data has been loaded
|
||||
* asynchronously. Care should be taken when using the methods to ensure that the main server thread is not blocked.
|
||||
*
|
||||
* Methods such as {@link CompletableFuture#get()} and equivalent should <strong>not</strong> be called on the main server thread.
|
||||
* If you need to use the result of these operations on the main server thread, please register a callback using
|
||||
* {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)} and {@link #getSyncExecutor()}.
|
||||
*
|
||||
* @since 2.14
|
||||
*/
|
||||
public interface Storage {
|
||||
|
||||
/**
|
||||
* Get the name of the storage implementation.
|
||||
* @return the name of the implementation
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Return whether the storage instance is allowing logins on the platform.
|
||||
* @return true if logins are enabled
|
||||
*/
|
||||
boolean isAcceptingLogins();
|
||||
|
||||
/**
|
||||
* Returns an executor which will run all passed runnables on the main server thread.
|
||||
* @return an executor instance
|
||||
*/
|
||||
Executor getSyncExecutor();
|
||||
|
||||
/**
|
||||
* Returns an executor which will run all passed runnables asynchronously using the platforms scheduler & thread pools.
|
||||
* @return an executor instance
|
||||
*/
|
||||
Executor getAsyncExecutor();
|
||||
|
||||
/**
|
||||
* Saves an action to storage
|
||||
* @param entry the log entry to be saved
|
||||
* @return true if the operation completed successfully.
|
||||
* @throws NullPointerException if entry is null
|
||||
*/
|
||||
CompletableFuture<Boolean> logAction(LogEntry entry);
|
||||
|
||||
/**
|
||||
* Loads and returns the entire log from storage
|
||||
* @return a log instance, could be null if loading failed
|
||||
*/
|
||||
CompletableFuture<Log> getLog();
|
||||
|
||||
/**
|
||||
* Loads a user's data from the main storage into the plugins local storage.
|
||||
* @param uuid the uuid of the user to load
|
||||
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
|
||||
* @return if the operation completed successfully
|
||||
* @throws NullPointerException if uuid or username is null
|
||||
*/
|
||||
CompletableFuture<Boolean> loadUser(UUID uuid, String username);
|
||||
|
||||
/**
|
||||
* Saves a user object back to storage. You should call this after you make any changes to a user.
|
||||
* @param user the user to save
|
||||
* @return true if the operation completed successfully.
|
||||
* @throws NullPointerException if user is null
|
||||
* @throws IllegalStateException if the user instance was not obtained from LuckPerms.
|
||||
*/
|
||||
CompletableFuture<Boolean> saveUser(User user);
|
||||
|
||||
/**
|
||||
* Removes users from the main storage who are "default". This is called every time the plugin loads.
|
||||
* @return true if the operation completed successfully
|
||||
*/
|
||||
CompletableFuture<Boolean> cleanupUsers();
|
||||
|
||||
/**
|
||||
* Gets a set all "unique" user UUIDs.
|
||||
* "Unique" meaning the user isn't just a member of the "default" group.
|
||||
* @return a set of uuids, or null if the operation failed.
|
||||
*/
|
||||
CompletableFuture<Set<UUID>> getUniqueUsers();
|
||||
|
||||
/**
|
||||
* Creates and loads a group into the plugins local storage
|
||||
* @param name the name of the group
|
||||
* @return true if the operation completed successfully
|
||||
* @throws NullPointerException if name is null
|
||||
* @throws IllegalArgumentException if the name is invalid
|
||||
*/
|
||||
CompletableFuture<Boolean> createAndLoadGroup(String name);
|
||||
|
||||
/**
|
||||
* Loads a group into the plugins local storage.
|
||||
* @param name the name of the group
|
||||
* @return true if the operation completed successfully
|
||||
* @throws NullPointerException if name is null
|
||||
* @throws IllegalArgumentException if the name is invalid
|
||||
*/
|
||||
CompletableFuture<Boolean> loadGroup(String name);
|
||||
|
||||
/**
|
||||
* Loads all groups from the storage into memory
|
||||
* @return true if the operation completed successfully.
|
||||
*/
|
||||
CompletableFuture<Boolean> loadAllGroups();
|
||||
|
||||
/**
|
||||
* Saves a group back to storage. You should call this after you make any changes to a group.
|
||||
* @param group the group to save
|
||||
* @return true if the operation completed successfully.
|
||||
* @throws NullPointerException if group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
CompletableFuture<Boolean> saveGroup(Group group);
|
||||
|
||||
/**
|
||||
* Permanently deletes a group from storage.
|
||||
* @param group the group to delete
|
||||
* @return true if the operation completed successfully.
|
||||
* @throws NullPointerException if group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
CompletableFuture<Boolean> deleteGroup(Group group);
|
||||
|
||||
/**
|
||||
* Creates and loads a track into the plugins local storage
|
||||
* @param name the name of the track
|
||||
* @return true if the operation completed successfully
|
||||
* @throws NullPointerException if name is null
|
||||
* @throws IllegalArgumentException if the name is invalid
|
||||
*/
|
||||
CompletableFuture<Boolean> createAndLoadTrack(String name);
|
||||
|
||||
/**
|
||||
* Loads a track into the plugins local storage.
|
||||
* @param name the name of the track
|
||||
* @return true if the operation completed successfully
|
||||
* @throws NullPointerException if name is null
|
||||
* @throws IllegalArgumentException if the name is invalid
|
||||
*/
|
||||
CompletableFuture<Boolean> loadTrack(String name);
|
||||
|
||||
/**
|
||||
* Loads all tracks from the storage into memory
|
||||
* @return true if the operation completed successfully.
|
||||
*/
|
||||
CompletableFuture<Boolean> loadAllTracks();
|
||||
|
||||
/**
|
||||
* Saves a track back to storage. You should call this after you make any changes to a track.
|
||||
* @param track the track to save
|
||||
* @return true if the operation completed successfully.
|
||||
* @throws NullPointerException if track is null
|
||||
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
|
||||
*/
|
||||
CompletableFuture<Boolean> saveTrack(Track track);
|
||||
|
||||
/**
|
||||
* Permanently deletes a track from storage
|
||||
* @param track the track to delete
|
||||
* @return true if the operation completed successfully.
|
||||
* @throws NullPointerException if track is null
|
||||
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
|
||||
*/
|
||||
CompletableFuture<Boolean> deleteTrack(Track track);
|
||||
|
||||
/**
|
||||
* Saves UUID caching data to the global cache
|
||||
* @param username the users username
|
||||
* @param uuid the users mojang unique id
|
||||
* @return true if the operation completed successfully.
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @throws IllegalArgumentException if the username is invalid
|
||||
*/
|
||||
CompletableFuture<Boolean> saveUUIDData(String username, UUID uuid);
|
||||
|
||||
/**
|
||||
* Gets a UUID from a username
|
||||
* @param username the corresponding username
|
||||
* @return a uuid object, could be null
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @throws IllegalArgumentException if the username is invalid
|
||||
*/
|
||||
CompletableFuture<UUID> getUUID(String username);
|
||||
|
||||
}
|
||||
@@ -28,19 +28,20 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal Track instances
|
||||
*
|
||||
* <p> 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.
|
||||
* Interface for internal Track instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Track {
|
||||
|
||||
/**
|
||||
* @return the name of this track
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets an ordered list of the groups on this track
|
||||
* @return am ordered {@link List} of the groups on this track
|
||||
* Index 0 is the first/lowest group in (or start of) the track
|
||||
* @return an ordered {@link List} of the groups on this track
|
||||
*/
|
||||
List<String> getGroups();
|
||||
|
||||
@@ -55,14 +56,18 @@ public interface Track {
|
||||
* @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
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
String getNext(Group current) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Gets the group before the group provided
|
||||
* Gets the previous group on the track, before the one 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
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
String getPrevious(Group current) throws ObjectLacksException;
|
||||
|
||||
@@ -70,6 +75,8 @@ public interface Track {
|
||||
* 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
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
void appendGroup(Group group) throws ObjectAlreadyHasException;
|
||||
|
||||
@@ -79,6 +86,8 @@ public interface Track {
|
||||
* @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
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
void insertGroup(Group group, int position) throws ObjectAlreadyHasException, IndexOutOfBoundsException;
|
||||
|
||||
@@ -86,6 +95,8 @@ public interface Track {
|
||||
* Removes a group from this track
|
||||
* @param group the group to remove
|
||||
* @throws ObjectLacksException if the group is not on this track
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
void removeGroup(Group group) throws ObjectLacksException;
|
||||
|
||||
@@ -93,6 +104,7 @@ public interface Track {
|
||||
* Removes a group from this track
|
||||
* @param group the group to remove
|
||||
* @throws ObjectLacksException if the group is not on this track
|
||||
* @throws NullPointerException if the group is null
|
||||
*/
|
||||
void removeGroup(String group) throws ObjectLacksException;
|
||||
|
||||
@@ -100,6 +112,8 @@ public interface Track {
|
||||
* Checks if a group features on this track
|
||||
* @param group the group to check
|
||||
* @return true if the group is on this track
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
boolean containsGroup(Group group);
|
||||
|
||||
@@ -107,6 +121,7 @@ public interface Track {
|
||||
* Checks if a group features on this track
|
||||
* @param group the group to check
|
||||
* @return true if the group is on this track
|
||||
* @throws NullPointerException if the group is null
|
||||
*/
|
||||
boolean containsGroup(String group);
|
||||
|
||||
|
||||
+16
-11
@@ -20,23 +20,28 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.users;
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.LPBungeePlugin;
|
||||
/**
|
||||
* Represents a permission value
|
||||
*/
|
||||
public enum Tristate {
|
||||
|
||||
import java.util.UUID;
|
||||
TRUE(true),
|
||||
FALSE(false),
|
||||
UNDEFINED(false);
|
||||
|
||||
public class BungeeUser extends User {
|
||||
BungeeUser(UUID uuid, LPBungeePlugin plugin) {
|
||||
super(uuid, plugin);
|
||||
private final boolean booleanValue;
|
||||
|
||||
Tristate(boolean booleanValue) {
|
||||
this.booleanValue = booleanValue;
|
||||
}
|
||||
|
||||
BungeeUser(UUID uuid, String username, LPBungeePlugin plugin) {
|
||||
super(uuid, username, plugin);
|
||||
public boolean asBoolean() {
|
||||
return booleanValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPermissions() {
|
||||
// Do nothing. Permissions are applied when needed in a listener.
|
||||
public static Tristate fromBoolean(boolean b) {
|
||||
return b ? TRUE : FALSE;
|
||||
}
|
||||
}
|
||||
@@ -22,17 +22,16 @@
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.caching.UserData;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal User instances
|
||||
*
|
||||
* <p> 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.
|
||||
* Interface for internal User instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface User extends PermissionHolder {
|
||||
@@ -55,20 +54,30 @@ public interface User extends PermissionHolder {
|
||||
|
||||
/**
|
||||
* Sets a users primary group
|
||||
* @param s the new primary group
|
||||
* @param group the new primary group
|
||||
* @throws ObjectAlreadyHasException if the user already has this set as their primary group
|
||||
* @throws IllegalStateException if the user is not a member of that group
|
||||
* @throws NullPointerException if the group is null
|
||||
*/
|
||||
void setPrimaryGroup(String s) throws ObjectAlreadyHasException;
|
||||
void setPrimaryGroup(String group) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Refresh and re-assign the users permissions
|
||||
*/
|
||||
void refreshPermissions();
|
||||
|
||||
/**
|
||||
* Gets the user's {@link UserData} cache, if they have one setup.
|
||||
* @return an optional, possibly containing the user's cached lookup data.
|
||||
* @since 2.13
|
||||
*/
|
||||
Optional<UserData> getUserDataCache();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @throws NullPointerException if the group is null
|
||||
*/
|
||||
boolean isInGroup(Group group);
|
||||
|
||||
@@ -77,15 +86,19 @@ public interface User extends PermissionHolder {
|
||||
* @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
|
||||
* @throws NullPointerException if the group or server is null
|
||||
* @throws IllegalArgumentException if the server is invalid
|
||||
*/
|
||||
boolean isInGroup(Group group, String server);
|
||||
|
||||
/**
|
||||
* Check to see if a user is a member of a group on a specific server
|
||||
* Check to see if a user is a member of a group on a specific server and world
|
||||
* @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
|
||||
* @throws NullPointerException if the group, server or world is null
|
||||
* @throws IllegalArgumentException if the server or world is invalid
|
||||
*/
|
||||
boolean isInGroup(Group group, String server, String world);
|
||||
|
||||
@@ -93,6 +106,8 @@ public interface User extends PermissionHolder {
|
||||
* 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
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
void addGroup(Group group) throws ObjectAlreadyHasException;
|
||||
|
||||
@@ -101,42 +116,57 @@ public interface User extends PermissionHolder {
|
||||
* @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
|
||||
* @throws NullPointerException if the group or server is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the server is invalid
|
||||
*/
|
||||
void addGroup(Group group, String server) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Add a user to a group on a specific server
|
||||
* Add a user to a group on a specific server and world
|
||||
* @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
|
||||
* @throws NullPointerException if the group, server or world is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the server or world is invalid
|
||||
*/
|
||||
void addGroup(Group group, String server, String world) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Add a user to a group on a specific server
|
||||
* Add a user to a group temporarily 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
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the expiry time is in the past
|
||||
*/
|
||||
void addGroup(Group group, long expireAt) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Add a user to a group on a specific server
|
||||
* Add a user to a group temporarily 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
|
||||
* @throws NullPointerException if the group or server is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the expiry time is in the past or the server is invalid
|
||||
*/
|
||||
void addGroup(Group group, String server, long expireAt) throws ObjectAlreadyHasException;
|
||||
|
||||
/**
|
||||
* Add a user to a group on a specific server
|
||||
* Add a user to a group temporarily on a specific server and world
|
||||
* @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
|
||||
* @throws NullPointerException if the group, server or world is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the expiry time is in the past or the server/world is invalid
|
||||
*/
|
||||
void addGroup(Group group, String server, String world, long expireAt) throws ObjectAlreadyHasException;
|
||||
|
||||
@@ -144,6 +174,8 @@ public interface User extends PermissionHolder {
|
||||
* 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
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
void removeGroup(Group group) throws ObjectLacksException;
|
||||
|
||||
@@ -152,42 +184,56 @@ public interface User extends PermissionHolder {
|
||||
* @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
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
void removeGroup(Group group, boolean temporary) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Remove the user from a group
|
||||
* Remove the user from a group on a specific server
|
||||
* @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
|
||||
* @throws NullPointerException if the group or server is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the server is invalid
|
||||
*/
|
||||
void removeGroup(Group group, String server) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Remove the user from a group
|
||||
* Remove the user from a group on a specific server and world
|
||||
* @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
|
||||
* @throws NullPointerException if the group, server or world is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the server or world is invalid
|
||||
*/
|
||||
void removeGroup(Group group, String server, String world) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Remove the user from a group
|
||||
* Remove the user from a group on a specific server
|
||||
* @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
|
||||
* @throws NullPointerException if the group or server is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the expiry time is in the past or the server is invalid
|
||||
*/
|
||||
void removeGroup(Group group, String server, boolean temporary) throws ObjectLacksException;
|
||||
|
||||
/**
|
||||
* Remove the user from a group
|
||||
* Remove the user from a group on a specific server and world
|
||||
* @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
|
||||
* @throws NullPointerException if the group, server or world is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
* @throws IllegalArgumentException if the expiry time is in the past or the server/world is invalid
|
||||
*/
|
||||
void removeGroup(Group group, String server, String world, boolean temporary) throws ObjectLacksException;
|
||||
|
||||
@@ -207,6 +253,8 @@ public interface User extends PermissionHolder {
|
||||
* @param server the server to check
|
||||
* @param world the world to check
|
||||
* @return a {@link List} of group names
|
||||
* @throws NullPointerException if the server or world is null
|
||||
* @throws IllegalArgumentException if the server or world is invalid
|
||||
*/
|
||||
List<String> getLocalGroups(String server, String world);
|
||||
|
||||
@@ -214,6 +262,8 @@ public interface User extends PermissionHolder {
|
||||
* 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
|
||||
* @throws NullPointerException if the server is null
|
||||
* @throws IllegalArgumentException if the server is invalid
|
||||
*/
|
||||
List<String> getLocalGroups(String server);
|
||||
|
||||
|
||||
@@ -25,16 +25,19 @@ package me.lucko.luckperms.api;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This UuidCache is a means of allowing users to have the same internal UUID across a network of offline mode servers
|
||||
* A UUID cache for online users, between external Mojang UUIDs, and internal LuckPerms UUIDs.
|
||||
*
|
||||
* <p> This UuidCache is a means of allowing users to have the same internal UUID across a network of offline mode servers
|
||||
* or mixed offline mode and online mode servers. Platforms running in offline mode generate a random UUID for a user when
|
||||
* they first join the server, but this UUID will then not be consistent across the network. LuckPerms will instead check
|
||||
* the datastore cache, to get a UUID for a user that is consistent across an entire network.
|
||||
*
|
||||
* <p> If you want to get a user object from the datastore using the api on a server in offline mode, you will need to use this cache,
|
||||
* OR use Datastore#getUUID, for users that are not online.
|
||||
* <p> If you want to get a user object from the Storage using the api on a server in offline mode, you will need to use this cache,
|
||||
* OR use Storage#getUUID, for users that are not online.
|
||||
*
|
||||
* <p> WARNING: THIS IS ONLY EFFECTIVE FOR ONLINE PLAYERS. USE THE DATASTORE METHODS FOR OFFLINE PLAYERS.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface UuidCache {
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.caching;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
|
||||
/**
|
||||
* Holds cached Meta lookup data for a specific set of contexts
|
||||
* @since 2.13
|
||||
*/
|
||||
public interface MetaData {
|
||||
|
||||
/**
|
||||
* Gets an immutable copy of the meta this user has
|
||||
* @return an immutable map of meta
|
||||
*/
|
||||
Map<String, String> getMeta();
|
||||
|
||||
/**
|
||||
* Gets an immutable sorted map of all of the prefixes the user has, whereby the first value is the highest priority prefix.
|
||||
* @return a sorted map of prefixes
|
||||
*/
|
||||
SortedMap<Integer, String> getPrefixes();
|
||||
|
||||
/**
|
||||
* Gets an immutable sorted map of all of the suffixes the user has, whereby the first value is the highest priority suffix.
|
||||
* @return a sorted map of suffixes
|
||||
*/
|
||||
SortedMap<Integer, String> getSuffixes();
|
||||
|
||||
/**
|
||||
* Gets the user's highest priority prefix, or null if the user has no prefixes
|
||||
* @return a prefix string, or null
|
||||
*/
|
||||
String getPrefix();
|
||||
|
||||
/**
|
||||
* Gets the user's highest priority suffix, or null if the user has no suffixes
|
||||
* @return a suffix string, or null
|
||||
*/
|
||||
String getSuffix();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.caching;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Holds cached Permission lookup data for a specific set of contexts
|
||||
* @since 2.13
|
||||
*/
|
||||
public interface PermissionData {
|
||||
|
||||
/**
|
||||
* Gets a permission value for the given permission node
|
||||
* @param permission the permission node
|
||||
* @return a tristate result
|
||||
* @throws NullPointerException if permission is null
|
||||
*/
|
||||
Tristate getPermissionValue(String permission);
|
||||
|
||||
/**
|
||||
* Invalidates the underlying permission calculator cache.
|
||||
* Can be called to allow for an update in defaults.
|
||||
*/
|
||||
void invalidateCache();
|
||||
|
||||
/**
|
||||
* Gets an immutable copy of the permission map backing the permission calculator
|
||||
* @return an immutable set of permissions
|
||||
*/
|
||||
Map<String, Boolean> getImmutableBacking();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.caching;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Holds cached permission and meta lookup data for a {@link me.lucko.luckperms.api.User}.
|
||||
* Data is only likely to be available for online users. All calls will account for inheritance, as well as any
|
||||
* default data provided by the platform. This calls are heavily cached and are therefore fast.
|
||||
*
|
||||
* @since 2.13
|
||||
*/
|
||||
public interface UserData {
|
||||
|
||||
/**
|
||||
* Gets PermissionData from the cache, given a specified context.
|
||||
* If the data is not cached, it is calculated. Therefore, this call could be costly.
|
||||
* @param contexts the contexts to get the permission data in
|
||||
* @return a permission data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
PermissionData getPermissionData(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Gets MetaData from the cache, given a specified context.
|
||||
* If the data is not cached, it is calculated. Therefore, this call could be costly.
|
||||
* @param contexts the contexts to get the permission data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
MetaData getMetaData(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates permission data, bypassing the cache.
|
||||
* @param contexts the contexts to get permission data in
|
||||
* @return a permission data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
PermissionData calculatePermissions(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates meta data, bypassing the cache.
|
||||
* @param contexts the contexts to get meta data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
MetaData calculateMeta(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates permission data and stores it in the cache. If there is already data cached for the given contexts,
|
||||
* and if the resultant output is different, the cached value is updated.
|
||||
* @param contexts the contexts to recalculate in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void recalculatePermissions(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates meta data and stores it in the cache. If there is already data cached for the given contexts,
|
||||
* and if the resultant output is different, the cached value is updated.
|
||||
* @param contexts the contexts to recalculate in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void recalculateMeta(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calls {@link #recalculatePermissions(Contexts)} for all current loaded contexts
|
||||
*/
|
||||
void recalculatePermissions();
|
||||
|
||||
/**
|
||||
* Calls {@link #recalculateMeta(Contexts)} for all current loaded contexts
|
||||
*/
|
||||
void recalculateMeta();
|
||||
|
||||
/**
|
||||
* Calls {@link #preCalculate(Contexts)} for the given contexts
|
||||
* @param contexts a set of contexts
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void preCalculate(Set<Contexts> contexts);
|
||||
|
||||
/**
|
||||
* Ensures that PermissionData and MetaData is cached for a context. If the cache does not contain any data for the
|
||||
* context, it will be calculated and saved.
|
||||
* @param contexts the contexts to pre-calculate for
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void preCalculate(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Invalidates all of the underlying Permission calculators.
|
||||
* Can be called to allow for an update in defaults.
|
||||
*/
|
||||
void invalidatePermissionCalculators();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* A simple implementation of the listener aspects of {@link IContextCalculator}
|
||||
* @param <T> the subject type
|
||||
*/
|
||||
public abstract class ContextCalculator<T> implements IContextCalculator<T> {
|
||||
private final List<ContextListener<T>> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
/**
|
||||
* Pushes an update to all registered {@link ContextListener}s.
|
||||
* Make sure any changes are applied internally before this method is called.
|
||||
* @param subject the subject that changed
|
||||
* @param before the context state before the change
|
||||
* @param current the context state after the change (now)
|
||||
* @throws NullPointerException if any parameters are null
|
||||
*/
|
||||
protected void pushUpdate(T subject, Map.Entry<String, String> before, Map.Entry<String, String> current) {
|
||||
if (subject == null) {
|
||||
throw new NullPointerException("subject");
|
||||
}
|
||||
if (before == null) {
|
||||
throw new NullPointerException("before");
|
||||
}
|
||||
if (current == null) {
|
||||
throw new NullPointerException("current");
|
||||
}
|
||||
|
||||
for (ContextListener<T> listener : listeners) {
|
||||
try {
|
||||
listener.onContextChange(subject, before, current);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception whilst passing context change to listener: " + listener);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(ContextListener<T> listener) {
|
||||
if (listener == null) {
|
||||
throw new NullPointerException("listener");
|
||||
}
|
||||
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Listens to context changes
|
||||
* @param <T> the subject type, Is ALWAYS the player class of the platform.
|
||||
*/
|
||||
public interface ContextListener<T> {
|
||||
|
||||
/**
|
||||
* Called whenever a context changes on the
|
||||
* @param subject the subject that had context changed
|
||||
* @param before the context state before the change
|
||||
* @param current the context state after the change (now)
|
||||
*/
|
||||
void onContextChange(T subject, Map.Entry<String, String> before, Map.Entry<String, String> current) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Holds contexts.
|
||||
* All contained contexts are immutable, and unlike {@link MutableContextSet}, contexts cannot be added or removed.
|
||||
*
|
||||
* @since 2.13
|
||||
*/
|
||||
public class ContextSet {
|
||||
|
||||
/**
|
||||
* Make a singleton ContextSet from a context pair
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return a new ContextSet containing one KV pair
|
||||
* @throws NullPointerException if key or value is null
|
||||
*/
|
||||
public static ContextSet singleton(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.add(key, value);
|
||||
return set.immutableCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ContextSet from an existing map
|
||||
* @param map the map to copy from
|
||||
* @return a new ContextSet representing the pairs from the map
|
||||
* @throws NullPointerException if the map is null
|
||||
*/
|
||||
public static ContextSet fromMap(Map<String, String> map) {
|
||||
if (map == null) {
|
||||
throw new NullPointerException("map");
|
||||
}
|
||||
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(map);
|
||||
return set.immutableCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ContextSet from an existing iterable of Map Entries
|
||||
* @param iterable the iterable to copy from
|
||||
* @return a new ContextSet representing the pairs in the iterable
|
||||
* @throws NullPointerException if the iterable is null
|
||||
*/
|
||||
public static ContextSet fromEntries(Iterable<Map.Entry<String, String>> iterable) {
|
||||
if (iterable == null) {
|
||||
throw new NullPointerException("iterable");
|
||||
}
|
||||
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(iterable);
|
||||
return set.immutableCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ContextSet from an existing set.
|
||||
* Only really useful for converting between mutable and immutable types.
|
||||
* @param contextSet the context set to copy from
|
||||
* @return a new ContextSet with the same content and the one provided
|
||||
* @throws NullPointerException if contextSet is null
|
||||
*/
|
||||
public static ContextSet fromSet(ContextSet contextSet) {
|
||||
if (contextSet == null) {
|
||||
throw new NullPointerException("contextSet");
|
||||
}
|
||||
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(contextSet.toSet());
|
||||
return set.immutableCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new empty ContextSet.
|
||||
* @return a new ContextSet
|
||||
*/
|
||||
public static ContextSet empty() {
|
||||
return new ContextSet();
|
||||
}
|
||||
|
||||
final Set<Map.Entry<String, String>> contexts;
|
||||
|
||||
public ContextSet() {
|
||||
this.contexts = new HashSet<>();
|
||||
}
|
||||
|
||||
protected ContextSet(Set<Map.Entry<String, String>> contexts) {
|
||||
this.contexts = contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if this set is in an immutable form
|
||||
* @return true if the set is immutable
|
||||
*/
|
||||
public boolean isImmutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the set is mutable, this method will return an immutable copy. Otherwise just returns itself.
|
||||
* @return an immutable ContextSet
|
||||
*/
|
||||
public ContextSet makeImmutable() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this ContextSet to an immutable {@link Set} of {@link Map.Entry}s.
|
||||
* @return an immutable set
|
||||
*/
|
||||
public Set<Map.Entry<String, String>> toSet() {
|
||||
synchronized (contexts) {
|
||||
return ImmutableSet.copyOf(contexts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this ContextSet to an immutable {@link Map}
|
||||
*
|
||||
* <b>NOTE: Use of this method may result in data being lost. ContextSets can contain lots of different values for
|
||||
* one key.</b>
|
||||
*
|
||||
* @return an immutable map
|
||||
*/
|
||||
public Map<String, String> toMap() {
|
||||
synchronized (contexts) {
|
||||
return ImmutableMap.copyOf(contexts.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the set contains at least one value for the given key.
|
||||
* @param key the key to check for
|
||||
* @return true if the set contains a value for the key
|
||||
* @throws NullPointerException if the key is null
|
||||
*/
|
||||
public boolean containsKey(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
for (Map.Entry<String, String> e : contexts) {
|
||||
if (e.getKey().equalsIgnoreCase(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a set of all of the values mapped to the given key
|
||||
* @param key the key to find values for
|
||||
* @return a set of values
|
||||
* @throws NullPointerException if the key is null
|
||||
*/
|
||||
public Set<String> getValues(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
return ImmutableSet.copyOf(contexts.stream()
|
||||
.filter(e -> e.getKey().equalsIgnoreCase(key))
|
||||
.map(Map.Entry::getValue)
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if thr set contains a given key mapped to a given value
|
||||
* @param key the key to look for
|
||||
* @param value the value to look for (case sensitive)
|
||||
* @return true if the set contains the KV pair
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public boolean has(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
for (Map.Entry<String, String> e : contexts) {
|
||||
if (!e.getKey().equalsIgnoreCase(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!e.getValue().equals(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #has(String, String)}, except ignores the case of the value.
|
||||
* @param key the key to look for
|
||||
* @param value the value to look for
|
||||
* @return true if the set contains the KV pair
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public boolean hasIgnoreCase(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
for (Map.Entry<String, String> e : contexts) {
|
||||
if (!e.getKey().equalsIgnoreCase(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!e.getValue().equalsIgnoreCase(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the set is empty
|
||||
* @return true if the set is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
synchronized (contexts) {
|
||||
return contexts.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of key-value context pairs in the set
|
||||
* @return the size of the set
|
||||
*/
|
||||
public int size() {
|
||||
synchronized (contexts) {
|
||||
return contexts.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof ContextSet)) return false;
|
||||
final ContextSet other = (ContextSet) o;
|
||||
|
||||
final Object thisContexts = this.contexts;
|
||||
final Object otherContexts = other.contexts;
|
||||
return thisContexts == null ? otherContexts == null : thisContexts.equals(otherContexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 59 + (this.contexts == null ? 43 : this.contexts.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ContextSet(contexts=" + this.contexts + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Calculates whether contexts are applicable to {@link T}
|
||||
*
|
||||
* <p>Somewhat inspired by the system used on Sponge.
|
||||
* @param <T> the subject type. Is ALWAYS the player class of the platform.
|
||||
*/
|
||||
public interface IContextCalculator<T> {
|
||||
|
||||
/**
|
||||
* Gives the subject all of the applicable contexts they meet
|
||||
* @param subject the subject to add contexts to
|
||||
* @param accumulator a map of contexts to add to
|
||||
* @return the map
|
||||
* @deprecated in favour of {@link #giveApplicableContext(Object, MutableContextSet)}. Older implementations of this interface
|
||||
* will still work, as the replacement method is given as a default, and falls back to using this method.
|
||||
*/
|
||||
@Deprecated
|
||||
default Map<String, String> giveApplicableContext(T subject, Map<String, String> accumulator) {
|
||||
MutableContextSet acc = new MutableContextSet();
|
||||
giveApplicableContext(subject, acc);
|
||||
|
||||
accumulator.putAll(acc.toMap());
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the subject all of the applicable contexts they meet
|
||||
*
|
||||
* <p><b>You MUST implement this method. The default is only provided for backwards compatibility with
|
||||
* {@link #giveApplicableContext(Object, Map)}.</b>
|
||||
*
|
||||
* @param subject the subject to add contexts to
|
||||
* @param accumulator a map of contexts to add to
|
||||
* @return the map
|
||||
* @since 2.13
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
default MutableContextSet giveApplicableContext(T subject, MutableContextSet accumulator) {
|
||||
Map<String, String> acc = new HashMap<>();
|
||||
giveApplicableContext(subject, acc);
|
||||
|
||||
accumulator.addAll(acc.entrySet());
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a context is applicable to a subject
|
||||
* @param subject the subject to check against
|
||||
* @param context the context to check for
|
||||
* @return true if met, or false if not. If this calculator does not calculate the given context, return false.
|
||||
*/
|
||||
boolean isContextApplicable(T subject, Map.Entry<String, String> context);
|
||||
|
||||
/**
|
||||
* Adds a listener to be called whenever a context handled by this calculator changes
|
||||
* @param listener the listener instance
|
||||
* @throws NullPointerException if listener is null
|
||||
*/
|
||||
void addListener(ContextListener<T> listener);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Holds contexts
|
||||
* All contained contexts are immutable, but contexts can be added or removed from the set.
|
||||
*
|
||||
* @since 2.13
|
||||
*/
|
||||
public class MutableContextSet extends ContextSet {
|
||||
|
||||
/**
|
||||
* Make a singleton MutableContextSet from a context pair
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return a new MutableContextSet containing one KV pair
|
||||
* @throws NullPointerException if key or value is null
|
||||
*/
|
||||
public static MutableContextSet singleton(String key, String value) {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.add(key, value);
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MutableContextSet from an existing map
|
||||
* @param map the map to copy from
|
||||
* @return a new MutableContextSet representing the pairs from the map
|
||||
* @throws NullPointerException if the map is null
|
||||
*/
|
||||
public static MutableContextSet fromMap(Map<String, String> map) {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(map);
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MutableContextSet from an existing iterable of Map Entries
|
||||
* @param iterable the iterable to copy from
|
||||
* @return a new MutableContextSet representing the pairs in the iterable
|
||||
* @throws NullPointerException if the iterable is null
|
||||
*/
|
||||
public static MutableContextSet fromEntries(Iterable<Map.Entry<String, String>> iterable) {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(iterable);
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new MutableContextSet from an existing set.
|
||||
* Only really useful for converting between mutable and immutable types.
|
||||
* @param contextSet the context set to copy from
|
||||
* @return a new MutableContextSet with the same content and the one provided
|
||||
* @throws NullPointerException if contextSet is null
|
||||
*/
|
||||
public static MutableContextSet fromSet(ContextSet contextSet) {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(contextSet.toSet());
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new empty MutableContextSet.
|
||||
* @return a new MutableContextSet
|
||||
*/
|
||||
public static MutableContextSet empty() {
|
||||
return new MutableContextSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextSet makeImmutable() {
|
||||
return immutableCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable copy of this set.
|
||||
* @return an immutable copy of this set
|
||||
*/
|
||||
public ContextSet immutableCopy() {
|
||||
synchronized (contexts) {
|
||||
return new ContextSet(new HashSet<>(contexts));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new key value pair to the set
|
||||
* @param key the key to add
|
||||
* @param value the value to add
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void add(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
contexts.add(Maps.immutableEntry(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new key value pair to the set
|
||||
* @param entry the entry to add
|
||||
* @throws NullPointerException if the entry is null
|
||||
*/
|
||||
public void add(Map.Entry<String, String> entry) {
|
||||
if (entry == null) {
|
||||
throw new NullPointerException("context");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
contexts.add(Maps.immutableEntry(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an iterable containing contexts to the set
|
||||
* @param iterable an iterable of key value context pairs
|
||||
* @throws NullPointerException if iterable is null
|
||||
*/
|
||||
public void addAll(Iterable<Map.Entry<String, String>> iterable) {
|
||||
if (iterable == null) {
|
||||
throw new NullPointerException("contexts");
|
||||
}
|
||||
|
||||
synchronized (this.contexts) {
|
||||
for (Map.Entry<String, String> e : iterable) {
|
||||
this.contexts.add(Maps.immutableEntry(e.getKey(), e.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the entry set of a map to the set
|
||||
* @param map the map to add from
|
||||
* @throws NullPointerException if the map is null
|
||||
*/
|
||||
public void addAll(Map<String, String> map) {
|
||||
if (map == null) {
|
||||
throw new NullPointerException("contexts");
|
||||
}
|
||||
addAll(map.entrySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds of of the values in another ContextSet to this set
|
||||
* @param contextSet the set to add from
|
||||
* @throws NullPointerException if the contextSet is null
|
||||
*/
|
||||
public void addAll(ContextSet contextSet) {
|
||||
if (contextSet == null) {
|
||||
throw new NullPointerException("contextSet");
|
||||
}
|
||||
|
||||
synchronized (this.contexts) {
|
||||
this.contexts.addAll(contextSet.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a key value pair from this set
|
||||
* @param key the key to remove
|
||||
* @param value the value to remove (case sensitive)
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void remove(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
contexts.removeIf(e -> e.getKey().equalsIgnoreCase(key) && e.getValue().equals(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #remove(String, String)}, except ignores the case of the value
|
||||
* @param key the key to remove
|
||||
* @param value the value to remove
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void removeIgnoreCase(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
contexts.removeIf(e -> e.getKey().equalsIgnoreCase(key) && e.getValue().equalsIgnoreCase(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all pairs with the given key
|
||||
* @param key the key to remove
|
||||
* @throws NullPointerException if the key is null
|
||||
*/
|
||||
public void removeAll(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
contexts.removeIf(e -> e.getKey().equalsIgnoreCase(key));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the set
|
||||
*/
|
||||
public void clear() {
|
||||
synchronized (contexts) {
|
||||
contexts.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof ContextSet)) return false;
|
||||
final ContextSet other = (ContextSet) o;
|
||||
|
||||
final Object thisContexts = this.contexts;
|
||||
final Object otherContexts = other.contexts;
|
||||
return thisContexts == null ? otherContexts == null : thisContexts.equals(otherContexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 59 + (this.contexts == null ? 43 : this.contexts.hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,8 +24,19 @@ package me.lucko.luckperms.api.data;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A callback used to wait for the completion of asynchronous operations.
|
||||
* All callbacks are ran on the main server thread.
|
||||
* @param <T> the return type
|
||||
* @deprecated in favour of {@link Consumer}
|
||||
*/
|
||||
@Deprecated
|
||||
public interface Callback<T> {
|
||||
|
||||
/**
|
||||
* Called when the operation completes.
|
||||
* @param t the return value, may be null
|
||||
*/
|
||||
void onComplete(T t);
|
||||
|
||||
static <T> Callback<T> empty() {
|
||||
@@ -46,4 +57,17 @@ public interface Callback<T> {
|
||||
return consumer::accept;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for converting old {@link Callback}s to use the new {@link me.lucko.luckperms.api.Storage} interface.
|
||||
* @param callback the callback to convert
|
||||
* @param <T> the return type
|
||||
* @return a consumer instance
|
||||
* @since 2.14
|
||||
* @deprecated in favour of just using {@link Consumer}s.
|
||||
*/
|
||||
@Deprecated
|
||||
static <T> Consumer<T> convertToConsumer(Callback<T> callback) {
|
||||
return callback::onComplete;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,10 @@
|
||||
|
||||
package me.lucko.luckperms.api.data;
|
||||
|
||||
/**
|
||||
* Represents the data section of the main LuckPerms configuration.
|
||||
* All methods could return null.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public interface DatastoreConfiguration extends MySQLConfiguration {
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.event;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
|
||||
/**
|
||||
* @since 2.6
|
||||
*/
|
||||
public class AbstractPermissionEvent extends TargetedEvent<PermissionHolder> {
|
||||
|
||||
private final Node node;
|
||||
|
||||
protected AbstractPermissionEvent(String eventName, PermissionHolder target, Node node) {
|
||||
super(eventName, target);
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public Node getNode() {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@@ -47,8 +47,16 @@ public class AbstractPermissionRemoveEvent extends TargetedEvent<PermissionHolde
|
||||
return Optional.ofNullable(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #isTemporary()}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean getTemporary() {
|
||||
return temporary;
|
||||
}
|
||||
|
||||
public boolean isTemporary() {
|
||||
return temporary;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,7 +22,10 @@
|
||||
|
||||
package me.lucko.luckperms.api.event;
|
||||
|
||||
public class CancellableEvent extends LPEvent {
|
||||
/**
|
||||
* Event that allows listeners to set the cancelled state of an event.
|
||||
*/
|
||||
public abstract class CancellableEvent extends LPEvent {
|
||||
|
||||
private boolean cancelled = false;
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ package me.lucko.luckperms.api.event;
|
||||
|
||||
import me.lucko.luckperms.api.LuckPermsApi;
|
||||
|
||||
/**
|
||||
* Abstract LuckPerms Event class.
|
||||
*/
|
||||
public abstract class LPEvent {
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
|
||||
package me.lucko.luckperms.api.event;
|
||||
|
||||
/**
|
||||
* Represents an event acting upon a target
|
||||
* @param <T> the target type
|
||||
*/
|
||||
public class TargetedEvent<T> extends LPEvent {
|
||||
|
||||
private final T target;
|
||||
|
||||
@@ -24,6 +24,9 @@ package me.lucko.luckperms.api.event;
|
||||
|
||||
import me.lucko.luckperms.api.User;
|
||||
|
||||
/**
|
||||
* Represents an event acting upon a user.
|
||||
*/
|
||||
public class UserEvent extends LPEvent {
|
||||
|
||||
private final User user;
|
||||
|
||||
@@ -26,8 +26,14 @@ import me.lucko.luckperms.api.Group;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
import me.lucko.luckperms.api.event.AbstractPermissionAddEvent;
|
||||
|
||||
/**
|
||||
* Called whenever a user or group is added to / starts to inherit another group
|
||||
*/
|
||||
public class GroupAddEvent extends AbstractPermissionAddEvent {
|
||||
|
||||
/**
|
||||
* The group being added to the target
|
||||
*/
|
||||
private final Group group;
|
||||
|
||||
public GroupAddEvent(PermissionHolder target, Group group, String server, String world, long expiry) {
|
||||
|
||||
@@ -25,8 +25,15 @@ package me.lucko.luckperms.api.event.events;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
import me.lucko.luckperms.api.event.AbstractPermissionRemoveEvent;
|
||||
|
||||
/**
|
||||
* Called whenever a user or group is removed from / stops inheriting another group
|
||||
*/
|
||||
public class GroupRemoveEvent extends AbstractPermissionRemoveEvent {
|
||||
|
||||
/**
|
||||
* The name of group being removed from the target.
|
||||
* Be aware that this group may have already been deleted, and and instance may therefore not exist internally.
|
||||
*/
|
||||
private final String group;
|
||||
|
||||
public GroupRemoveEvent(PermissionHolder target, String group, String server, String world, boolean temporary) {
|
||||
|
||||
@@ -25,8 +25,16 @@ package me.lucko.luckperms.api.event.events;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.api.event.CancellableEvent;
|
||||
|
||||
/**
|
||||
* Called before a LogEntry is broadcasted to players only with the notify permission.
|
||||
* The log entry will still be recorded in the datastore, regardless of the cancellation state of this event.
|
||||
* Cancelling this event only stops the broadcast.
|
||||
*/
|
||||
public class LogNotifyEvent extends CancellableEvent {
|
||||
|
||||
/**
|
||||
* The log entry to be broadcasted
|
||||
*/
|
||||
private final LogEntry entry;
|
||||
|
||||
public LogNotifyEvent(LogEntry entry) {
|
||||
|
||||
@@ -25,6 +25,11 @@ package me.lucko.luckperms.api.event.events;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
import me.lucko.luckperms.api.event.TargetedEvent;
|
||||
|
||||
/**
|
||||
* Called when a permission expires for an object.
|
||||
* @deprecated in favour of {@link PermissionNodeExpireEvent}
|
||||
*/
|
||||
@Deprecated
|
||||
public class PermissionExpireEvent extends TargetedEvent<PermissionHolder> {
|
||||
|
||||
private final String node;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.event.events;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
import me.lucko.luckperms.api.event.AbstractPermissionEvent;
|
||||
|
||||
/**
|
||||
* Called when a temporary permission node expires
|
||||
* @since 2.6
|
||||
*/
|
||||
public class PermissionNodeExpireEvent extends AbstractPermissionEvent {
|
||||
public PermissionNodeExpireEvent(PermissionHolder target, Node node) {
|
||||
super("Permission Node Expire Event", target, node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.event.events;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
import me.lucko.luckperms.api.event.AbstractPermissionEvent;
|
||||
|
||||
/**
|
||||
* Called when a permission node is set on a holder
|
||||
* @since 2.6
|
||||
*/
|
||||
public class PermissionNodeSetEvent extends AbstractPermissionEvent {
|
||||
public PermissionNodeSetEvent(PermissionHolder target, Node node) {
|
||||
super("Permission Node Set Event", target, node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.event.events;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
import me.lucko.luckperms.api.event.AbstractPermissionEvent;
|
||||
|
||||
/**
|
||||
* Called when a permission node is unset from a holder
|
||||
* @since 2.6
|
||||
*/
|
||||
public class PermissionNodeUnsetEvent extends AbstractPermissionEvent {
|
||||
public PermissionNodeUnsetEvent(PermissionHolder target, Node node) {
|
||||
super("Permission Node Unset Event", target, node);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,11 @@ import me.lucko.luckperms.api.event.AbstractPermissionAddEvent;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Called whenever a user or group has a permission set.
|
||||
* @deprecated in favour of {@link PermissionNodeSetEvent}
|
||||
*/
|
||||
@Deprecated
|
||||
public class PermissionSetEvent extends AbstractPermissionAddEvent {
|
||||
|
||||
private final String node;
|
||||
|
||||
@@ -25,6 +25,11 @@ package me.lucko.luckperms.api.event.events;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
import me.lucko.luckperms.api.event.AbstractPermissionRemoveEvent;
|
||||
|
||||
/**
|
||||
* Called whenever a user or group has a permission unset.
|
||||
* @deprecated in favour of {@link PermissionNodeUnsetEvent}
|
||||
*/
|
||||
@Deprecated
|
||||
public class PermissionUnsetEvent extends AbstractPermissionRemoveEvent {
|
||||
|
||||
private final String node;
|
||||
|
||||
@@ -24,6 +24,9 @@ package me.lucko.luckperms.api.event.events;
|
||||
|
||||
import me.lucko.luckperms.api.event.LPEvent;
|
||||
|
||||
/**
|
||||
* Called after the sync task has ran.
|
||||
*/
|
||||
public class PostSyncEvent extends LPEvent {
|
||||
|
||||
public PostSyncEvent() {
|
||||
|
||||
@@ -24,6 +24,10 @@ package me.lucko.luckperms.api.event.events;
|
||||
|
||||
import me.lucko.luckperms.api.event.CancellableEvent;
|
||||
|
||||
/**
|
||||
* Called before the sync task is about to run.
|
||||
* Set this event to cancelled to prevent the sync task from running.
|
||||
*/
|
||||
public class PreSyncEvent extends CancellableEvent {
|
||||
|
||||
public PreSyncEvent() {
|
||||
|
||||
@@ -26,6 +26,9 @@ import me.lucko.luckperms.api.Track;
|
||||
import me.lucko.luckperms.api.User;
|
||||
import me.lucko.luckperms.api.event.TrackEvent;
|
||||
|
||||
/**
|
||||
* Called whenever a user is demoted down a track
|
||||
*/
|
||||
public class UserDemoteEvent extends TrackEvent {
|
||||
|
||||
public UserDemoteEvent(Track track, User user, String from, String to) {
|
||||
|
||||
@@ -27,7 +27,10 @@ import me.lucko.luckperms.api.event.LPEvent;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This event is fired before the player has actually joined the game on the async login / auth event.
|
||||
* Called when the user logs into the network for the first time.
|
||||
* Particularly useful for networks with multiple lobbies, who want to welcome a user when they join for the first time.
|
||||
*
|
||||
* <p>This event is fired before the player has actually joined the game on the async login / auth event.
|
||||
* If you want to do something with the user, store the UUID in a set, and then check the set in the PlayerJoinEvent o.e.
|
||||
*/
|
||||
public class UserFirstLoginEvent extends LPEvent {
|
||||
|
||||
@@ -25,6 +25,10 @@ package me.lucko.luckperms.api.event.events;
|
||||
import me.lucko.luckperms.api.User;
|
||||
import me.lucko.luckperms.api.event.UserEvent;
|
||||
|
||||
/**
|
||||
* Called after a user has their permissions refreshed.
|
||||
* If you cache user permissions within your own plugin, it's a good idea to update said cache whenever this event is called.
|
||||
*/
|
||||
public class UserPermissionRefreshEvent extends UserEvent {
|
||||
|
||||
public UserPermissionRefreshEvent(User user) {
|
||||
|
||||
@@ -26,6 +26,9 @@ import me.lucko.luckperms.api.Track;
|
||||
import me.lucko.luckperms.api.User;
|
||||
import me.lucko.luckperms.api.event.TrackEvent;
|
||||
|
||||
/**
|
||||
* Called whenever a user is promoted up a track
|
||||
*/
|
||||
public class UserPromoteEvent extends TrackEvent {
|
||||
|
||||
public UserPromoteEvent(Track track, User user, String from, String to) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.exceptions;
|
||||
|
||||
/**
|
||||
* Thrown when a permission holding object doesn't / already has a permission or isn't / is already is a member of a group
|
||||
* @since 2.7
|
||||
*/
|
||||
public abstract class MembershipException extends Exception {
|
||||
}
|
||||
@@ -26,5 +26,5 @@ package me.lucko.luckperms.exceptions;
|
||||
* Thrown when a permission holding object already has a permission, is already a member of a group, or when a track
|
||||
* already contains a group.
|
||||
*/
|
||||
public class ObjectAlreadyHasException extends Exception {
|
||||
public class ObjectAlreadyHasException extends MembershipException {
|
||||
}
|
||||
@@ -26,5 +26,5 @@ package me.lucko.luckperms.exceptions;
|
||||
* Thrown when a permission holding object does not already have a permission, is not already a member of a group,
|
||||
* or when a track doesn't contain a group.
|
||||
*/
|
||||
public class ObjectLacksException extends Exception {
|
||||
public class ObjectLacksException extends MembershipException {
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
<?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.luckperms</groupId>
|
||||
<version>2.14-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>luckperms-bukkit-legacy</artifactId>
|
||||
<build>
|
||||
<defaultGoal>clean package</defaultGoal>
|
||||
<finalName>LuckPerms-bukkit-legacy-${release.version}.${git.closest.tag.commit.count}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<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>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.xerial:*</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.slf4j</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.slf4j</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.zaxxer.hikari</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mongodb</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bson</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.common</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.guava</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.gson</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.gson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>redis.clients.jedis</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.jedis.jedis</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>redis.clients.util</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.jedis.util</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.apache.commons.pool2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.jedis.pool2</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>revision</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<injectAllReactorProjects>true</injectAllReactorProjects>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- LuckPerms Bukkit -->
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-bukkit</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Shade gson and guava, as they are not included in earlier Bukkit releases -->
|
||||
<!-- gson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- guava -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>19.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,52 @@
|
||||
<?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.luckperms</groupId>
|
||||
<version>2.14-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>luckperms-bukkit-placeholders</artifactId>
|
||||
<build>
|
||||
<finalName>LuckPermsPlaceholderExpansion</finalName>
|
||||
<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>
|
||||
|
||||
<dependencies>
|
||||
<!-- LuckPerms API -->
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-api</artifactId>
|
||||
<version>2.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- BukkitAPI -->
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- PlaceholderAPI -->
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.placeholders;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.clip.placeholderapi.util.TimeUtil;
|
||||
import me.lucko.luckperms.api.*;
|
||||
import me.lucko.luckperms.api.caching.UserData;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/*
|
||||
* PlaceholderAPI Expansion for LuckPerms, implemented using the LuckPerms API.
|
||||
*
|
||||
* Placeholders:
|
||||
* - group_name
|
||||
* - groups
|
||||
* - has_permission_<node>
|
||||
* - inherits_permission_<node>
|
||||
* - in_group_<name>
|
||||
* - inherits_group_<name>
|
||||
* - on_track_<track>
|
||||
* - expiry_time_<node>
|
||||
* - group_expiry_time_<group>
|
||||
* - prefix
|
||||
* - suffix
|
||||
* - meta_<node>
|
||||
*/
|
||||
public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
private static final String IDENTIFIER = "luckperms";
|
||||
private static final String PLUGIN_NAME = "LuckPerms";
|
||||
private static final String AUTHOR = "Luck";
|
||||
|
||||
private LuckPermsApi api = null;
|
||||
|
||||
@Override
|
||||
public boolean canRegister() {
|
||||
return Bukkit.getServicesManager().isProvidedFor(LuckPermsApi.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean register() {
|
||||
if (!canRegister()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
api = Bukkit.getServicesManager().getRegistration(LuckPermsApi.class).getProvider();
|
||||
return super.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "2.13";
|
||||
}
|
||||
|
||||
private Contexts makeContexts(Player player) {
|
||||
MutableContextSet contextSet = new MutableContextSet();
|
||||
contextSet.add("server", api.getConfiguration().getVaultServer());
|
||||
contextSet.add("world", player.getWorld().getName());// ignore world?
|
||||
return Contexts.of(contextSet.makeImmutable(), api.getConfiguration().getVaultIncludeGlobal(), true, true, true, true, player.isOp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onPlaceholderRequest(Player player, String identifier) {
|
||||
if (player == null || api == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
Optional<User> u = api.getUserSafe(api.getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (!u.isPresent()) {
|
||||
return "";
|
||||
}
|
||||
final User user = u.get();
|
||||
|
||||
Optional<UserData> d = user.getUserDataCache();
|
||||
if (!d.isPresent()) {
|
||||
return "";
|
||||
}
|
||||
final UserData data = d.get();
|
||||
|
||||
identifier = identifier.toLowerCase();
|
||||
|
||||
if (identifier.equalsIgnoreCase("group_name")) {
|
||||
return user.getPrimaryGroup();
|
||||
}
|
||||
|
||||
if (identifier.equalsIgnoreCase("groups")) {
|
||||
return user.getGroupNames().stream().collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
if (identifier.startsWith("has_permission_") && identifier.length() > "has_permission_".length()) {
|
||||
String node = identifier.substring("has_permission_".length());
|
||||
return formatBoolean(user.hasPermission(node, true));
|
||||
}
|
||||
|
||||
if (identifier.startsWith("inherits_permission_") && identifier.length() > "inherits_permission_".length()) {
|
||||
String node = identifier.substring("inherits_permission_".length());
|
||||
return formatBoolean(data.getPermissionData(makeContexts(player)).getPermissionValue(node).asBoolean());
|
||||
}
|
||||
|
||||
if (identifier.startsWith("in_group_") && identifier.length() > "in_group_".length()) {
|
||||
String groupName = identifier.substring("in_group_".length());
|
||||
return formatBoolean(user.getGroupNames().contains(groupName));
|
||||
}
|
||||
|
||||
if (identifier.startsWith("inherits_group_") && identifier.length() > "inherits_group_".length()) {
|
||||
String groupName = identifier.substring("inherits_group_".length());
|
||||
return formatBoolean(data.getPermissionData(makeContexts(player)).getPermissionValue("group." + groupName).asBoolean());
|
||||
}
|
||||
|
||||
if (identifier.startsWith("on_track_") && identifier.length() > "on_track_".length()) {
|
||||
String trackName = identifier.substring("on_track_".length());
|
||||
|
||||
Optional<Track> track = api.getTrackSafe(trackName);
|
||||
if (!track.isPresent()) return "";
|
||||
|
||||
return formatBoolean(track.get().containsGroup(user.getPrimaryGroup()));
|
||||
}
|
||||
|
||||
if (identifier.startsWith("expiry_time_") && identifier.length() > "expiry_time_".length()) {
|
||||
String node = identifier.substring("expiry_time_".length());
|
||||
long currentTime = System.currentTimeMillis() / 1000L;
|
||||
for (Node n : user.getTemporaryPermissionNodes()) {
|
||||
if (n.toSerializedNode().equalsIgnoreCase(node)) {
|
||||
return TimeUtil.getTime((int) (n.getExpiryUnixTime() - currentTime));
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
if (identifier.startsWith("group_expiry_time_") && identifier.length() > "group_expiry_time_".length()) {
|
||||
String node = "group." + identifier.substring("group_expiry_time_".length());
|
||||
long currentTime = System.currentTimeMillis() / 1000L;
|
||||
for (Node n : user.getTemporaryPermissionNodes()) {
|
||||
if (n.getPermission().equalsIgnoreCase(node)) {
|
||||
return TimeUtil.getTime((int) (n.getExpiryUnixTime() - currentTime));
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
if (identifier.equalsIgnoreCase("prefix")) {
|
||||
String prefix = data.calculateMeta(makeContexts(player)).getPrefix();
|
||||
if (prefix == null) {
|
||||
prefix = "";
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
if (identifier.equalsIgnoreCase("suffix")) {
|
||||
String suffix = data.calculateMeta(makeContexts(player)).getSuffix();
|
||||
if (suffix == null) {
|
||||
suffix = "";
|
||||
}
|
||||
return suffix;
|
||||
}
|
||||
|
||||
if (identifier.startsWith("meta_") && identifier.length() > "meta_".length()) {
|
||||
String node = identifier.substring("meta_".length());
|
||||
String meta = data.getMetaData(makeContexts(player)).getMeta().get(node);
|
||||
if (meta == null) {
|
||||
meta = "";
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return IDENTIFIER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlugin() {
|
||||
return PLUGIN_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
return AUTHOR;
|
||||
}
|
||||
|
||||
private static String formatBoolean(boolean b) {
|
||||
return b ? PlaceholderAPIPlugin.booleanTrue() : PlaceholderAPIPlugin.booleanFalse();
|
||||
}
|
||||
}
|
||||
+54
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.5-SNAPSHOT</version>
|
||||
<version>2.14-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -70,6 +70,18 @@
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>redis.clients.jedis</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.jedis.jedis</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>redis.clients.util</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.jedis.util</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.apache.commons.pool2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.jedis.pool2</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
@@ -129,5 +141,46 @@
|
||||
<version>1.16.10</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- **************Migration Plugins************** -->
|
||||
<dependency>
|
||||
<groupId>org.tyrannyofheaven.bukkit</groupId>
|
||||
<artifactId>zPermissions</artifactId>
|
||||
<version>1.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.tehkode</groupId>
|
||||
<artifactId>PermissionsEx</artifactId>
|
||||
<version>1.23</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.gravitydevelopment.updater</groupId>
|
||||
<artifactId>updater</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.cheesesoftware</groupId>
|
||||
<artifactId>PowerfulPermsAPI</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.anjocaido</groupId>
|
||||
<artifactId>GroupManager</artifactId>
|
||||
<version>1.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.bananaco</groupId>
|
||||
<artifactId>bpermissions-api</artifactId>
|
||||
<version>2.12</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.users.BukkitUser;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.AbstractListener;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.*;
|
||||
|
||||
class BukkitListener extends AbstractListener implements Listener {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
BukkitListener(LPBukkitPlugin plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
|
||||
if (!plugin.getDatastore().isAcceptingLogins()) {
|
||||
// Datastore is disabled, prevent players from joining the server
|
||||
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
onAsyncLogin(e.getUniqueId(), e.getName());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerLogin(PlayerLoginEvent e) {
|
||||
final Player player = e.getPlayer();
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
|
||||
if (user == null) {
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (user instanceof BukkitUser) {
|
||||
BukkitUser u = (BukkitUser) user;
|
||||
u.setAttachment(player.addAttachment(plugin));
|
||||
}
|
||||
|
||||
user.refreshPermissions();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent e) {
|
||||
// Refresh permissions again
|
||||
refreshPlayer(e.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
|
||||
refreshPlayer(e.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||
onLeave(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.LuckPermsApi;
|
||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||
import me.lucko.luckperms.api.vault.VaultHook;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import me.lucko.luckperms.core.UuidCache;
|
||||
import me.lucko.luckperms.data.Importer;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.runnables.ExpireTemporaryTask;
|
||||
import me.lucko.luckperms.runnables.UpdateTask;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.storage.StorageFactory;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.BukkitUserManager;
|
||||
import me.lucko.luckperms.users.UserManager;
|
||||
import me.lucko.luckperms.utils.LogFactory;
|
||||
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;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
private final Set<UUID> ignoringLogs = new HashSet<>();
|
||||
private LPConfiguration configuration;
|
||||
private UserManager userManager;
|
||||
private GroupManager groupManager;
|
||||
private TrackManager trackManager;
|
||||
private Datastore datastore;
|
||||
private UuidCache uuidCache;
|
||||
private ApiProvider apiProvider;
|
||||
private Logger log;
|
||||
private Importer importer;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
log = LogFactory.wrap(getLogger());
|
||||
|
||||
getLog().info("Loading configuration...");
|
||||
configuration = new BukkitConfig(this);
|
||||
|
||||
// register events
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new BukkitListener(this), this);
|
||||
|
||||
// register commands
|
||||
getLog().info("Registering commands...");
|
||||
BukkitCommand commandManager = new BukkitCommand(this);
|
||||
PluginCommand main = getServer().getPluginCommand("luckperms");
|
||||
main.setExecutor(commandManager);
|
||||
main.setTabCompleter(commandManager);
|
||||
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
|
||||
|
||||
datastore = StorageFactory.getDatastore(this, "h2");
|
||||
|
||||
getLog().info("Loading internal permission managers...");
|
||||
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
|
||||
userManager = new BukkitUserManager(this);
|
||||
groupManager = new GroupManager(this);
|
||||
trackManager = new TrackManager();
|
||||
importer = new Importer(commandManager);
|
||||
|
||||
// Run update task to refresh any online users
|
||||
getLog().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) {
|
||||
long ticks = mins * 60 * 20;
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, new UpdateTask(this), ticks, ticks);
|
||||
}
|
||||
|
||||
getServer().getScheduler().runTaskTimer(this, BukkitSenderFactory.get(), 1L, 1L);
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpireTemporaryTask(this), 60L, 60L);
|
||||
|
||||
// Provide vault support
|
||||
getLog().info("Attempting to hook into Vault...");
|
||||
try {
|
||||
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
|
||||
VaultHook.hook(this);
|
||||
getLog().info("Registered Vault permission & chat hook.");
|
||||
} else {
|
||||
getLog().info("Vault not found.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
getLog().severe("Error occurred whilst hooking into Vault.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
getLog().info("Registering API...");
|
||||
apiProvider = new ApiProvider(this);
|
||||
LuckPerms.registerProvider(apiProvider);
|
||||
getServer().getServicesManager().register(LuckPermsApi.class, apiProvider, this, ServicePriority.Normal);
|
||||
|
||||
getLog().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLog().info("Closing datastore...");
|
||||
datastore.shutdown();
|
||||
|
||||
getLog().info("Unregistering API...");
|
||||
LuckPerms.unregisterProvider();
|
||||
getServer().getServicesManager().unregisterAll(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
getServer().getScheduler().runTaskAsynchronously(this, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
getServer().getScheduler().runTask(this, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getMainDir() {
|
||||
return getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getPlayerStatus(UUID uuid) {
|
||||
return getServer().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getServer().getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPlayerList() {
|
||||
return getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getSenders() {
|
||||
return getServer().getOnlinePlayers().stream().map(p -> BukkitSenderFactory.get().wrap(p)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return BukkitSenderFactory.get().wrap(getServer().getConsoleSender());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPossiblePermissions() {
|
||||
final List<String> perms = new ArrayList<>();
|
||||
|
||||
getServer().getPluginManager().getPermissions().forEach(p -> {
|
||||
perms.add(p.getName());
|
||||
p.getChildren().keySet().forEach(perms::add);
|
||||
});
|
||||
|
||||
return perms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runUpdateTask() {
|
||||
getServer().getScheduler().runTaskAsynchronously(this, new UpdateTask(this));
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.vault;
|
||||
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
|
||||
/**
|
||||
* Dummy class for hooking with Vault plugins that need both Chat + Perms
|
||||
* This doesn't return anything useful, or change anything internally
|
||||
*
|
||||
* Registered on the lowest priority so other plugins can override
|
||||
*/
|
||||
class VaultChatHook extends Chat {
|
||||
|
||||
VaultChatHook(Permission perms) {
|
||||
super(perms);
|
||||
}
|
||||
|
||||
private void throwNotSupported() {
|
||||
// throw new UnsupportedOperationException("LuckPerms cannot perform this operation.");
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "LuckPerms";
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getPlayerPrefix(String world, String player) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void setPlayerPrefix(String world, String player, String prefix) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public String getPlayerSuffix(String world, String player) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void setPlayerSuffix(String world, String player, String suffix) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public String getGroupPrefix(String world, String group) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void setGroupPrefix(String world, String group, String prefix) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public String getGroupSuffix(String world, String group) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void setGroupSuffix(String world, String group, String suffix) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public int getPlayerInfoInteger(String world, String player, String node, int defaultValue) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setPlayerInfoInteger(String world, String player, String node, int value) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public int getGroupInfoInteger(String world, String group, String node, int defaultValue) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setGroupInfoInteger(String world, String group, String node, int value) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public double getPlayerInfoDouble(String world, String player, String node, double defaultValue) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setPlayerInfoDouble(String world, String player, String node, double value) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public double getGroupInfoDouble(String world, String group, String node, double defaultValue) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setGroupInfoDouble(String world, String group, String node, double value) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public boolean getPlayerInfoBoolean(String world, String player, String node, boolean defaultValue) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setPlayerInfoBoolean(String world, String player, String node, boolean value) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public boolean getGroupInfoBoolean(String world, String group, String node, boolean defaultValue) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setGroupInfoBoolean(String world, String group, String node, boolean value) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public String getPlayerInfoString(String world, String player, String node, String defaultValue) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setPlayerInfoString(String world, String player, String node, String value) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
public String getGroupInfoString(String world, String group, String node, String defaultValue) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setGroupInfoString(String world, String group, String node, String value) {
|
||||
throwNotSupported();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.vault;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
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() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean objectHas(String world, PermissionHolder 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, PermissionHolder 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, PermissionHolder 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(PermissionHolder t) {
|
||||
if (t instanceof User) {
|
||||
((User) t).refreshPermissions();
|
||||
plugin.getDatastore().saveUser(((User) t), Callback.empty());
|
||||
}
|
||||
if (t instanceof Group) {
|
||||
plugin.getDatastore().saveGroup(((Group) t), c -> plugin.runUpdateTask());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHas(String world, @NonNull String player, @NonNull String permission) {
|
||||
return objectHas(world, plugin.getUserManager().get(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAdd(String world, @NonNull String player, @NonNull String permission) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return objectAdd(world, user, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemove(String world, @NonNull String player, @NonNull String permission) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return objectRemove(world, user, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupHas(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
return objectHas(world, group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupAdd(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
return objectAdd(world, group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupRemove(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
return objectRemove(world, group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerInGroup(String world, @NonNull String player, @NonNull String group) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
final Group group1 = plugin.getGroupManager().get(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().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
final Group group = plugin.getGroupManager().get(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().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
final Group group = plugin.getGroupManager().get(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().get(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().get(player);
|
||||
return (user == null) ? null : user.getPrimaryGroup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return plugin.getGroupManager().getAll().keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGroupSupport() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.bukkit.calculators.AttachmentProcessor;
|
||||
import me.lucko.luckperms.bukkit.calculators.ChildProcessor;
|
||||
import me.lucko.luckperms.bukkit.calculators.DefaultsProcessor;
|
||||
import me.lucko.luckperms.bukkit.inject.Injector;
|
||||
import me.lucko.luckperms.bukkit.inject.LPPermissible;
|
||||
import me.lucko.luckperms.common.calculators.*;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class BukkitCalculatorFactory implements CalculatorFactory {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
@Override
|
||||
public PermissionCalculator build(Contexts contexts, User user) {
|
||||
UUID uuid = plugin.getUuidCache().getExternalUUID(user.getUuid());
|
||||
|
||||
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
|
||||
processors.add(new MapProcessor());
|
||||
processors.add(new ChildProcessor(plugin.getChildPermissionProvider()));
|
||||
processors.add(new AttachmentProcessor(() -> {
|
||||
LPPermissible permissible = Injector.getPermissible(uuid);
|
||||
return permissible == null ? null : permissible.getAttachmentPermissions();
|
||||
}));
|
||||
if (plugin.getConfiguration().isApplyingWildcards()) {
|
||||
processors.add(new WildcardProcessor());
|
||||
}
|
||||
if (plugin.getConfiguration().isApplyingRegex()) {
|
||||
processors.add(new RegexProcessor());
|
||||
}
|
||||
processors.add(new DefaultsProcessor(contexts.isOp(), plugin.getDefaultsProvider()));
|
||||
|
||||
return new PermissionCalculator(plugin, user.getName(), processors.build());
|
||||
}
|
||||
}
|
||||
+17
-6
@@ -20,10 +20,14 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Patterns;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -33,19 +37,26 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
class BukkitCommand extends CommandManager implements CommandExecutor, TabExecutor {
|
||||
BukkitCommand(LuckPermsPlugin plugin) {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
BukkitCommand(LPBukkitPlugin plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
onCommand(BukkitSenderFactory.get().wrap(sender), label, Arrays.asList(args), Callback.empty());
|
||||
onCommand(
|
||||
plugin.getSenderFactory().wrap(sender),
|
||||
label,
|
||||
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
|
||||
Callback.empty()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
|
||||
return onTabComplete(BukkitSenderFactory.get().wrap(sender), Arrays.asList(args));
|
||||
return onTabComplete(plugin.getSenderFactory().wrap(sender), Arrays.asList(args));
|
||||
}
|
||||
}
|
||||
+41
-17
@@ -20,16 +20,20 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import me.lucko.luckperms.common.config.AbstractConfiguration;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class BukkitConfig extends LPConfiguration<LPBukkitPlugin> {
|
||||
class BukkitConfig extends AbstractConfiguration<LPBukkitPlugin> {
|
||||
private YamlConfiguration configuration;
|
||||
|
||||
BukkitConfig(LPBukkitPlugin plugin) {
|
||||
@@ -46,18 +50,7 @@ class BukkitConfig extends LPConfiguration<LPBukkitPlugin> {
|
||||
getPlugin().saveResource("config.yml", false);
|
||||
}
|
||||
|
||||
configuration = new YamlConfiguration();
|
||||
|
||||
try {
|
||||
configuration.load(configFile);
|
||||
} catch (InvalidConfigurationException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void set(String path, Object value) {
|
||||
configuration.set(path, value);
|
||||
configuration = YamlConfiguration.loadConfiguration(configFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,4 +67,35 @@ class BukkitConfig extends LPConfiguration<LPBukkitPlugin> {
|
||||
protected boolean getBoolean(String path, boolean def) {
|
||||
return configuration.getBoolean(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getList(String path, List<String> def) {
|
||||
return Optional.ofNullable(configuration.getStringList(path)).orElse(def);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getObjectList(String path, List<String> def) {
|
||||
ConfigurationSection section = configuration.getConfigurationSection(path);
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return Optional.ofNullable(section.getKeys(false).stream().collect(Collectors.toList())).orElse(def);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected Map<String, String> getMap(String path, Map<String, String> def) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
ConfigurationSection section = configuration.getConfigurationSection(path);
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
for (String key : section.getKeys(false)) {
|
||||
map.put(key, section.getString(key));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import me.lucko.luckperms.bukkit.inject.Injector;
|
||||
import me.lucko.luckperms.bukkit.inject.LPPermissible;
|
||||
import me.lucko.luckperms.common.constants.Message;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.utils.AbstractListener;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
class BukkitListener extends AbstractListener implements Listener {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
BukkitListener(LPBukkitPlugin plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
|
||||
if (!plugin.isStarted() || !plugin.getStorage().isAcceptingLogins()) {
|
||||
|
||||
// The datastore is disabled, prevent players from joining the server
|
||||
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
// Process login
|
||||
onAsyncLogin(e.getUniqueId(), e.getName());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerPreLoginMonitor(AsyncPlayerPreLoginEvent e) {
|
||||
if (plugin.isStarted() && plugin.getStorage().isAcceptingLogins() && e.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
||||
|
||||
// Login event was cancelled by another plugin
|
||||
onLeave(e.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerLogin(PlayerLoginEvent e) {
|
||||
final Player player = e.getPlayer();
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
|
||||
if (user == null) {
|
||||
// User wasn't loaded for whatever reason.
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Make a new permissible for the user
|
||||
LPPermissible lpPermissible = new LPPermissible(player, user, plugin);
|
||||
|
||||
// Inject into the player
|
||||
Injector.inject(player, lpPermissible);
|
||||
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
||||
if (player.isOp()) {
|
||||
|
||||
// We assume all users are not op, but those who are need extra calculation.
|
||||
plugin.doAsync(() -> user.getUserData().preCalculate(plugin.getPreProcessContexts(true)));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerLoginMonitor(PlayerLoginEvent e) {
|
||||
if (e.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||
|
||||
// The player got denied on sync login.
|
||||
onLeave(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR) // Allow other plugins to see data when this event gets called.
|
||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||
final Player player = e.getPlayer();
|
||||
final UUID internal = plugin.getUuidCache().getUUID(player.getUniqueId());
|
||||
|
||||
// Remove from World cache
|
||||
plugin.getWorldCalculator().getWorldCache().remove(internal);
|
||||
|
||||
// Remove the custom permissible
|
||||
Injector.unInject(player);
|
||||
|
||||
// Handle auto op
|
||||
if (plugin.getConfiguration().isAutoOp()) {
|
||||
player.setOp(false);
|
||||
}
|
||||
|
||||
// Call internal leave handling
|
||||
onLeave(player.getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerCommand(PlayerCommandPreprocessEvent e) {
|
||||
if (plugin.getConfiguration().isOpsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String s = e.getMessage()
|
||||
.replace("/", "")
|
||||
.replace("bukkit:", "")
|
||||
.replace("spigot:", "")
|
||||
.replace("minecraft:", "");
|
||||
|
||||
if (s.startsWith("op") || s.startsWith("deop")) {
|
||||
e.setCancelled(true);
|
||||
e.getPlayer().sendMessage(Message.OP_DISABLED.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-12
@@ -20,25 +20,19 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import me.lucko.luckperms.commands.SenderFactory;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.commands.sender.SenderFactory;
|
||||
import me.lucko.luckperms.common.constants.Constants;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class BukkitSenderFactory extends SenderFactory<CommandSender> {
|
||||
private static BukkitSenderFactory instance = null;
|
||||
public static BukkitSenderFactory get() {
|
||||
if (instance == null){
|
||||
instance = new BukkitSenderFactory();
|
||||
}
|
||||
return instance;
|
||||
public BukkitSenderFactory(LuckPermsPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,432 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.ApiHandler;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.LuckPermsApi;
|
||||
import me.lucko.luckperms.api.PlatformType;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.bukkit.calculators.AutoOPListener;
|
||||
import me.lucko.luckperms.bukkit.calculators.ChildPermissionProvider;
|
||||
import me.lucko.luckperms.bukkit.calculators.DefaultsProvider;
|
||||
import me.lucko.luckperms.bukkit.vault.VaultHook;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.api.ApiProvider;
|
||||
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||
import me.lucko.luckperms.common.commands.ConsecutiveExecutor;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.config.LPConfiguration;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.contexts.ContextManager;
|
||||
import me.lucko.luckperms.common.contexts.ServerCalculator;
|
||||
import me.lucko.luckperms.common.core.UuidCache;
|
||||
import me.lucko.luckperms.common.data.Importer;
|
||||
import me.lucko.luckperms.common.groups.GroupManager;
|
||||
import me.lucko.luckperms.common.messaging.RedisMessaging;
|
||||
import me.lucko.luckperms.common.runnables.ExpireTemporaryTask;
|
||||
import me.lucko.luckperms.common.runnables.UpdateTask;
|
||||
import me.lucko.luckperms.common.storage.Storage;
|
||||
import me.lucko.luckperms.common.storage.StorageFactory;
|
||||
import me.lucko.luckperms.common.tracks.TrackManager;
|
||||
import me.lucko.luckperms.common.users.UserManager;
|
||||
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||
import me.lucko.luckperms.common.utils.DebugHandler;
|
||||
import me.lucko.luckperms.common.utils.LocaleManager;
|
||||
import me.lucko.luckperms.common.utils.LogFactory;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
private ExecutorService executorService;
|
||||
private Executor syncExecutor;
|
||||
private Executor asyncExecutor;
|
||||
private VaultHook vaultHook = null;
|
||||
|
||||
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
|
||||
private LPConfiguration configuration;
|
||||
private UserManager userManager;
|
||||
private GroupManager groupManager;
|
||||
private TrackManager trackManager;
|
||||
private Storage storage;
|
||||
private RedisMessaging redisMessaging = null;
|
||||
private UuidCache uuidCache;
|
||||
private ApiProvider apiProvider;
|
||||
private Logger log;
|
||||
private Importer importer;
|
||||
private ConsecutiveExecutor consecutiveExecutor;
|
||||
private DefaultsProvider defaultsProvider;
|
||||
private ChildPermissionProvider childPermissionProvider;
|
||||
private LocaleManager localeManager;
|
||||
private ContextManager<Player> contextManager;
|
||||
private WorldCalculator worldCalculator;
|
||||
private CalculatorFactory calculatorFactory;
|
||||
private BufferedRequest<Void> updateTaskBuffer;
|
||||
private boolean started = false;
|
||||
private DebugHandler debugHandler;
|
||||
private BukkitSenderFactory senderFactory;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Used whilst the server is still starting
|
||||
executorService = Executors.newCachedThreadPool();
|
||||
asyncExecutor = executorService;
|
||||
syncExecutor = r -> getServer().getScheduler().runTask(this, r);
|
||||
|
||||
log = LogFactory.wrap(getLogger());
|
||||
debugHandler = new DebugHandler();
|
||||
senderFactory = new BukkitSenderFactory(this);
|
||||
|
||||
getLog().info("Loading configuration...");
|
||||
configuration = new BukkitConfig(this);
|
||||
|
||||
// setup the Bukkit defaults hook
|
||||
defaultsProvider = new DefaultsProvider();
|
||||
childPermissionProvider = new ChildPermissionProvider();
|
||||
|
||||
// give all plugins a chance to load their defaults, then refresh.
|
||||
getServer().getScheduler().runTaskLater(this, () -> {
|
||||
defaultsProvider.refresh();
|
||||
childPermissionProvider.setup();
|
||||
}, 1L);
|
||||
|
||||
// register events
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new BukkitListener(this), this);
|
||||
|
||||
// initialise datastore
|
||||
storage = StorageFactory.getInstance(this, "h2");
|
||||
|
||||
// initialise redis
|
||||
if (getConfiguration().isRedisEnabled()) {
|
||||
getLog().info("Loading redis...");
|
||||
redisMessaging = new RedisMessaging(this);
|
||||
try {
|
||||
redisMessaging.init(getConfiguration().getRedisAddress(), getConfiguration().getRedisPassword());
|
||||
getLog().info("Loaded redis successfully...");
|
||||
} catch (Exception e) {
|
||||
getLog().info("Couldn't load redis...");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// setup the update task buffer
|
||||
updateTaskBuffer = new BufferedRequest<Void>(1000L, this::doAsync) {
|
||||
@Override
|
||||
protected Void perform() {
|
||||
new UpdateTask(LPBukkitPlugin.this).run();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// load locale
|
||||
localeManager = new LocaleManager();
|
||||
File locale = new File(getDataFolder(), "lang.yml");
|
||||
if (locale.exists()) {
|
||||
getLog().info("Found locale file. Attempting to load from it.");
|
||||
try {
|
||||
localeManager.loadFromFile(locale);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// register commands
|
||||
getLog().info("Registering commands...");
|
||||
BukkitCommand commandManager = new BukkitCommand(this);
|
||||
PluginCommand main = getServer().getPluginCommand("luckperms");
|
||||
main.setExecutor(commandManager);
|
||||
main.setTabCompleter(commandManager);
|
||||
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
|
||||
|
||||
// load internal managers
|
||||
getLog().info("Loading internal permission managers...");
|
||||
uuidCache = new UuidCache(getConfiguration().isOnlineMode());
|
||||
userManager = new UserManager(this);
|
||||
groupManager = new GroupManager(this);
|
||||
trackManager = new TrackManager();
|
||||
importer = new Importer(commandManager);
|
||||
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
|
||||
calculatorFactory = new BukkitCalculatorFactory(this);
|
||||
|
||||
contextManager = new ContextManager<>();
|
||||
worldCalculator = new WorldCalculator(this);
|
||||
pm.registerEvents(worldCalculator, this);
|
||||
contextManager.registerCalculator(worldCalculator);
|
||||
contextManager.registerCalculator(new ServerCalculator<>(getConfiguration().getServer()));
|
||||
|
||||
// handle server operators
|
||||
if (getConfiguration().isAutoOp()) {
|
||||
contextManager.registerListener(new AutoOPListener());
|
||||
}
|
||||
|
||||
// Provide vault support
|
||||
getLog().info("Attempting to hook into Vault...");
|
||||
try {
|
||||
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
|
||||
vaultHook = new VaultHook();
|
||||
vaultHook.hook(this);
|
||||
getLog().info("Registered Vault permission & chat hook.");
|
||||
} else {
|
||||
getLog().info("Vault not found.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
getLog().severe("Error occurred whilst hooking into Vault.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// register with the LP API
|
||||
getLog().info("Registering API...");
|
||||
apiProvider = new ApiProvider(this);
|
||||
ApiHandler.registerProvider(apiProvider);
|
||||
getServer().getServicesManager().register(LuckPermsApi.class, apiProvider, this, ServicePriority.Normal);
|
||||
|
||||
|
||||
// schedule update tasks
|
||||
int mins = getConfiguration().getSyncTime();
|
||||
if (mins > 0) {
|
||||
long ticks = mins * 60 * 20;
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, () -> updateTaskBuffer.request(), 20L, ticks);
|
||||
}
|
||||
|
||||
// run an update instantly.
|
||||
updateTaskBuffer.requestDirectly();
|
||||
|
||||
// register tasks
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpireTemporaryTask(this), 60L, 60L);
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, consecutiveExecutor, 20L, 20L);
|
||||
|
||||
// register permissions
|
||||
registerPermissions(getConfiguration().isCommandsAllowOp() ? PermissionDefault.OP : PermissionDefault.FALSE);
|
||||
if (!getConfiguration().isOpsEnabled()) {
|
||||
getServer().getOperators().forEach(o -> o.setOp(false));
|
||||
}
|
||||
|
||||
// replace the temporary executor when the Bukkit one starts
|
||||
getServer().getScheduler().runTaskAsynchronously(this, () -> {
|
||||
asyncExecutor = r -> getServer().getScheduler().runTaskAsynchronously(this, r);
|
||||
});
|
||||
|
||||
started = true;
|
||||
getLog().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
started = false;
|
||||
getLog().info("Closing datastore...");
|
||||
storage.shutdown();
|
||||
|
||||
if (redisMessaging != null) {
|
||||
getLog().info("Closing redis...");
|
||||
redisMessaging.shutdown();
|
||||
}
|
||||
|
||||
getLog().info("Unregistering API...");
|
||||
ApiHandler.unregisterProvider();
|
||||
getServer().getServicesManager().unregisterAll(this);
|
||||
|
||||
if (vaultHook != null) {
|
||||
vaultHook.unhook(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
asyncExecutor.execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
syncExecutor.execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsyncRepeating(Runnable r, long interval) {
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, r, interval, interval);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformType getType() {
|
||||
return PlatformType.BUKKIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getMainDir() {
|
||||
return getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getServer().getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPlayerList() {
|
||||
return getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getOnlinePlayers() {
|
||||
return getServer().getOnlinePlayers().stream().map(Player::getUniqueId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline(UUID external) {
|
||||
return getServer().getPlayer(external) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getSenders() {
|
||||
return getServer().getOnlinePlayers().stream()
|
||||
.map(p -> getSenderFactory().wrap(p))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return getSenderFactory().wrap(getServer().getConsoleSender());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Contexts> getPreProcessContexts(boolean op) {
|
||||
Set<ContextSet> c = new HashSet<>();
|
||||
c.add(ContextSet.empty());
|
||||
c.add(ContextSet.singleton("server", getConfiguration().getServer()));
|
||||
|
||||
// Pre process all worlds
|
||||
c.addAll(getServer().getWorlds().stream()
|
||||
.map(World::getName)
|
||||
.map(s -> {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.add("server", getConfiguration().getServer());
|
||||
set.add("world", s);
|
||||
return set.makeImmutable();
|
||||
})
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
|
||||
// Pre process the separate Vault server, if any
|
||||
if (!getConfiguration().getServer().equals(getConfiguration().getVaultServer())) {
|
||||
c.add(ContextSet.singleton("server", getConfiguration().getVaultServer()));
|
||||
c.addAll(getServer().getWorlds().stream()
|
||||
.map(World::getName)
|
||||
.map(s -> {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.add("server", getConfiguration().getVaultServer());
|
||||
set.add("world", s);
|
||||
return set.makeImmutable();
|
||||
})
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
Set<Contexts> contexts = new HashSet<>();
|
||||
|
||||
// Convert to full Contexts
|
||||
contexts.addAll(c.stream()
|
||||
.map(set -> new Contexts(
|
||||
set,
|
||||
getConfiguration().isIncludingGlobalPerms(),
|
||||
getConfiguration().isIncludingGlobalWorldPerms(),
|
||||
true,
|
||||
getConfiguration().isApplyingGlobalGroups(),
|
||||
getConfiguration().isApplyingGlobalWorldGroups(),
|
||||
op
|
||||
))
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
|
||||
// Check for and include varying Vault config options
|
||||
boolean vaultDiff = getConfiguration().isVaultIncludingGlobal() != getConfiguration().isIncludingGlobalPerms() ||
|
||||
!getConfiguration().isIncludingGlobalWorldPerms() ||
|
||||
!getConfiguration().isApplyingGlobalGroups() ||
|
||||
!getConfiguration().isApplyingGlobalWorldGroups();
|
||||
|
||||
if (vaultDiff) {
|
||||
contexts.addAll(c.stream()
|
||||
.map(map -> new Contexts(map, getConfiguration().isVaultIncludingGlobal(), true, true, true, true, op))
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
}
|
||||
|
||||
return contexts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPlugin(String name) {
|
||||
return getServer().getPluginManager().getPlugin(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getService(Class clazz) {
|
||||
return getServer().getServicesManager().load(clazz);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public UUID getUUID(String playerName) {
|
||||
try {
|
||||
return getServer().getOfflinePlayer(playerName).getUniqueId();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginLoaded(String name) {
|
||||
return getServer().getPluginManager().isPluginEnabled(name);
|
||||
}
|
||||
|
||||
private void registerPermissions(PermissionDefault def) {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
|
||||
for (Permission p : Permission.values()) {
|
||||
for (String node : p.getNodes()) {
|
||||
pm.addPermission(new org.bukkit.permissions.Permission(node, def));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.api.context.ContextCalculator;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class WorldCalculator extends ContextCalculator<Player> implements Listener {
|
||||
private static final String WORLD_KEY = "world";
|
||||
|
||||
private final LuckPermsPlugin plugin;
|
||||
|
||||
@Getter
|
||||
private final Map<UUID, String> worldCache = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public MutableContextSet giveApplicableContext(Player subject, MutableContextSet accumulator) {
|
||||
String world = getWorld(subject);
|
||||
|
||||
if (world != null) {
|
||||
accumulator.add(Maps.immutableEntry(WORLD_KEY, world));
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isContextApplicable(Player subject, Map.Entry<String, String> context) {
|
||||
if (!context.getKey().equals(WORLD_KEY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String world = getWorld(subject);
|
||||
return world != null && world.equals(context.getValue());
|
||||
}
|
||||
|
||||
private String getWorld(Player player) {
|
||||
UUID internal = plugin.getUuidCache().getUUID(player.getUniqueId());
|
||||
String world = worldCache.get(internal);
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return plugin.getConfiguration().getWorldRewrites().getOrDefault(world, world);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerJoin(PlayerLoginEvent e) {
|
||||
UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
|
||||
worldCache.put(internal, e.getPlayer().getWorld().getName());
|
||||
pushUpdate(
|
||||
e.getPlayer(),
|
||||
Maps.immutableEntry(WORLD_KEY, null),
|
||||
Maps.immutableEntry(WORLD_KEY, e.getPlayer().getWorld().getName())
|
||||
);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
|
||||
UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
|
||||
worldCache.put(internal, e.getPlayer().getWorld().getName());
|
||||
pushUpdate(
|
||||
e.getPlayer(),
|
||||
Maps.immutableEntry(WORLD_KEY, e.getFrom().getName()),
|
||||
Maps.immutableEntry(WORLD_KEY, e.getPlayer().getWorld().getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.calculators;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.common.calculators.PermissionProcessor;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class AttachmentProcessor implements PermissionProcessor {
|
||||
|
||||
@Getter
|
||||
private final Supplier<Map<String, PermissionAttachmentInfo>> map;
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
Map<String, PermissionAttachmentInfo> m = map.get();
|
||||
if (m == null) {
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
|
||||
PermissionAttachmentInfo pai = m.get(permission);
|
||||
return pai == null ? Tristate.UNDEFINED : Tristate.fromBoolean(pai.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBacking(Map<String, Boolean> map) {
|
||||
// Do nothing, this doesn't use the backing
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.calculators;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextListener;
|
||||
import me.lucko.luckperms.bukkit.inject.Injector;
|
||||
import me.lucko.luckperms.bukkit.inject.LPPermissible;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class AutoOPListener implements ContextListener<Player> {
|
||||
|
||||
@Override
|
||||
public void onContextChange(Player subject, Map.Entry<String, String> before, Map.Entry<String, String> current) throws Exception {
|
||||
LPPermissible permissible = Injector.getPermissible(subject.getUniqueId());
|
||||
if (permissible == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Boolean> backing = permissible.getUser().getUserData().getPermissionData(permissible.calculateContexts()).getImmutableBacking();
|
||||
boolean op = Optional.ofNullable(backing.get("luckperms.autoop")).orElse(false);
|
||||
subject.setOp(op);
|
||||
}
|
||||
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.calculators;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.permissions.Permission;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChildPermissionProvider {
|
||||
|
||||
@Getter
|
||||
private ImmutableMap<Map.Entry<String, Boolean>, ImmutableMap<String, Boolean>> permissions = ImmutableMap.of();
|
||||
|
||||
public void setup() {
|
||||
ImmutableMap.Builder<Map.Entry<String, Boolean>, ImmutableMap<String, Boolean>> permissions = ImmutableMap.builder();
|
||||
|
||||
for (Permission permission : Bukkit.getServer().getPluginManager().getPermissions()) {
|
||||
// handle true
|
||||
Map<String, Boolean> children = new HashMap<>();
|
||||
resolveChildren(children, Collections.singletonMap(permission.getName(), true), false);
|
||||
permissions.put(Maps.immutableEntry(permission.getName().toLowerCase(), true), ImmutableMap.copyOf(children));
|
||||
|
||||
// handle false
|
||||
Map<String, Boolean> nChildren = new HashMap<>();
|
||||
resolveChildren(nChildren, Collections.singletonMap(permission.getName(), false), false);
|
||||
permissions.put(Maps.immutableEntry(permission.getName().toLowerCase(), false), ImmutableMap.copyOf(nChildren));
|
||||
}
|
||||
|
||||
this.permissions = permissions.build();
|
||||
}
|
||||
|
||||
private static void resolveChildren(Map<String, Boolean> accumulator, Map<String, Boolean> children, boolean invert) {
|
||||
for (Map.Entry<String, Boolean> e : children.entrySet()) {
|
||||
if (accumulator.containsKey(e.getKey())) {
|
||||
continue; // Prevent infinite loops
|
||||
}
|
||||
|
||||
Permission perm = Bukkit.getServer().getPluginManager().getPermission(e.getKey());
|
||||
boolean value = e.getValue() ^ invert;
|
||||
String lName = e.getKey().toLowerCase();
|
||||
|
||||
accumulator.put(lName, value);
|
||||
|
||||
if (perm != null) {
|
||||
resolveChildren(accumulator, perm.getChildren(), !value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.calculators;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.common.calculators.PermissionProcessor;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ChildProcessor implements PermissionProcessor {
|
||||
private final ChildPermissionProvider provider;
|
||||
private Map<String, Boolean> childPermissions = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
Boolean b = childPermissions.get(permission);
|
||||
return b == null ? Tristate.UNDEFINED : Tristate.fromBoolean(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBacking(Map<String, Boolean> map) {
|
||||
childPermissions.clear();
|
||||
for (Map.Entry<String, Boolean> e : map.entrySet()) {
|
||||
Map<String, Boolean> children = provider.getPermissions().get(e);
|
||||
if (children != null) {
|
||||
childPermissions.putAll(children);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.calculators;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.common.calculators.PermissionProcessor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.permissions.Permission;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class DefaultsProcessor implements PermissionProcessor {
|
||||
private final boolean isOp;
|
||||
private final DefaultsProvider defaultsProvider;
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
Tristate t = defaultsProvider.hasDefault(permission, isOp);
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
|
||||
Permission defPerm = Bukkit.getServer().getPluginManager().getPermission(permission);
|
||||
return defPerm == null ? Tristate.UNDEFINED : Tristate.fromBoolean(defPerm.getDefault().getValue(isOp));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBacking(Map<String, Boolean> map) {
|
||||
// Do nothing, this doesn't use the backing
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.calculators;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class DefaultsProvider {
|
||||
|
||||
private final DummyPermissible opDummy = new DummyPermissible(this::refreshOp);
|
||||
private final DummyPermissible nonOpDummy = new DummyPermissible(this::refreshNonOp);
|
||||
|
||||
private final Map<String, Boolean> op = new HashMap<>();
|
||||
private final Map<String, Boolean> nonOp = new HashMap<>();
|
||||
|
||||
public void refresh() {
|
||||
refreshOp();
|
||||
refreshNonOp();
|
||||
}
|
||||
|
||||
private void refreshOp() {
|
||||
calculateDefaults(op, opDummy, true);
|
||||
}
|
||||
|
||||
private void refreshNonOp() {
|
||||
calculateDefaults(nonOp, nonOpDummy, false);
|
||||
}
|
||||
|
||||
private static void calculateDefaults(Map<String, Boolean> map, DummyPermissible p, boolean op) {
|
||||
Set<String> perms = map.keySet();
|
||||
|
||||
for (String name : perms) {
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromPermission(name, p);
|
||||
}
|
||||
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(false, p);
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(true, p);
|
||||
|
||||
map.clear();
|
||||
|
||||
Set<Permission> defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(op);
|
||||
Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(op, p);
|
||||
|
||||
for (Permission perm : defaults) {
|
||||
String name = perm.getName().toLowerCase();
|
||||
map.put(name, true);
|
||||
Bukkit.getServer().getPluginManager().subscribeToPermission(name, p);
|
||||
calculateChildPermissions(map, p, perm.getChildren(), false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void calculateChildPermissions(Map<String, Boolean> map, DummyPermissible p, Map<String, Boolean> children, boolean invert) {
|
||||
for (Map.Entry<String, Boolean> e : children.entrySet()) {
|
||||
Permission perm = Bukkit.getServer().getPluginManager().getPermission(e.getKey());
|
||||
boolean value = e.getValue() ^ invert;
|
||||
String lName = e.getKey().toLowerCase();
|
||||
|
||||
map.put(lName, value);
|
||||
Bukkit.getServer().getPluginManager().subscribeToPermission(e.getKey(), p);
|
||||
|
||||
if (perm != null) {
|
||||
calculateChildPermissions(map, p, perm.getChildren(), !value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Tristate hasDefault(String permission, boolean isOp) {
|
||||
Map<String, Boolean> map = isOp ? op : nonOp;
|
||||
|
||||
Boolean b = map.get(permission);
|
||||
return b == null ? Tristate.UNDEFINED : Tristate.fromBoolean(b);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private static class DummyPermissible implements Permissible {
|
||||
private final Runnable onRefresh;
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions() {
|
||||
onRefresh.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(Permission perm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Permission perm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttachment(PermissionAttachment attachment) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOp(boolean value) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.inject;
|
||||
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public class DummyPermissibleBase extends PermissibleBase {
|
||||
public DummyPermissibleBase() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOp(boolean value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(Permission perm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String inName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Permission perm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttachment(PermissionAttachment attachment) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void clearPermissions() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.inject;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Injects a {@link LPPermissible} into a {@link Player}
|
||||
*/
|
||||
@UtilityClass
|
||||
public class Injector {
|
||||
private static final Map<UUID, LPPermissible> INJECTED_PERMISSIBLES = new ConcurrentHashMap<>();
|
||||
private static Field HUMAN_ENTITY_FIELD;
|
||||
|
||||
static {
|
||||
try {
|
||||
HUMAN_ENTITY_FIELD = Class.forName(getVersionedClassName("entity.CraftHumanEntity")).getDeclaredField("perm");
|
||||
HUMAN_ENTITY_FIELD.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean inject(Player player, LPPermissible permissible) {
|
||||
try {
|
||||
HUMAN_ENTITY_FIELD.set(player, permissible);
|
||||
INJECTED_PERMISSIBLES.put(player.getUniqueId(), permissible);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean unInject(Player player) {
|
||||
try {
|
||||
Permissible permissible = (Permissible) HUMAN_ENTITY_FIELD.get(player);
|
||||
if (permissible instanceof LPPermissible) {
|
||||
/* The player is most likely leaving. Bukkit will attempt to call #clearPermissions, so we cannot set to null.
|
||||
However, there's no need to re-inject a real PermissibleBase, so we just inject a dummy instead.
|
||||
This saves tick time, pointlessly recalculating defaults when the instance will never be used. */
|
||||
HUMAN_ENTITY_FIELD.set(player, new DummyPermissibleBase());
|
||||
}
|
||||
INJECTED_PERMISSIBLES.remove(player.getUniqueId());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static LPPermissible getPermissible(UUID uuid) {
|
||||
return INJECTED_PERMISSIBLES.get(uuid);
|
||||
}
|
||||
|
||||
private static String getVersionedClassName(String className) {
|
||||
Class server = Bukkit.getServer().getClass();
|
||||
if (!server.getSimpleName().equals("CraftServer")) {
|
||||
throw new RuntimeException("Couldn't inject into server " + server);
|
||||
}
|
||||
|
||||
String version;
|
||||
if (server.getName().equals("org.bukkit.craftbukkit.CraftServer")) {
|
||||
// Non versioned class
|
||||
version = ".";
|
||||
} else {
|
||||
version = server.getName().substring("org.bukkit.craftbukkit".length());
|
||||
version = version.substring(0, version.length() - "CraftServer".length());
|
||||
}
|
||||
|
||||
return "org.bukkit.craftbukkit" + version + className;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.inject;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.*;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Modified PermissibleBase for LuckPerms
|
||||
*/
|
||||
public class LPPermissible extends PermissibleBase {
|
||||
|
||||
@Getter
|
||||
private final User user;
|
||||
|
||||
@Getter
|
||||
private final Player parent;
|
||||
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
// Attachment stuff.
|
||||
@Getter
|
||||
private final Map<String, PermissionAttachmentInfo> attachmentPermissions = new HashMap<>();
|
||||
private final List<PermissionAttachment> attachments = new LinkedList<>();
|
||||
|
||||
public LPPermissible(@NonNull Player parent, User user, LPBukkitPlugin plugin) {
|
||||
super(parent);
|
||||
this.user = user;
|
||||
this.parent = parent;
|
||||
this.plugin = plugin;
|
||||
|
||||
recalculatePermissions();
|
||||
}
|
||||
|
||||
public Contexts calculateContexts() {
|
||||
return new Contexts(
|
||||
plugin.getContextManager().getApplicableContext(parent),
|
||||
plugin.getConfiguration().isIncludingGlobalPerms(),
|
||||
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
|
||||
true,
|
||||
plugin.getConfiguration().isApplyingGlobalGroups(),
|
||||
plugin.getConfiguration().isApplyingGlobalWorldGroups(),
|
||||
parent.isOp()
|
||||
);
|
||||
}
|
||||
|
||||
private boolean hasData() {
|
||||
return user.getUserData() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOp(boolean value) {
|
||||
parent.setOp(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NonNull String name) {
|
||||
return hasData() && user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(name) != Tristate.UNDEFINED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NonNull Permission perm) {
|
||||
return isPermissionSet(perm.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull String name) {
|
||||
if (hasData()) {
|
||||
Tristate ts = user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(name);
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
return ts.asBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
return Permission.DEFAULT_PERMISSION.getValue(isOp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull Permission perm) {
|
||||
if (hasData()) {
|
||||
Tristate ts = user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(perm.getName());
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
return ts.asBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
return perm.getDefault().getValue(isOp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
||||
Set<PermissionAttachmentInfo> perms = new HashSet<>();
|
||||
perms.addAll(attachmentPermissions.values());
|
||||
|
||||
if (hasData()) {
|
||||
perms.addAll(
|
||||
user.getUserData().getPermissionData(calculateContexts()).getImmutableBacking().entrySet().stream()
|
||||
.map(e -> new PermissionAttachmentInfo(parent, e.getKey(), null, e.getValue()))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
return perms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, @NonNull String name, boolean value) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = addAttachment(plugin);
|
||||
result.setPermission(name, value);
|
||||
|
||||
recalculatePermissions();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = new PermissionAttachment(plugin, parent);
|
||||
|
||||
attachments.add(result);
|
||||
recalculatePermissions();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, @NonNull String name, boolean value, int ticks) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = addAttachment(plugin, ticks);
|
||||
if (result != null) {
|
||||
result.setPermission(name, value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, int ticks) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = addAttachment(plugin);
|
||||
if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> result.remove(), ticks) == -1) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add PermissionAttachment to " + parent + " for plugin " + plugin.getDescription().getFullName() + ": Scheduler returned -1");
|
||||
result.remove();
|
||||
return null;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttachment(@NonNull PermissionAttachment attachment) {
|
||||
if (attachments.contains(attachment)) {
|
||||
attachments.remove(attachment);
|
||||
PermissionRemovedExecutor ex = attachment.getRemovalCallback();
|
||||
|
||||
if (ex != null) {
|
||||
ex.attachmentRemoved(attachment);
|
||||
}
|
||||
|
||||
recalculatePermissions();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Given attachment is not part of Permissible object " + parent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions() {
|
||||
if (attachmentPermissions == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
attachmentPermissions.clear();
|
||||
|
||||
for (PermissionAttachment attachment : attachments) {
|
||||
calculateChildPermissions(attachment.getPermissions(), false, attachment);
|
||||
}
|
||||
|
||||
if (hasData()) {
|
||||
user.getUserData().invalidatePermissionCalculators();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void clearPermissions() {
|
||||
Set<String> perms = attachmentPermissions.keySet();
|
||||
|
||||
for (String name : perms) {
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromPermission(name, parent);
|
||||
}
|
||||
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(false, parent);
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(true, parent);
|
||||
|
||||
attachmentPermissions.clear();
|
||||
}
|
||||
|
||||
private void calculateChildPermissions(Map<String, Boolean> children, boolean invert, PermissionAttachment attachment) {
|
||||
for (Map.Entry<String, Boolean> e : children.entrySet()) {
|
||||
Permission perm = Bukkit.getServer().getPluginManager().getPermission(e.getKey());
|
||||
boolean value = e.getValue() ^ invert;
|
||||
String name = e.getKey().toLowerCase();
|
||||
|
||||
attachmentPermissions.put(name, new PermissionAttachmentInfo(parent, name, attachment, value));
|
||||
Bukkit.getServer().getPluginManager().subscribeToPermission(name, parent);
|
||||
|
||||
if (perm != null) {
|
||||
calculateChildPermissions(perm.getChildren(), !value, attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import de.bananaco.bpermissions.api.*;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.MetaUtils;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.constants.Constants;
|
||||
import me.lucko.luckperms.common.core.PermissionHolder;
|
||||
import me.lucko.luckperms.common.data.LogEntry;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
import static me.lucko.luckperms.common.constants.Permission.MIGRATION;
|
||||
|
||||
public class MigrationBPermissions extends SubCommand<Object> {
|
||||
private static Field uConfigField;
|
||||
private static Method getConfigurationSectionMethod = null;
|
||||
private static Method getKeysMethod = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
uConfigField = Class.forName("de.bananaco.bpermissions.imp.YamlWorld").getDeclaredField("uconfig");
|
||||
uConfigField.setAccessible(true);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Set<String> getUsers(World world) {
|
||||
try {
|
||||
Object yamlWorldUsers = uConfigField.get(world);
|
||||
if (getConfigurationSectionMethod == null) {
|
||||
getConfigurationSectionMethod = yamlWorldUsers.getClass().getMethod("getConfigurationSection", String.class);
|
||||
getConfigurationSectionMethod.setAccessible(true);
|
||||
}
|
||||
|
||||
Object configSection = getConfigurationSectionMethod.invoke(yamlWorldUsers, "users");
|
||||
if (configSection == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
if (getKeysMethod == null) {
|
||||
getKeysMethod = configSection.getClass().getMethod("getKeys", boolean.class);
|
||||
getKeysMethod.setAccessible(true);
|
||||
}
|
||||
|
||||
return (Set<String>) getKeysMethod.invoke(configSection, false);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public MigrationBPermissions() {
|
||||
super("bpermissions", "Migration from bPermissions", MIGRATION, Predicates.alwaysFalse(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
|
||||
final Logger log = plugin.getLog();
|
||||
|
||||
WorldManager worldManager = WorldManager.getInstance();
|
||||
if (worldManager == null) {
|
||||
log.severe("bPermissions Migration: Error -> bPermissions is not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
log.info("bPermissions Migration: Forcing the plugin to load all data. This could take a while.");
|
||||
for (World world : worldManager.getAllWorlds()) {
|
||||
Set<String> users = getUsers(world);
|
||||
if (users == null) {
|
||||
log.severe("bPermissions Migration: Couldn't get a list of users.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
users.forEach(s -> world.loadOne(s, CalculableType.USER));
|
||||
}
|
||||
|
||||
// Migrate one world at a time.
|
||||
log.info("bPermissions Migration: Starting world migration.");
|
||||
for (World world : worldManager.getAllWorlds()) {
|
||||
log.info("bPermissions Migration: Migrating world: " + world.getName());
|
||||
|
||||
// Migrate all groups
|
||||
log.info("bPermissions Migration: Starting group migration in world " + world.getName() + ".");
|
||||
int groupCount = 0;
|
||||
for (Calculable group : world.getAll(CalculableType.GROUP)) {
|
||||
groupCount++;
|
||||
String groupName = group.getName().toLowerCase();
|
||||
if (group.getName().equalsIgnoreCase(world.getDefaultGroup())) {
|
||||
groupName = "default";
|
||||
}
|
||||
|
||||
// Make a LuckPerms group for the one being migrated.
|
||||
plugin.getStorage().createAndLoadGroup(groupName).join();
|
||||
me.lucko.luckperms.common.groups.Group lpGroup = plugin.getGroupManager().get(groupName);
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("create")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
migrateHolder(plugin, world, group, lpGroup);
|
||||
plugin.getStorage().saveGroup(lpGroup);
|
||||
}
|
||||
log.info("bPermissions Migration: Migrated " + groupCount + " groups in world " + world.getName() + ".");
|
||||
|
||||
// Migrate all users
|
||||
log.info("bPermissions Migration: Starting user migration in world " + world.getName() + ".");
|
||||
int userCount = 0;
|
||||
for (Calculable user : world.getAll(CalculableType.USER)) {
|
||||
userCount++;
|
||||
|
||||
// There is no mention of UUIDs in the API. I assume that name = uuid. idk?
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = UUID.fromString(user.getName());
|
||||
} catch (IllegalArgumentException e) {
|
||||
uuid = plugin.getUUID(user.getName());
|
||||
}
|
||||
|
||||
if (uuid == null) {
|
||||
log.info("bPermissions Migration: Unable to migrate user " + user.getName() + ". Unable to get UUID.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make a LuckPerms user for the one being migrated.
|
||||
plugin.getStorage().loadUser(uuid, "null").join();
|
||||
me.lucko.luckperms.common.users.User lpUser = plugin.getUserManager().get(uuid);
|
||||
|
||||
migrateHolder(plugin, world, user, lpUser);
|
||||
|
||||
plugin.getStorage().saveUser(lpUser);
|
||||
plugin.getUserManager().cleanup(lpUser);
|
||||
}
|
||||
|
||||
log.info("bPermissions Migration: Migrated " + userCount + " users in world " + world.getName() + ".");
|
||||
}
|
||||
|
||||
log.info("bPermissions Migration: Success! Completed without any errors.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static void migrateHolder(LuckPermsPlugin plugin, World world, Calculable c, PermissionHolder holder) {
|
||||
// Migrate the groups permissions in this world
|
||||
for (Permission p : c.getPermissions()) {
|
||||
try {
|
||||
holder.setPermission(p.name(), p.isTrue(), "global", world.getName());
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + p.name() + " " + p.isTrue() + " global " + world.getName())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Include any child permissions
|
||||
for (Map.Entry<String, Boolean> child : p.getChildren().entrySet()) {
|
||||
try {
|
||||
holder.setPermission(child.getKey(), child.getValue(), "global", world.getName());
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + child.getKey() + " " + child.getValue() + " global " + world.getName())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate any inherited groups
|
||||
for (Group parent : c.getGroups()) {
|
||||
try {
|
||||
holder.setPermission("group." + parent.getName(), true, "global", world.getName());
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("setinherit " + parent.getName() + " global " + world.getName())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate existing meta
|
||||
for (Map.Entry<String, String> meta : c.getMeta().entrySet()) {
|
||||
if (meta.getKey().equalsIgnoreCase("prefix") || meta.getKey().equalsIgnoreCase("suffix")) {
|
||||
String chatMeta = MetaUtils.escapeCharacters(meta.getValue());
|
||||
try {
|
||||
holder.setPermission(meta.getKey().toLowerCase() + "." + c.getPriority() + "." + chatMeta, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + meta.getKey().toLowerCase() + "." + c.getPriority() + "." + chatMeta + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission("meta." + meta.getKey() + "." + meta.getValue(), true, "global", world.getName());
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set meta." + meta.getKey() + "." + meta.getValue() + " true global " + world.getName())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.constants.Constants;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.core.NodeFactory;
|
||||
import me.lucko.luckperms.common.data.LogEntry;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import org.anjocaido.groupmanager.GlobalGroups;
|
||||
import org.anjocaido.groupmanager.GroupManager;
|
||||
import org.anjocaido.groupmanager.data.Group;
|
||||
import org.anjocaido.groupmanager.data.User;
|
||||
import org.anjocaido.groupmanager.dataholder.WorldDataHolder;
|
||||
import org.anjocaido.groupmanager.dataholder.worlds.WorldsHolder;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MigrationGroupManager extends SubCommand<Object> {
|
||||
public MigrationGroupManager() {
|
||||
super("groupmanager", "Migration from GroupManager", Permission.MIGRATION, Predicates.is(0),
|
||||
Arg.list(Arg.create("world names...", false, "a list of worlds to migrate permissions from"))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
|
||||
final Logger log = plugin.getLog();
|
||||
if (!plugin.isPluginLoaded("GroupManager")) {
|
||||
log.severe("GroupManager Migration: Error -> GroupManager is not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
final List<String> worlds = args.stream()
|
||||
.map(String::toLowerCase)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
GroupManager gm = (GroupManager) plugin.getPlugin("GroupManager");
|
||||
|
||||
// Migrate Global Groups
|
||||
log.info("GroupManager Migration: Starting Global Group migration.");
|
||||
GlobalGroups gg = GroupManager.getGlobalGroups();
|
||||
|
||||
for (Group g : gg.getGroupList()) {
|
||||
plugin.getStorage().createAndLoadGroup(g.getName().toLowerCase()).join();
|
||||
me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("create")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
for (String node : g.getPermissionList()) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("!") || node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
} else if (node.startsWith("+")) {
|
||||
node = node.substring(1);
|
||||
value = true;
|
||||
}
|
||||
|
||||
try {
|
||||
group.setPermission(node, value);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("set " + node + " " + value)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String s : g.getInherits()) {
|
||||
try {
|
||||
group.setPermission("group." + s.toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("setinherit " + s.toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(group);
|
||||
}
|
||||
|
||||
Map<UUID, Map<Map.Entry<String, String>, Boolean>> users = new HashMap<>();
|
||||
Map<UUID, String> primaryGroups = new HashMap<>();
|
||||
Map<String, Map<Map.Entry<String, String>, Boolean>> groups = new HashMap<>();
|
||||
|
||||
WorldsHolder wh = gm.getWorldsHolder();
|
||||
|
||||
// Collect data for all users and groups.
|
||||
log.info("GroupManager Migration: Starting user and group migration.");
|
||||
for (String world : worlds) {
|
||||
world = world.toLowerCase();
|
||||
|
||||
WorldDataHolder wdh = wh.getWorldData(world);
|
||||
|
||||
for (Group g : wdh.getGroupList()) {
|
||||
groups.putIfAbsent(g.getName().toLowerCase(), new HashMap<>());
|
||||
|
||||
for (String node : g.getPermissionList()) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("!") || node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
} else if (node.startsWith("+")) {
|
||||
node = node.substring(1);
|
||||
value = true;
|
||||
}
|
||||
|
||||
groups.get(g.getName().toLowerCase()).put(new AbstractMap.SimpleEntry<>(world, node), value);
|
||||
}
|
||||
|
||||
for (String s : g.getInherits()) {
|
||||
groups.get(g.getName().toLowerCase()).put(new AbstractMap.SimpleEntry<>(world, "group." + s.toLowerCase()), true);
|
||||
}
|
||||
}
|
||||
|
||||
for (User user : wdh.getUserList()) {
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = UUID.fromString(user.getUUID());
|
||||
} catch (IllegalArgumentException e){
|
||||
continue;
|
||||
}
|
||||
|
||||
users.putIfAbsent(uuid, new HashMap<>());
|
||||
|
||||
for (String node : user.getPermissionList()) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("!") || node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
} else if (node.startsWith("+")) {
|
||||
node = node.substring(1);
|
||||
value = true;
|
||||
}
|
||||
|
||||
users.get(uuid).put(new AbstractMap.SimpleEntry<>(world, node), value);
|
||||
}
|
||||
|
||||
String finalWorld = world;
|
||||
users.get(uuid).putAll(user.subGroupListStringCopy().stream()
|
||||
.map(n -> "group." + n)
|
||||
.map(n -> new AbstractMap.SimpleEntry<>(finalWorld, n))
|
||||
.collect(Collectors.toMap(n -> n, n -> true))
|
||||
);
|
||||
primaryGroups.put(uuid, user.getGroupName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log.info("GroupManager Migration: All existing GroupManager data has been processed. Now beginning the import process.");
|
||||
log.info("GroupManager Migration: Found a total of " + users.size() + " users and " + groups.size() + " groups.");
|
||||
|
||||
for (Map.Entry<String, Map<Map.Entry<String, String>, Boolean>> e : groups.entrySet()) {
|
||||
plugin.getStorage().createAndLoadGroup(e.getKey()).join();
|
||||
me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(e.getKey());
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("create")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
for (Map.Entry<Map.Entry<String, String>, Boolean> n : e.getValue().entrySet()) {
|
||||
// n.key.key = world
|
||||
// n.key.value = node
|
||||
// n.value = true/false
|
||||
try {
|
||||
group.setPermission(NodeFactory.fromSerialisedNode("global-" + n.getKey().getKey() + "/" + n.getKey().getValue(), n.getValue()));
|
||||
|
||||
if (n.getKey().getValue().startsWith("group.")) {
|
||||
String groupName = n.getKey().getValue().substring(6);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("setinherit " + groupName + " global " + n.getKey().getKey())
|
||||
.build().submit(plugin);
|
||||
} else {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("set " + n.getKey().getValue() + " " + n.getValue() + " global " + n.getKey().getKey())
|
||||
.build().submit(plugin);
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(group);
|
||||
}
|
||||
|
||||
for (Map.Entry<UUID, Map<Map.Entry<String, String>, Boolean>> e : users.entrySet()) {
|
||||
plugin.getStorage().loadUser(e.getKey(), "null").join();
|
||||
me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(e.getKey());
|
||||
|
||||
for (Map.Entry<Map.Entry<String, String>, Boolean> n : e.getValue().entrySet()) {
|
||||
// n.key.key = world
|
||||
// n.key.value = node
|
||||
// n.value = true/false
|
||||
try {
|
||||
user.setPermission(NodeFactory.fromSerialisedNode("global-" + n.getKey().getKey() + "/" + n.getKey().getValue(), n.getValue()));
|
||||
|
||||
if (n.getKey().getValue().startsWith("group.")) {
|
||||
String group = n.getKey().getValue().substring(6);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + group + " global " + n.getKey().getKey())
|
||||
.build().submit(plugin);
|
||||
} else {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("set " + n.getKey().getValue() + " " + n.getValue() + " global " + n.getKey().getKey())
|
||||
.build().submit(plugin);
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String primaryGroup = primaryGroups.get(e.getKey());
|
||||
if (primaryGroup != null) {
|
||||
try {
|
||||
user.setPermission("group." + primaryGroup, true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
user.setPrimaryGroup(primaryGroup);
|
||||
try {
|
||||
user.unsetPermission("group.default");
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
}
|
||||
|
||||
plugin.getStorage().saveUser(user);
|
||||
plugin.getUserManager().cleanup(user);
|
||||
}
|
||||
|
||||
log.info("GroupManager Migration: Success! Completed without any errors.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.MetaUtils;
|
||||
import me.lucko.luckperms.api.PlatformType;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.constants.Constants;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.data.LogEntry;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import ru.tehkode.permissions.NativeInterface;
|
||||
import ru.tehkode.permissions.PermissionGroup;
|
||||
import ru.tehkode.permissions.PermissionManager;
|
||||
import ru.tehkode.permissions.PermissionUser;
|
||||
import ru.tehkode.permissions.bukkit.PermissionsEx;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
public MigrationPermissionsEx() {
|
||||
super("permissionsex", "Migration from PermissionsEx", Permission.MIGRATION, Predicates.alwaysFalse(),
|
||||
Arg.list(Arg.create("world names...", false, "a list of worlds to migrate permissions from"))
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
|
||||
final Logger log = plugin.getLog();
|
||||
if (!plugin.isPluginLoaded("PermissionsEx")) {
|
||||
log.severe("PermissionsEx Migration: Error -> PermissionsEx is not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
if (plugin.getType() != PlatformType.BUKKIT) {
|
||||
// Sponge uses a completely different version of PEX.
|
||||
log.severe("PEX import is not supported on this platform.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
final List<String> worlds = args.stream()
|
||||
.map(String::toLowerCase)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
PermissionsEx pex = (PermissionsEx) plugin.getPlugin("PermissionsEx");
|
||||
PermissionManager manager = pex.getPermissionsManager();
|
||||
|
||||
NativeInterface ni;
|
||||
try {
|
||||
Field f = manager.getClass().getDeclaredField("nativeI");
|
||||
f.setAccessible(true);
|
||||
ni = (NativeInterface) f.get(manager);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
// Migrate all groups.
|
||||
log.info("PermissionsEx Migration: Starting group migration.");
|
||||
|
||||
int maxGroupWeight = 0;
|
||||
int groupCount = 0;
|
||||
|
||||
for (PermissionGroup group : manager.getGroupList()) {
|
||||
int groupWeight = group.getWeight() * -1;
|
||||
groupCount ++;
|
||||
maxGroupWeight = Math.max(maxGroupWeight, groupWeight);
|
||||
|
||||
final String name = group.getName().toLowerCase();
|
||||
plugin.getStorage().createAndLoadGroup(name).join();
|
||||
Group lpGroup = plugin.getGroupManager().get(name);
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("create")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
for (String node : group.getOwnPermissions(null)) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
|
||||
try {
|
||||
lpGroup.setPermission(node, value);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("set " + node + " " + value)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (NullPointerException ignored) {
|
||||
// Probably won't happen. I have no API docs on getOwnPermissions#null though.
|
||||
}
|
||||
|
||||
if (worlds != null && !worlds.isEmpty()) {
|
||||
for (String world : worlds) {
|
||||
for (String node : group.getOwnPermissions(world)) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
|
||||
try {
|
||||
lpGroup.setPermission(node, value, "global", world);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("set " + node + " " + value + " global " + world)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (PermissionGroup g : group.getParents()) {
|
||||
try {
|
||||
lpGroup.setPermission("group." + g.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("setinherit " + g.getName().toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (worlds != null && !worlds.isEmpty()) {
|
||||
for (String world : worlds) {
|
||||
for (PermissionGroup g : group.getParents(world)) {
|
||||
try {
|
||||
lpGroup.setPermission("group." + g.getName().toLowerCase(), true, "global", world);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("setinherit " + g.getName().toLowerCase() + " global " + world)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String prefix = group.getOwnPrefix();
|
||||
String suffix = group.getOwnSuffix();
|
||||
|
||||
if (prefix != null && !prefix.equals("")) {
|
||||
prefix = MetaUtils.escapeCharacters(prefix);
|
||||
try {
|
||||
lpGroup.setPermission("prefix." + groupWeight + "." + prefix, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("set prefix." + groupWeight + "." + prefix + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (suffix != null && !suffix.equals("")) {
|
||||
suffix = MetaUtils.escapeCharacters(suffix);
|
||||
try {
|
||||
lpGroup.setPermission("suffix." + groupWeight + "." + suffix, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpGroup).action("set suffix." + groupWeight + "." + suffix + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(lpGroup);
|
||||
|
||||
}
|
||||
|
||||
log.info("PermissionsEx Migration: Migrated " + groupCount + " groups");
|
||||
|
||||
// Migrate all users
|
||||
log.info("PermissionsEx Migration: Starting user migration.");
|
||||
int userCount = 0;
|
||||
maxGroupWeight++;
|
||||
for (PermissionUser user : manager.getUsers()) {
|
||||
UUID u = null;
|
||||
|
||||
try {
|
||||
u = UUID.fromString(user.getIdentifier());
|
||||
} catch (IllegalArgumentException e) {
|
||||
u = ni.nameToUUID(user.getIdentifier());
|
||||
if (u == null) {
|
||||
u = plugin.getUUID(user.getIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
if (u == null) {
|
||||
log.severe("Unable to get a UUID for user identifier: " + user.getIdentifier());
|
||||
continue;
|
||||
}
|
||||
|
||||
userCount++;
|
||||
plugin.getStorage().loadUser(u, "null").join();
|
||||
User lpUser = plugin.getUserManager().get(u);
|
||||
|
||||
try {
|
||||
for (String node : user.getOwnPermissions(null)) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
|
||||
try {
|
||||
lpUser.setPermission(node, value);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpUser).action("set " + node + " " + value)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (NullPointerException ignored) {
|
||||
// Probably won't happen. I have no API docs on getOwnPermissions#null though.
|
||||
}
|
||||
|
||||
if (worlds != null && !worlds.isEmpty()) {
|
||||
for (String world : worlds) {
|
||||
for (String node : user.getOwnPermissions(world)) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
|
||||
try {
|
||||
lpUser.setPermission(node, value, "global", world);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpUser).action("set " + node + " " + value + " global " + world)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String s : user.getGroupNames()) {
|
||||
try {
|
||||
lpUser.setPermission("group." + s.toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpUser).action("addgroup " + s.toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (worlds != null && !worlds.isEmpty()) {
|
||||
for (String world : worlds) {
|
||||
for (String s : user.getGroupNames(world)) {
|
||||
try {
|
||||
lpUser.setPermission("group." + s.toLowerCase(), true, "global", world);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpUser).action("addgroup " + s.toLowerCase() + " global " + world)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String prefix = user.getOwnPrefix();
|
||||
String suffix = user.getOwnSuffix();
|
||||
|
||||
if (prefix != null && !prefix.equals("")) {
|
||||
prefix = MetaUtils.escapeCharacters(prefix);
|
||||
try {
|
||||
lpUser.setPermission("prefix." + maxGroupWeight + "." + prefix, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpUser).action("set prefix." + maxGroupWeight + "." + prefix + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (suffix != null && !suffix.equals("")) {
|
||||
suffix = MetaUtils.escapeCharacters(suffix);
|
||||
try {
|
||||
lpUser.setPermission("suffix." + maxGroupWeight + "." + suffix, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(lpUser).action("set suffix." + maxGroupWeight + "." + suffix + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String primary = null;
|
||||
int weight = -100;
|
||||
for (PermissionGroup group : user.getOwnParents()) {
|
||||
if (group.getRank() > weight) {
|
||||
primary = group.getName();
|
||||
weight = group.getWeight();
|
||||
}
|
||||
}
|
||||
|
||||
if (primary != null) {
|
||||
try {
|
||||
lpUser.setPermission("group." + primary.toLowerCase(), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
lpUser.setPrimaryGroup(primary);
|
||||
}
|
||||
|
||||
plugin.getUserManager().cleanup(lpUser);
|
||||
plugin.getStorage().saveUser(lpUser);
|
||||
}
|
||||
|
||||
log.info("PermissionsEx Migration: Migrated " + userCount + " users.");
|
||||
log.info("PermissionsEx Migration: Success! Completed without any errors.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,612 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import com.github.cheesesoftware.PowerfulPermsAPI.*;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.bukkit.migration.utils.LPResultRunnable;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.constants.Constants;
|
||||
import me.lucko.luckperms.common.core.PermissionHolder;
|
||||
import me.lucko.luckperms.common.data.LogEntry;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static me.lucko.luckperms.common.constants.Permission.MIGRATION;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
/* <sadness>
|
||||
The PowerfulPerms API is a complete joke. Seriously, it would probably be easier reflecting into the actual plugin.
|
||||
Methods move about randomly every version...
|
||||
|
||||
What kind of API requires reflection to function with multiple versions...
|
||||
Doesn't that just defeat the whole god damn point of having an API in the first place?
|
||||
Whatever happened to depreciation?
|
||||
</sadness> */
|
||||
|
||||
private static Method getPlayerPermissionsMethod = null;
|
||||
private static Method getPlayerGroupsMethod = null;
|
||||
private static Method getGroupMethod = null;
|
||||
|
||||
// lol
|
||||
private static boolean superLegacy = false;
|
||||
private static boolean legacy = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class.forName("com.github.cheesesoftware.PowerfulPermsAPI.ResponseRunnable");
|
||||
legacy = true;
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
|
||||
if (legacy) {
|
||||
try {
|
||||
getPlayerPermissionsMethod = PermissionManager.class.getMethod("getPlayerOwnPermissions", UUID.class, ResultRunnable.class);
|
||||
getPlayerPermissionsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
} else {
|
||||
try {
|
||||
getPlayerPermissionsMethod = PermissionManager.class.getMethod("getPlayerOwnPermissions", UUID.class);
|
||||
getPlayerPermissionsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
}
|
||||
|
||||
try {
|
||||
getGroupMethod = CachedGroup.class.getMethod("getGroup");
|
||||
getGroupMethod.setAccessible(true);
|
||||
superLegacy = true;
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
|
||||
if (!legacy) {
|
||||
try {
|
||||
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerOwnGroups", UUID.class);
|
||||
getPlayerGroupsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerOwnGroups", UUID.class, ResultRunnable.class);
|
||||
getPlayerGroupsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
try {
|
||||
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerGroups", UUID.class, ResultRunnable.class);
|
||||
getPlayerGroupsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public MigrationPowerfulPerms() {
|
||||
super("powerfulperms", "Migration from PowerfulPerms", MIGRATION, Predicates.not(5),
|
||||
Arg.list(
|
||||
Arg.create("address", true, "the address of the PP database"),
|
||||
Arg.create("database", true, "the name of the PP database"),
|
||||
Arg.create("username", true, "the username to log into the DB"),
|
||||
Arg.create("password", true, "the password to log into the DB"),
|
||||
Arg.create("db table", true, "the name of the PP table where player data is stored")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
|
||||
try {
|
||||
return run(plugin, args);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
private static void getPlayerPermissions(PermissionManager manager, UUID uuid, Callback<List<Permission>> callback) {
|
||||
if (legacy) {
|
||||
try {
|
||||
getPlayerPermissionsMethod.invoke(manager, uuid, new LPResultRunnable<List<Permission>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onComplete(getResult());
|
||||
}
|
||||
});
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
ListenableFuture<List<Permission>> lf = (ListenableFuture<List<Permission>>) getPlayerPermissionsMethod.invoke(manager, uuid);
|
||||
try {
|
||||
if (lf.isDone()) {
|
||||
callback.onComplete(lf.get());
|
||||
} else {
|
||||
lf.addListener(() -> {
|
||||
try {
|
||||
callback.onComplete(lf.get());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, Runnable::run);
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CommandResult run(LuckPermsPlugin plugin, List<String> args) {
|
||||
final Logger log = plugin.getLog();
|
||||
if (!plugin.isPluginLoaded("PowerfulPerms")) {
|
||||
log.severe("PowerfulPerms Migration: Error -> PowerfulPerms is not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
final String address = args.get(0);
|
||||
final String database = args.get(1);
|
||||
final String username = args.get(2);
|
||||
final String password = args.get(3);
|
||||
final String dbTable = args.get(4);
|
||||
|
||||
// Find a list of UUIDs
|
||||
log.info("PowerfulPerms Migration: Getting a list of UUIDs to migrate.");
|
||||
|
||||
@Cleanup HikariDataSource hikari = new HikariDataSource();
|
||||
hikari.setMaximumPoolSize(2);
|
||||
hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
|
||||
hikari.addDataSourceProperty("serverName", address.split(":")[0]);
|
||||
hikari.addDataSourceProperty("port", address.split(":")[1]);
|
||||
hikari.addDataSourceProperty("databaseName", database);
|
||||
hikari.addDataSourceProperty("user", username);
|
||||
hikari.addDataSourceProperty("password", password);
|
||||
|
||||
Set<UUID> uuids = new HashSet<>();
|
||||
|
||||
try {
|
||||
@Cleanup Connection connection = hikari.getConnection();
|
||||
DatabaseMetaData meta = connection.getMetaData();
|
||||
|
||||
@Cleanup ResultSet tables = meta.getTables(null, null, dbTable, null);
|
||||
if (!tables.next()) {
|
||||
log.severe("PowerfulPerms Migration: Error - Couldn't find table.");
|
||||
return CommandResult.FAILURE;
|
||||
|
||||
} else {
|
||||
@Cleanup PreparedStatement columnPs = connection.prepareStatement("SELECT COLUMN_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=?");
|
||||
columnPs.setString(1, dbTable);
|
||||
@Cleanup ResultSet columnRs = columnPs.executeQuery();
|
||||
|
||||
log.info("Found table: " + dbTable);
|
||||
while (columnRs.next()) {
|
||||
log.info("" + columnRs.getString("COLUMN_NAME") + " - " + columnRs.getString("COLUMN_TYPE"));
|
||||
}
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement("SELECT `uuid` FROM " + dbTable);
|
||||
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
|
||||
|
||||
while (resultSet.next()) {
|
||||
uuids.add(UUID.fromString(resultSet.getString("uuid")));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
if (uuids.isEmpty()) {
|
||||
log.severe("PowerfulPerms Migration: Error - Unable to find any UUIDs to migrate.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
log.info("PowerfulPerms Migration: Found " + uuids.size() + " uuids. Starting migration.");
|
||||
|
||||
PowerfulPermsPlugin ppPlugin = (PowerfulPermsPlugin) plugin.getPlugin("PowerfulPerms");
|
||||
PermissionManager pm = ppPlugin.getPermissionManager();
|
||||
|
||||
// Groups first.
|
||||
log.info("PowerfulPerms Migration: Starting group migration.");
|
||||
Map<Integer, Group> groups = pm.getGroups(); // All versions
|
||||
for (Group g : groups.values()) {
|
||||
plugin.getStorage().createAndLoadGroup(g.getName().toLowerCase()).join();
|
||||
final me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("create")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
for (Permission p : g.getOwnPermissions()) { // All versions
|
||||
applyPerm(group, p, plugin);
|
||||
}
|
||||
|
||||
for (Group parent : g.getParents()) { // All versions
|
||||
try {
|
||||
group.setPermission("group." + parent.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("setinherit " + parent.getName().toLowerCase()) // All versions
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(group);
|
||||
}
|
||||
log.info("PowerfulPerms Migration: Group migration complete.");
|
||||
|
||||
// Now users.
|
||||
log.info("PowerfulPerms Migration: Starting user migration.");
|
||||
final Map<UUID, CountDownLatch> progress = new HashMap<>();
|
||||
|
||||
// Migrate all users and their groups
|
||||
for (UUID uuid : uuids) {
|
||||
progress.put(uuid, new CountDownLatch(2));
|
||||
|
||||
// Create a LuckPerms user for the UUID
|
||||
plugin.getStorage().loadUser(uuid, "null").join();
|
||||
User user = plugin.getUserManager().get(uuid);
|
||||
|
||||
// Get a list of Permissions held by the user from the PP API.
|
||||
getPlayerPermissions(pm, uuid, perms -> { // Changes each version
|
||||
perms.forEach(p -> applyPerm(user, p, plugin));
|
||||
|
||||
// Update the progress so the user can be saved and unloaded.
|
||||
synchronized (progress) {
|
||||
progress.get(uuid).countDown();
|
||||
if (progress.get(uuid).getCount() == 0) {
|
||||
plugin.getStorage().saveUser(user);
|
||||
plugin.getUserManager().cleanup(user);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Migrate the user's groups to LuckPerms from PP.
|
||||
Callback<Map<String, List<CachedGroup>>> callback = groups1 -> {
|
||||
for (Map.Entry<String, List<CachedGroup>> e : groups1.entrySet()) {
|
||||
final String server;
|
||||
if (e.getKey() != null && (e.getKey().equals("") || e.getKey().equalsIgnoreCase("all"))) {
|
||||
server = null;
|
||||
} else {
|
||||
server = e.getKey();
|
||||
}
|
||||
|
||||
if (superLegacy) {
|
||||
e.getValue().stream()
|
||||
.filter(cg -> !cg.isNegated())
|
||||
.map(cg -> {
|
||||
try {
|
||||
return (Group) getGroupMethod.invoke(cg);
|
||||
} catch (IllegalAccessException | InvocationTargetException e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.forEach(g -> {
|
||||
if (g != null) {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + g.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + g.getName().toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + g.getName().toLowerCase(), true, server);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + g.getName().toLowerCase() + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
e.getValue().stream()
|
||||
.filter(g -> !g.hasExpired() && !g.isNegated())
|
||||
.forEach(g -> {
|
||||
final Group group = pm.getGroup(g.getGroupId());
|
||||
if (g.willExpire()) {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, g.getExpirationDate().getTime() / 1000L);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addtempgroup " + group.getName().toLowerCase() + " " + g.getExpirationDate().getTime() / 1000L)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, server, g.getExpirationDate().getTime() / 1000L);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addtempgroup " + group.getName().toLowerCase() + " " + g.getExpirationDate().getTime() / 1000L + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + group.getName().toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, server);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + group.getName().toLowerCase() + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update the progress so the user can be saved and unloaded.
|
||||
synchronized (progress) {
|
||||
progress.get(uuid).countDown();
|
||||
if (progress.get(uuid).getCount() == 0) {
|
||||
plugin.getStorage().saveUser(user);
|
||||
plugin.getUserManager().cleanup(user);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!legacy) {
|
||||
try {
|
||||
ListenableFuture<LinkedHashMap<String, List<CachedGroup>>> future = (ListenableFuture<LinkedHashMap<String, List<CachedGroup>>>) getPlayerGroupsMethod.invoke(pm, uuid);
|
||||
try {
|
||||
if (future.isDone()) {
|
||||
callback.onComplete(future.get());
|
||||
} else {
|
||||
future.addListener(() -> {
|
||||
try {
|
||||
callback.onComplete(future.get());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, Runnable::run);
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.info("PowerfulPerms Migration: Error");
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
getPlayerGroupsMethod.invoke(pm, uuid, new LPResultRunnable<LinkedHashMap<String, List<CachedGroup>>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onComplete(getResult());
|
||||
}
|
||||
});
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.info("PowerfulPerms Migration: Error");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All groups are migrated, but there may still be some users being migrated.
|
||||
// This block will wait for all users to be completed.
|
||||
log.info("PowerfulPerms Migration: Waiting for user migration to complete. This may take some time");
|
||||
boolean sleep = true;
|
||||
while (sleep) {
|
||||
sleep = false;
|
||||
|
||||
for (Map.Entry<UUID, CountDownLatch> e : progress.entrySet()) {
|
||||
if (e.getValue().getCount() != 0) {
|
||||
sleep = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sleep) {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We done.
|
||||
log.info("PowerfulPerms Migration: Success! Completed without any errors.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private void applyPerm(PermissionHolder holder, Permission p, LuckPermsPlugin plugin) {
|
||||
String node = p.getPermissionString();
|
||||
boolean value = true;
|
||||
if (node.startsWith("!")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
|
||||
String server = p.getServer();
|
||||
if (server != null && server.equalsIgnoreCase("all")) {
|
||||
server = null;
|
||||
}
|
||||
|
||||
String world = p.getWorld();
|
||||
if (world != null && world.equalsIgnoreCase("all")) {
|
||||
world = null;
|
||||
}
|
||||
|
||||
long expireAt = 0L;
|
||||
if (!superLegacy) {
|
||||
if (p.willExpire()) {
|
||||
expireAt = p.getExpirationDate().getTime() / 1000L;
|
||||
}
|
||||
}
|
||||
|
||||
if (world != null && server == null) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
if (world != null) {
|
||||
if (expireAt == 0L) {
|
||||
try {
|
||||
holder.setPermission(node, value, server, world);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + node + " " + value + " " + server + " " + world)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
holder.setPermission(node, value, server, world, expireAt);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("settemp " + node + " " + value + " " + expireAt + " " + server + " " + world)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (server != null) {
|
||||
if (expireAt == 0L) {
|
||||
try {
|
||||
holder.setPermission(node, value, server);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + node + " " + value + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
holder.setPermission(node, value, server, expireAt);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("settemp " + node + " " + value + " " + expireAt + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (expireAt == 0L) {
|
||||
try {
|
||||
holder.setPermission(node, value);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + node + " " + value)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
holder.setPermission(node, value, expireAt);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("settemp " + node + " " + value + " " + expireAt)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.MetaUtils;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.commands.Arg;
|
||||
import me.lucko.luckperms.common.commands.CommandException;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.constants.Constants;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.data.LogEntry;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.tracks.Track;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.utils.Predicates;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MigrationZPermissions extends SubCommand<Object> {
|
||||
public MigrationZPermissions() {
|
||||
super("zpermissions", "Migration from zPermissions", Permission.MIGRATION, Predicates.alwaysFalse(),
|
||||
Arg.list(Arg.create("world names...", false, "a list of worlds to migrate permissions from"))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) throws CommandException {
|
||||
final Logger log = plugin.getLog();
|
||||
if (!plugin.isPluginLoaded("zPermissions")) {
|
||||
log.severe("zPermissions Migration: Error -> zPermissions is not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
ZPermissionsService service = (ZPermissionsService) plugin.getService(ZPermissionsService.class);
|
||||
if (service == null) {
|
||||
log.severe("zPermissions Migration: Error -> zPermissions is not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
final List<String> worlds = args.stream()
|
||||
.map(String::toLowerCase)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Migrate all groups
|
||||
log.info("zPermissions Migration: Starting group migration.");
|
||||
for (String g : service.getAllGroups()) {
|
||||
plugin.getStorage().createAndLoadGroup(g.toLowerCase()).join();
|
||||
Group group = plugin.getGroupManager().get(g.toLowerCase());
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("create")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Boolean> e : service.getGroupPermissions(null, null, g).entrySet()) {
|
||||
try {
|
||||
group.setPermission(e.getKey(), e.getValue());
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("set " + e.getKey() + " " + e.getValue())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (worlds != null && !worlds.isEmpty()) {
|
||||
for (String world : worlds) {
|
||||
for (Map.Entry<String, Boolean> e : service.getGroupPermissions(world, null, g).entrySet()) {
|
||||
try {
|
||||
group.setPermission(e.getKey(), e.getValue(), "global", world);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("set " + e.getKey() + " true " + e.getValue() + " " + world)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(group);
|
||||
}
|
||||
|
||||
// Migrate all tracks
|
||||
log.info("zPermissions Migration: Starting track migration.");
|
||||
for (String t : service.getAllTracks()) {
|
||||
plugin.getStorage().createAndLoadTrack(t.toLowerCase()).join();
|
||||
Track track = plugin.getTrackManager().get(t.toLowerCase());
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(track).action("create")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
track.setGroups(service.getTrackGroups(t));
|
||||
for (String group : track.getGroups()) {
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(track).action("append " + group)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getStorage().saveTrack(track);
|
||||
}
|
||||
|
||||
// Migrate all users.
|
||||
log.info("zPermissions Migration: Starting user migration.");
|
||||
for (UUID u : service.getAllPlayersUUID()) {
|
||||
plugin.getStorage().loadUser(u, "null").join();
|
||||
User user = plugin.getUserManager().get(u);
|
||||
|
||||
for (Map.Entry<String, Boolean> e : service.getPlayerPermissions(null, null, u).entrySet()) {
|
||||
try {
|
||||
user.setPermission(e.getKey(), e.getValue());
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("set " + e.getKey() + " " + e.getValue())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (worlds != null && !worlds.isEmpty()) {
|
||||
for (String world : worlds) {
|
||||
for (Map.Entry<String, Boolean> e : service.getPlayerPermissions(world, null, u).entrySet()) {
|
||||
try {
|
||||
user.setPermission(e.getKey(), e.getValue(), "global", world);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("set " + e.getKey() + " true " + e.getValue() + " " + world)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String g : service.getPlayerAssignedGroups(u)) {
|
||||
try {
|
||||
user.setPermission("group." + g.toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + g.toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
user.setPrimaryGroup(service.getPlayerPrimaryGroup(u));
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("setprimarygroup " + service.getPlayerPrimaryGroup(u))
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
String prefix = service.getPlayerPrefix(u);
|
||||
String suffix = service.getPlayerSuffix(u);
|
||||
|
||||
if (prefix != null && !prefix.equals("")) {
|
||||
prefix = MetaUtils.escapeCharacters(prefix);
|
||||
try {
|
||||
user.setPermission("prefix.100." + prefix, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("set prefix.100." + prefix + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (suffix != null && !suffix.equals("")) {
|
||||
suffix = MetaUtils.escapeCharacters(suffix);
|
||||
try {
|
||||
user.setPermission("suffix.100." + suffix, true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("set suffix.100." + suffix + " true")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getUserManager().cleanup(user);
|
||||
plugin.getStorage().saveUser(user);
|
||||
}
|
||||
|
||||
log.info("zPermissions Migration: Success! Completed without any errors.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration.utils;
|
||||
|
||||
import com.github.cheesesoftware.PowerfulPermsAPI.ResultRunnable;
|
||||
|
||||
/**
|
||||
* Overrides the default ResultRunnable, callbacks will always run in the same thread. (an async one, hopefully.)
|
||||
* @param <T> type
|
||||
*/
|
||||
public abstract class LPResultRunnable<T> extends ResultRunnable<T> {
|
||||
public LPResultRunnable() {
|
||||
super();
|
||||
super.sameThread = true;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return super.result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.vault;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.caching.MetaData;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.common.core.NodeBuilder;
|
||||
import me.lucko.luckperms.common.core.PermissionHolder;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static me.lucko.luckperms.api.MetaUtils.escapeCharacters;
|
||||
import static me.lucko.luckperms.api.MetaUtils.unescapeCharacters;
|
||||
|
||||
/**
|
||||
* Provides the Vault Chat service through the use of normal permission nodes.
|
||||
*
|
||||
* Prefixes / Suffixes:
|
||||
* Normal inheritance rules apply.
|
||||
* Permission Nodes = prefix.priority.value OR suffix.priority.value
|
||||
* If a user/group has / inherits multiple prefixes and suffixes, the one with the highest priority is the one that
|
||||
* will apply.
|
||||
*
|
||||
* Meta:
|
||||
* Normal inheritance rules DO NOT apply.
|
||||
* Permission Nodes = meta.node.value
|
||||
*
|
||||
* Node that special characters used within LuckPerms are escaped:
|
||||
* See {@link me.lucko.luckperms.api.MetaUtils#unescapeCharacters(String)}
|
||||
*/
|
||||
public class VaultChatHook extends Chat {
|
||||
private final VaultPermissionHook perms;
|
||||
|
||||
VaultChatHook(VaultPermissionHook perms) {
|
||||
super(perms);
|
||||
this.perms = perms;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return perms.getName();
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return perms.isEnabled();
|
||||
}
|
||||
|
||||
private void setMeta(PermissionHolder holder, String world, String node, String value) {
|
||||
String finalWorld = perms.isIgnoreWorld() ? null : world;
|
||||
if (holder == null) return;
|
||||
if (node.equals("")) return;
|
||||
|
||||
perms.log("Setting meta: '" + node + "' for " + holder.getObjectName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
perms.getScheduler().scheduleTask(() -> {
|
||||
String k = escapeCharacters(node);
|
||||
String v = escapeCharacters(value);
|
||||
|
||||
List<Node> toRemove = holder.getNodes().stream()
|
||||
.filter(n -> n.isMeta() && n.getMeta().getKey().equals(k))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(n -> {
|
||||
try {
|
||||
holder.unsetPermission(n);
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
});
|
||||
|
||||
Node.Builder metaNode = new NodeBuilder("meta." + k + "." + v).setValue(true);
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
metaNode.setServer(perms.getServer());
|
||||
}
|
||||
if (finalWorld != null && !finalWorld.equals("")) {
|
||||
metaNode.setServer(perms.getServer()).setWorld(finalWorld);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(metaNode.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.save(holder);
|
||||
});
|
||||
}
|
||||
|
||||
private void setChatMeta(boolean prefix, PermissionHolder holder, String value, String world) {
|
||||
String finalWorld = perms.isIgnoreWorld() ? null : world;
|
||||
if (holder == null) return;
|
||||
if (value.equals("")) return;
|
||||
|
||||
perms.log("Setting " + (prefix ? "prefix" : "suffix") + " for " + holder.getObjectName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
perms.getScheduler().scheduleTask(() -> {
|
||||
Node.Builder node = new NodeBuilder(prefix ? "prefix" : "suffix" + ".1000." + escapeCharacters(value));
|
||||
node.setValue(true);
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
node.setServer(perms.getServer());
|
||||
}
|
||||
|
||||
if (finalWorld != null && !finalWorld.equals("")) {
|
||||
node.setServer(perms.getServer()).setWorld(finalWorld);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(node.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.save(holder);
|
||||
});
|
||||
}
|
||||
|
||||
private String getUserMeta(User user, String world, String node, String defaultValue) {
|
||||
if (user == null) return defaultValue;
|
||||
world = perms.isIgnoreWorld() ? null : world;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
perms.log("Getting meta: '" + node + "' for user " + user.getName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
if (user.getUserData() == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return unescapeCharacters(user.getUserData().getMetaData(perms.createContext(perms.getServer(), world)).getMeta().getOrDefault(node, defaultValue));
|
||||
}
|
||||
|
||||
private String getUserChatMeta(boolean prefix, User user, String world) {
|
||||
if (user == null) return "";
|
||||
world = perms.isIgnoreWorld() ? null : world;
|
||||
|
||||
perms.log("Getting " + (prefix ? "prefix" : "suffix") + " for user " + user.getName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
if (user.getUserData() == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
MetaData data = user.getUserData().getMetaData(perms.createContext(perms.getServer(), world));
|
||||
String v = prefix ? data.getPrefix() : data.getSuffix();
|
||||
return v == null ? "" : unescapeCharacters(v);
|
||||
}
|
||||
|
||||
private String getGroupMeta(Group group, String world, String node, String defaultValue) {
|
||||
world = perms.isIgnoreWorld() ? null : world;
|
||||
if (group == null) return defaultValue;
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
perms.log("Getting meta: '" + node + "' for group " + group.getName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
for (Node n : group.getPermissions(true)) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnServer(perms.getServer(), perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
return unescapeCharacters(meta.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private String getGroupChatMeta(boolean prefix, Group group, String world) {
|
||||
world = perms.isIgnoreWorld() ? null : world;
|
||||
if (group == null) return "";
|
||||
|
||||
perms.log("Getting " + (prefix ? "prefix" : "suffix") + " for group " + group + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
int priority = Integer.MIN_VALUE;
|
||||
String meta = null;
|
||||
|
||||
Map<String, String> context = new HashMap<>();
|
||||
context.put("server", perms.getServer());
|
||||
if (world != null) {
|
||||
context.put("world", world);
|
||||
}
|
||||
|
||||
for (Node n : group.getAllNodes(null, new Contexts(ContextSet.fromMap(context), perms.isIncludeGlobal(), true, true, true, true, false))) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix ? !n.isPrefix() : !n.isSuffix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnServer(perms.getServer(), perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> value = prefix ? n.getPrefix() : n.getSuffix();
|
||||
if (value.getKey() > priority) {
|
||||
meta = value.getValue();
|
||||
priority = value.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return meta == null ? "" : unescapeCharacters(meta);
|
||||
}
|
||||
|
||||
public String getPlayerPrefix(String world, @NonNull String player) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
return getUserChatMeta(true, user, world);
|
||||
}
|
||||
|
||||
public void setPlayerPrefix(String world, @NonNull String player, @NonNull String prefix) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setChatMeta(true, user, prefix, world);
|
||||
}
|
||||
|
||||
public String getPlayerSuffix(String world, @NonNull String player) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
return getUserChatMeta(false, user, world);
|
||||
}
|
||||
|
||||
public void setPlayerSuffix(String world, @NonNull String player, @NonNull String suffix) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setChatMeta(false, user, suffix, world);
|
||||
}
|
||||
|
||||
public String getGroupPrefix(String world, @NonNull String group) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
return getGroupChatMeta(false, g, world);
|
||||
}
|
||||
|
||||
public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setChatMeta(true, g, prefix, world);
|
||||
}
|
||||
|
||||
public String getGroupSuffix(String world, @NonNull String group) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
return getGroupChatMeta(false, g, world);
|
||||
}
|
||||
|
||||
public void setGroupSuffix(String world, @NonNull String group, @NonNull String suffix) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setChatMeta(false, g, suffix, world);
|
||||
}
|
||||
|
||||
public int getPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int defaultValue) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
try {
|
||||
return Integer.parseInt(getUserMeta(user, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int value) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public int getGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int defaultValue) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
try {
|
||||
return Integer.parseInt(getGroupMeta(g, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int value) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public double getPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double defaultValue) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
try {
|
||||
return Double.parseDouble(getUserMeta(user, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double value) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public double getGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double defaultValue) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
try {
|
||||
return Double.parseDouble(getGroupMeta(g, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double value) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public boolean getPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean defaultValue) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
String s = getUserMeta(user, world, node, String.valueOf(defaultValue));
|
||||
if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Boolean.parseBoolean(s);
|
||||
}
|
||||
|
||||
public void setPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean value) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public boolean getGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean defaultValue) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
String s = getGroupMeta(g, world, node, String.valueOf(defaultValue));
|
||||
if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Boolean.parseBoolean(s);
|
||||
}
|
||||
|
||||
public void setGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean value) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public String getPlayerInfoString(String world, @NonNull String player, @NonNull String node, String defaultValue) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
return getUserMeta(user, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setPlayerInfoString(String world, @NonNull String player, @NonNull String node, String value) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setMeta(user, world, node, value);
|
||||
}
|
||||
|
||||
public String getGroupInfoString(String world, @NonNull String group, @NonNull String node, String defaultValue) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
return getGroupMeta(g, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setGroupInfoString(String world, @NonNull String group, @NonNull String node, String value) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setMeta(g, world, node, value);
|
||||
}
|
||||
|
||||
}
|
||||
+29
-8
@@ -20,39 +20,60 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.vault;
|
||||
package me.lucko.luckperms.bukkit.vault;
|
||||
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.ServicesManager;
|
||||
|
||||
@Getter
|
||||
public class VaultHook {
|
||||
private VaultChatHook chatHook = null;
|
||||
private VaultPermissionHook permissionHook = null;
|
||||
|
||||
private static VaultChatHook chatHook = null;
|
||||
private static VaultPermissionHook permissionHook = null;
|
||||
|
||||
public static void hook(LPBukkitPlugin plugin) {
|
||||
public void hook(LPBukkitPlugin plugin) {
|
||||
try {
|
||||
if (permissionHook == null) {
|
||||
permissionHook = new VaultPermissionHook();
|
||||
}
|
||||
permissionHook.setPlugin(plugin);
|
||||
permissionHook.setServer(plugin.getConfiguration().getVaultServer());
|
||||
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIncludingGlobal());
|
||||
permissionHook.setIgnoreWorld(plugin.getConfiguration().isVaultIgnoreWorld());
|
||||
permissionHook.setPgo(plugin.getConfiguration().isVaultPrimaryGroupOverrides());
|
||||
permissionHook.setPgoCheckInherited(plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckInherited());
|
||||
permissionHook.setPgoCheckExists(plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckExists());
|
||||
permissionHook.setPgoCheckMemberOf(plugin.getConfiguration().isVaultPrimaryGroupOverridesCheckMemberOf());
|
||||
permissionHook.setup();
|
||||
|
||||
if (chatHook == null) {
|
||||
chatHook = new VaultChatHook(permissionHook);
|
||||
}
|
||||
|
||||
final ServicesManager sm = plugin.getServer().getServicesManager();
|
||||
sm.unregisterAll(plugin);
|
||||
sm.register(Permission.class, permissionHook, plugin, ServicePriority.High);
|
||||
sm.register(Chat.class, chatHook, plugin, ServicePriority.Lowest);
|
||||
sm.register(Chat.class, chatHook, plugin, ServicePriority.High);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void unhook(LPBukkitPlugin plugin) {
|
||||
final ServicesManager sm = plugin.getServer().getServicesManager();
|
||||
if (permissionHook != null) {
|
||||
sm.unregister(Permission.class, permissionHook);
|
||||
}
|
||||
if (chatHook != null) {
|
||||
sm.unregister(Chat.class, chatHook);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isHooked() {
|
||||
return permissionHook != null && chatHook != null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.vault;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.LocalizedNode;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.caching.PermissionData;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.common.core.PermissionHolder;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The LuckPerms Vault Permission implementation
|
||||
* Most lookups are cached.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class VaultPermissionHook extends Permission {
|
||||
private LPBukkitPlugin plugin;
|
||||
|
||||
@Setter(value = AccessLevel.NONE)
|
||||
private VaultScheduler scheduler;
|
||||
|
||||
private String server = "global";
|
||||
private boolean includeGlobal = true;
|
||||
private boolean ignoreWorld = false;
|
||||
|
||||
// Primary Group override settings
|
||||
private boolean pgo = false;
|
||||
private boolean pgoCheckInherited = false;
|
||||
private boolean pgoCheckExists = true;
|
||||
private boolean pgoCheckMemberOf = true;
|
||||
|
||||
public void setup() {
|
||||
scheduler = new VaultScheduler(plugin);
|
||||
}
|
||||
|
||||
public void log(String s) {
|
||||
if (plugin.getConfiguration().isVaultDebug()) {
|
||||
plugin.getLog().info("[VAULT] " + s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "LuckPerms";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return plugin.getStorage().isAcceptingLogins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSuperPermsCompat() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method to add a permission to a holder
|
||||
* @param world the world to add in
|
||||
* @param holder the holder to add the permission to
|
||||
* @param permission the permission to add
|
||||
*/
|
||||
private void add(String world, PermissionHolder holder, String permission) {
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
holder.setPermission(permission, true, server, world);
|
||||
} else {
|
||||
holder.setPermission(permission, true, server);
|
||||
}
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
save(holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method to remove a permission from a holder
|
||||
* @param world the world to remove in
|
||||
* @param holder the holder to remove the permission from
|
||||
* @param permission the permission to remove
|
||||
*/
|
||||
private void remove(String world, PermissionHolder holder, String permission) {
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
holder.unsetPermission(permission, server, world);
|
||||
} else {
|
||||
holder.unsetPermission(permission, server);
|
||||
}
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
|
||||
save(holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for saving a user or group
|
||||
* @param holder the holder instance
|
||||
*/
|
||||
void save(PermissionHolder holder) {
|
||||
if (holder instanceof User) {
|
||||
plugin.getStorage().saveUser(((User) holder))
|
||||
.thenRunAsync(() -> ((User) holder).getRefreshBuffer().request(), plugin.getAsyncExecutor());
|
||||
}
|
||||
if (holder instanceof Group) {
|
||||
plugin.getStorage().saveGroup(((Group) holder))
|
||||
.thenRunAsync(() -> plugin.getUpdateTaskBuffer().request(), plugin.getAsyncExecutor());
|
||||
}
|
||||
}
|
||||
|
||||
Contexts createContext(String server, String world) {
|
||||
Map<String, String> context = new HashMap<>();
|
||||
if (world != null && !world.equals("")) {
|
||||
context.put("world", world);
|
||||
}
|
||||
context.put("server", server);
|
||||
return new Contexts(ContextSet.fromMap(context), isIncludeGlobal(), true, true, true, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHas(String world, @NonNull String player, @NonNull String permission) {
|
||||
world = ignoreWorld ? null : world; // Correct world value
|
||||
log("Checking if player " + player + " has permission: " + permission + " on world " + world + ", server " + server);
|
||||
|
||||
User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
if (user.getUserData() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Effectively fallback to the standard Bukkit #hasPermission check.
|
||||
return user.getUserData().getPermissionData(createContext(server, world)).getPermissionValue(permission).asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAdd(String world, @NonNull String player, @NonNull String permission) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Adding permission to player " + player + ": '" + permission + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> add(finalWorld, user, permission));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemove(String world, @NonNull String player, @NonNull String permission) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Removing permission from player " + player + ": '" + permission + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> remove(finalWorld, user, permission));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupHas(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
world = ignoreWorld ? null : world; // Correct world value
|
||||
log("Checking if group " + groupName + " has permission: " + permission + " on world " + world + ", server " + server);
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
// This is a nasty call. Groups aren't cached. :(
|
||||
Map<String, Boolean> permissions = group.exportNodes(createContext(server, world), true);
|
||||
|
||||
return permissions.containsKey(permission) && permissions.get(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupAdd(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Adding permission to group " + groupName + ": '" + permission + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> add(finalWorld, group, permission));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupRemove(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Removing permission from group " + groupName + ": '" + permission + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> remove(finalWorld, group, permission));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerInGroup(String world, @NonNull String player, @NonNull String group) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Checking if player " + player + " is in group: " + group + " on world " + finalWorld + ", server " + server);
|
||||
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
return user.getNodes().stream()
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false))
|
||||
.filter(n -> n.shouldApplyOnWorld(finalWorld, true, false))
|
||||
.map(Node::getGroupName)
|
||||
.filter(s -> s.equalsIgnoreCase(group))
|
||||
.findAny().isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAddGroup(String world, @NonNull String player, @NonNull String groupName) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Adding player " + player + " to group: '" + groupName + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> {
|
||||
try {
|
||||
if (finalWorld != null && !finalWorld.equals("")) {
|
||||
user.setInheritGroup(group, server, finalWorld);
|
||||
} else {
|
||||
user.setInheritGroup(group, server);
|
||||
}
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
save(user);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemoveGroup(String world, @NonNull String player, @NonNull String groupName) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Removing player " + player + " from group: '" + groupName + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> {
|
||||
try {
|
||||
if (finalWorld != null && !finalWorld.equals("")) {
|
||||
user.unsetInheritGroup(group, server, finalWorld);
|
||||
} else {
|
||||
user.unsetInheritGroup(group, server);
|
||||
}
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
save(user);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPlayerGroups(String world, @NonNull String player) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Getting groups of player: " + player + ", on world " + finalWorld + ", server " + server);
|
||||
|
||||
User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return new String[0];
|
||||
|
||||
return user.getNodes().stream()
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false))
|
||||
.filter(n -> n.shouldApplyOnWorld(finalWorld, true, false))
|
||||
.map(Node::getGroupName)
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimaryGroup(String world, @NonNull String player) {
|
||||
world = ignoreWorld ? null : world; // Correct world value
|
||||
log("Getting primary group of player: " + player);
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!pgo) {
|
||||
return user.getPrimaryGroup();
|
||||
}
|
||||
|
||||
if (pgoCheckInherited) {
|
||||
PermissionData data = user.getUserData().getPermissionData(createContext(server, world));
|
||||
for (Map.Entry<String, Boolean> e : data.getImmutableBacking().entrySet()) {
|
||||
if (!e.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!e.getKey().toLowerCase().startsWith("vault.primarygroup.")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String group = e.getKey().substring("vault.primarygroup.".length());
|
||||
if (pgoCheckExists) {
|
||||
if (!plugin.getGroupManager().isLoaded(group)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (pgoCheckMemberOf) {
|
||||
if (data.getPermissionValue("group." + group) != Tristate.TRUE) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
} else {
|
||||
for (LocalizedNode node : user.getPermissions(true)) {
|
||||
if (!node.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.getPermission().toLowerCase().startsWith("vault.primarygroup.")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.shouldApplyOnServer(server, isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.shouldApplyOnWorld(world, true, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String group = node.getPermission().substring("vault.primarygroup.".length());
|
||||
if (pgoCheckExists) {
|
||||
if (!plugin.getGroupManager().isLoaded(group)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (pgoCheckMemberOf) {
|
||||
if (!user.getLocalGroups(server, world, isIncludeGlobal()).contains(group.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return user.getPrimaryGroup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return plugin.getGroupManager().getAll().keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGroupSupport() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+22
-14
@@ -20,26 +20,34 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.misc;
|
||||
package me.lucko.luckperms.bukkit.vault;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SingleMainCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SyncCommand extends SingleMainCommand {
|
||||
public SyncCommand() {
|
||||
super("Sync", "/%s sync", 0, Permission.SYNC);
|
||||
public class VaultScheduler implements Runnable {
|
||||
private final List<Runnable> tasks = new ArrayList<>();
|
||||
|
||||
public VaultScheduler(LPBukkitPlugin plugin) {
|
||||
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, this, 1L, 1L);
|
||||
}
|
||||
|
||||
public void scheduleTask(Runnable r) {
|
||||
synchronized (tasks) {
|
||||
tasks.add(r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
|
||||
Message.UPDATE_TASK_RUN.send(sender);
|
||||
plugin.runUpdateTask();
|
||||
return CommandResult.SUCCESS;
|
||||
public void run() {
|
||||
List<Runnable> toRun = new ArrayList<>();
|
||||
synchronized (tasks) {
|
||||
toRun.addAll(tasks);
|
||||
tasks.clear();
|
||||
}
|
||||
|
||||
toRun.forEach(Runnable::run);
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.users;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
|
||||
import me.lucko.luckperms.api.implementation.internal.UserLink;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BukkitUser extends User {
|
||||
private static Field permissionsField = null;
|
||||
private static Field getPermissionsField() {
|
||||
if (permissionsField == null) {
|
||||
try {
|
||||
permissionsField = PermissionAttachment.class.getDeclaredField("permissions");
|
||||
permissionsField.setAccessible(true);
|
||||
} catch (SecurityException | NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return permissionsField;
|
||||
}
|
||||
|
||||
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private PermissionAttachment attachment = null;
|
||||
|
||||
BukkitUser(UUID uuid, LPBukkitPlugin plugin) {
|
||||
super(uuid, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
BukkitUser(UUID uuid, String username, LPBukkitPlugin plugin) {
|
||||
super(uuid, username, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void refreshPermissions() {
|
||||
plugin.doSync(() -> {
|
||||
final Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid()));
|
||||
if (player == null) return;
|
||||
|
||||
if (attachment == null) {
|
||||
getPlugin().getLog().warn("User " + getName() + " does not have a permissions attachment defined.");
|
||||
setAttachment(player.addAttachment(plugin));
|
||||
}
|
||||
|
||||
// Calculate the permissions that should be applied
|
||||
Map<String, Boolean> toApply = getLocalPermissions(getPlugin().getConfiguration().getServer(), player.getWorld().getName(), null);
|
||||
|
||||
try {
|
||||
Map<String, Boolean> existing = (Map<String, Boolean>) getPermissionsField().get(attachment);
|
||||
|
||||
boolean different = false;
|
||||
if (toApply.size() != existing.size()) {
|
||||
different = true;
|
||||
} else {
|
||||
for (Map.Entry<String, Boolean> e : existing.entrySet()) {
|
||||
if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) {
|
||||
continue;
|
||||
}
|
||||
different = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!different) return;
|
||||
|
||||
// Faster than recalculating permissions after each PermissionAttachment#setPermission
|
||||
existing.clear();
|
||||
existing.putAll(toApply);
|
||||
attachment.getPermissible().recalculatePermissions();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.users;
|
||||
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
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;
|
||||
|
||||
public BukkitUserManager(LPBukkitPlugin plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(User user) {
|
||||
if (user != null) {
|
||||
|
||||
if (user instanceof BukkitUser) {
|
||||
BukkitUser u = (BukkitUser) user;
|
||||
|
||||
if (u.getAttachment() != null) {
|
||||
Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid()));
|
||||
|
||||
if (player != null) {
|
||||
player.removeAttachment(u.getAttachment());
|
||||
}
|
||||
u.setAttachment(null);
|
||||
}
|
||||
}
|
||||
|
||||
getAll().remove(user.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup(User user) {
|
||||
if (plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) {
|
||||
unload(user);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User make(UUID uuid) {
|
||||
return new BukkitUser(uuid, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User make(UUID uuid, String username) {
|
||||
return new BukkitUser(uuid, username, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAllUsers() {
|
||||
// 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)));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -5,54 +5,260 @@
|
||||
# +------------------------------------------------------------------------+ #
|
||||
##############################################################################
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | General | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# The name of the server, used for server specific permissions. Set to 'global' to disable.
|
||||
server: global
|
||||
|
||||
# The default group assigned to all users on their first join.
|
||||
default-group: default
|
||||
|
||||
# If users on this server should have their global permissions/groups applied.
|
||||
# If users on this server should have their global permissions applied.
|
||||
# If set to false, only server specific permissions will apply for users on this server
|
||||
include-global: true
|
||||
|
||||
# If users on this server should have their global world permissions applied.
|
||||
# If set to false, only world specific permissions will apply for users on this server
|
||||
include-global-world: true
|
||||
|
||||
# If users on this server should have global (non-server specific) groups applied
|
||||
apply-global-groups: true
|
||||
|
||||
# If users on this server should have global (non-world specific) groups applied
|
||||
apply-global-world-groups: 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, despite 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)
|
||||
#
|
||||
# 3. If your proxy is running in offline mode, and you are using PaperSpigot (https://ci.destroystokyo.com/job/PaperSpigot/),
|
||||
# you should set "bungee-online-mode" to false in the paper.yml, and set "online-mode" to true in all LuckPerms configs.
|
||||
# This approach is thoroughly recommended for offline mode networks.
|
||||
online-mode: true
|
||||
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
log-notify: true
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | Permission Calculation | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
# If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered permissions matching
|
||||
# the wildcard. This will only work for plugins that define all of their permissions to the server.
|
||||
# the wildcard.
|
||||
apply-wildcards: true
|
||||
|
||||
# If the plugin should parse regex permissions.
|
||||
# If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the node, and resolve &
|
||||
# apply all registered permissions matching the regex. This will only work for plugins that define all of their
|
||||
# permissions to the server.
|
||||
# apply all registered permissions matching the regex.
|
||||
apply-regex: true
|
||||
|
||||
# If the plugin should complete and apply shorthand permissions.
|
||||
# If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||
apply-shorthand: true
|
||||
|
||||
# Define special group weights for this server.
|
||||
# Default is just 0.
|
||||
group-weight:
|
||||
# admin: 10
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | OP (Server Operator) Settings | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# If the vanilla OP system is enabled. If set to false, all users will be de-opped, and the op/deop commands will be disabled.
|
||||
enable-ops: true
|
||||
|
||||
# If set to true, any user with the permission "luckperms.autoop" will automatically be granted server operator status.
|
||||
# This permission can be inherited, or set on specific servers/worlds, temporarily, etc.
|
||||
# Additionally, setting this to true will force the "enable-ops" option above to false. All users will be de-opped unless
|
||||
# they have the permission node, and the op/deop commands will be disabled.
|
||||
#
|
||||
# It is important to note that this setting is only checked when a player first joins the server, and when they switch
|
||||
# worlds. Therefore, simply removing this permission from a user will not automatically de-op them. A player needs to
|
||||
# relog to have the change take effect.
|
||||
#
|
||||
# It is recommended that you use this option instead of assigning a single '*' permission.
|
||||
auto-op: false
|
||||
|
||||
# If opped players should be allowed to use LuckPerms commands. Set to false to only allow users who have the permissions access to the commands
|
||||
commands-allow-op: true
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | Vault | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# The name of the server used within Vault operations. If you don't want Vault operations to be server specific, set this
|
||||
# to "global".
|
||||
vault-server: global
|
||||
|
||||
# If global permissions should be considered when retrieving meta or player groups
|
||||
vault-include-global: true
|
||||
|
||||
# If Vault operations should ignore any world arguments if supplied.
|
||||
vault-ignore-world: false
|
||||
|
||||
# This block controls the Primary Group override feature
|
||||
# See the wiki for more information.
|
||||
vault-primary-groups-overrides:
|
||||
# If the feature is enabled
|
||||
enabled: false
|
||||
# If the check should query the user's inherited permissions.
|
||||
# (a value of false only checks the permissions they explicitly have)
|
||||
check-inherited-permissions: false
|
||||
# If LuckPerms should check if the group exists
|
||||
check-group-exists: true
|
||||
# If LuckPerms should check if the user is actually a member of the group
|
||||
check-user-member-of: true
|
||||
|
||||
# If LuckPerms should print debugging info to console when a plugin uses a Vault function
|
||||
vault-debug: false
|
||||
|
||||
# Mirrors world names. Whenever LuckPerms checks what world a user is in, if the world name is in this list, the value assigned
|
||||
# will be sent forward for permission calculation instead.
|
||||
world-rewrite:
|
||||
# world_nether: world
|
||||
# world_the_end: world
|
||||
|
||||
# Rewrites group names. The underlying name of the group does not change, just the output in commands / placeholders / Vault.
|
||||
group-name-rewrite:
|
||||
# default: Member
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | Storage | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
||||
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
|
||||
# Fill out connection info below if you're using MySQL or MongoDB
|
||||
storage-method: h2
|
||||
|
||||
# This block enables support for split datastores.
|
||||
split-storage:
|
||||
enabled: false
|
||||
methods:
|
||||
user: h2
|
||||
group: h2
|
||||
track: h2
|
||||
uuid: h2
|
||||
log: h2
|
||||
|
||||
data:
|
||||
address: localhost:3306
|
||||
database: minecraft
|
||||
username: root
|
||||
password: ''
|
||||
pool-size: 10 # The size of the MySQL connection pool.
|
||||
|
||||
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
|
||||
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
|
||||
sync-minutes: 3
|
||||
sync-minutes: 3
|
||||
|
||||
# Settings for Redis.
|
||||
#
|
||||
# If enabled and configured, LuckPerms will use the Redis PubSub system to inform other
|
||||
# connected servers of changes. Use the command "/luckperms networksync" to push changes.
|
||||
# Data is NOT stored on redis. It is only used as a messaging platform.
|
||||
#
|
||||
# If you decide to enable this feature, you should set "sync-minutes" to -1, as there is no need for LuckPerms
|
||||
# to poll the database for changes.
|
||||
redis:
|
||||
enabled: false
|
||||
address: localhost:6379
|
||||
password: ''
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | Default Assignments | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# This section allows you to define defaults to give users whenever they connect to the server.
|
||||
# The default assignments are highly configurable and conditional.
|
||||
#
|
||||
# There is one default assignment built into LuckPerms, which will add all users to the "default" group if they
|
||||
# are not a member of any other group. This setting cannot be disabled. However, you can use this section to add more of
|
||||
# your own.
|
||||
#
|
||||
# IMPORTANT:
|
||||
# In order to save storage space, LuckPerms does not store users who have no permissions defined, and are only a member
|
||||
# of the default group. Adding default assignments to this section will negate this effect. It is HIGHLY RECCOMENDED
|
||||
# that instead of assigning defaults here, you add permissions to the "default" group, or set the "default" group to inherit
|
||||
# other groups, and then use the group-name-rewrite rule above.
|
||||
#
|
||||
# It is also important to note that these rules are considered every time a player logs into the server, and are applied
|
||||
# directly to the user's data. Simply removing a rule here will not reserse the effect of that rule on any users who have
|
||||
# already had it applied to them.
|
||||
#
|
||||
# The "has" and "lacks" conditions below support standard boolean logic, using the 'and' & 'or' characters used in Java.
|
||||
# e.g. "(some.other.permission | some.permission.other) & some.thing.else" == a user has 'some.other.permission', or
|
||||
# 'some.permission.other', and they also have 'some.thing.else'
|
||||
#
|
||||
# Groups are represented by the permission node: group.<group name>
|
||||
# Per server and per world nodes are represented by: "server-world/permission" or "server/permission"
|
||||
#
|
||||
# Within conditions, permission nodes MUST be escaped using "<" and ">". See the example below.
|
||||
#
|
||||
# Explaination of the examples below: (they're just to demonstrate the features & use cases)
|
||||
#
|
||||
# rule1:
|
||||
# If a user is either in the vip or vip+ group, and they have the "titles.titlecollector" permission set to true, and the
|
||||
# "some.random.permission" set to false... if they're not in the group "prison_titlepack" on the "prison" server, then
|
||||
# give add them to the "prison_titlepack" group on the "prison" server, and remove "some.random.permission".
|
||||
#
|
||||
# rule2:
|
||||
# If the user isn't in any of the following groups on the skyblock server: sb_level1, sb_level2, sb_level3, then add
|
||||
# them to sb_level1 on the skyblock server.
|
||||
#
|
||||
# rule3:
|
||||
# If the user is a member of the default group, remove them from default, add them to member, and set their primary group
|
||||
# to member.
|
||||
#
|
||||
# WARNING: Unlike internal commands, this system does not ensure that a group exists before adding a user to it.
|
||||
# It also does not unsure that a user is a member of a group before making that group their primary group.
|
||||
#
|
||||
# Before you use "give: group.<name>" or "set-primary-group", make sure that the group exists, and that the user is
|
||||
# a member of the group.
|
||||
default-assignments:
|
||||
# rule1:
|
||||
# if:
|
||||
# has-true: (<group.vip> | <group.vip+>) & <titles.tilecollector>
|
||||
# has-false: <some.random.permission>
|
||||
# lacks: <prison/group.prison_titlepack>
|
||||
# give:
|
||||
# - prison/group.prison_titlepack
|
||||
# take:
|
||||
# - some.random.permission
|
||||
# rule2:
|
||||
# if:
|
||||
# lacks: <skyblock/group.sb_level1> & <skyblock/group.sb_level2> & <skyblock/group.sb_level3>
|
||||
# give:
|
||||
# - skyblock/group.sb_level1
|
||||
# rule3:
|
||||
# if:
|
||||
# has-true: <group.default>
|
||||
# take:
|
||||
# - group.default
|
||||
# give:
|
||||
# - group.member
|
||||
# set-primary-group: member
|
||||
@@ -1,126 +1,16 @@
|
||||
name: LuckPerms
|
||||
author: Luck
|
||||
version: ${release.version}.${git.closest.tag.commit.count}
|
||||
main: me.lucko.luckperms.LPBukkitPlugin
|
||||
softdepend: [Vault]
|
||||
description: A permissions plugin
|
||||
author: Luck
|
||||
website: https://github.com/lucko/LuckPerms
|
||||
|
||||
main: me.lucko.luckperms.bukkit.LPBukkitPlugin
|
||||
softdepend: [Vault, PermissionsEx, GroupManager, PowerfulPerms, zPermissions, bPermissions] # For migration
|
||||
|
||||
commands:
|
||||
luckperms:
|
||||
description: Manage permissions
|
||||
aliases: [perms, permissions, lp, p, perm]
|
||||
permissions:
|
||||
luckperms.*:
|
||||
description: Gives access to all LuckPerms commands
|
||||
children:
|
||||
luckperms.sync: true
|
||||
luckperms.info: true
|
||||
luckperms.debug: true
|
||||
luckperms.import: true
|
||||
luckperms.creategroup: true
|
||||
luckperms.deletegroup: true
|
||||
luckperms.listgroups: true
|
||||
luckperms.createtrack: true
|
||||
luckperms.deletetrack: true
|
||||
luckperms.listtracks: true
|
||||
luckperms.user.info: true
|
||||
luckperms.user.getuuid: true
|
||||
luckperms.user.listnodes: true
|
||||
luckperms.user.haspermission: true
|
||||
luckperms.user.inheritspermission: true
|
||||
luckperms.user.setpermission: true
|
||||
luckperms.user.unsetpermission: true
|
||||
luckperms.user.addgroup: true
|
||||
luckperms.user.removegroup: true
|
||||
luckperms.user.settemppermission: true
|
||||
luckperms.user.unsettemppermission: true
|
||||
luckperms.user.addtempgroup: true
|
||||
luckperms.user.removetempgroup: true
|
||||
luckperms.user.setprimarygroup: true
|
||||
luckperms.user.showtracks: true
|
||||
luckperms.user.promote: true
|
||||
luckperms.user.demote: true
|
||||
luckperms.user.showpos: true
|
||||
luckperms.user.clear: true
|
||||
luckperms.group.info: true
|
||||
luckperms.group.listnodes: true
|
||||
luckperms.group.haspermission: true
|
||||
luckperms.group.inheritspermission: true
|
||||
luckperms.group.setpermission: true
|
||||
luckperms.group.unsetpermission: true
|
||||
luckperms.group.setinherit: true
|
||||
luckperms.group.unsetinherit: true
|
||||
luckperms.group.settemppermission: true
|
||||
luckperms.group.unsettemppermission: true
|
||||
luckperms.group.settempinherit: true
|
||||
luckperms.group.unsettempinherit: true
|
||||
luckperms.group.showtracks: true
|
||||
luckperms.group.clear: true
|
||||
luckperms.track.info: true
|
||||
luckperms.track.append: true
|
||||
luckperms.track.insert: true
|
||||
luckperms.track.remove: true
|
||||
luckperms.track.clear: true
|
||||
luckperms.log.export: true
|
||||
luckperms.log.userhistory: true
|
||||
luckperms.log.grouphistory: true
|
||||
luckperms.log.trackhistory: true
|
||||
luckperms.log.notify: true
|
||||
luckperms.log.recent: true
|
||||
luckperms.log.search: true
|
||||
luckperms.user.*:
|
||||
description: Gives access to all LuckPerms user commands
|
||||
children:
|
||||
luckperms.user.info: true
|
||||
luckperms.user.getuuid: true
|
||||
luckperms.user.listnodes: true
|
||||
luckperms.user.haspermission: true
|
||||
luckperms.user.inheritspermission: true
|
||||
luckperms.user.setpermission: true
|
||||
luckperms.user.unsetpermission: true
|
||||
luckperms.user.addgroup: true
|
||||
luckperms.user.removegroup: true
|
||||
luckperms.user.settemppermission: true
|
||||
luckperms.user.unsettemppermission: true
|
||||
luckperms.user.addtempgroup: true
|
||||
luckperms.user.removetempgroup: true
|
||||
luckperms.user.setprimarygroup: true
|
||||
luckperms.user.showtracks: true
|
||||
luckperms.user.promote: true
|
||||
luckperms.user.demote: true
|
||||
luckperms.user.showpos: true
|
||||
luckperms.user.clear: true
|
||||
luckperms.group.*:
|
||||
description: Gives access to all LuckPerms group commands
|
||||
children:
|
||||
luckperms.group.info: true
|
||||
luckperms.group.listnodes: true
|
||||
luckperms.group.haspermission: true
|
||||
luckperms.group.inheritspermission: true
|
||||
luckperms.group.setpermission: true
|
||||
luckperms.group.unsetpermission: true
|
||||
luckperms.group.setinherit: true
|
||||
luckperms.group.unsetinherit: true
|
||||
luckperms.group.settemppermission: true
|
||||
luckperms.group.unsettemppermission: true
|
||||
luckperms.group.settempinherit: true
|
||||
luckperms.group.unsettempinherit: true
|
||||
luckperms.group.showtracks: true
|
||||
luckperms.group.clear: true
|
||||
luckperms.track.*:
|
||||
description: Gives access to all LuckPerms track commands
|
||||
children:
|
||||
luckperms.track.info: true
|
||||
luckperms.track.append: true
|
||||
luckperms.track.insert: true
|
||||
luckperms.track.remove: true
|
||||
luckperms.track.clear: true
|
||||
luckperms.log.*:
|
||||
description: Gives access to all LuckPerms log commands
|
||||
children:
|
||||
luckperms.log.export: true
|
||||
luckperms.log.userhistory: true
|
||||
luckperms.log.grouphistory: true
|
||||
luckperms.log.trackhistory: true
|
||||
luckperms.log.notify: true
|
||||
luckperms.log.recent: true
|
||||
luckperms.log.search: true
|
||||
|
||||
|
||||
# Permissions are registered programmatically instead of here.
|
||||
+24
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.5-SNAPSHOT</version>
|
||||
<version>2.14-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -65,6 +65,22 @@
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.sqlite</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.sqlite</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>redis.clients.jedis</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.jedis.jedis</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>redis.clients.util</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.jedis.util</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.apache.commons.pool2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.jedis.pool2</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
@@ -117,6 +133,13 @@
|
||||
<version>1.16.10</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- **************Migration Plugins************** -->
|
||||
<dependency>
|
||||
<groupId>net.alpenblock</groupId>
|
||||
<artifactId>BungeePerms</artifactId>
|
||||
<version>3.0-dev-52</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import me.lucko.luckperms.core.UuidCache;
|
||||
import me.lucko.luckperms.data.Importer;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.runnables.ExpireTemporaryTask;
|
||||
import me.lucko.luckperms.runnables.UpdateTask;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.storage.StorageFactory;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.BungeeUserManager;
|
||||
import me.lucko.luckperms.users.UserManager;
|
||||
import me.lucko.luckperms.utils.LogFactory;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
private final Set<UUID> ignoringLogs = new HashSet<>();
|
||||
private LPConfiguration configuration;
|
||||
private UserManager userManager;
|
||||
private GroupManager groupManager;
|
||||
private TrackManager trackManager;
|
||||
private Datastore datastore;
|
||||
private UuidCache uuidCache;
|
||||
private ApiProvider apiProvider;
|
||||
private Logger log;
|
||||
private Importer importer;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
log = LogFactory.wrap(getLogger());
|
||||
|
||||
getLog().info("Loading configuration...");
|
||||
configuration = new BungeeConfig(this);
|
||||
|
||||
// register events
|
||||
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
|
||||
|
||||
// register commands
|
||||
getLog().info("Registering commands...");
|
||||
CommandManager commandManager = new CommandManager(this);
|
||||
getProxy().getPluginManager().registerCommand(this, new BungeeCommand(commandManager));
|
||||
|
||||
// disable the default Bungee /perms command so it gets handled by the Bukkit plugin
|
||||
getProxy().getDisabledCommands().add("perms");
|
||||
|
||||
datastore = StorageFactory.getDatastore(this, "h2");
|
||||
|
||||
getLog().info("Loading internal permission managers...");
|
||||
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
|
||||
userManager = new BungeeUserManager(this);
|
||||
groupManager = new GroupManager(this);
|
||||
trackManager = new TrackManager();
|
||||
importer = new Importer(commandManager);
|
||||
|
||||
// Run update task to refresh any online users
|
||||
getLog().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);
|
||||
}
|
||||
|
||||
// 20 times per second (once per "tick")
|
||||
getProxy().getScheduler().schedule(this, BungeeSenderFactory.get(), 50L, 50L, TimeUnit.MILLISECONDS);
|
||||
getProxy().getScheduler().schedule(this, new ExpireTemporaryTask(this), 3L, 3L, TimeUnit.SECONDS);
|
||||
|
||||
getLog().info("Registering API...");
|
||||
apiProvider = new ApiProvider(this);
|
||||
LuckPerms.registerProvider(apiProvider);
|
||||
|
||||
getLog().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLog().info("Closing datastore...");
|
||||
datastore.shutdown();
|
||||
|
||||
getLog().info("Unregistering API...");
|
||||
LuckPerms.unregisterProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getMainDir() {
|
||||
return getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getPlayerStatus(UUID uuid) {
|
||||
return getProxy().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getProxy().getOnlineCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPlayerList() {
|
||||
return getProxy().getPlayers().stream().map(ProxiedPlayer::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getSenders() {
|
||||
return getProxy().getPlayers().stream().map(p -> BungeeSenderFactory.get().wrap(p)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return BungeeSenderFactory.get().wrap(getProxy().getConsole());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPossiblePermissions() {
|
||||
// No such thing on Bungee. Wildcards are processed in the listener instead.
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runUpdateTask() {
|
||||
doAsync(new UpdateTask(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
getProxy().getScheduler().runAsync(this, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import me.lucko.luckperms.api.context.ContextCalculator;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
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.util.Map;
|
||||
|
||||
public class BackendServerCalculator extends ContextCalculator<ProxiedPlayer> implements Listener {
|
||||
private static final String WORLD_KEY = "world";
|
||||
|
||||
@Override
|
||||
public MutableContextSet giveApplicableContext(ProxiedPlayer subject, MutableContextSet accumulator) {
|
||||
String server = getServer(subject);
|
||||
|
||||
if (server != null) {
|
||||
accumulator.add(Maps.immutableEntry(WORLD_KEY, server));
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isContextApplicable(ProxiedPlayer subject, Map.Entry<String, String> context) {
|
||||
if (!context.getKey().equals(WORLD_KEY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String server = getServer(subject);
|
||||
return server != null && server.equals(context.getValue());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerServerSwitch(ServerSwitchEvent e) {
|
||||
pushUpdate(e.getPlayer(), Maps.immutableEntry("null", "null"), Maps.immutableEntry(WORLD_KEY, getServer(e.getPlayer())));
|
||||
}
|
||||
|
||||
private static String getServer(ProxiedPlayer player) {
|
||||
return player.getServer() == null ? null : (player.getServer().getInfo() == null ? null : player.getServer().getInfo().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.common.calculators.*;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class BungeeCalculatorFactory implements CalculatorFactory {
|
||||
private final LPBungeePlugin plugin;
|
||||
|
||||
@Override
|
||||
public PermissionCalculator build(Contexts contexts, User user) {
|
||||
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
|
||||
processors.add(new MapProcessor());
|
||||
if (plugin.getConfiguration().isApplyingWildcards()) {
|
||||
processors.add(new WildcardProcessor());
|
||||
}
|
||||
if (plugin.getConfiguration().isApplyingRegex()) {
|
||||
processors.add(new RegexProcessor());
|
||||
}
|
||||
|
||||
return new PermissionCalculator(plugin, user.getName(), processors.build());
|
||||
}
|
||||
}
|
||||
+16
-5
@@ -20,10 +20,14 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.utils.Util;
|
||||
import me.lucko.luckperms.common.constants.Patterns;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
@@ -31,20 +35,27 @@ import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
import java.util.Arrays;
|
||||
|
||||
class BungeeCommand extends Command implements TabExecutor {
|
||||
private final LPBungeePlugin plugin;
|
||||
private final CommandManager manager;
|
||||
|
||||
BungeeCommand(CommandManager manager) {
|
||||
BungeeCommand(LPBungeePlugin plugin, CommandManager manager) {
|
||||
super("luckpermsbungee", null, "bperms", "lpb", "bpermissions", "bp", "bperm");
|
||||
this.plugin = plugin;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
manager.onCommand(BungeeSenderFactory.get().wrap(sender), "bperms", Arrays.asList(args), Callback.empty());
|
||||
manager.onCommand(
|
||||
plugin.getSenderFactory().wrap(sender),
|
||||
"bperms",
|
||||
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
|
||||
Callback.empty()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return manager.onTabComplete(BungeeSenderFactory.get().wrap(sender), Arrays.asList(args));
|
||||
return manager.onTabComplete(plugin.getSenderFactory().wrap(sender), Arrays.asList(args));
|
||||
}
|
||||
}
|
||||
+38
-8
@@ -20,9 +20,9 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import me.lucko.luckperms.common.config.AbstractConfiguration;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
import net.md_5.bungee.config.ConfigurationProvider;
|
||||
import net.md_5.bungee.config.YamlConfiguration;
|
||||
@@ -31,8 +31,13 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class BungeeConfig extends LPConfiguration<LPBungeePlugin> {
|
||||
class BungeeConfig extends AbstractConfiguration<LPBungeePlugin> {
|
||||
private Configuration configuration;
|
||||
|
||||
BungeeConfig(LPBungeePlugin plugin) {
|
||||
@@ -62,11 +67,6 @@ class BungeeConfig extends LPConfiguration<LPBungeePlugin> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void set(String path, Object value) {
|
||||
configuration.set(path, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getString(String path, String def) {
|
||||
return configuration.getString(path, def);
|
||||
@@ -81,4 +81,34 @@ class BungeeConfig extends LPConfiguration<LPBungeePlugin> {
|
||||
protected boolean getBoolean(String path, boolean def) {
|
||||
return configuration.getBoolean(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getList(String path, List<String> def) {
|
||||
return Optional.ofNullable(configuration.getStringList(path)).orElse(def);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getObjectList(String path, List<String> def) {
|
||||
Configuration section = configuration.getSection(path);
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return Optional.ofNullable(section.getKeys().stream().collect(Collectors.toList())).orElse(def);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getMap(String path, Map<String, String> def) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
Configuration section = configuration.getSection(path);
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
for (String key : section.getKeys()) {
|
||||
map.put(key, section.getString(key));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 372 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user