Compare commits

..
241 Commits
Author SHA1 Message Date
Luck 3424b0542a Release 2.10 2016-09-25 17:32:58 +01:00
Luck fec90b8958 Add bulkchange commands 2016-09-25 17:29:11 +01:00
Luck 4da7fe4ff9 Small fixes to context system 2016-09-25 16:55:14 +01:00
Luck c53623dd67 Make command usage output easier to read 2016-09-25 14:34:27 +01:00
Luck 6540ffa4dd Refactor storage 2016-09-25 12:47:15 +01:00
Luck 5ee6db02ff Proper context implementation - WIP 2016-09-25 10:19:36 +01:00
Luck d8221f466a Fix messages not being formatted correctly 2016-09-24 17:22:33 +01:00
Luck 462bea2a09 Remove broken repo, maybe fix build 2016-09-24 16:58:45 +01:00
Luck f452a97278 fix typo 2016-09-23 22:19:17 +01:00
Luck eb9d2be587 Add locale file support 2016-09-23 22:14:40 +01:00
Luck df1e747861 Add commands to view inherited groups 2016-09-23 19:23:31 +01:00
Luck f48595b1ff Add world and group name rewriting, refactor configs 2016-09-23 18:58:19 +01:00
Luck 12cd4e19cb Update config comments 2016-09-22 18:25:49 +01:00
Luck a195e94522 Calculate defaults after all plugins have loaded 2016-09-22 17:34:51 +01:00
Luck 02abb39dc2 Change #isPermissionSet to be more like the Bukkit impl 2016-09-21 22:04:18 +01:00
Luck f7a0b1ef78 Refactor default permissions to be less bad 2016-09-21 21:30:42 +01:00
Luck 7678f25879 Fix default permissions not properly applying on Bukkit 2016-09-21 17:40:05 +01:00
Luck fa9324bda8 Implement basic standalone base, working towards #9 2016-09-20 21:50:28 +01:00
Luck 1e72f9d8fe Listen on lowest priority, may fix issues with plugins checking for permissions on login events 2016-09-20 21:04:53 +01:00
Luck 50fd954599 Use a BiMap in UuidCache 2016-09-19 21:13:45 +01:00
Luck b1e34b55f8 Re-add regex permissions & actually take note of the config options 2016-09-19 21:00:23 +01:00
Luck cff1b8a411 Separate PermissionProcessor into own class 2016-09-19 20:45:37 +01:00
Luck 6ffa6720be Make more specific wildcards take priority over less specific ones 2016-09-19 20:36:52 +01:00
Luck f52a106165 Order nodes alphabetically after other priority rules have been applied 2016-09-19 17:31:00 +01:00
Luck bf247b71e1 Fix possible race condition & maybe use better Hikari flags 2016-09-18 23:13:20 +01:00
Luck 66818e4c82 Fix build 2016-09-17 23:46:11 +01:00
Luck 23d53d39b4 Refactor permission calculation 2016-09-17 23:15:07 +01:00
Luck 30ea5a5b69 Fix no permissions applying when include-global is false, and better support per-server/per-world groups 2016-09-17 19:05:56 +01:00
Luck e7a210dc06 Update default configs 2016-09-16 22:09:55 +01:00
Luck 497de9824a Actually pass on a single wildcard node so it gets applied 2016-09-16 21:46:55 +01:00
Luck be74b50762 Fixes for offline mode servers 2016-09-16 21:24:25 +01:00
Luck f2e06b56e7 Cache permission lookups 2016-09-16 21:11:12 +01:00
Luck f6aa20c300 Fix compile 2016-09-15 17:12:19 +01:00
Luck 5e16134f6f Provide prefixes and suffixes through the PS options 2016-09-15 17:06:27 +01:00
Luck 6165fcbb21 Fix #getDefaults for users 2016-09-15 16:54:12 +01:00
Luck 831e882db0 Actually apply default permissions on Sponge 2016-09-15 16:53:03 +01:00
Luck feb8bf4bd3 Update readme 2016-09-14 20:16:36 +01:00
Luck ce3ee866ca Sponge fixes 2016-09-14 19:37:20 +01:00
Luck d29dd35689 Support the latest powerfulperms so-called "api" 2016-09-13 20:14:16 +01:00
Luck 3a0a89853f Apply negated wildcards 2016-09-13 17:23:16 +01:00
Luck e7ca79d251 Use Splitter instead of Patterns, don't split arguments in quotes 2016-09-12 19:00:37 +01:00
Luck 22426bab33 Update placeholders to use the latest API version 2016-09-11 15:36:19 +01:00
Luck 116094ea96 Maybe fix an issue with per-server prefixes/suffixes 2016-09-11 14:34:38 +01:00
Luck 9df39a9545 Inject PermissibleBase instead of using attachments. Resolves #14 2016-09-11 11:50:59 +01:00
Luck b8f44df723 Add missing headers 2016-09-10 22:40:36 +01:00
Luck 74f275eb69 Add more info the importer error output 2016-09-10 22:08:07 +01:00
Luck 1142cbcb2c Add platform type to the info command 2016-09-10 21:54:31 +01:00
Luck 37749e5829 Don't apply the default group when exporting users 2016-09-10 16:53:04 +01:00
Luck f9025c7a51 fix #getUniqueUsers for SQL storage types 2016-09-10 16:38:37 +01:00
Luck c7bfc38477 Build an extra jar with guava and gson shaded to support 1.7 2016-09-10 16:32:37 +01:00
Luck 7ca394d7b9 Add some extra console output to the debug command 2016-09-10 14:35:12 +01:00
Luck 31884ea59d Maybe fix race condition with messages not sending 2016-09-10 14:31:42 +01:00
Luck e79b7c7023 Update readme 2016-09-10 09:04:59 +01:00
Luck 1fdb4e8ade Merge pull request #11 from HeroCC/patch-1
Fix PermissionsEx false node migration
2016-09-09 21:49:43 +01:00
HeroCC 53db8c5928 Fix PermissionsEx false node migration
PermissionsEx false nodes begin with a '-' not a '!'
2016-09-09 16:39:13 -04:00
Luck 07514000a4 Fix global groups not being migrated from GroupManager 2016-09-09 18:41:15 +01:00
Luck f28721e55a Possible fix for permissions not applying on BungeeCord 2016-09-09 18:32:50 +01:00
Luck fc230291d3 Fix ops not receiving all permission nodes 2016-09-09 18:00:38 +01:00
Luck 89ff4cfa40 Add a much better system for exporting data 2016-09-08 21:01:37 +01:00
Luck d786b6abb2 Fix removing negative nodes 2016-09-08 17:28:31 +01:00
Luck fb0e694155 Add auto-op. Closes #8 2016-09-07 23:21:24 +01:00
Luck cd6cac1fb6 Fix bad grammar in config option comment 2016-09-07 21:01:03 +01:00
Luck ea07f05097 Release 2.8 2016-09-07 20:53:33 +01:00
Luck d84767af68 Fix blank users not receiving group permission updates 2016-09-06 22:28:37 +01:00
Luck aab73a8d81 Add more shorthand nodes 2016-09-06 22:27:46 +01:00
Luck 995fc2ccd8 Bump internal release version and add missing javadoc 2016-09-05 20:06:41 +01:00
Luck 60bcd5f643 Release 2.7 2016-09-05 20:00:01 +01:00
Luck ba04fb320b Remove unnecessary reflection 2016-09-05 16:44:59 +01:00
Luck 770b7dc282 Fix permissions not being removed on Sponge 2016-09-04 17:59:01 +01:00
Luck ed85eee36c Fix inherited permissions not applying on Sponge 2016-09-04 16:25:10 +01:00
Luck 23df8a2df8 Some small fixes 2016-09-04 16:24:36 +01:00
Luck 36cd388607 Slight re-wording 2016-09-03 21:34:35 +01:00
Luck 4d48ef1939 Add comment about Paper's "bungee-online-mode" option. Resolves #6 2016-09-03 21:30:37 +01:00
Luck 7970e2a1c6 Add bPermissions migration 2016-09-03 18:15:52 +01:00
Luck cee96d7daa make SenderFactory nicer & maybe faster 2016-09-03 00:14:40 +01:00
Luck 861c1ddd69 remove #childInit 2016-09-02 19:19:22 +01:00
Luck 5dec5a54cb Add YAML storage support 2016-09-02 19:15:31 +01:00
Luck 5c760aabd4 Fire PermissionRefreshEvent after the nodes have actually updated 2016-09-01 13:00:22 +01:00
Luck 1a2fa5d8c3 Fix log notify 2016-08-31 21:02:06 +01:00
Luck ef0c53da82 fix formatting 2016-08-31 09:38:47 +01:00
Luck 3fd62a80e2 Add support for split storage 2016-08-31 09:30:19 +01:00
Luck 5c19dd8b15 .-. 2016-08-30 22:38:08 +01:00
Luck 1fc88e147f Make output of listnodes nicer 2016-08-30 18:04:30 +01:00
Luck 9b4bbe0500 Make log notifications toggleable 2016-08-30 16:02:01 +01:00
Luck b37fdd3619 Add user to group instead of failing in setprimarygroup command 2016-08-30 13:23:48 +01:00
Luck ab00c41452 Fix NPE, and properly send possible permissions in BukkitUser 2016-08-30 13:06:36 +01:00
Luck c15727377b Apply single '*' wildcard 2016-08-30 12:49:46 +01:00
Luck 1e6f32bdc4 Add extra disallowed character 2016-08-30 11:54:18 +01:00
Luck 42e69c98a7 Change name limitation to be more flexible 2016-08-30 11:52:32 +01:00
Luck a217727bb4 Match negative priorities and fix PEX weight migration 2016-08-30 11:04:34 +01:00
Luck ba10b1c06e Fix removal of temporary nodes 2016-08-30 10:22:55 +01:00
Luck 075ba33e8b Add prefix/suffix/meta commands 2016-08-30 10:22:25 +01:00
Luck 19dbc7d90a formatting pls 2016-08-30 07:47:52 +01:00
Boomclaw ade70bb7ba PEX migration carries weights of prefixes/suffixes of groups and individuals (#5)
* PEX migration carries weights of prefixes/suffixes of groups and individuals.

* Forgot to increase maxGroupWeight.
2016-08-29 22:45:19 +01:00
Luck 4b67913eee getGroup methods should not include inherited groups 2016-08-29 22:03:10 +01:00
Luck 75858c1555 Use new Node system in #getGroups 2016-08-29 21:38:47 +01:00
Luck 659baaf5fb Make #getPlayerGroups return global too 2016-08-29 21:35:11 +01:00
Luck 3c83c578eb Fix typo 2016-08-29 18:40:37 +01:00
Luck 3ddbf1da87 Migrate PEX primary groups 2016-08-29 17:57:47 +01:00
Luck 35cb5b81dc hopefully fix server stopped responding error with SkipListSet 2016-08-29 16:28:36 +01:00
Luck 02d9b996a7 woops 2016-08-29 15:51:19 +01:00
Luck d4cf6a5ad7 Remove subjects from cache when they leave the server 2016-08-29 13:32:21 +01:00
Luck 9fdb4fa25f Maybe fix sponge permissions not expiring 2016-08-29 13:02:56 +01:00
Luck d5bc1cdf5d Fix not clearing user's permissions, and issue with unsetting permissions 2016-08-29 12:53:05 +01:00
Luck f5995c0afa Fix usernames showing as "null" and NPE related to primaryGroup not copying correctly 2016-08-29 12:11:03 +01:00
Luck 2cc65160b4 Bump release version 2016-08-28 22:12:34 +01:00
Luck 57f5a7c4cd Release 1.6 2016-08-28 22:05:10 +01:00
Luck 6aea3b53f3 Only save unique users 2016-08-28 21:36:16 +01:00
Luck 9f5e194a6e bug fixes 2016-08-28 17:43:02 +01:00
Luck 0831585a27 Fix SQL datastore 2016-08-28 15:43:21 +01:00
Luck b2cf6dce2d Prepare for 1.6 release 2016-08-28 15:29:02 +01:00
Luck a3ebf86f6b More progress towards 1.6: implement PermissionService 2016-08-28 14:57:03 +01:00
Luck 2a305b1c55 More progress towards 1.6: add transient permissions 2016-08-27 22:01:17 +01:00
Luck 2ea9b36c77 Build against Sponge API 5.0.0 2016-08-27 16:59:00 +01:00
Luck edaf174ebf Complete refactor of permissions/nodes. progress towards 1.6 2016-08-27 00:32:39 +01:00
Luck c4497db06c progress towards permissionservice 2016-08-26 16:58:47 +01:00
Luck 9873415303 Fix NPE 2016-08-25 18:07:50 +01:00
Luck 2b71476cfe Implement ConsecutiveExecutor 2016-08-25 18:07:32 +01:00
Luck 44d14001e1 Partially implement PermissionService 2016-08-25 17:23:27 +01:00
Luck de5fda6a18 Add some extra debugging output to PP migration 2016-08-25 01:31:38 +01:00
Luck 8b83a1d9a2 Fix sponge startup exception 2016-08-24 22:38:52 +01:00
Luck c0a0239eeb Update readme 2016-08-24 10:24:37 +01:00
Luck 84f377451e Make placeholder identifier lowercase 2016-08-23 20:11:53 +01:00
Luck 21d0c9ab0e Add some PlaceholderAPI placeholders 2016-08-23 19:32:58 +01:00
Luck f9c1cdb4bd Add group and track rename commands 2016-08-23 15:52:51 +01:00
Luck e89444141b Add logging for the migration processes 2016-08-23 15:18:20 +01:00
Luck 9cd4e01d8e Copy prefixes and suffixes during migration processes 2016-08-23 12:36:20 +01:00
Luck f7fa08d5e9 Call #recalculatePermissions on the main thread 2016-08-23 12:10:11 +01:00
Luck 7a4135319f Convert PermissionAttachment to use ConcurrentMap, and do refreshPermissions async 2016-08-22 22:39:40 +01:00
Luck 41fca40a36 Add some null / arg checks to Vault chat impl 2016-08-22 21:12:42 +01:00
Luck 9dbfa76b26 Add Vault chat support using permission nodes 2016-08-22 20:59:52 +01:00
Luck 20eeade06f Migration for BungeePerms 2016-08-22 19:46:37 +01:00
Luck cd9f18ffdb Properly close DB objects once PP migration is complete 2016-08-22 17:01:41 +01:00
Luck f7baf67985 Improvements to the JavaDocs in the API 2016-08-22 15:50:20 +01:00
Luck 692bf30cf5 Attempt to fix PermissionsEx migration 2016-08-22 07:07:13 +01:00
Luck 41b33fbd7a Fix typo 2016-08-22 00:22:06 +01:00
Luck 5dc551c05d Complete the migration system 2016-08-21 23:31:38 +01:00
Luck dd7aee9d15 Partially add migration support 2016-08-21 22:20:14 +01:00
Luck bbeed1e4ed A few small fixes 2016-08-20 17:49:23 +01:00
Luck 471084a9ef Fix NPE 2016-08-20 16:29:59 +01:00
Luck 6fc00976a0 Fire PermRefreshEvent in sponge too 2016-08-20 16:26:32 +01:00
Luck 4aa753515d Add events 2016-08-20 15:43:54 +01:00
Luck 7e933966cf revert remove sources 2016-08-20 02:19:03 +01:00
Luck b4d179f7b2 use a proper repo instead of the rubbish jenkins one 2016-08-20 01:39:19 +01:00
Luck a51acdbc88 remove sources 2016-08-19 22:23:28 +01:00
Luck 52e63a228d Update readme 2016-08-19 21:54:40 +01:00
Luck 9424d2d2ba Process shorthand in server/world names 2016-08-19 19:36:04 +01:00
Luck 0c12eebe6f Check temporary permissions separately to the sync task 2016-08-19 19:10:36 +01:00
Luck a15a0752f4 Add support for MongoDB and H2 database formats 2016-08-19 18:21:16 +01:00
Luck 31cef46b56 Fix sponge tab complete, fix bungee listeners & change some messages 2016-08-18 20:14:12 +01:00
Luck bfe0126816 fix format 2016-08-18 13:52:38 +01:00
Luck 98b56691dd Allow expiry timestamp for temporary assignment args 2016-08-18 13:51:31 +01:00
Luck 6451175d0e Fix some broken messages 2016-08-18 12:47:33 +01:00
Luck 9b4319c42d fix readme 2016-08-18 12:33:46 +01:00
Luck e9e7d81ddf Add import/export support 2016-08-18 12:30:51 +01:00
Luck 84afbf26f8 refactor LogEntry & cleanup stream formatting 2016-08-18 00:07:56 +01:00
Luck ca9037461a remove lombok from api and attach sources 2016-08-15 16:09:16 +02:00
Luck 9a3eeca411 idk 2016-08-15 12:06:36 +02:00
Luck e216c235ce Add logging, prepare for import/export system 2016-08-15 01:51:38 +02:00
Luck fbf062933f Fix build 2016-08-09 13:52:25 +02:00
Luck cf85f31da8 Bump minor version 2016-08-09 11:13:01 +02:00
Luck b70b6f8af1 Add support for regex permissions/servers/worlds and shorthand permissions 2016-08-09 11:09:45 +02:00
Luck 90e074d3ab Apply bukkit permissions directly, fix sponge listener, other misc changes/fixes 2016-08-07 17:10:37 +02:00
Luck e14ea73626 Add wildcard permissions 2016-08-07 01:16:05 +02:00
Luck e07b677632 Update readme 2016-08-06 19:47:39 +02:00
Luck 4e7547c92e Add proper versioning, bump to 2.0 2016-08-06 18:28:38 +02:00
Luck 8483e78082 Add license headers 2016-08-06 14:36:56 +02:00
Luck 4ca1e26f0f Set version on build in sponge plugin 2016-08-06 12:25:23 +02:00
Luck d88657f369 Add more stuff to api 2016-08-06 11:04:06 +02:00
Luck caf03379f2 Move stuff into commons, rename PermissionObject, add more javadocs to api 2016-08-06 00:11:00 +02:00
Luck 03450c3339 Sponge support 2016-08-05 12:58:27 +02:00
Luck 56e11b8b85 Various small changes 2016-08-03 12:08:10 +02:00
Luck 5e23b6961e Use generics for sub commands, fix user lookup bugs 2016-08-03 00:54:50 +02:00
Luck 98c5a91beb Update readme 2016-08-02 15:12:06 +02:00
Luck d6cd0b162b Update vault version 2016-08-02 11:17:52 +02:00
Luck 1c064daccb Fix build 2016-08-02 10:56:15 +02:00
Luck 0cfdd8c862 Remove slow vault-repo, fix long build time 2016-08-02 10:54:16 +02:00
Luck a9619bc08c small fix 2016-08-02 00:50:47 +02:00
Luck a7a84952fe Update readme 2016-08-02 00:20:49 +02:00
Luck 9c867dee28 Revert message colorization 2016-07-26 15:53:15 +01:00
Luck db862b38c9 Fix version tags 2016-07-26 10:19:33 +01:00
Luck cba12c3e78 Update readme 2016-07-26 03:39:56 +01:00
Luck 0ecd899ec5 Fix bad javadoc issues 2016-07-26 03:12:27 +01:00
Luck e9805b7532 Remove travis 2016-07-26 02:23:16 +01:00
Luck c000b9c009 Update build 2016-07-26 02:21:51 +01:00
Luck 8f6435b9e8 Try to add travis 2016-07-25 22:08:08 +01:00
Luck a3604c7464 Bump version, and make future version changes easier 2016-07-25 21:05:09 +01:00
Luck 10574748ff Add inheritance methods to Group 2016-07-25 20:44:01 +01:00
Luck c7336dbcad Change Vault hook to use new per-world perms system 2016-07-25 20:20:51 +01:00
Luck ebeb69dd3a Per-world permissions 2016-07-25 18:19:36 +01:00
Luck 9ad40be210 Add complete offline-mode support 2016-07-25 11:18:35 +01:00
Luck df209f6515 Fix possible race condition 2016-07-23 22:34:42 +01:00
Luck d32d6b5474 Generics are cool 2016-07-23 21:57:19 +01:00
Luck 623b7b775c Fix readme markdown 2016-07-22 12:27:50 +01:00
Luck b3b687d9b7 Add Api 2016-07-21 21:40:24 +01:00
Luck a413c0a50a Cleanup & multiple small fixes 2016-07-21 14:15:14 +01:00
Luck 1870893fe1 Fix promotions/demotions 2016-07-19 17:10:40 +01:00
Luck f24562c642 Fix compile 2016-07-19 13:02:54 +01:00
Luck ea358e88e1 Remove test files, bump version 2016-07-19 13:01:58 +01:00
Luck cdf8a4ce18 Add temporary permissions 2016-07-19 12:54:39 +01:00
Luck 24ff465679 Make command usage send with the correct label & bump version 2016-07-17 14:44:52 +01:00
Luck d33a3ffcea Add tab completion 2016-07-17 13:18:43 +01:00
Luck 874a90253b Add support for tracks 2016-07-15 22:44:25 +01:00
Luck 90b6f41f13 Don't shade gson 2016-07-15 16:11:31 +01:00
Luck 33fc4f537a General cleanup 2016-07-15 15:53:13 +01:00
Luck 42322ef932 Pre-compile patterns, add two new commands, check args before doing DB lookup, and limit group names slightly 2016-07-15 15:03:21 +01:00
Luck d5a6a4261d Update project dependencies 2016-07-15 11:56:28 +01:00
Luck 69ab488c47 Only store prefix in one place 2016-07-12 23:15:47 +01:00
Luck ad9b190a7c small cleanup 2016-07-12 11:50:49 +01:00
Luck f35cb95001 enum names should be singular 2016-07-12 11:32:04 +01:00
Luck f803082b15 Move all messages to one class 2016-07-11 20:56:01 +01:00
Luck 2413f0f379 Merge branch 'master' of https://github.com/lucko/LuckPerms 2016-07-05 20:54:09 +01:00
Luck 7ca7fdd472 javaassist is not a dependency of hikari 2016-07-05 20:53:13 +01:00
Luck f6e3f1ca0b Fix NPE and plugin not loading when Vault missing 2016-06-29 20:09:34 +01:00
Luck 84335afacd Huge cleanup 2016-06-29 15:35:57 +01:00
Luck 0e449cdd7a Fix save user query 2016-06-29 11:59:16 +01:00
Luck 3c83c31e9f Use group.<name> instead of luckperms.group.<name> to indicate group membership 2016-06-29 11:57:55 +01:00
Luck 776ec45701 Multiple fixes/improvements to command system 2016-06-28 18:07:55 +01:00
Luck ebbc0511bf don't clear proxiedplayer permission map 2016-06-28 17:28:08 +01:00
Luck d4c335e33e Fix clear command not resetting primary group 2016-06-28 17:21:41 +01:00
Luck e5e1333769 woops 2016-06-28 17:13:14 +01:00
Luck d855be1c65 Fix concurrency issue, remove sqlite from Bungee version and fix join message 2016-06-28 17:10:01 +01:00
Luck d35774b401 Fix primary group not loading and Vault support with EssentialsChat 2016-06-24 21:02:56 +01:00
Luck 1b09488859 Update readme 2016-06-24 18:42:03 +01:00
Luck 697b349167 Add primary groups 2016-06-24 18:38:05 +01:00
Luck 34ca3b3c25 Refactor sql datastore 2016-06-24 11:53:33 +01:00
Luck e07a346e16 fix group deletion not syncing across multiple instances 2016-06-23 21:48:25 +01:00
Luck 4610b3db7e Correct some messages 2016-06-23 18:05:02 +01:00
Luck 0781637617 Add flatfile storage support 2016-06-23 16:37:29 +01:00
Luck 85989aeb7c small cleanup 2016-06-23 13:29:51 +01:00
Luck 0380b7017d Update readme 2016-06-22 21:58:25 +01:00
Luck 91e24ccba1 Fix uuid data not saving 2016-06-22 17:34:48 +01:00
Luck 10a58e372c Fix user group issues 2016-06-22 17:24:30 +01:00
Luck 60f6bac903 Add sqlite support 2016-06-22 16:47:54 +01:00
Luck f6d8fb5286 Use gson instead of internal serialization method 2016-06-22 12:51:37 +01:00
Luck 484bc44288 Change users being updated async and refactor update task 2016-06-17 23:23:28 +01:00
Luck 00c3a8b415 Don't include global groups when global permissions are requested 2016-06-17 20:40:28 +01:00
Luck 20f34d9b45 Slight cleanup and better support for server reloads 2016-06-17 20:06:45 +01:00
Luck 50f4a84d04 Add priority system to permission handling 2016-06-17 19:38:16 +01:00
Luck 96476a2796 cleanup 2016-05-22 18:04:39 +01:00
Luck 17883f21d6 Fix encapsulation & make group inheritance work properly 2016-05-22 11:16:15 +01:00
310 changed files with 33031 additions and 2940 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2016 Luck
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
+19 -21
View File
@@ -1,28 +1,26 @@
# LuckPerms
A quite possibly shit™ permissions implementation for Bukkit/BungeeCord.
![alt text](https://i.imgur.com/7TwJZ5e.png "Banner")
# LuckPerms [![Build Status](https://ci.lucko.me/job/LuckPerms/badge/icon)](https://ci.lucko.me/job/LuckPerms/)
An advanced permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
### Why?
Yeah, I don't know. There are other more advanced, optimized, better programmed and thoroughly tested alternative plugins around, you should probably use those instead. I just wanted some specific features, and something that was compatible with BungeeCord.
## Links
* **Development Builds** - <https://ci.lucko.me/job/LuckPerms>
* **Javadocs** - <https://jd.lucko.me/LuckPerms>
* **Wiki** - <https://github.com/lucko/LuckPerms/wiki>
### Features
- **Group inheritance** - users can be members of multiple groups, groups can inherit other groups
- **Multi-server support** - data is synced across all servers/platforms
- **Per-server permissions/groups** - define permissions that only apply on certain servers
- **Vault Support** - hooks into Vault to integrate with other plugins
- **Everything is configured using commands** - no editing yml files, yuck
- **Efficient** - maybe? Who knows, it might be.
- **BungeeCord compatible** - my main motive for making this was that all other Bungee/Bukkit compatible perms plugins are utter aids. (At least, I couldn't find any decent ones)
## 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.
### Caveats
- Only supports MySQL
- Not at all tested and could be super unreliable
- It's quite possibly shit™
* [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")
So, not anything major, really ¯\ _(ツ)_ /¯
## LuckPerms vs Other Plugins
![alt text](https://static.lucko.me/luckperms-compare-copy.png "Feature comparison")
_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._
### Commands
Command usage is printed when you supply too little arguments.
## License
See LICENSE.md.
Bukkit: `/luckperms` `/perms` `/permissions` `/lp` `/perm`
## Thanks to:
[![JProfiler](https://www.ej-technologies.com/images/product_banners/jprofiler_large.png)](http://www.ej-technologies.com/products/jprofiler/overview.html)
Bungee: `/luckpermsbungee` `/bperms` `/bpermissions` `/lpb` `/bperm`
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").
+37
View File
@@ -0,0 +1,37 @@
<?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.10-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-api</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms;
import me.lucko.luckperms.api.LuckPermsApi;
import java.util.Optional;
/**
* Static access to LuckPerms
*/
public final class LuckPerms {
private static LuckPermsApi api = null;
/**
* Gets an instance of {@link LuckPermsApi}
* @return an api instance
* @throws IllegalStateException if the api is not loaded
*/
public static LuckPermsApi getApi() {
if (api == null) {
throw new IllegalStateException("API is not loaded.");
}
return api;
}
/**
* Gets an instance of {@link LuckPermsApi} safely. Unlike {@link LuckPerms#getApi}, this method will not throw an
* {@link IllegalStateException} if the api is not loaded, rather return an empty {@link Optional}.
* @return an optional api instance
*/
public static Optional<LuckPermsApi> getApiSafe() {
return Optional.ofNullable(api);
}
static void registerProvider(LuckPermsApi luckPermsApi) {
api = luckPermsApi;
}
static void unregisterProvider() {
api = null;
}
private LuckPerms() {
throw new UnsupportedOperationException("This class cannot be instantiated.");
}
}
@@ -0,0 +1,308 @@
/*
* 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.data.Callback;
import java.util.Set;
import java.util.UUID;
/**
* Interface for the internal Datastore instance
*/
@SuppressWarnings("unused")
public interface Datastore {
String getName();
boolean isAcceptingLogins();
/**
* Gets the {@link Sync} interface.
*
* All operations through this interface are called immediately and in the same thread as they are called.
* Datastore operations are thread blocking, and Sync operations should not be called on the main server thread.
* @return the sync interface
*/
Sync sync();
/**
* Gets the {@link Async} interface.
*
* All operations through this interface are called in a new, separate asynchronous thread.
* When the operation is complete, the provided callback method is called, in applicable, in the main server thread.
* @return the async interface
*/
Async async();
/**
* Gets the {@link Future} interface.
*
* All operations through this interface are called in a new, separate asynchronous thread, similar to {@link Async}.
* The only difference is that instead of providing a callback, a {@link java.util.concurrent.Future} is returned.
* See the Oracle JavaDocs for usage of the Future class.
* @return the future interface
*/
Future future();
/**
* All operations through this interface are called immediately and in the same thread as they are called.
* Datastore operations are thread blocking, and Sync operations should not be called on the main server thread.
*/
interface Sync {
/**
* Saves an action to the datastore
* @param entry the log entry to be saved
* @return true if the operation completed successfully.
* @throws NullPointerException if entry is null
*/
boolean logAction(LogEntry entry);
/**
* Loads and returns the log from the datastore
* @return a log instance, could be null
*/
Log getLog();
/**
* Either loads or creates a user object, and loads it into the plugins internal storage
* @param uuid the uuid of the user
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
* @return true if the operation completed successfully.
* @throws NullPointerException if uuid or username is null
* @throws IllegalArgumentException if either of the parameters are invalid
* @deprecated functionality of this method is taken on by {@link #loadUser(UUID, String)}
*/
@Deprecated
boolean loadOrCreateUser(UUID uuid, String username);
/**
* Loads a user from the datastore into the plugins internal storage.
* @param uuid the uuid of the user to load
* @return true if the user exists, and was loaded correctly.
* @throws NullPointerException if uuid is null
* @deprecated replaced by {@link #loadUser(UUID, String)}
*/
@Deprecated
boolean loadUser(UUID uuid);
/**
* Loads a user's data into the plugins internal storage.
* @param uuid the uuid of the user to load
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
* @return if the operation was performed successfully
* @throws NullPointerException if uuid or username is null
* @since 2.6
*/
boolean loadUser(UUID uuid, String username);
/**
* Saves a user object into the datastore. You should call this after you make any changes to a user.
* @param user the user to save
* @return true if the operation completed successfully.
* @throws NullPointerException if user is null
* @throws IllegalStateException if the user instance was not obtained from LuckPerms.
*/
boolean saveUser(User user);
/**
* Removes users from the datastore who are "default". This is called every time the plugin loads.
* @return true if the operation completed successfully
* @since 2.6
*/
boolean cleanupUsers();
/**
* Gets a set all user's UUIDs who are "unique", and aren't just a member of the "default" group.
* @return a set of uuids, or null if the operation failed.
* @since 2.6
*/
Set<UUID> getUniqueUsers();
/**
* Creates and loads a group into the plugins internal storage
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean createAndLoadGroup(String name);
/**
* Loads a group into the plugins internal storage.
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean loadGroup(String name);
/**
* Loads all groups from the datastore into the plugins internal storage
* @return true if the operation completed successfully.
*/
boolean loadAllGroups();
/**
* Saves a group back to the datastore. You should call this after you make any changes to a group.
* @param group the group to save
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
boolean saveGroup(Group group);
/**
* Permanently deletes a group from the datastore
* @param group the group to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
boolean deleteGroup(Group group);
/**
* Creates and loads a track into the plugins internal storage
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean createAndLoadTrack(String name);
/**
* Loads a track into the plugins internal storage.
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean loadTrack(String name);
/**
* Loads all tracks from the datastore into the plugins internal storage
* @return true if the operation completed successfully.
*/
boolean loadAllTracks();
/**
* Saves a track back to the datastore. You should call this after you make any changes to a track.
* @param track the track to save
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
*/
boolean saveTrack(Track track);
/**
* Permanently deletes a track from the datastore
* @param track the track to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
*/
boolean deleteTrack(Track track);
/**
* Saves UUID caching data to the datastore
* @param username the users username
* @param uuid the users mojang unique id
* @return true if the operation completed successfully.
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
*/
boolean saveUUIDData(String username, UUID uuid);
/**
* Gets a UUID from a username
* @param username the corresponding username
* @return a uuid object, could be null
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
*/
UUID getUUID(String username);
}
/**
* All operations through this interface are called in a new, separate asynchronous thread.
* When the operation is complete, the provided callback method is called, in applicable, in the main server thread.
*
* See {@link Sync} for method documentation.
*/
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);
}
/**
* All operations through this interface are called in a new, separate asynchronous thread, similar to {@link Async}.
* The only difference is that instead of providing a callback, a {@link java.util.concurrent.Future} is returned.
* See the Oracle JavaDocs for usage of the Future class.
*
* See {@link Sync} for method documentation.
*/
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();
java.util.concurrent.Future<Boolean> saveGroup(Group group);
java.util.concurrent.Future<Boolean> deleteGroup(Group group);
java.util.concurrent.Future<Boolean> createAndLoadTrack(String name);
java.util.concurrent.Future<Boolean> loadTrack(String name);
java.util.concurrent.Future<Boolean> loadAllTracks();
java.util.concurrent.Future<Boolean> saveTrack(Track track);
java.util.concurrent.Future<Boolean> deleteTrack(Track track);
java.util.concurrent.Future<Boolean> saveUUIDData(String username, UUID uuid);
java.util.concurrent.Future<UUID> getUUID(String username);
}
}
@@ -0,0 +1,237 @@
/*
* 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.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
/**
* Interface for internal Group instances
*/
@SuppressWarnings("unused")
public interface Group extends PermissionHolder {
/**
* @return the name of the group
*/
String getName();
/**
* Check to see if a group inherits a group
* @param group The group to check membership of
* @return true if the 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
* @param group The group to check membership of
* @param server The server to check on
* @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 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 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);
/**
* 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 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 and world
* @param group the group to be inherited
* @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 temporarily
* @param group the group to be inherited
* @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 temporarily
* @param group the group to be inherited
* @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 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 and world temporarily
* @param group the group to be inherited
* @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 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 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 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 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 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 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 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 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 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;
/**
* Clear all of the groups permission nodes
*/
void clearNodes();
/**
* Get a {@link List} of all of the groups the group inherits, on all servers
* @return a {@link List} of group names
*/
List<String> getGroupNames();
/**
* Get a {@link List} of the groups the group inherits on a specific server
* @param server the server to check
* @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);
/**
* 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);
}
@@ -0,0 +1,176 @@
/*
* 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.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 {
/**
* @return the name of this server
*/
String getServer();
/**
* @return how often a sync task will run in minutes
*/
int getSyncTime();
/**
* @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();
/**
* @return if the users on this server will have their global permissions applied
*/
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
*/
boolean getOnlineMode();
/**
* @return if LuckPerms is applying wildcard permissions
*/
boolean getApplyWildcards();
/**
* @return if LuckPerms is resolving and applying regex permissions
*/
boolean getApplyRegex();
/**
* @return if LuckPerms is expanding shorthand permissions
*/
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
*/
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()}
*/
@SuppressWarnings("deprecation")
@Deprecated
MySQLConfiguration getDatabaseValues();
/**
* @return the values set for data storage in the configuration
*/
DatastoreConfiguration getDatastoreConfig();
/**
* @return the storage method string from the configuration
*/
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,161 @@
/*
* 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.SortedMap;
import java.util.SortedSet;
import java.util.UUID;
/**
* Represents the internal LuckPerms log.
* All content internally is immutable. You can add to the log using the {@link Datastore}, and then request an updated copy.
*/
@SuppressWarnings("unused")
public interface Log {
/**
* @return a {@link SortedSet} of all of the {@link LogEntry} objects in this {@link 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);
}
@@ -0,0 +1,319 @@
/*
* 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.UUID;
/**
* Represents a single entry in a log
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public class LogEntry implements Comparable<LogEntry> {
public static LogEntryBuilder builder() {
return new LogEntryBuilder();
}
private static final String FORMAT = "&8(&e%s&8) [&a%s&8] (&b%s&8) &7--> &f%s";
private long timestamp;
private UUID actor;
private String actorName;
private char type;
private UUID acted;
private String actedName;
private String action;
public LogEntry(long timestamp, UUID actor, String actorName, char type, UUID acted, String actedName, String action) {
if (actor == null) {
throw new NullPointerException("actor");
}
if (actorName == null) {
throw new NullPointerException("actorName");
}
if (actedName == null) {
throw new NullPointerException("actedName");
}
if (action == null) {
throw new NullPointerException("action");
}
this.timestamp = timestamp;
this.actor = actor;
this.actorName = actorName;
this.type = type;
this.acted = acted;
this.actedName = actedName;
this.action = action;
}
protected LogEntry() {
this.timestamp = 0L;
this.actor = null;
this.actorName = null;
this.type = Character.MIN_VALUE;
this.acted = null;
this.actedName = null;
this.action = null;
}
@Override
public int compareTo(LogEntry o) {
return equals(o) ? 0 : (Long.compare(timestamp, o.getTimestamp()) == 0 ? 1 : Long.compare(timestamp, o.getTimestamp()));
}
public boolean matchesSearch(String query) {
query = query.toLowerCase();
return actorName.toLowerCase().contains(query) || actedName.toLowerCase().contains(query)
|| action.toLowerCase().contains(query);
}
public String getFormatted() {
return String.format(FORMAT,
actorName,
Character.toString(type),
actedName,
action
);
}
public long getTimestamp() {
return timestamp;
}
public UUID getActor() {
return actor;
}
public String getActorName() {
return actorName;
}
public char getType() {
return type;
}
public UUID getActed() {
return acted;
}
public String getActedName() {
return actedName;
}
public String getAction() {
return action;
}
void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
void setActor(UUID actor) {
this.actor = actor;
}
void setActorName(String actorName) {
this.actorName = actorName;
}
void setType(char type) {
this.type = type;
}
void setActed(UUID acted) {
this.acted = acted;
}
void setActedName(String actedName) {
this.actedName = actedName;
}
void setAction(String action) {
this.action = action;
}
@Override
public String toString() {
return "LogEntry(timestamp=" + this.getTimestamp() + ", actor=" + this.getActor() + ", actorName=" +
this.getActorName() + ", type=" + this.getType() + ", acted=" + this.getActed() + ", actedName=" +
this.getActedName() + ", action=" + this.getAction() + ")";
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof LogEntry)) return false;
final LogEntry other = (LogEntry) o;
if (this.getTimestamp() != other.getTimestamp()) return false;
final Object this$actor = this.getActor();
final Object other$actor = other.getActor();
if (this$actor == null ? other$actor != null : !this$actor.equals(other$actor)) return false;
final Object this$actorName = this.getActorName();
final Object other$actorName = other.getActorName();
if (this$actorName == null ? other$actorName != null : !this$actorName.equals(other$actorName)) return false;
if (this.getType() != other.getType()) return false;
final Object this$acted = this.getActed();
final Object other$acted = other.getActed();
if (this$acted == null ? other$acted != null : !this$acted.equals(other$acted)) return false;
final Object this$actedName = this.getActedName();
final Object other$actedName = other.getActedName();
if (this$actedName == null ? other$actedName != null : !this$actedName.equals(other$actedName)) return false;
final Object this$action = this.getAction();
final Object other$action = other.getAction();
return this$action == null ? other$action == null : this$action.equals(other$action);
}
@Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
final long $timestamp = this.getTimestamp();
result = result * PRIME + (int) ($timestamp >>> 32 ^ $timestamp);
final Object $actor = this.getActor();
result = result * PRIME + ($actor == null ? 43 : $actor.hashCode());
final Object $actorName = this.getActorName();
result = result * PRIME + ($actorName == null ? 43 : $actorName.hashCode());
result = result * PRIME + this.getType();
final Object $acted = this.getActed();
result = result * PRIME + ($acted == null ? 43 : $acted.hashCode());
final Object $actedName = this.getActedName();
result = result * PRIME + ($actedName == null ? 43 : $actedName.hashCode());
final Object $action = this.getAction();
result = result * PRIME + ($action == null ? 43 : $action.hashCode());
return result;
}
public static class LogEntryBuilder extends AbstractLogEntryBuilder<LogEntry, LogEntry.LogEntryBuilder> {
@Override
protected LogEntry createObj() {
return new LogEntry();
}
@Override
protected LogEntryBuilder getThis() {
return this;
}
}
public static abstract class AbstractLogEntryBuilder<T extends LogEntry, B extends AbstractLogEntryBuilder<T, B>> {
private T obj;
private B thisObj;
public AbstractLogEntryBuilder() {
obj = createObj();
thisObj = getThis();
}
protected abstract T createObj();
protected abstract B getThis();
public long getTimestamp() {
return obj.getTimestamp();
}
public UUID getActor() {
return obj.getActor();
}
public String getActorName() {
return obj.getActorName();
}
public char getType() {
return obj.getType();
}
public UUID getActed() {
return obj.getActed();
}
public String getActedName() {
return obj.getActedName();
}
public String getAction() {
return obj.getAction();
}
public B timestamp(long timestamp) {
obj.setTimestamp(timestamp);
return thisObj;
}
public B actor(UUID actor) {
obj.setActor(actor);
return thisObj;
}
public B actorName(String actorName) {
obj.setActorName(actorName);
return thisObj;
}
public B type(char type) {
obj.setType(type);
return thisObj;
}
public B acted(UUID acted) {
obj.setActed(acted);
return thisObj;
}
public B actedName(String actedName) {
obj.setActedName(actedName);
return thisObj;
}
public B action(String action) {
obj.setAction(action);
return thisObj;
}
public T build() {
if (getActor() == null) {
throw new NullPointerException("actor");
}
if (getActorName() == null) {
throw new NullPointerException("actorName");
}
if (getActedName() == null) {
throw new NullPointerException("actedName");
}
if (getAction() == null) {
throw new NullPointerException("action");
}
return obj;
}
@Override
public String toString() {
return "LogEntry.LogEntryBuilder(timestamp=" + getTimestamp() + ", actor=" + getActor() + ", actorName=" +
getActorName() + ", type=" + getType() + ", acted=" + getActed() + ", actedName=" + getActedName() +
", action=" + getAction() + ")";
}
}
}
@@ -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;
/**
* 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.
*/
public interface Logger {
void info(String s);
void warn(String s);
void severe(String s);
}
@@ -0,0 +1,237 @@
/*
* 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.ContextListener;
import me.lucko.luckperms.api.context.IContextCalculator;
import me.lucko.luckperms.api.event.LPListener;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
/**
* The root API interface in LuckPerms
*/
@SuppressWarnings("unused")
public interface LuckPermsApi {
/**
* Schedules an update task to run
*/
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);
/**
* Gets a wrapped {@link LPConfiguration} instance, with read only access
* @return a configuration instance
*/
LPConfiguration getConfiguration();
/**
* Gets a wrapped {@link Datastore} instance, with somewhat limited access
* @return a datastore instance
*/
Datastore getDatastore();
/**
* Gets the {@link Logger} wrapping used by the platform
* @return the logger instance
*/
Logger getLogger();
/**
* Gets a wrapped {@link UuidCache} instance, providing read access to the LuckPerms internal uuid caching system
* @return a uuidcache instance
*/
UuidCache getUuidCache();
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* Gets a set of all loaded users.
* @return a {@link Set} of {@link User} objects
*/
Set<User> getUsers();
/**
* 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);
/**
* 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);
/**
* Gets a set of all loaded groups.
* @return a {@link Set} of {@link Group} objects
*/
Set<Group> getGroups();
/**
* 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);
/**
* 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 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);
/**
* Gets a set of all loaded tracks.
* @return a {@link Set} of {@link Track} objects
*/
Set<Track> getTracks();
/**
* 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,316 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api;
import me.lucko.luckperms.LuckPerms;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* A collection of utilities to help retrieve meta values for {@link PermissionHolder}s
* @since 2.7
*/
public class MetaUtils {
private MetaUtils(){}
/**
* Escapes special characters used within LuckPerms, so the string can be saved without issues
* @param s the string to escape
* @return an escaped string
* @throws NullPointerException if the string is null
*/
public static String escapeCharacters(String s) {
if (s == null) {
throw new NullPointerException();
}
s = s.replace(".", "{SEP}");
s = s.replace("/", "{FSEP}");
s = s.replace("$", "{DSEP}");
return s;
}
/**
* Unescapes special characters used within LuckPerms, the inverse of {@link #escapeCharacters(String)}
* @param s the string to unescape
* @return an unescaped string
* @throws NullPointerException if the string is null
*/
public static String unescapeCharacters(String s) {
if (s == null) {
throw new NullPointerException();
}
s = s.replace("{SEP}", ".");
s = s.replace("{FSEP}", "/");
s = s.replace("{DSEP}", "$");
return s;
}
/**
* Sets a meta value on a holder
* @param holder the holder to apply the meta node to
* @param server the server to apply the meta on, can be null
* @param world the world to apply the meta on, can be null
* @param node the meta node
* @param value the meta value
* @throws NullPointerException if the holder, node or value is null
* @throws IllegalArgumentException if the node or value is empty
*/
public static void setMeta(PermissionHolder holder, String server, String world, String node, String value) {
if (holder == null) {
throw new NullPointerException("holder");
}
if (node == null) {
throw new NullPointerException("node");
}
if (value == null) {
throw new NullPointerException("value");
}
if (node.equals("")) {
throw new IllegalArgumentException("node is empty");
}
if (value.equals("")) {
throw new IllegalArgumentException("value is empty");
}
if (server == null || server.equals("")) {
server = "global";
}
node = escapeCharacters(node);
value = escapeCharacters(value);
Set<Node> toRemove = new HashSet<>();
for (Node n : holder.getEnduringPermissions()) {
if (n.isMeta() && n.getMeta().getKey().equals(node)) {
toRemove.add(n);
}
}
for (Node n : toRemove) {
try {
holder.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
}
Node.Builder metaNode = LuckPerms.getApi().buildNode("meta." + node + "." + value).setValue(true);
if (!server.equalsIgnoreCase("global")) {
metaNode.setServer(server);
}
if (world != null && !world.equals("")) {
metaNode.setServer(server).setWorld(world);
}
try {
holder.setPermission(metaNode.build());
} catch (ObjectAlreadyHasException ignored) {}
}
/**
* Gets a meta value for the holder
* @param holder the holder to get the meta from
* @param server the server to retrieve the meta on, can be null
* @param world the world to retrieve the meta on, can be null
* @param node the node to get
* @param defaultValue the default value to return if the node is not set
* @param includeGlobal if global nodes should be considered when retrieving the meta
* @return a meta string, or the default value if the user does not have the meta node
* @throws NullPointerException if the holder or node is null
* @throws IllegalArgumentException if the node is empty
*/
public static String getMeta(PermissionHolder holder, String server, String world, String node, String defaultValue, boolean includeGlobal) {
if (holder == null) {
throw new NullPointerException("holder");
}
if (server == null || server.equals("")) {
server = "global";
}
if (node == null) {
throw new NullPointerException("node");
}
if (node.equals("")) {
throw new IllegalArgumentException("node is empty");
}
node = escapeCharacters(node);
for (Node n : holder.getPermissions()) {
if (!n.getValue()) {
continue;
}
if (!n.isMeta()) {
continue;
}
if (!server.equalsIgnoreCase("global")) {
if (!n.shouldApplyOnServer(server, includeGlobal, false)) {
continue;
}
}
if (!n.shouldApplyOnWorld(world, includeGlobal, false)) {
continue;
}
Map.Entry<String, String> meta = n.getMeta();
if (meta.getKey().equalsIgnoreCase(node)) {
return unescapeCharacters(meta.getValue());
}
}
return defaultValue;
}
private static void setChatMeta(boolean prefix, PermissionHolder holder, String value, int priority, String server, String world) {
if (holder == null) {
throw new NullPointerException("holder");
}
if (value == null || value.equals("")) {
throw new IllegalArgumentException("value is null/empty");
}
Node.Builder node = LuckPerms.getApi().buildNode(prefix ? "prefix" : "suffix" + "." + priority + "." + escapeCharacters(value));
node.setValue(true);
if (!server.equalsIgnoreCase("global")) {
node.setServer(server);
}
if (world != null && !world.equals("")) {
node.setServer(server).setWorld(world);
}
try {
holder.setPermission(node.build());
} catch (ObjectAlreadyHasException ignored) {}
}
/**
* Adds a prefix to a holder on a specific server and world
* @param holder the holder to set the prefix for
* @param prefix the prefix value
* @param priority the priority to set the prefix at
* @param server the server to set the prefix on, can be null
* @param world the world to set the prefix on, can be null
* @throws NullPointerException if the holder is null
* @throws IllegalArgumentException if the prefix is null or empty
*/
public static void setPrefix(PermissionHolder holder, String prefix, int priority, String server, String world) {
setChatMeta(true, holder, prefix, priority, server, world);
}
/**
* Adds a suffix to a holder on a specific server and world
* @param holder the holder to set the suffix for
* @param suffix the suffix value
* @param priority the priority to set the suffix at
* @param server the server to set the suffix on, can be null
* @param world the world to set the suffix on, can be null
* @throws NullPointerException if the holder is null
* @throws IllegalArgumentException if the suffix is null or empty
*/
public static void setSuffix(PermissionHolder holder, String suffix, int priority, String server, String world) {
setChatMeta(false, holder, suffix, priority, server, world);
}
private static String getChatMeta(boolean prefix, PermissionHolder holder, String server, String world, boolean includeGlobal) {
if (holder == null) {
throw new NullPointerException("holder");
}
if (server == null) {
server = "global";
}
int priority = Integer.MIN_VALUE;
String meta = null;
for (Node n : holder.getAllNodes()) {
if (!n.getValue()) {
continue;
}
if (!server.equalsIgnoreCase("global")) {
if (!n.shouldApplyOnServer(server, includeGlobal, false)) {
continue;
}
}
if (!n.shouldApplyOnWorld(world, includeGlobal, false)) {
continue;
}
if (prefix ? !n.isPrefix() : !n.isSuffix()) {
continue;
}
Map.Entry<Integer, String> value = prefix ? n.getPrefix() : n.getSuffix();
if (value.getKey() > priority) {
meta = value.getValue();
priority = value.getKey();
}
}
return meta == null ? "" : unescapeCharacters(meta);
}
/**
* Returns a holders highest priority prefix, if they have one
* @param holder the holder
* @param server the server to retrieve the prefix on
* @param world the world to retrieve the prefix on
* @param includeGlobal if global nodes should be considered when retrieving the prefix
* @return a prefix string, if the holder has one, or an empty string if not.
* @throws NullPointerException if the holder is null
*/
public static String getPrefix(PermissionHolder holder, String server, String world, boolean includeGlobal) {
return getChatMeta(true, holder, server, world, includeGlobal);
}
/**
* Returns a holders highest priority suffix, if they have one
* @param holder the holder
* @param server the server to retrieve the suffix on
* @param world the world to retrieve the suffix on
* @param includeGlobal if global nodes should be considered when retrieving the suffix
* @return a suffix string, if the holder has one, or an empty string if not.
* @throws NullPointerException if the holder is null
*/
public static String getSuffix(PermissionHolder holder, String server, String world, boolean includeGlobal) {
return getChatMeta(false, holder, server, world, includeGlobal);
}
}
@@ -0,0 +1,309 @@
/*
* 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.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* 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
*/
boolean shouldApplyWithContext(Map<String, String> 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
*/
boolean shouldApplyWithContext(Map<String, String> 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
*/
Map<String, String> getExtraContexts();
/**
* 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(Map.Entry<String, String> entry);
Node build();
}
}
@@ -0,0 +1,540 @@
/*
* 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.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
/**
* 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<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
*/
Set<Node> getAllNodes();
/**
* 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 object has the permission
* @throws NullPointerException if the node is null
* @throws IllegalArgumentException if the node is invalid
*/
boolean hasPermission(String node, boolean b);
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @return true if the 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 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 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
* @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 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);
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server to check on
* @param temporary if the permission is temporary
* @return true if the 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 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 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 object inherits the permission
* @throws NullPointerException if the node is null
* @throws IllegalArgumentException if the node is invalid
*/
boolean inheritsPermission(String node, boolean b);
/**
* Checks to see the the object inherits a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @return true if the 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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);
/**
* Gets the permissions and inherited permissions that apply to a specific server
* @param server The server 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, List<String> excludedGroups, List<String> possibleNodes);
/**
* Gets the permissions and inherited permissions that apply to a specific server
* @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);
/**
* 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
*/
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 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
*/
void auditTemporaryPermissions();
}
@@ -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,133 @@
/*
* 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.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
/**
* 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
* 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();
/**
* Gets the number of groups on this track
* @return the number of groups on this track
*/
int getSize();
/**
* Gets the next group on the track, after the one provided
* @param current the group before the group being requested
* @return the group name, or null if the end of the track has been reached
* @throws ObjectLacksException if the track does not contain the group given
* @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 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;
/**
* 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;
/**
* Inserts a group at a certain position on this track
* @param group the group to be inserted
* @param position the index position (a value of 0 inserts at the start)
* @throws ObjectAlreadyHasException if the group is already on this track somewhere
* @throws IndexOutOfBoundsException if the position is less than 0 or greater than the size of the track
* @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;
/**
* 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;
/**
* 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;
/**
* 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);
/**
* 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);
/**
* Clear all of the groups within this track
*/
void clearGroups();
}
@@ -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.api;
/**
* Represents a permission value
*/
public enum Tristate {
TRUE(true),
FALSE(false),
UNDEFINED(false);
private final boolean booleanValue;
Tristate(boolean booleanValue) {
this.booleanValue = booleanValue;
}
public boolean asBoolean() {
return booleanValue;
}
public static Tristate fromBoolean(boolean b) {
return b ? TRUE : FALSE;
}
}
@@ -0,0 +1,261 @@
/*
* 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.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.UUID;
/**
* Interface for internal User instances
*/
@SuppressWarnings("unused")
public interface User extends PermissionHolder {
/**
* @return the users Mojang assigned unique id
*/
UUID getUuid();
/**
* @return the Users Username
*/
String getName();
/**
* Gets the users primary group
* @return the users primary group
*/
String getPrimaryGroup();
/**
* Sets a users primary group
* @param 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 group) throws ObjectAlreadyHasException;
/**
* Refresh and re-assign the users permissions
*/
void refreshPermissions();
/**
* Check to see if the user is a member of a group
* @param group The group to check membership of
* @return true if the user is a member of the group
* @throws NullPointerException if the group is null
*/
boolean isInGroup(Group group);
/**
* Check to see if a user is a member of a group on a specific server
* @param group The group to check membership of
* @param server The server to check on
* @return true if the user is a member of the group
* @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 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);
/**
* 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;
/**
* Add a user to a group on a specific server
* @param group The group to add the user to
* @param server The server to add the group on
* @throws ObjectAlreadyHasException if the user is already a member of the group on that server
* @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 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 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 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 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;
/**
* 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;
/**
* Remove the user from a group
* @param group the group to remove the user from
* @param temporary if the group being removed is temporary
* @throws ObjectLacksException if the user isn't a member of the group
* @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 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 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 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 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;
/**
* Clear all of the users permission nodes
*/
void clearNodes();
/**
* Get a {@link List} of all of the groups the user is a member of, on all servers
* @return a {@link List} of group names
*/
List<String> getGroupNames();
/**
* Get a {@link List} of the groups the user is a member of on a specific server
* @param server the server to check
* @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);
/**
* 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);
}
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api;
import java.util.UUID;
/**
* A UUID cache for online users, between external Mojang UUIDs, and internal LuckPerms UUIDs.
*
* <p> This UuidCache is a means of allowing users to have the same internal UUID across a network of offline mode servers
* or mixed offline mode and online mode servers. Platforms running in offline mode generate a random UUID for a 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> WARNING: THIS IS ONLY EFFECTIVE FOR ONLINE PLAYERS. USE THE DATASTORE METHODS FOR OFFLINE PLAYERS.
*/
@SuppressWarnings("unused")
public interface UuidCache {
/**
* Gets a users internal "LuckPerms" UUID, from the one given by the server.
* @param external the UUID assigned by the server, through Player#getUniqueId or ProxiedPlayer#getUniqueId
* @return the corresponding internal UUID
*/
UUID getUUID(UUID external);
/**
* Gets a users external, server assigned or Mojang assigned unique id, from the internal one used within LuckPerms.
* @param internal the UUID used within LuckPerms, through User#getUuid
* @return the corresponding external UUID
*/
UUID getExternalUUID(UUID internal);
}
@@ -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<T>}
* @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,58 @@
/*
* 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;
/**
* 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 tp
* @param accumulator a map of contexts to add to
* @return the map
*/
Map<String, String> giveApplicableContext(T subject, Map<String, String> 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,58 @@
/*
* 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.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
*/
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() {
return t -> {};
}
static <T> Callback<T> of(Runnable runnable) {
if (runnable == null) {
throw new NullPointerException("runnable");
}
return t -> runnable.run();
}
static <T> Callback<T> of(Consumer<T> consumer) {
if (consumer == null) {
throw new NullPointerException("consumer");
}
return consumer::accept;
}
}
@@ -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.data;
/**
* Represents the data section of the main LuckPerms configuration.
* All methods could return null.
*/
@SuppressWarnings("deprecation")
public interface DatastoreConfiguration extends MySQLConfiguration {
String getAddress();
String getDatabase();
String getUsername();
String getPassword();
}
@@ -0,0 +1,35 @@
/*
* 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.data;
/**
* @deprecated Use {@link DatastoreConfiguration}. This is now used by multiple datastores, not just MySQL.
*/
@Deprecated
public interface MySQLConfiguration {
String getAddress();
String getDatabase();
String getUsername();
String getPassword();
}
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.event;
import me.lucko.luckperms.api.PermissionHolder;
import java.util.Optional;
public class AbstractPermissionAddEvent extends TargetedEvent<PermissionHolder> {
private final String server;
private final String world;
private final long expiry;
protected AbstractPermissionAddEvent(String eventName, PermissionHolder target, String server, String world, long expiry) {
super(eventName, target);
this.server = server;
this.world = world;
this.expiry = expiry;
}
public Optional<String> getServer() {
return Optional.ofNullable(server);
}
public Optional<String> getWorld() {
return Optional.ofNullable(world);
}
public boolean isTemporary() {
return expiry != 0L;
}
public long getExpiry() {
return expiry;
}
}
@@ -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;
}
}
@@ -0,0 +1,62 @@
/*
* 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.PermissionHolder;
import java.util.Optional;
public class AbstractPermissionRemoveEvent extends TargetedEvent<PermissionHolder> {
private final String server;
private final String world;
private final boolean temporary;
protected AbstractPermissionRemoveEvent(String eventName, PermissionHolder target, String server, String world, boolean temporary) {
super(eventName, target);
this.server = server;
this.world = world;
this.temporary = temporary;
}
public Optional<String> getServer() {
return Optional.ofNullable(server);
}
public Optional<String> getWorld() {
return Optional.ofNullable(world);
}
/**
* @deprecated use {@link #isTemporary()}
*/
@Deprecated
public boolean getTemporary() {
return temporary;
}
public boolean isTemporary() {
return temporary;
}
}
@@ -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;
/**
* Event that allows listeners to set the cancelled state of an event.
*/
public abstract class CancellableEvent extends LPEvent {
private boolean cancelled = false;
protected CancellableEvent(String eventName) {
super(eventName);
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.event;
import me.lucko.luckperms.api.LuckPermsApi;
/**
* Abstract LuckPerms Event class.
*/
public abstract class LPEvent {
/**
* A link to the API instance provided for convenience.
*/
private LuckPermsApi api = null;
/**
* A friendly name of the event
*/
private final String eventName;
protected LPEvent(String eventName) {
this.eventName = eventName;
}
public String getEventName() {
return eventName;
}
public LuckPermsApi getApi() {
return api;
}
public void setApi(LuckPermsApi api) {
if (this.api != null) {
throw new IllegalStateException("API can only be set once.");
}
this.api = api;
}
}
@@ -0,0 +1,29 @@
/*
* 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;
/**
* Used to mark a class that listens for LuckPerms events
*/
public interface LPListener {
}
@@ -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.event;
/**
* Represents an event acting upon a target
* @param <T> the target type
*/
public class TargetedEvent<T> extends LPEvent {
private final T target;
protected TargetedEvent(String eventName, T target) {
super(eventName);
this.target = target;
}
public T getTarget() {
return target;
}
}
@@ -0,0 +1,58 @@
/*
* 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.Track;
import me.lucko.luckperms.api.User;
public abstract class TrackEvent extends LPEvent {
private final Track track;
private final User user;
private final String fromGroup;
private final String toGroup;
protected TrackEvent(String eventName, Track track, User user, String fromGroup, String toGroup) {
super(eventName);
this.track = track;
this.user = user;
this.fromGroup = fromGroup;
this.toGroup = toGroup;
}
public Track getTrack() {
return track;
}
public User getUser() {
return user;
}
public String getFromGroup() {
return fromGroup;
}
public String getToGroup() {
return toGroup;
}
}
@@ -0,0 +1,42 @@
/*
* 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.User;
/**
* Represents an event acting upon a user.
*/
public class UserEvent extends LPEvent {
private final User user;
protected UserEvent(String eventName, User user) {
super(eventName);
this.user = user;
}
public User getUser() {
return user;
}
}
@@ -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.api.event.events;
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) {
super("Group Add Event", target, server, world, expiry);
this.group = group;
}
public Group getGroup() {
return group;
}
}
@@ -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.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) {
super("Group Remove Event", target, server, world, temporary);
this.group = group;
}
public String getGroup() {
return group;
}
}
@@ -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.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) {
super("Log Notify Event");
this.entry = entry;
}
public LogEntry getEntry() {
return entry;
}
}
@@ -0,0 +1,45 @@
/*
* 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.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;
public PermissionExpireEvent(PermissionHolder target, String node) {
super("Permission Expire Event", target);
this.node = node;
}
public String getNode() {
return 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);
}
}
@@ -0,0 +1,58 @@
/*
* 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.PermissionHolder;
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;
private final boolean value;
public PermissionSetEvent(PermissionHolder target, String node, boolean value, String server, String world, long expiry) {
super("Permission Set Event", target, server, world, expiry);
this.node = node;
this.value = value;
}
public String getNode() {
return node;
}
public boolean getValue() {
return value;
}
public Map.Entry<String, Boolean> getEntry() {
return new AbstractMap.SimpleEntry<>(node, value);
}
}
@@ -0,0 +1,45 @@
/*
* 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.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;
public PermissionUnsetEvent(PermissionHolder target, String node, String server, String world, boolean temporary) {
super("Permission Unset Event", target, server, world, temporary);
this.node = node;
}
public String getNode() {
return node;
}
}
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.events;
import me.lucko.luckperms.api.event.LPEvent;
/**
* Called after the sync task has ran.
*/
public class PostSyncEvent extends LPEvent {
public PostSyncEvent() {
super("Post Sync Event");
}
}
@@ -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.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() {
super("Pre Sync Event");
}
}
@@ -0,0 +1,38 @@
/*
* 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.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) {
super("User Demote Event", track, user, from, to);
}
}
@@ -0,0 +1,54 @@
/*
* 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.event.LPEvent;
import java.util.UUID;
/**
* 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 {
private final UUID uuid;
private final String username;
public UserFirstLoginEvent(UUID uuid, String username) {
super("User First Join Event");
this.uuid = uuid;
this.username = username;
}
public UUID getUuid() {
return uuid;
}
public String getUsername() {
return username;
}
}
@@ -0,0 +1,38 @@
/*
* 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.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) {
super("User Permission Refresh Event", user);
}
}
@@ -0,0 +1,38 @@
/*
* 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.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) {
super("User Promote Event", track, user, from, 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 {
}
@@ -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 already has a permission, is already a member of a group, or when a track
* already contains a group.
*/
public class ObjectAlreadyHasException extends MembershipException {
}
@@ -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 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 MembershipException {
}
+119
View File
@@ -0,0 +1,119 @@
<?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.10-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>
</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>
+52
View File
@@ -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.10-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.8</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>
@@ -0,0 +1,182 @@
/*
* 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 org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.Optional;
/*
* PlaceholderAPI Expansion for LuckPerms, implemented using the LuckPerms API.
*
* Placeholders:
* - group_name
* - 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.8";
}
@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 "";
}
identifier = identifier.toLowerCase();
final User user = u.get();
if (identifier.equalsIgnoreCase("group_name")) {
return user.getPrimaryGroup();
}
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(user.inheritsPermission(node, true));
}
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(user.getLocalGroups("global").contains(groupName));
}
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.getPermission().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")) {
return MetaUtils.getPrefix(user, null, null, true);
}
if (identifier.equalsIgnoreCase("suffix")) {
return MetaUtils.getSuffix(user, null, null, true);
}
if (identifier.startsWith("meta_") && identifier.length() > "meta_".length()) {
String node = identifier.substring("meta_".length());
return MetaUtils.getMeta(user, null, null, node, "", true);
}
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();
}
}
+66 -12
View File
@@ -4,19 +4,17 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko</groupId>
<version>1.0-SNAPSHOT</version>
<groupId>me.lucko.luckperms</groupId>
<version>2.10-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-bukkit</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>LuckPerms</name>
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>LuckPerms</finalName>
<finalName>LuckPerms-${release.version}.${git.closest.tag.commit.count}</finalName>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
@@ -28,7 +26,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
@@ -37,7 +35,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
@@ -45,11 +43,53 @@
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<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>
</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>
@@ -65,15 +105,29 @@
<dependency>
<groupId>net.milkbowl.vault</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.5</version>
<version>1.6</version>
<scope>provided</scope>
</dependency>
<!-- LuckPerms Common -->
<dependency>
<groupId>me.lucko</groupId>
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-common</artifactId>
<version>${project.parent.version}</version>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- LuckPerms API -->
<dependency>
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
</project>
@@ -0,0 +1,60 @@
/*
* 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 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.commands.Util;
import me.lucko.luckperms.constants.Patterns;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import java.util.Arrays;
import java.util.List;
class BukkitCommand extends CommandManager implements CommandExecutor, TabExecutor {
BukkitCommand(LuckPermsPlugin plugin) {
super(plugin);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
onCommand(
BukkitSenderFactory.get(getPlugin()).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(getPlugin()).wrap(sender), Arrays.asList(args));
}
}
@@ -1,71 +1,91 @@
/*
* 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.utils.LPConfiguration;
import me.lucko.luckperms.config.AbstractConfiguration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class BukkitConfig implements LPConfiguration {
private final LPBukkitPlugin plugin;
class BukkitConfig extends AbstractConfiguration<LPBukkitPlugin> {
private YamlConfiguration configuration;
public BukkitConfig(LPBukkitPlugin plugin) {
this.plugin = plugin;
create();
BukkitConfig(LPBukkitPlugin plugin) {
super(plugin, "global", true, "sqlite");
}
private void create() {
File configFile = new File(plugin.getDataFolder(), "config.yml");
@SuppressWarnings("ResultOfMethodCallIgnored")
@Override
protected void init() {
File configFile = new File(getPlugin().getDataFolder(), "config.yml");
if (!configFile.exists()) {
configFile.getParentFile().mkdirs();
plugin.saveResource("config.yml", false);
getPlugin().saveResource("config.yml", false);
}
configuration = new YamlConfiguration();
try {
configuration.load(configFile);
} catch (InvalidConfigurationException | IOException e) {
e.printStackTrace();
}
}
@Override
public String getServer() {
return configuration.getString("server");
protected String getString(String path, String def) {
return configuration.getString(path, def);
}
@Override
public String getPrefix() {
return configuration.getString("prefix");
protected int getInt(String path, int def) {
return configuration.getInt(path, def);
}
@Override
public int getSyncTime() {
return configuration.getInt("sql.sync-minutes");
protected boolean getBoolean(String path, boolean def) {
return configuration.getBoolean(path, def);
}
@SuppressWarnings("unchecked")
@Override
public String getDefaultGroupNode() {
return "luckperms.group." + configuration.getString("default-group");
}
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;
}
@Override
public String getDefaultGroupName() {
return configuration.getString("default-group");
}
for (String key : section.getKeys(false)) {
map.put(key, section.getString(key));
}
@Override
public boolean getIncludeGlobalPerms() {
return configuration.getBoolean("include-global");
}
@Override
public String getDatabaseValue(String value) {
return configuration.getString("sql." + value);
return map;
}
}
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.inject.Injector;
import me.lucko.luckperms.inject.LPPermissible;
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.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.*;
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.getDatastore().isAcceptingLogins()) {
// The 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(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) {
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
return;
}
if (user instanceof BukkitUser) {
BukkitUser u = (BukkitUser) user;
try {
LPPermissible lpPermissible = new LPPermissible(player, plugin, plugin.getDefaultsProvider());
Injector.inject(player, lpPermissible);
u.setLpPermissible(lpPermissible);
} catch (Throwable t) {
t.printStackTrace();
}
}
plugin.doAsync(user::refreshPermissions);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerJoin(PlayerJoinEvent e) {
// Refresh permissions again
UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
plugin.getWorldCalculator().getWorldCache().put(internal, e.getPlayer().getWorld().getName());
plugin.doAsync(() -> refreshPlayer(internal));
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerQuit(PlayerQuitEvent e) {
plugin.getWorldCalculator().getWorldCache().remove(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
onLeave(e.getPlayer().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());
}
}
}
@@ -0,0 +1,71 @@
/*
* 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.commands.SenderFactory;
import me.lucko.luckperms.constants.Constants;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.UUID;
public class BukkitSenderFactory extends SenderFactory<CommandSender> {
private static BukkitSenderFactory instance = null;
private BukkitSenderFactory(LuckPermsPlugin plugin) {
super(plugin);
}
public static synchronized BukkitSenderFactory get(LuckPermsPlugin plugin) {
if (instance == null) {
instance = new BukkitSenderFactory(plugin);
}
return instance;
}
@Override
protected String getName(CommandSender sender) {
if (sender instanceof Player) {
return sender.getName();
}
return Constants.getConsoleName();
}
@Override
protected UUID getUuid(CommandSender sender) {
if (sender instanceof Player) {
return ((Player) sender).getUniqueId();
}
return Constants.getConsoleUUID();
}
@Override
protected void sendMessage(CommandSender sender, String s) {
sender.sendMessage(s);
}
@Override
protected boolean hasPermission(CommandSender sender, String node) {
return sender.hasPermission(node);
}
}
@@ -1,30 +0,0 @@
package me.lucko.luckperms;
import me.lucko.luckperms.commands.CommandManager;
import me.lucko.luckperms.commands.Sender;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import java.util.Arrays;
class CommandManagerBukkit extends CommandManager implements CommandExecutor {
CommandManagerBukkit(LuckPermsPlugin plugin) {
super(plugin);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
return onCommand(new Sender() {
@Override
public void sendMessage(String s) {
sender.sendMessage(s);
}
@Override
public boolean hasPermission(String node) {
return sender.hasPermission(node);
}
}, Arrays.asList(args));
}
}
@@ -1,100 +1,216 @@
/*
* 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.data.Datastore;
import me.lucko.luckperms.data.DatastoreConfiguration;
import me.lucko.luckperms.data.HikariDatastore;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.LuckPermsApi;
import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.api.implementation.ApiProvider;
import me.lucko.luckperms.api.vault.VaultHook;
import me.lucko.luckperms.commands.ConsecutiveExecutor;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.config.LPConfiguration;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.contexts.ContextManager;
import me.lucko.luckperms.contexts.ServerCalculator;
import me.lucko.luckperms.contexts.WorldCalculator;
import me.lucko.luckperms.core.UuidCache;
import me.lucko.luckperms.data.Importer;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.listeners.PlayerListener;
import me.lucko.luckperms.inject.DefaultsProvider;
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.LPConfiguration;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit;
import me.lucko.luckperms.utils.LocaleManager;
import me.lucko.luckperms.utils.LogFactory;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Arrays;
import java.util.UUID;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@Getter
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
public static final String VERSION = "v1.0";
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
private LPConfiguration configuration;
private UserManager userManager;
private BukkitUserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
private UuidCache uuidCache;
private ApiProvider apiProvider;
private Logger log;
private Importer importer;
private ConsecutiveExecutor consecutiveExecutor;
private DefaultsProvider defaultsProvider;
private LocaleManager localeManager;
private ContextManager<Player> contextManager;
private WorldCalculator worldCalculator;
@Override
public void onEnable() {
log = LogFactory.wrap(getLogger());
getLog().info("Loading configuration...");
configuration = new BukkitConfig(this);
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();
}
}
defaultsProvider = new DefaultsProvider();
getServer().getScheduler().runTaskLater(this, () -> defaultsProvider.refresh(), 1L);
// register events
PluginManager pm = Bukkit.getPluginManager();
pm.registerEvents(new PlayerListener(this), this);
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new BukkitListener(this), this);
// register commands
CommandManagerBukkit commandManager = new CommandManagerBukkit(this);
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 = new HikariDatastore(this);
datastore.init(new DatastoreConfiguration(
configuration.getDatabaseValue("address"),
configuration.getDatabaseValue("database"),
configuration.getDatabaseValue("username"),
configuration.getDatabaseValue("password")
));
datastore = StorageFactory.getDatastore(this, "h2");
getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().isOnlineMode());
userManager = new BukkitUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager();
importer = new Importer(commandManager);
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
contextManager = new ContextManager<>();
worldCalculator = new WorldCalculator(this);
pm.registerEvents(worldCalculator, this);
contextManager.registerCalculator(worldCalculator);
contextManager.registerCalculator(new ServerCalculator<>(getConfiguration().getServer()));
contextManager.registerListener(userManager);
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
long ticks = mins * 60 * 20;
new UpdateTask(this).runTaskTimer(this, ticks, ticks);
getServer().getScheduler().runTaskTimerAsynchronously(this, new UpdateTask(this), ticks, ticks);
}
getServer().getScheduler().runTaskTimer(this, BukkitSenderFactory.get(this), 1L, 1L);
getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpireTemporaryTask(this), 60L, 60L);
getServer().getScheduler().runTaskTimerAsynchronously(this, consecutiveExecutor, 20L, 20L);
// Provide vault support
getLog().info("Attempting to hook into Vault...");
try {
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
getServer().getServicesManager().register(Permission.class, new VaultHook(this), this, ServicePriority.High);
getLogger().info("Registered Vault permission hook.");
VaultHook.hook(this);
getLog().info("Registered Vault permission & chat hook.");
} else {
getLogger().info("Vault not found.");
getLog().info("Vault not found.");
}
} catch (Exception e) {
getLogger().warning("Error whilst hooking into Vault.");
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);
// 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();
}
registerPermissions(getConfiguration().isCommandsAllowOp() ? PermissionDefault.OP : PermissionDefault.FALSE);
if (!getConfiguration().isOpsEnabled()) {
getServer().getOperators().forEach(o -> o.setOp(false));
}
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) {
Bukkit.getScheduler().runTaskAsynchronously(this, r);
getServer().getScheduler().runTaskAsynchronously(this, r);
}
@Override
public void doSync(Runnable r) {
Bukkit.getScheduler().runTask(this, r);
getServer().getScheduler().runTask(this, r);
}
@Override
public String getVersion() {
return VERSION;
return getDescription().getVersion();
}
@Override
public String getPlayerStatus(UUID uuid) {
if (getServer().getPlayer(uuid) != null) return "&aOnline";
return "&cOffline";
public PlatformType getType() {
return PlatformType.BUKKIT;
}
@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
@@ -102,8 +218,93 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return getServer().getOnlinePlayers().size();
}
@Override
public List<String> getPlayerList() {
return getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
}
@Override
public List<Sender> getNotifyListeners() {
return getServer().getOnlinePlayers().stream()
.map(p -> BukkitSenderFactory.get(this).wrap(p, Collections.singleton(me.lucko.luckperms.constants.Permission.LOG_NOTIFY)))
.filter(me.lucko.luckperms.constants.Permission.LOG_NOTIFY::isAuthorized)
.collect(Collectors.toList());
}
@Override
public Sender getConsoleSender() {
return BukkitSenderFactory.get(this).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 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);
}
@Override
public void runUpdateTask() {
new UpdateTask(this).runTask(this);
getServer().getScheduler().runTaskAsynchronously(this, new UpdateTask(this));
}
private void registerPermissions(PermissionDefault def) {
PluginManager pm = getServer().getPluginManager();
Map<String, List<String>> wildcards = new HashMap<>();
List<String> all = new ArrayList<>();
for (me.lucko.luckperms.constants.Permission p : me.lucko.luckperms.constants.Permission.values()) {
pm.addPermission(new Permission(p.getNode(), def));
if (p.getGroup() != null) {
if (!wildcards.containsKey(p.getGroup())) {
wildcards.put(p.getGroup(), new ArrayList<>());
}
wildcards.get(p.getGroup()).add(p.getTag());
}
all.add(p.getNode());
}
for (Map.Entry<String, List<String>> e : wildcards.entrySet()) {
pm.addPermission(new Permission(
"luckperms." + e.getKey() + ".*", def,
e.getValue().stream()
.map(tag -> "luckperms." + e.getKey() + "." + tag)
.collect(Collectors.toMap(s -> s, s -> true))
)
);
}
pm.addPermission(new Permission("luckperms.*", def, all.stream().collect(Collectors.toMap(s -> s, s -> true))));
}
}
@@ -1,150 +0,0 @@
package me.lucko.luckperms;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import net.milkbowl.vault.permission.Permission;
@AllArgsConstructor
public class VaultHook extends Permission {
private final LPBukkitPlugin plugin;
@Override
public String getName() {
return "LuckPerms";
}
@Override
public boolean isEnabled() {
return plugin.getDatastore().isAcceptingLogins();
}
@Override
public boolean hasSuperPermsCompat() {
// Idk???
return true;
}
@Override
public boolean playerHas(String world, String player, String permission) {
final User user = plugin.getUserManager().getUser(player);
return user != null && user.hasPermission(permission, true);
}
@Override
public boolean playerAdd(String world, String player, String permission) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
try {
user.setPermission(permission, true);
} catch (ObjectAlreadyHasException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public boolean playerRemove(String world, String player, String permission) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
try {
user.unsetPermission(permission);
} catch (ObjectLacksPermissionException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public boolean groupHas(String world, String groupName, String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
return group != null && group.hasPermission(permission, true);
}
@Override
public boolean groupAdd(String world, String groupName, String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
group.setPermission(permission, true);
} catch (ObjectAlreadyHasException ignored) {}
plugin.runUpdateTask();
return true;
}
@Override
public boolean groupRemove(String world, String groupName, String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
group.unsetPermission(permission);
} catch (ObjectLacksPermissionException ignored) {}
plugin.runUpdateTask();
return true;
}
@Override
public boolean playerInGroup(String world, String player, String group) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
return user.getGroupNames().contains(group);
}
@Override
public boolean playerAddGroup(String world, String player, String groupName) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
user.addGroup(group);
} catch (ObjectAlreadyHasException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public boolean playerRemoveGroup(String world, String player, String groupName) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
user.removeGroup(group);
} catch (ObjectLacksPermissionException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public String[] getPlayerGroups(String world, String player) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return new String[0];
return user.getGroupNames().toArray(new String[0]);
}
@Override
public String getPrimaryGroup(String world, String player) {
throw new UnsupportedOperationException();
}
@Override
public String[] getGroups() {
return plugin.getGroupManager().getGroups().keySet().toArray(new String[0]);
}
@Override
public boolean hasGroupSupport() {
return true;
}
}
@@ -0,0 +1,337 @@
/*
* 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.Node;
import me.lucko.luckperms.contexts.Contexts;
import me.lucko.luckperms.core.PermissionHolder;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import net.milkbowl.vault.chat.Chat;
import java.util.Iterator;
import java.util.Map;
import static me.lucko.luckperms.utils.ArgumentChecker.escapeCharacters;
import static me.lucko.luckperms.utils.ArgumentChecker.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.utils.ArgumentChecker#escapeCharacters(String)}
*
* Registered on normal priority so other plugins can override.
*/
public class VaultChatHook extends Chat {
@Setter
private LPBukkitPlugin plugin;
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 saveMeta(PermissionHolder holder, String world, String node, String value) {
if (holder == null) return;
if (node.equals("")) return;
node = escapeCharacters(node);
value = escapeCharacters(value);
Iterator<Node> nodes = holder.getNodes().iterator();
while (nodes.hasNext()) {
Node n = nodes.next();
if (n.isMeta() && n.getMeta().getKey().equals(node)) {
nodes.remove();
}
}
Node.Builder metaNode = new me.lucko.luckperms.core.Node.Builder("meta." + node + "." + value).setValue(true);
if (!perms.getServer().equalsIgnoreCase("global")) {
metaNode.setServer(perms.getServer());
}
if (world != null && !world.equals("")) {
metaNode.setServer(perms.getServer()).setWorld(world);
}
try {
holder.setPermission(metaNode.build());
} catch (ObjectAlreadyHasException ignored) {}
perms.objectSave(holder);
}
private String getMeta(PermissionHolder holder, String world, String node, String defaultValue) {
if (holder == null) return defaultValue;
if (node.equals("")) return defaultValue;
node = escapeCharacters(node);
for (Node n : holder.getPermissions(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 void setChatMeta(boolean prefix, PermissionHolder holder, String value, String world) {
if (holder == null) return;
if (value.equals("")) return;
Node.Builder node = new me.lucko.luckperms.core.Node.Builder(prefix ? "prefix" : "suffix" + ".1000." + escapeCharacters(value));
node.setValue(true);
if (!perms.getServer().equalsIgnoreCase("global")) {
node.setServer(perms.getServer());
}
if (world != null && !world.equals("")) {
node.setServer(perms.getServer()).setWorld(world);
}
try {
holder.setPermission(node.build());
} catch (ObjectAlreadyHasException ignored) {}
perms.objectSave(holder);
}
private String getChatMeta(boolean prefix, PermissionHolder holder, String world) {
if (holder == null) return "";
int priority = Integer.MIN_VALUE;
String meta = null;
for (Node n : holder.getAllNodes(null, Contexts.allowAll())) {
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 = plugin.getUserManager().get(player);
return getChatMeta(true, user, world);
}
public void setPlayerPrefix(String world, @NonNull String player, @NonNull String prefix) {
final User user = plugin.getUserManager().get(player);
setChatMeta(true, user, prefix, world);
}
public String getPlayerSuffix(String world, @NonNull String player) {
final User user = plugin.getUserManager().get(player);
return getChatMeta(false, user, world);
}
public void setPlayerSuffix(String world, @NonNull String player, @NonNull String suffix) {
final User user = plugin.getUserManager().get(player);
setChatMeta(false, user, suffix, world);
}
public String getGroupPrefix(String world, @NonNull String group) {
final Group g = plugin.getGroupManager().get(group);
return getChatMeta(false, g, world);
}
public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) {
final Group g = plugin.getGroupManager().get(group);
setChatMeta(true, g, prefix, world);
}
public String getGroupSuffix(String world, @NonNull String group) {
final Group g = plugin.getGroupManager().get(group);
return getChatMeta(false, g, world);
}
public void setGroupSuffix(String world, @NonNull String group, @NonNull String suffix) {
final Group g = plugin.getGroupManager().get(group);
setChatMeta(false, g, suffix, world);
}
public int getPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int defaultValue) {
final User user = plugin.getUserManager().get(player);
try {
return Integer.parseInt(getMeta(user, world, node, String.valueOf(defaultValue)));
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void setPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int value) {
final User user = plugin.getUserManager().get(player);
saveMeta(user, world, node, String.valueOf(value));
}
public int getGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int defaultValue) {
final Group g = plugin.getGroupManager().get(group);
try {
return Integer.parseInt(getMeta(g, world, node, String.valueOf(defaultValue)));
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void setGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int value) {
final Group g = plugin.getGroupManager().get(group);
saveMeta(g, world, node, String.valueOf(value));
}
public double getPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double defaultValue) {
final User user = plugin.getUserManager().get(player);
try {
return Double.parseDouble(getMeta(user, world, node, String.valueOf(defaultValue)));
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void setPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double value) {
final User user = plugin.getUserManager().get(player);
saveMeta(user, world, node, String.valueOf(value));
}
public double getGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double defaultValue) {
final Group g = plugin.getGroupManager().get(group);
try {
return Double.parseDouble(getMeta(g, world, node, String.valueOf(defaultValue)));
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void setGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double value) {
final Group g = plugin.getGroupManager().get(group);
saveMeta(g, world, node, String.valueOf(value));
}
public boolean getPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean defaultValue) {
final User user = plugin.getUserManager().get(player);
String s = getMeta(user, world, node, String.valueOf(defaultValue));
if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) {
return defaultValue;
}
return Boolean.parseBoolean(s);
}
public void setPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean value) {
final User user = plugin.getUserManager().get(player);
saveMeta(user, world, node, String.valueOf(value));
}
public boolean getGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean defaultValue) {
final Group g = plugin.getGroupManager().get(group);
String s = getMeta(g, world, node, String.valueOf(defaultValue));
if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) {
return defaultValue;
}
return Boolean.parseBoolean(s);
}
public void setGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean value) {
final Group g = plugin.getGroupManager().get(group);
saveMeta(g, world, node, String.valueOf(value));
}
public String getPlayerInfoString(String world, @NonNull String player, @NonNull String node, String defaultValue) {
final User user = plugin.getUserManager().get(player);
return getMeta(user, world, node, defaultValue);
}
public void setPlayerInfoString(String world, @NonNull String player, @NonNull String node, String value) {
final User user = plugin.getUserManager().get(player);
saveMeta(user, world, node, value);
}
public String getGroupInfoString(String world, @NonNull String group, @NonNull String node, String defaultValue) {
final Group g = plugin.getGroupManager().get(group);
return getMeta(g, world, node, defaultValue);
}
public void setGroupInfoString(String world, @NonNull String group, @NonNull String node, String value) {
final Group g = plugin.getGroupManager().get(group);
saveMeta(g, world, node, value);
}
}
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.vault;
import me.lucko.luckperms.LPBukkitPlugin;
import net.milkbowl.vault.chat.Chat;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.ServicesManager;
public class VaultHook {
private static VaultChatHook chatHook = null;
private static VaultPermissionHook permissionHook = null;
public static void hook(LPBukkitPlugin plugin) {
try {
if (permissionHook == null) {
permissionHook = new VaultPermissionHook();
}
permissionHook.setPlugin(plugin);
permissionHook.setServer(plugin.getConfiguration().getVaultServer());
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIncludingGlobal());
if (chatHook == null) {
chatHook = new VaultChatHook(permissionHook);
}
chatHook.setPlugin(plugin);
final ServicesManager sm = plugin.getServer().getServicesManager();
sm.unregisterAll(plugin);
sm.register(Permission.class, permissionHook, plugin, ServicePriority.High);
sm.register(Chat.class, chatHook, plugin, ServicePriority.Low);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,226 @@
/*
* 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.Getter;
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;
public class VaultPermissionHook extends Permission {
@Setter
private LPBukkitPlugin plugin;
@Getter
@Setter
private String server = "global";
@Getter
@Setter
private boolean includeGlobal = true;
@Override
public String getName() {
return "LuckPerms";
}
@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, server, world);
} else {
return object.hasPermission(permission, true, server);
}
}
private boolean objectAdd(String world, PermissionHolder object, String permission) {
if (object == null) return false;
try {
if (world != null && !world.equals("")) {
object.setPermission(permission, true, server, world);
} else {
object.setPermission(permission, true, server);
}
} 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, server, world);
} else {
object.unsetPermission(permission, server);
}
} catch (ObjectLacksException ignored) {}
objectSave(object);
return true;
}
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, server, 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, server, 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, server, 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.getGroups(server, world, includeGlobal).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,90 @@
/*
* 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.contexts;
import com.google.common.collect.Maps;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.context.ContextCalculator;
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 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 Map<String, String> giveApplicableContext(Player subject, Map<String, String> accumulator) {
String world = getWorld(subject);
if (world != null) {
accumulator.put(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());
if (!worldCache.containsKey(internal)) {
return null;
}
String world = worldCache.get(internal);
return plugin.getConfiguration().getWorldRewrites().getOrDefault(world, world);
}
@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,177 @@
/*
* 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.inject;
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;
if (!map.containsKey(permission)) {
return Tristate.UNDEFINED;
}
return Tristate.fromBoolean(map.get(permission));
}
@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.inject;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.PermissibleBase;
import java.lang.reflect.Field;
/**
* Injects a {@link LPPermissible} into a {@link Player}
*/
@UtilityClass
public class Injector {
private static Field HUMAN_ENTITY_FIELD;
static {
try {
HUMAN_ENTITY_FIELD = Class.forName(getInternalClassName("entity.CraftHumanEntity")).getDeclaredField("perm");
HUMAN_ENTITY_FIELD.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean inject(CommandSender sender, PermissibleBase permissible) {
try {
Field f = getPermField(sender);
f.set(sender, permissible);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static boolean unInject(CommandSender sender) {
try {
Permissible permissible = getPermissible(sender);
if (permissible instanceof LPPermissible) {
getPermField(sender).set(sender, new PermissibleBase(sender));
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static Permissible getPermissible(CommandSender sender) {
try {
Field f = getPermField(sender);
return (Permissible) f.get(sender);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Field getPermField(CommandSender sender) {
if (sender instanceof Player) {
return HUMAN_ENTITY_FIELD;
}
throw new RuntimeException("Couldn't get perm field for sender " + sender.getClass().getName());
}
private static String getInternalClassName(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,301 @@
/*
* 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.inject;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.calculators.PermissionCalculator;
import me.lucko.luckperms.calculators.PermissionProcessor;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.permissions.*;
import org.bukkit.plugin.Plugin;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.stream.Collectors;
/**
* Modified PermissibleBase for LuckPerms
*/
public class LPPermissible extends PermissibleBase {
@Getter
private final CommandSender parent;
private final PermissionCalculator calculator;
@Getter
private final Map<String, Boolean> luckPermsPermissions = new ConcurrentHashMap<>();
private final List<PermissionAttachment> attachments = new LinkedList<>();
private final Map<String, PermissionAttachmentInfo> attachmentPermissions = new HashMap<>();
public LPPermissible(@NonNull CommandSender sender, LuckPermsPlugin plugin, DefaultsProvider defaultsProvider) {
super(sender);
this.parent = sender;
List<PermissionProcessor> processors = new ArrayList<>(5);
processors.add(new PermissionCalculator.MapProcessor(luckPermsPermissions));
processors.add(new AttachmentProcessor(attachmentPermissions));
if (plugin.getConfiguration().isApplyingWildcards()) {
processors.add(new PermissionCalculator.WildcardProcessor(luckPermsPermissions));
}
if (plugin.getConfiguration().isApplyingRegex()) {
processors.add(new PermissionCalculator.RegexProcessor(luckPermsPermissions));
}
processors.add(new BukkitDefaultsProcessor(parent::isOp, defaultsProvider));
calculator = new PermissionCalculator(plugin, parent.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors);
recalculatePermissions();
}
public void invalidateCache() {
calculator.invalidateCache();
}
@Override
public boolean isOp() {
return parent.isOp();
}
@Override
public void setOp(boolean value) {
parent.setOp(value);
}
@Override
public boolean isPermissionSet(@NonNull String name) {
return calculator.getPermissionValue(name) != Tristate.UNDEFINED;
}
@Override
public boolean isPermissionSet(@NonNull Permission perm) {
return isPermissionSet(perm.getName());
}
@Override
public boolean hasPermission(@NonNull String name) {
Tristate ts = calculator.getPermissionValue(name);
if (ts != Tristate.UNDEFINED) {
return ts.asBoolean();
}
return Permission.DEFAULT_PERMISSION.getValue(isOp());
}
@Override
public boolean hasPermission(@NonNull Permission perm) {
Tristate ts = calculator.getPermissionValue(perm.getName());
if (ts != Tristate.UNDEFINED) {
return ts.asBoolean();
}
return perm.getDefault().getValue(isOp());
}
@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, new RemoveAttachmentRunnable(result), 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);
}
invalidateCache();
}
@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);
}
}
}
@Override
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
Set<PermissionAttachmentInfo> perms = new HashSet<>();
perms.addAll(attachmentPermissions.values());
perms.addAll(luckPermsPermissions.entrySet().stream()
.map(e -> new PermissionAttachmentInfo(parent, e.getKey(), null, e.getValue()))
.collect(Collectors.toList()));
return perms;
}
private class RemoveAttachmentRunnable implements Runnable {
private PermissionAttachment attachment;
private RemoveAttachmentRunnable(PermissionAttachment attachment) {
this.attachment = attachment;
}
public void run() {
attachment.remove();
}
}
@AllArgsConstructor
private static class AttachmentProcessor implements PermissionProcessor {
@Getter
private final Map<String, PermissionAttachmentInfo> map;
@Override
public Tristate hasPermission(String permission) {
if (map.containsKey(permission)) {
return Tristate.fromBoolean(map.get(permission).getValue());
}
return Tristate.UNDEFINED;
}
}
@AllArgsConstructor
private static class BukkitDefaultsProcessor implements PermissionProcessor {
private final Supplier<Boolean> isOp;
private final DefaultsProvider defaultsProvider;
@Override
public Tristate hasPermission(String permission) {
Tristate t = defaultsProvider.hasDefault(permission, isOp.get());
if (t != Tristate.UNDEFINED) {
return t;
}
Permission defPerm = Bukkit.getServer().getPluginManager().getPermission(permission);
if (defPerm != null) {
return Tristate.fromBoolean(defPerm.getDefault().getValue(isOp.get()));
} else {
return Tristate.UNDEFINED;
}
}
}
}
@@ -1,75 +0,0 @@
package me.lucko.luckperms.listeners;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.users.BukkitUser;
import me.lucko.luckperms.users.User;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
@AllArgsConstructor
public class PlayerListener implements Listener {
private final LPBukkitPlugin plugin;
@EventHandler
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
if (!plugin.getDatastore().isAcceptingLogins()) {
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, color(plugin.getConfiguration().getPrefix() +
"&cError whilst validating login with the network. \nPlease contact an administrator."));
return;
}
plugin.getDatastore().loadOrCreateUser(e.getUniqueId(), e.getName());
}
@EventHandler
public void onPlayerLogin(PlayerLoginEvent e) {
Player player = e.getPlayer();
User user = plugin.getUserManager().getUser(player.getUniqueId());
if (user == null) {
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, color(plugin.getConfiguration().getPrefix() +
"&cUser data could not be loaded. Please contact an administrator."));
return;
}
if (user instanceof BukkitUser) {
BukkitUser u = (BukkitUser) user;
u.setAttachment(player.addAttachment(plugin));
}
user.refreshPermissions();
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
// Save UUID data for the player
plugin.getDatastore().saveUUIDData(e.getPlayer().getName(), e.getPlayer().getUniqueId(), success -> {});
User user = plugin.getUserManager().getUser(e.getPlayer().getUniqueId());
if (user != null) {
// Refresh permissions again
user.refreshPermissions();
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
Player player = e.getPlayer();
// Unload the user from memory when they disconnect
User user = plugin.getUserManager().getUser(player.getUniqueId());
plugin.getUserManager().unloadUser(user);
}
public static String color(String string) {
return ChatColor.translateAlternateColorCodes('&', string);
}
}
@@ -1,25 +0,0 @@
package me.lucko.luckperms.runnables;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBukkitPlugin;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
@AllArgsConstructor
public class UpdateTask extends BukkitRunnable {
private final LPBukkitPlugin plugin;
@Override
public void run() {
plugin.getLogger().info("Running update task.");
// Re-load all of the groups
plugin.getGroupManager().loadAllGroups();
// Refresh all online users.
for (Player p : Bukkit.getOnlinePlayers()) {
plugin.getDatastore().loadUser(p.getUniqueId(), success -> {});
}
}
}
@@ -1,52 +1,122 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.users;
import lombok.Getter;
import lombok.Setter;
import me.lucko.luckperms.LPBukkitPlugin;
import org.bukkit.Bukkit;
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import me.lucko.luckperms.contexts.Contexts;
import me.lucko.luckperms.inject.LPPermissible;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.Permissible;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class BukkitUser extends User {
private final LPBukkitPlugin plugin;
@Getter
@Setter
private PermissionAttachment attachment = null;
private LPPermissible lpPermissible = null;
public BukkitUser(UUID uuid, LPBukkitPlugin plugin) {
BukkitUser(UUID uuid, LPBukkitPlugin plugin) {
super(uuid, plugin);
this.plugin = plugin;
}
public BukkitUser(UUID uuid, String username, LPBukkitPlugin plugin) {
BukkitUser(UUID uuid, String username, LPBukkitPlugin plugin) {
super(uuid, username, plugin);
this.plugin = plugin;
}
@SuppressWarnings("unchecked")
@Override
public void refreshPermissions() {
Player player = Bukkit.getPlayer(getUuid());
if (player == null) return;
if (attachment == null) {
getPlugin().getLogger().warning("User " + getName() + " does not have a permissions attachment defined.");
setAttachment(player.addAttachment(plugin));
public synchronized void refreshPermissions() {
if (lpPermissible == null) {
return;
}
// Clear existing permissions
for (String p : attachment.getPermissions().keySet()) {
attachment.setPermission(p, false);
}
// Calculate the permissions that should be applied. This is done async, who cares about how long it takes or how often it's done.
Map<String, Boolean> toApply = exportNodes(
new Contexts(
plugin.getContextManager().giveApplicableContext((Player) lpPermissible.getParent(), new HashMap<>()),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
plugin.getConfiguration().isApplyingGlobalGroups(),
plugin.getConfiguration().isApplyingGlobalWorldGroups()
),
Collections.emptyList()
);
// Re-add all defined permissions for the user
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null);
for (String node : local.keySet()) {
attachment.setPermission(node, local.get(node));
try {
Map<String, Boolean> existing = lpPermissible.getLuckPermsPermissions();
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;
existing.clear();
lpPermissible.invalidateCache();
existing.putAll(toApply);
if (plugin.getConfiguration().isAutoOp()) {
boolean op = false;
for (Map.Entry<String, Boolean> e : toApply.entrySet()) {
if (e.getKey().equalsIgnoreCase("luckperms.autoop") && e.getValue()) {
op = true;
break;
}
}
final boolean finalOp = op;
if (lpPermissible.isOp() != op) {
final Permissible parent = lpPermissible.getParent();
plugin.doSync(() -> parent.setOp(finalOp));
}
}
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,53 +1,98 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.users;
import me.lucko.luckperms.LPBukkitPlugin;
import org.bukkit.Bukkit;
import me.lucko.luckperms.api.context.ContextListener;
import me.lucko.luckperms.inject.Injector;
import org.bukkit.entity.Player;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class BukkitUserManager extends UserManager {
public class BukkitUserManager extends UserManager implements ContextListener<Player> {
private final LPBukkitPlugin plugin;
public BukkitUserManager(LPBukkitPlugin plugin) {
super(plugin);
this.plugin = plugin;
}
@Override
public void unloadUser(User user) {
if (user != null) {
public void preUnload(User user) {
if (user instanceof BukkitUser) {
BukkitUser u = (BukkitUser) user;
Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid()));
if (player != null) {
if (u.getLpPermissible() != null) {
Injector.unInject(player);
u.setLpPermissible(null);
}
if (user instanceof BukkitUser) {
BukkitUser u = (BukkitUser) user;
if (u.getAttachment() != null) {
Player player = Bukkit.getPlayer(u.getUuid());
if (player != null) {
player.removeAttachment(u.getAttachment());
}
u.setAttachment(null);
if (plugin.getConfiguration().isAutoOp()) {
player.setOp(false);
}
}
getUsers().remove(user.getUuid());
}
}
@Override
public void cleanupUser(User user) {
if (Bukkit.getPlayer(user.getUuid()) == null) {
unloadUser(user);
public void cleanup(User user) {
if (plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) {
unload(user);
}
}
@Override
public User makeUser(UUID uuid) {
public User make(UUID uuid) {
return new BukkitUser(uuid, plugin);
}
@Override
public User makeUser(UUID uuid, String username) {
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, "null")));
});
}
@Override
public void onContextChange(Player subject, Map.Entry<String, String> before, Map.Entry<String, String> current) throws Exception {
UUID internal = plugin.getUuidCache().getUUID(subject.getUniqueId());
User user = get(internal);
if (user != null) {
plugin.doAsync(user::refreshPermissions);
}
}
}
+105 -8
View File
@@ -1,19 +1,116 @@
# LuckPerms Configuration
##############################################################################
# +------------------------------------------------------------------------+ #
# | LuckPerms Configuration | #
# | https://github.com/lucko/LuckPerms | #
# +------------------------------------------------------------------------+ #
##############################################################################
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server: global
# The default group assigned to all user on join. e.g. a value of "default" = luckperms.group.default
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
prefix: '&7&l[&b&lL&a&lP&7&l] &c'
# 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
sql:
# 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 apply wildcard permissions.
# If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered permissions matching
# 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.
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
# If the plugin should send log notifications to users whenever permissions are modified.
log-notify: true
# If LuckPerms should print to console every time a plugin checks if a player has a permission
debug-permission-checks: false
# 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 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
# 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
# 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
# Which storage method the plugin should use.
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
# Fill out connection info below if you're using MySQL or MongoDB
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: ''
sync-minutes: 3
# 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
+11 -5
View File
@@ -1,10 +1,16 @@
name: LuckPerms
author: Luck
version: 1.0
main: me.lucko.luckperms.LPBukkitPlugin
softdepend: [Vault]
version: ${release.version}.${git.closest.tag.commit.count}
description: A permissions plugin
author: Luck
website: https://github.com/lucko/LuckPerms
main: me.lucko.luckperms.LPBukkitPlugin
softdepend: [Vault, PermissionsEx, GroupManager, PowerfulPerms, zPermissions, bPermissions] # For migration
commands:
luckperms:
description: Manage permissions
aliases: [perms, permissions, lp, p, perm]
aliases: [perms, permissions, lp, p, perm]
# Permissions are registered programmatically instead of here.
+64 -12
View File
@@ -4,19 +4,17 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko</groupId>
<version>1.0-SNAPSHOT</version>
<groupId>me.lucko.luckperms</groupId>
<version>2.10-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-bungee</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>LuckPerms</name>
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>LuckPerms</finalName>
<finalName>LuckPermsBungee-${release.version}.${git.closest.tag.commit.count}</finalName>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
@@ -28,7 +26,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
@@ -37,7 +35,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
@@ -45,11 +43,52 @@
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<minimizeJar>false</minimizeJar>
<relocations>
<relocation>
<pattern>org.slf4j</pattern>
<shadedPattern>me.lucko.luckperms.lib.slf4j</shadedPattern>
</relocation>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
</relocation>
<relocation>
<pattern>com.mongodb</pattern>
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
</relocation>
<relocation>
<pattern>org.bson</pattern>
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
</relocation>
<relocation>
<pattern>org.h2</pattern>
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
</relocation>
<relocation>
<pattern>org.sqlite</pattern>
<shadedPattern>me.lucko.luckperms.lib.sqlite</shadedPattern>
</relocation>
</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>
@@ -59,16 +98,29 @@
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.9-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<!-- LuckPerms Common -->
<dependency>
<groupId>me.lucko</groupId>
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-common</artifactId>
<version>${project.parent.version}</version>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- LuckPerms API -->
<dependency>
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
</project>
@@ -0,0 +1,59 @@
/*
* 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 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.commands.Util;
import me.lucko.luckperms.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;
import java.util.Arrays;
class BungeeCommand extends Command implements TabExecutor {
private final CommandManager manager;
BungeeCommand(CommandManager manager) {
super("luckpermsbungee", null, "bperms", "lpb", "bpermissions", "bp", "bperm");
this.manager = manager;
}
@Override
public void execute(CommandSender sender, String[] args) {
manager.onCommand(
BungeeSenderFactory.get(manager.getPlugin()).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(manager.getPlugin()).wrap(sender), Arrays.asList(args));
}
}
@@ -1,6 +1,28 @@
/*
* 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.utils.LPConfiguration;
import me.lucko.luckperms.config.AbstractConfiguration;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
@@ -9,30 +31,23 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
public class BungeeConfig implements LPConfiguration {
private final LPBungeePlugin plugin;
class BungeeConfig extends AbstractConfiguration<LPBungeePlugin> {
private Configuration configuration;
public BungeeConfig(LPBungeePlugin plugin) {
this.plugin = plugin;
reload();
}
private void reload() {
try {
configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(makeFile("config.yml"));
} catch (IOException e) {
e.printStackTrace();
}
BungeeConfig(LPBungeePlugin plugin) {
super(plugin, "bungee", false, "flatfile");
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private File makeFile(String file) throws IOException {
File cfg = new File(plugin.getDataFolder(), file);
File cfg = new File(getPlugin().getDataFolder(), file);
if (!cfg.exists()) {
plugin.getDataFolder().mkdir();
try (InputStream is = plugin.getResourceAsStream(file)) {
getPlugin().getDataFolder().mkdir();
try (InputStream is = getPlugin().getResourceAsStream(file)) {
Files.copy(is, cfg.toPath());
}
}
@@ -40,39 +55,42 @@ public class BungeeConfig implements LPConfiguration {
return cfg;
}
@Override
public String getServer() {
return configuration.getString("server");
protected void init() {
try {
configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(makeFile("config.yml"));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String getPrefix() {
return configuration.getString("prefix");
protected String getString(String path, String def) {
return configuration.getString(path, def);
}
@Override
public int getSyncTime() {
return configuration.getInt("sql.sync-minutes");
protected int getInt(String path, int def) {
return configuration.getInt(path, def);
}
@Override
public String getDefaultGroupNode() {
return "luckperms.group." + configuration.getString("default-group");
protected boolean getBoolean(String path, boolean def) {
return configuration.getBoolean(path, def);
}
@Override
public String getDefaultGroupName() {
return configuration.getString("default-group");
}
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;
}
@Override
public boolean getIncludeGlobalPerms() {
return configuration.getBoolean("include-global");
}
for (String key : section.getKeys()) {
map.put(key, section.getString(key));
}
@Override
public String getDatabaseValue(String value) {
return configuration.getString("sql." + value);
return map;
}
}
@@ -0,0 +1,124 @@
/*
* 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.core.UuidCache;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.AbstractListener;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.api.event.PermissionCheckEvent;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@SuppressWarnings("WeakerAccess")
public class BungeeListener extends AbstractListener implements Listener {
private static final TextComponent WARN_MESSAGE = new TextComponent(Message.LOADING_ERROR.toString());
private final LPBungeePlugin plugin;
BungeeListener(LPBungeePlugin plugin) {
super(plugin);
this.plugin = plugin;
}
@EventHandler
public void onPlayerPermissionCheck(PermissionCheckEvent e) {
if (!(e.getSender() instanceof ProxiedPlayer)) {
e.setHasPermission(true);
return;
}
final ProxiedPlayer player = ((ProxiedPlayer) e.getSender());
BungeePlayerCache playerCache = plugin.getPlayerCache().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
if (playerCache == null) {
return;
}
e.setHasPermission(playerCache.getPermissionValue(e.getPermission()));
}
@EventHandler
public void onPlayerLogin(LoginEvent e) {
/* Delay the login here, as we want to cache UUID data before the player is connected to a backend bukkit server.
This means that a player will have the same UUID across the network, even if parts of the network are running in
Offline mode. */
e.registerIntent(plugin);
plugin.doAsync(() -> {
final long startTime = System.currentTimeMillis();
final UuidCache cache = plugin.getUuidCache();
final PendingConnection c = e.getConnection();
if (!cache.isOnlineMode()) {
UUID uuid = plugin.getDatastore().getUUID(c.getName());
if (uuid != null) {
cache.addToCache(c.getUniqueId(), uuid);
} else {
// No previous data for this player
cache.addToCache(c.getUniqueId(), c.getUniqueId());
plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId());
}
} else {
// Online mode, no cache needed. This is just for name -> uuid lookup.
plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId());
}
// We have to make a new user on this thread whilst the connection is being held, or we get concurrency issues as the Bukkit server
// and the BungeeCord server try to make a new user at the same time.
plugin.getDatastore().loadUser(cache.getUUID(c.getUniqueId()), c.getName());
final long time = System.currentTimeMillis() - startTime;
if (time >= 1000) {
plugin.getLog().warn("Processing login for " + c.getName() + " took " + time + "ms.");
}
e.completeIntent(plugin);
});
}
@EventHandler
public void onPlayerPostLogin(PostLoginEvent e) {
final ProxiedPlayer player = e.getPlayer();
final UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
final User user = plugin.getUserManager().get(internal);
if (user == null) {
plugin.getProxy().getScheduler().schedule(plugin, () -> player.sendMessage(WARN_MESSAGE), 3, TimeUnit.SECONDS);
} else {
plugin.getPlayerCache().put(internal, new BungeePlayerCache(plugin, e.getPlayer().getName()));
user.refreshPermissions();
}
}
@EventHandler
public void onPlayerQuit(PlayerDisconnectEvent e) {
plugin.getPlayerCache().remove(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
onLeave(e.getPlayer().getUniqueId());
}
}
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms;
import lombok.Getter;
import me.lucko.luckperms.calculators.PermissionCalculator;
import me.lucko.luckperms.calculators.PermissionProcessor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class BungeePlayerCache {
private final PermissionCalculator calculator;
@Getter
private final Map<String, Boolean> permissions = new ConcurrentHashMap<>();
public BungeePlayerCache(LuckPermsPlugin plugin, String name) {
List<PermissionProcessor> processors = new ArrayList<>(3);
processors.add(new PermissionCalculator.MapProcessor(permissions));
if (plugin.getConfiguration().isApplyingWildcards()) {
processors.add(new PermissionCalculator.WildcardProcessor(permissions));
}
if (plugin.getConfiguration().isApplyingRegex()) {
processors.add(new PermissionCalculator.RegexProcessor(permissions));
}
calculator = new PermissionCalculator(plugin, name, plugin.getConfiguration().isDebugPermissionChecks(), processors);
}
public void invalidateCache() {
calculator.invalidateCache();
}
public boolean getPermissionValue(String permission) {
return calculator.getPermissionValue(permission).asBoolean();
}
}
@@ -0,0 +1,72 @@
/*
* 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.commands.SenderFactory;
import me.lucko.luckperms.constants.Constants;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.UUID;
public class BungeeSenderFactory extends SenderFactory<CommandSender> {
private static BungeeSenderFactory instance = null;
private BungeeSenderFactory(LuckPermsPlugin plugin) {
super(plugin);
}
public static synchronized BungeeSenderFactory get(LuckPermsPlugin plugin) {
if (instance == null) {
instance = new BungeeSenderFactory(plugin);
}
return instance;
}
@Override
protected String getName(CommandSender sender) {
if (sender instanceof ProxiedPlayer) {
return sender.getName();
}
return Constants.getConsoleName();
}
@Override
protected UUID getUuid(CommandSender sender) {
if (sender instanceof ProxiedPlayer) {
return ((ProxiedPlayer) sender).getUniqueId();
}
return Constants.getConsoleUUID();
}
@Override
protected void sendMessage(CommandSender sender, String s) {
sender.sendMessage(new TextComponent(s));
}
@Override
protected boolean hasPermission(CommandSender sender, String node) {
return sender.hasPermission(node);
}
}
@@ -1,83 +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;
import lombok.Getter;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.api.implementation.ApiProvider;
import me.lucko.luckperms.commands.CommandManager;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.data.DatastoreConfiguration;
import me.lucko.luckperms.data.HikariDatastore;
import me.lucko.luckperms.commands.ConsecutiveExecutor;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.config.LPConfiguration;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.contexts.BackendServerCalculator;
import me.lucko.luckperms.contexts.ContextManager;
import me.lucko.luckperms.contexts.ServerCalculator;
import me.lucko.luckperms.core.UuidCache;
import me.lucko.luckperms.data.Importer;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.listeners.PlayerListener;
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.LPConfiguration;
import me.lucko.luckperms.utils.LocaleManager;
import me.lucko.luckperms.utils.LogFactory;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import java.util.UUID;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Getter
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
public static final String VERSION = "v1.0";
@Getter
LPConfiguration configuration;
@Getter
UserManager userManager;
@Getter
GroupManager groupManager;
@Getter
Datastore datastore;
private final Map<UUID, BungeePlayerCache> playerCache = new ConcurrentHashMap<>();
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
private LPConfiguration configuration;
private BungeeUserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
private UuidCache uuidCache;
private ApiProvider apiProvider;
private Logger log;
private Importer importer;
private ConsecutiveExecutor consecutiveExecutor;
private LocaleManager localeManager;
private ContextManager<ProxiedPlayer> contextManager;
@Override
public void onEnable() {
log = LogFactory.wrap(getLogger());
getLog().info("Loading configuration...");
configuration = new BungeeConfig(this);
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 events
getProxy().getPluginManager().registerListener(this, new PlayerListener(this));
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
// register commands
getProxy().getPluginManager().registerCommand(this, new MainCommand(new CommandManager(this)));
getLog().info("Registering commands...");
CommandManager commandManager = new CommandManager(this);
getProxy().getPluginManager().registerCommand(this, new BungeeCommand(commandManager));
datastore = new HikariDatastore(this);
datastore.init(new DatastoreConfiguration(
configuration.getDatabaseValue("address"),
configuration.getDatabaseValue("database"),
configuration.getDatabaseValue("username"),
configuration.getDatabaseValue("password")
));
// 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().isOnlineMode());
userManager = new BungeeUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager();
importer = new Importer(commandManager);
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
contextManager = new ContextManager<>();
BackendServerCalculator serverCalculator = new BackendServerCalculator();
getProxy().getPluginManager().registerListener(this, serverCalculator);
contextManager.registerCalculator(serverCalculator);
contextManager.registerCalculator(new ServerCalculator<>(getConfiguration().getServer()));
contextManager.registerListener(userManager);
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
getProxy().getScheduler().schedule(this, new UpdateTask(this), mins, mins, TimeUnit.MINUTES);
}
}
// 20 times per second (once per "tick")
getProxy().getScheduler().schedule(this, BungeeSenderFactory.get(this), 50L, 50L, TimeUnit.MILLISECONDS);
getProxy().getScheduler().schedule(this, new ExpireTemporaryTask(this), 3L, 3L, TimeUnit.SECONDS);
getProxy().getScheduler().schedule(this, consecutiveExecutor, 1L, 1L, TimeUnit.SECONDS);
@Override
public UserManager getUserManager() {
return userManager;
getLog().info("Registering API...");
apiProvider = new ApiProvider(this);
LuckPerms.registerProvider(apiProvider);
// 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();
}
getLog().info("Successfully loaded.");
}
@Override
public GroupManager getGroupManager() {
return groupManager;
public void onDisable() {
getLog().info("Closing datastore...");
datastore.shutdown();
getLog().info("Unregistering API...");
LuckPerms.unregisterProvider();
}
@Override
public String getVersion() {
return VERSION;
return getDescription().getVersion();
}
@Override
public String getPlayerStatus(UUID uuid) {
if (getProxy().getPlayer(uuid) != null) return "&aOnline";
return "&cOffline";
public PlatformType getType() {
return PlatformType.BUNGEE;
}
@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
@@ -86,18 +178,55 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
}
@Override
public LPConfiguration getConfiguration() {
return configuration;
public List<String> getPlayerList() {
return getProxy().getPlayers().stream().map(ProxiedPlayer::getName).collect(Collectors.toList());
}
@Override
public Datastore getDatastore() {
return datastore;
public List<Sender> getNotifyListeners() {
return getProxy().getPlayers().stream()
.map(p -> BungeeSenderFactory.get(this).wrap(p, Collections.singleton(Permission.LOG_NOTIFY)))
.filter(Permission.LOG_NOTIFY::isAuthorized)
.collect(Collectors.toList());
}
@Override
public Sender getConsoleSender() {
return BungeeSenderFactory.get(this).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 Object getPlugin(String name) {
return getProxy().getPluginManager().getPlugin(name);
}
@Override
public Object getService(Class clazz) {
return null;
}
@Override
public UUID getUUID(String playerName) {
return null; // Not needed on Bungee
}
@Override
public boolean isPluginLoaded(String name) {
return getProxy().getPluginManager().getPlugins().stream()
.filter(p -> p.getDescription().getName().equalsIgnoreCase(name))
.findAny()
.isPresent();
}
@Override
public void runUpdateTask() {
new UpdateTask(this).run();
doAsync(new UpdateTask(this));
}
@Override
@@ -1,34 +0,0 @@
package me.lucko.luckperms;
import me.lucko.luckperms.commands.CommandManager;
import me.lucko.luckperms.commands.Sender;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.plugin.Command;
import java.util.Arrays;
public class MainCommand extends Command {
private final CommandManager manager;
public MainCommand(CommandManager manager) {
super("luckpermsbungee", "luckperms.use", "bperms", "lpb", "bpermissions", "bp", "bperm");
this.manager = manager;
}
@Override
public void execute(CommandSender sender, String[] args) {
manager.onCommand(new Sender() {
@Override
public void sendMessage(String s) {
sender.sendMessage(new TextComponent(s));
}
@Override
public boolean hasPermission(String node) {
return sender.hasPermission(node);
}
}, Arrays.asList(args));
}
}
@@ -0,0 +1,66 @@
/*
* 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.contexts;
import com.google.common.collect.Maps;
import me.lucko.luckperms.api.context.ContextCalculator;
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 Map<String, String> giveApplicableContext(ProxiedPlayer subject, Map<String, String> accumulator) {
String server = getServer(subject);
if (server != null) {
accumulator.put(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());
}
}
@@ -1,44 +0,0 @@
package me.lucko.luckperms.listeners;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBungeePlugin;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.users.User;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
@AllArgsConstructor
public class PlayerListener implements Listener {
private final LPBungeePlugin plugin;
@EventHandler
public void onPlayerPostLogin(PostLoginEvent e) {
final ProxiedPlayer player = e.getPlayer();
plugin.getDatastore().loadOrCreateUser(player.getUniqueId(), player.getName(), success -> {
if (!success) {
e.getPlayer().sendMessage(new TextComponent(Util.color("&e&l[LP] &cPermissions data could not be loaded. Please contact an administrator.")));
} else {
User user = plugin.getUserManager().getUser(player.getUniqueId());
user.refreshPermissions();
}
});
plugin.getDatastore().saveUUIDData(e.getPlayer().getName(), e.getPlayer().getUniqueId(), success -> {});
}
@EventHandler
public void onPlayerQuit(PlayerDisconnectEvent e) {
ProxiedPlayer player = e.getPlayer();
// Unload the user from memory when they disconnect
User user = plugin.getUserManager().getUser(player.getUniqueId());
plugin.getUserManager().unloadUser(user);
}
}
@@ -1,23 +0,0 @@
package me.lucko.luckperms.runnables;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBungeePlugin;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@AllArgsConstructor
public class UpdateTask implements Runnable {
private final LPBungeePlugin plugin;
@Override
public void run() {
plugin.getLogger().info("Running update task.");
// Re-load all of the groups
plugin.getGroupManager().loadAllGroups();
// Refresh all online users.
for (ProxiedPlayer p : plugin.getProxy().getPlayers()) {
plugin.getDatastore().loadUser(p.getUniqueId(), success -> {});
}
}
}
@@ -1,42 +1,98 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.users;
import me.lucko.luckperms.BungeePlayerCache;
import me.lucko.luckperms.LPBungeePlugin;
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import me.lucko.luckperms.contexts.Contexts;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class BungeeUser extends User {
private final LPBungeePlugin plugin;
public BungeeUser(UUID uuid, LPBungeePlugin plugin) {
BungeeUser(UUID uuid, LPBungeePlugin plugin) {
super(uuid, plugin);
this.plugin = plugin;
}
public BungeeUser(UUID uuid, String username, LPBungeePlugin plugin) {
BungeeUser(UUID uuid, String username, LPBungeePlugin plugin) {
super(uuid, username, plugin);
this.plugin = plugin;
}
@Override
public void refreshPermissions() {
ProxiedPlayer player = plugin.getProxy().getPlayer(getUuid());
if (player == null) return;
// Clear existing permissions
Collection<String> perms = new ArrayList<>(player.getPermissions());
for (String p : perms) {
player.setPermission(p, false);
public synchronized void refreshPermissions() {
ProxiedPlayer player = plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid()));
if (player == null) {
return;
}
// Re-add all defined permissions for the user
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null);
for (String node : local.keySet()) {
player.setPermission(node, local.get(node));
BungeePlayerCache playerCache = plugin.getPlayerCache().get(getUuid());
if (playerCache == null) {
return;
}
// Calculate the permissions that should be applied. This is done async.
Map<String, Boolean> toApply = exportNodes(
new Contexts(
plugin.getContextManager().giveApplicableContext(player, new HashMap<>()),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
plugin.getConfiguration().isApplyingGlobalGroups(),
plugin.getConfiguration().isApplyingGlobalWorldGroups()
),
Collections.emptyList()
);
Map<String, Boolean> existing = playerCache.getPermissions();
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;
existing.clear();
playerCache.invalidateCache();
existing.putAll(toApply);
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
}
}
@@ -1,44 +1,73 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.users;
import me.lucko.luckperms.LPBungeePlugin;
import me.lucko.luckperms.api.context.ContextListener;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.Map;
import java.util.UUID;
public class BungeeUserManager extends UserManager {
public class BungeeUserManager extends UserManager implements ContextListener<ProxiedPlayer> {
private final LPBungeePlugin plugin;
public BungeeUserManager(LPBungeePlugin plugin) {
super(plugin);
this.plugin = plugin;
}
@Override
public void unloadUser(User user) {
if (user != null) {
ProxiedPlayer player = plugin.getProxy().getPlayer(user.getUuid());
if (player != null) {
player.getPermissions().clear();
}
getUsers().remove(user.getUuid());
public void cleanup(User user) {
if (plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) {
unload(user);
}
}
@Override
public void cleanupUser(User user) {
if (plugin.getProxy().getPlayer(user.getUuid()) == null) {
unloadUser(user);
}
}
@Override
public User makeUser(UUID uuid) {
public User make(UUID uuid) {
return new BungeeUser(uuid, plugin);
}
@Override
public User makeUser(UUID uuid, String username) {
public User make(UUID uuid, String username) {
return new BungeeUser(uuid, username, plugin);
}
@Override
public void updateAllUsers() {
plugin.getProxy().getPlayers().stream()
.map(p -> plugin.getUuidCache().getUUID(p.getUniqueId()))
.forEach(u -> plugin.getDatastore().loadUser(u, "null"));
}
@Override
public void onContextChange(ProxiedPlayer subject, Map.Entry<String, String> before, Map.Entry<String, String> current) throws Exception {
UUID internal = plugin.getUuidCache().getUUID(subject.getUniqueId());
User user = get(internal);
if (user != null) {
plugin.doAsync(user::refreshPermissions);
}
}
}
+85 -7
View File
@@ -1,19 +1,97 @@
# LuckPerms Configuration
##############################################################################
# +------------------------------------------------------------------------+ #
# | LuckPerms Configuration | #
# | https://github.com/lucko/LuckPerms | #
# +------------------------------------------------------------------------+ #
##############################################################################
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server: bungee
# The default group assigned to all user on join. e.g. a value of "default" = luckperms.group.default
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: false
prefix: '&7&l[&b&lL&a&lP&7&l] &c'
# 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
sql:
# 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 apply wildcard permissions.
# If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered permissions matching
# 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.
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
# If the plugin should send log notifications to users whenever permissions are modified.
log-notify: true
# If LuckPerms should print to console every time a plugin checks if a player has a permission
debug-permission-checks: false
# Mirrors world names. Whenever LuckPerms checks what world a user is in, if the world name is in this list, the value assigned
# will be sent forward for permission calculation instead.
# Remember world names on BungeeCord relate to the backend server name a user is connected to.
world-rewrite:
#hub2: hub
#hub3: hub
#opfactions: factions
# Rewrites group names. The underlying name of the group does not change, just the output in commands / placeholders / Vault.
group-name-rewrite:
#default: Member
# Which storage method the plugin should use.
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
# Fill out connection info below if you're using MySQL or MongoDB
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: ''
# 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
+4 -1
View File
@@ -1,3 +1,6 @@
name: LuckPerms
version: ${release.version}.${git.closest.tag.commit.count}
description: A permissions plugin
author: Luck
main: me.lucko.luckperms.LPBungeePlugin
author: Luck
softdepends: [PowerfulPerms] # For migration
+125 -4
View File
@@ -4,8 +4,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko</groupId>
<version>1.0-SNAPSHOT</version>
<groupId>me.lucko.luckperms</groupId>
<version>2.10-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -15,7 +15,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
@@ -23,4 +23,125 @@
</plugin>
</plugins>
</build>
</project>
<dependencies>
<!-- LuckPerms API -->
<dependency>
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.4.7</version>
<scope>compile</scope>
</dependency>
<!-- SQLite -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.8.11.2</version>
<scope>compile</scope>
</dependency>
<!-- H2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.192</version>
<scope>compile</scope>
</dependency>
<!-- MongoDB -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.3.0</version>
<scope>compile</scope>
</dependency>
<!-- slf4j library -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.9</version>
<scope>compile</scope>
</dependency>
<!-- SnakeYAML -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.14</version>
<scope>provided</scope>
</dependency>
<!-- gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
<scope>provided</scope>
</dependency>
<!-- guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
<scope>provided</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
<!-- **************Migration Plugins************** -->
<dependency>
<groupId>org.tyrannyofheaven.bukkit</groupId>
<artifactId>zPermissions</artifactId>
<version>1.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ru.tehkode</groupId>
<artifactId>PermissionsEx</artifactId>
<version>1.23</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
</exclusion>
<exclusion>
<groupId>net.gravitydevelopment.updater</groupId>
<artifactId>updater</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.cheesesoftware</groupId>
<artifactId>PowerfulPermsAPI</artifactId>
<version>1.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.anjocaido</groupId>
<artifactId>GroupManager</artifactId>
<version>1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.alpenblock</groupId>
<artifactId>BungeePerms</artifactId>
<version>3.0-dev-52</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.bananaco</groupId>
<artifactId>bpermissions-api</artifactId>
<version>2.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -1,56 +1,96 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.api.implementation.ApiProvider;
import me.lucko.luckperms.commands.ConsecutiveExecutor;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.config.LPConfiguration;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.contexts.ContextManager;
import me.lucko.luckperms.core.UuidCache;
import me.lucko.luckperms.data.Importer;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.storage.Datastore;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import me.lucko.luckperms.utils.LocaleManager;
import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
/**
* Main internal interface for LuckPerms plugins, allowing the luckperms-common module to bind with the plugin instance.
* All plugin platforms implement this interface.
*/
public interface LuckPermsPlugin {
/**
* Retrieves the {@link UserManager} used to manage users and their permissions/groups
* @return the {@link UserManager} object
/*
* Access to all of the main internal manager classes
*/
UserManager getUserManager();
/**
* Retrieves the {@link GroupManager} used to manage the loaded groups and modify their permissions
* @return the {@link GroupManager} object
*/
GroupManager getGroupManager();
/**
* Retrieves the {@link LPConfiguration} for getting values from the config
* @return the {@link LPConfiguration} implementation for the platform
*/
TrackManager getTrackManager();
LPConfiguration getConfiguration();
/**
* Retrieves the {@link Datastore} for loading/saving plugin data
* @return the {@link Datastore} object
*/
Datastore getDatastore();
/**
* Retrieves the {@link Logger} for the plugin
* @return the plugin's {@link Logger}
*/
Logger getLogger();
Logger getLog();
UuidCache getUuidCache();
ApiProvider getApiProvider();
Importer getImporter();
ConsecutiveExecutor getConsecutiveExecutor();
LocaleManager getLocaleManager();
ContextManager getContextManager();
/**
* @return the version of the plugin
*/
String getVersion();
/**
* @return the platform type
*/
PlatformType getType();
/**
* @return the main plugin directory
*/
File getMainDir();
/**
* @return the platforms data folder
*/
File getDataFolder();
/**
* Returns a colored string indicating the status of a player
* @param uuid The player's uuid
* @return a formatted status string
*/
String getPlayerStatus(UUID uuid);
Message getPlayerStatus(UUID uuid);
/**
* Gets the number of users online on the platform
@@ -58,6 +98,62 @@ public interface LuckPermsPlugin {
*/
int getPlayerCount();
/**
* Gets the usernames of the users online on the platform
* @return a {@link List} of usernames
*/
List<String> getPlayerList();
/**
* @return a {@link List} of senders online on the platform
*/
List<Sender> getNotifyListeners();
/**
* @return the console sender of the instance
*/
Sender getConsoleSender();
/**
* Gets all possible permission nodes, used for resolving wildcards
* @return a {@link List} of permission nodes
*/
List<String> getPossiblePermissions();
/**
* Gets a set of players ignoring logging output
* @return a {@link Set} of uuids
*/
Set<UUID> getIgnoringLogs();
/**
* Gets a loaded plugins instance from the platform
* @param name the name of the plugin
* @return a plugin instance
*/
Object getPlugin(String name);
/**
* Gets a provided service from the platform.
* @param clazz the class of the service
* @return the service instance, if it is provided for
*/
Object getService(Class clazz);
/**
* Used as a backup for migration
* @param playerName the players name
* @return a uuid if found, or null if not
*/
UUID getUUID(String playerName);
/**
* Checks if a plugin is loaded on the platform
* @param name the name of the plugin
* @return true if the plugin is loaded
*/
boolean isPluginLoaded(String name);
/**
* Runs an update task
*/
@@ -74,4 +170,5 @@ public interface LuckPermsPlugin {
* @param r the task to run
*/
void doSync(Runnable r);
}
@@ -0,0 +1,227 @@
/*
* 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.implementation;
import com.google.common.eventbus.EventBus;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.context.ContextListener;
import me.lucko.luckperms.api.context.IContextCalculator;
import me.lucko.luckperms.api.event.LPEvent;
import me.lucko.luckperms.api.event.LPListener;
import me.lucko.luckperms.api.implementation.internal.*;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import static me.lucko.luckperms.api.implementation.internal.Utils.checkNode;
/**
* Implements the LuckPerms API using the plugin instance
*/
@AllArgsConstructor
public class ApiProvider implements LuckPermsApi {
private final LuckPermsPlugin plugin;
private final EventBus eventBus = new EventBus("LuckPerms");
public void fireEventAsync(LPEvent event) {
plugin.doAsync(() -> fireEvent(event));
}
public void fireEvent(LPEvent event) {
try {
event.setApi(this);
eventBus.post(event);
} catch (Exception e) {
getLogger().severe("Couldn't fire LuckPerms Event: " + event.getEventName());
e.printStackTrace();
}
}
@Override
public void runUpdateTask() {
plugin.runUpdateTask();
}
@Override
public double getApiVersion() {
return 2.10;
}
@Override
public String getVersion() {
return plugin.getVersion();
}
@Override
public PlatformType getPlatformType() {
return plugin.getType();
}
@Override
public void registerListener(@NonNull LPListener listener) {
eventBus.register(listener);
}
@Override
public void unregisterListener(@NonNull LPListener listener) {
eventBus.unregister(listener);
}
@Override
public LPConfiguration getConfiguration() {
return new LPConfigurationLink(plugin.getConfiguration());
}
@Override
public Datastore getDatastore() {
return new DatastoreLink(plugin, plugin.getDatastore());
}
@Override
public UuidCache getUuidCache() {
return new UuidCacheLink(plugin.getUuidCache());
}
@Override
public Logger getLogger() {
return plugin.getLog();
}
@Override
public User getUser(@NonNull UUID uuid) {
final me.lucko.luckperms.users.User user = plugin.getUserManager().get(uuid);
if (user == null) {
return null;
}
return new UserLink(user);
}
@Override
public Optional<User> getUserSafe(@NonNull UUID uuid) {
return Optional.ofNullable(getUser(uuid));
}
@Override
public User getUser(@NonNull String name) {
final me.lucko.luckperms.users.User user = plugin.getUserManager().get(name);
if (user == null) {
return null;
}
return new UserLink(user);
}
@Override
public Optional<User> getUserSafe(@NonNull String name) {
return Optional.ofNullable(getUser(name));
}
@Override
public Set<User> getUsers() {
return plugin.getUserManager().getAll().values().stream().map(UserLink::new).collect(Collectors.toSet());
}
@Override
public boolean isUserLoaded(@NonNull UUID uuid) {
return plugin.getUserManager().isLoaded(uuid);
}
@Override
public void cleanupUser(@NonNull User user) {
Utils.checkUser(user);
plugin.getUserManager().cleanup(((UserLink) user).getMaster());
}
@Override
public Group getGroup(@NonNull String name) {
final me.lucko.luckperms.groups.Group group = plugin.getGroupManager().get(name);
if (group == null) {
return null;
}
return new GroupLink(group);
}
@Override
public Optional<Group> getGroupSafe(@NonNull String name) {
return Optional.ofNullable(getGroup(name));
}
@Override
public Set<Group> getGroups() {
return plugin.getGroupManager().getAll().values().stream().map(GroupLink::new).collect(Collectors.toSet());
}
@Override
public boolean isGroupLoaded(@NonNull String name) {
return plugin.getGroupManager().isLoaded(name);
}
@Override
public Track getTrack(@NonNull String name) {
final me.lucko.luckperms.tracks.Track track = plugin.getTrackManager().get(name);
if (track == null) {
return null;
}
return new TrackLink(track);
}
@Override
public Optional<Track> getTrackSafe(@NonNull String name) {
return Optional.ofNullable(getTrack(name));
}
@Override
public Set<Track> getTracks() {
return plugin.getTrackManager().getAll().values().stream().map(TrackLink::new).collect(Collectors.toSet());
}
@Override
public boolean isTrackLoaded(@NonNull String name) {
return plugin.getTrackManager().isLoaded(name);
}
@Override
public Node.Builder buildNode(@NonNull String permission) throws IllegalArgumentException {
return new me.lucko.luckperms.core.Node.Builder(checkNode(permission));
}
@SuppressWarnings("unchecked")
@Override
public void registerContextCalculator(IContextCalculator<?> contextCalculator) {
plugin.getContextManager().registerCalculator(contextCalculator);
}
@SuppressWarnings("unchecked")
@Override
public void registerContextListener(ContextListener<?> contextListener) {
plugin.getContextManager().registerListener(contextListener);
}
}
@@ -0,0 +1,516 @@
/*
* 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.implementation.internal;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.data.Callback;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static me.lucko.luckperms.api.implementation.internal.Utils.*;
/**
* Provides a link between {@link Datastore} and {@link me.lucko.luckperms.storage.Datastore}
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public class DatastoreLink implements Datastore {
private final LuckPermsPlugin plugin;
private final me.lucko.luckperms.storage.Datastore master;
private final Async async;
private final Sync sync;
private final Future future;
public DatastoreLink(@NonNull LuckPermsPlugin plugin, @NonNull me.lucko.luckperms.storage.Datastore master) {
this.plugin = plugin;
this.master = master;
this.async = new Async(master);
this.sync = new Sync(master);
this.future = new Future(master);
}
private static <T> Callback<T> checkCallback(Callback<T> c) {
// If no callback was given, just send an empty one
if (c == null) {
c = Callback.empty();
}
return c;
}
@Override
public String getName() {
return master.getName();
}
@Override
public boolean isAcceptingLogins() {
return master.isAcceptingLogins();
}
@Override
public Datastore.Async async() {
return async;
}
@Override
public Datastore.Sync sync() {
return sync;
}
@Override
public Datastore.Future future() {
return future;
}
@AllArgsConstructor
public class Async implements Datastore.Async {
private final me.lucko.luckperms.storage.Datastore master;
@Override
public void logAction(@NonNull LogEntry entry, Callback<Boolean> callback) {
master.logAction(entry, checkCallback(callback));
}
@Override
public void getLog(Callback<Log> callback) {
master.getLog(log -> callback.onComplete(new LogLink(log)));
}
@Override
public void loadOrCreateUser(@NonNull UUID uuid, @NonNull String username, Callback<Boolean> callback) {
master.loadUser(uuid, checkUsername(username), checkCallback(callback));
}
@Override
public void loadUser(@NonNull UUID uuid, Callback<Boolean> callback) {
master.loadUser(uuid, "null", checkCallback(callback));
}
@Override
public void loadUser(@NonNull UUID uuid, @NonNull String username, Callback<Boolean> callback) {
master.loadUser(uuid, checkUsername(username), checkCallback(callback));
}
@Override
public void saveUser(@NonNull User user, Callback<Boolean> callback) {
checkUser(user);
master.saveUser(((UserLink) user).getMaster(), checkCallback(callback));
}
@Override
public void cleanupUsers(Callback<Boolean> callback) {
master.cleanupUsers(checkCallback(callback));
}
@Override
public void getUniqueUsers(Callback<Set<UUID>> callback) {
master.getUniqueUsers(checkCallback(callback));
}
@Override
public void createAndLoadGroup(@NonNull String name, Callback<Boolean> callback) {
master.createAndLoadGroup(checkName(name), checkCallback(callback));
}
@Override
public void loadGroup(@NonNull String name, Callback<Boolean> callback) {
master.loadGroup(checkName(name), checkCallback(callback));
}
@Override
public void loadAllGroups(Callback<Boolean> callback) {
master.loadAllGroups(checkCallback(callback));
}
@Override
public void saveGroup(@NonNull Group group, Callback<Boolean> callback) {
checkGroup(group);
master.saveGroup(((GroupLink) group).getMaster(), checkCallback(callback));
}
@Override
public void deleteGroup(@NonNull Group group, Callback<Boolean> callback) {
checkGroup(group);
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
master.deleteGroup(((GroupLink) group).getMaster(), checkCallback(callback));
}
@Override
public void createAndLoadTrack(@NonNull String name, Callback<Boolean> callback) {
master.createAndLoadTrack(checkName(name), checkCallback(callback));
}
@Override
public void loadTrack(@NonNull String name, Callback<Boolean> callback) {
master.loadTrack(checkName(name), checkCallback(callback));
}
@Override
public void loadAllTracks(Callback<Boolean> callback) {
master.loadAllTracks(checkCallback(callback));
}
@Override
public void saveTrack(@NonNull Track track, Callback<Boolean> callback) {
checkTrack(track);
master.saveTrack(((TrackLink) track).getMaster(), checkCallback(callback));
}
@Override
public void deleteTrack(@NonNull Track track, Callback<Boolean> callback) {
checkTrack(track);
master.deleteTrack(((TrackLink) track).getMaster(), checkCallback(callback));
}
@Override
public void saveUUIDData(@NonNull String username, @NonNull UUID uuid, Callback<Boolean> callback) {
master.saveUUIDData(checkUsername(username), uuid, checkCallback(callback));
}
@Override
public void getUUID(@NonNull String username, Callback<UUID> callback) {
master.getUUID(checkUsername(username), checkCallback(callback));
}
}
@AllArgsConstructor
public class Sync implements Datastore.Sync {
private final me.lucko.luckperms.storage.Datastore master;
@Override
public boolean logAction(@NonNull LogEntry entry) {
return master.logAction(entry);
}
@Override
public Log getLog() {
return new LogLink(master.getLog());
}
@Override
public boolean loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) {
return master.loadUser(uuid, checkUsername(username));
}
@Override
public boolean loadUser(@NonNull UUID uuid) {
return master.loadUser(uuid, "null");
}
@Override
public boolean loadUser(@NonNull UUID uuid, @NonNull String username) {
return master.loadUser(uuid, checkUsername(username));
}
@Override
public boolean saveUser(@NonNull User user) {
checkUser(user);
return master.saveUser(((UserLink) user).getMaster());
}
@Override
public boolean cleanupUsers() {
return master.cleanupUsers();
}
@Override
public Set<UUID> getUniqueUsers() {
return master.getUniqueUsers();
}
@Override
public boolean createAndLoadGroup(@NonNull String name) {
return master.createAndLoadGroup(checkName(name));
}
@Override
public boolean loadGroup(@NonNull String name) {
return master.loadGroup(checkName(name));
}
@Override
public boolean loadAllGroups() {
return master.loadAllGroups();
}
@Override
public boolean saveGroup(@NonNull Group group) {
checkGroup(group);
return master.saveGroup(((GroupLink) group).getMaster());
}
@Override
public boolean deleteGroup(@NonNull Group group) {
checkGroup(group);
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
return master.deleteGroup(((GroupLink) group).getMaster());
}
@Override
public boolean createAndLoadTrack(@NonNull String name) {
return master.createAndLoadTrack(checkName(name));
}
@Override
public boolean loadTrack(@NonNull String name) {
return master.loadTrack(checkName(name));
}
@Override
public boolean loadAllTracks() {
return master.loadAllTracks();
}
@Override
public boolean saveTrack(@NonNull Track track) {
checkTrack(track);
return master.saveTrack(((TrackLink) track).getMaster());
}
@Override
public boolean deleteTrack(@NonNull Track track) {
checkTrack(track);
return master.deleteTrack(((TrackLink) track).getMaster());
}
@Override
public boolean saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
return master.saveUUIDData(checkUsername(username), uuid);
}
@Override
public UUID getUUID(@NonNull String username) {
return master.getUUID(checkUsername(username));
}
}
@AllArgsConstructor
public class Future implements Datastore.Future {
private final me.lucko.luckperms.storage.Datastore master;
@Override
public java.util.concurrent.Future<Boolean> logAction(@NonNull LogEntry entry) {
LPFuture<Boolean> lpf = new LPFuture<>();
master.logAction(entry, lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Log> getLog() {
LPFuture<Log> lpf = new LPFuture<>();
master.getLog(log -> lpf.onComplete(new LogLink(log)));
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) {
LPFuture<Boolean> lpf = new LPFuture<>();
master.loadUser(uuid, checkUsername(username), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> loadUser(@NonNull UUID uuid) {
LPFuture<Boolean> lpf = new LPFuture<>();
master.loadUser(uuid, "null", lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> loadUser(@NonNull UUID uuid, @NonNull String username) {
LPFuture<Boolean> lpf = new LPFuture<>();
master.loadUser(uuid, checkUsername(username), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> saveUser(@NonNull User user) {
LPFuture<Boolean> lpf = new LPFuture<>();
checkUser(user);
master.saveUser(((UserLink) user).getMaster(), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> cleanupUsers() {
LPFuture<Boolean> lpf = new LPFuture<>();
master.cleanupUsers(lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Set<UUID>> getUniqueUsers() {
LPFuture<Set<UUID>> lpf = new LPFuture<>();
master.getUniqueUsers(lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> createAndLoadGroup(@NonNull String name) {
LPFuture<Boolean> lpf = new LPFuture<>();
master.createAndLoadGroup(checkName(name), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> loadGroup(@NonNull String name) {
LPFuture<Boolean> lpf = new LPFuture<>();
master.loadGroup(checkName(name), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> loadAllGroups() {
LPFuture<Boolean> lpf = new LPFuture<>();
master.loadAllGroups(lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> saveGroup(@NonNull Group group) {
LPFuture<Boolean> lpf = new LPFuture<>();
checkGroup(group);
master.saveGroup(((GroupLink) group).getMaster(), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> deleteGroup(@NonNull Group group) {
LPFuture<Boolean> lpf = new LPFuture<>();
checkGroup(group);
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
master.deleteGroup(((GroupLink) group).getMaster(), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> createAndLoadTrack(@NonNull String name) {
LPFuture<Boolean> lpf = new LPFuture<>();
master.createAndLoadTrack(checkName(name), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> loadTrack(@NonNull String name) {
LPFuture<Boolean> lpf = new LPFuture<>();
master.loadTrack(checkName(name), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> loadAllTracks() {
LPFuture<Boolean> lpf = new LPFuture<>();
master.loadAllTracks(lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> saveTrack(@NonNull Track track) {
LPFuture<Boolean> lpf = new LPFuture<>();
checkTrack(track);
master.saveTrack(((TrackLink) track).getMaster(), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> deleteTrack(@NonNull Track track) {
LPFuture<Boolean> lpf = new LPFuture<>();
checkTrack(track);
master.deleteTrack(((TrackLink) track).getMaster(), lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<Boolean> saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
LPFuture<Boolean> lpf = new LPFuture<>();
master.saveUUIDData(checkUsername(username), uuid, lpf);
return lpf;
}
@Override
public java.util.concurrent.Future<UUID> getUUID(@NonNull String username) {
LPFuture<UUID> lpf = new LPFuture<>();
master.getUUID(checkUsername(username), lpf);
return lpf;
}
}
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public static class LPFuture<T> implements Callback<T>, java.util.concurrent.Future<T> {
private final CountDownLatch latch = new CountDownLatch(1);
private T value;
@Override
public void onComplete(T t) {
value = t;
latch.countDown();
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
// Not supported
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return latch.getCount() == 0;
}
@Override
public T get() throws InterruptedException {
latch.await();
return value;
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
if (latch.await(timeout, unit)) {
return value;
} else {
throw new TimeoutException();
}
}
}
}
@@ -0,0 +1,165 @@
/*
* 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.implementation.internal;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import static me.lucko.luckperms.api.implementation.internal.Utils.*;
/**
* Provides a link between {@link Group} and {@link me.lucko.luckperms.groups.Group}
*/
@EqualsAndHashCode(of = {"name"}, callSuper = false)
@SuppressWarnings("unused")
public class GroupLink extends PermissionHolderLink implements Group {
@Getter(AccessLevel.PACKAGE)
private final me.lucko.luckperms.groups.Group master;
@Getter
private final String name;
public GroupLink(@NonNull me.lucko.luckperms.groups.Group master) {
super(master);
this.master = master;
this.name = master.getName();
}
@Override
public boolean inheritsGroup(@NonNull Group group) {
checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster());
}
@Override
public boolean inheritsGroup(@NonNull Group group, @NonNull String server) {
checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster(), server);
}
@Override
public boolean inheritsGroup(@NonNull Group group, @NonNull String server, @NonNull String world) {
checkGroup(group);
return master.inheritsGroup(((GroupLink) group).getMaster(), server, world);
}
@Override
public void setInheritGroup(@NonNull Group group) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster());
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server));
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world);
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull long expireAt) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkTime(expireAt));
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server, @NonNull long expireAt) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), checkTime(expireAt));
}
@Override
public void setInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull long expireAt) throws ObjectAlreadyHasException {
checkGroup(group);
master.setInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world, checkTime(expireAt));
}
@Override
public void unsetInheritGroup(@NonNull Group group) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster());
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull boolean temporary) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), temporary);
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server));
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world);
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server, @NonNull boolean temporary) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), temporary);
}
@Override
public void unsetInheritGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull boolean temporary) throws ObjectLacksException {
checkGroup(group);
master.unsetInheritGroup(((GroupLink) group).getMaster(), checkServer(server), world, temporary);
}
@Override
public void clearNodes() {
master.clearNodes();
}
@Override
public List<String> getGroupNames() {
return master.getGroupNames();
}
@Override
public List<String> getLocalGroups(@NonNull String server, @NonNull String world) {
return master.getLocalGroups(checkServer(server), world);
}
@Override
public List<String> getLocalGroups(@NonNull String server) {
return master.getLocalGroups(checkServer(server));
}
}
@@ -0,0 +1,159 @@
/*
* 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.implementation.internal;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.LPConfiguration;
import me.lucko.luckperms.api.data.DatastoreConfiguration;
import me.lucko.luckperms.api.data.MySQLConfiguration;
import java.util.Map;
/**
* Provides a link between {@link LPConfiguration} and {@link me.lucko.luckperms.config.LPConfiguration}
*/
@AllArgsConstructor
public class LPConfigurationLink implements LPConfiguration {
private final me.lucko.luckperms.config.LPConfiguration master;
@Override
public String getServer() {
return master.getServer();
}
@Override
public int getSyncTime() {
return master.getSyncTime();
}
@Override
public String getDefaultGroupNode() {
return master.getDefaultGroupNode();
}
@Override
public String getDefaultGroupName() {
return master.getDefaultGroupName();
}
@Override
public boolean getIncludeGlobalPerms() {
return master.isIncludingGlobalPerms();
}
@Override
public boolean getIncludeGlobalWorldPerms() {
return master.isIncludingGlobalWorldPerms();
}
@Override
public boolean getApplyGlobalGroups() {
return master.isApplyingGlobalGroups();
}
@Override
public boolean getApplyGlobalWorldGroups() {
return master.isApplyingGlobalWorldGroups();
}
@Override
public boolean getOnlineMode() {
return master.isOnlineMode();
}
@Override
public boolean getApplyWildcards() {
return master.isApplyingWildcards();
}
@Override
public boolean getApplyRegex() {
return master.isApplyingRegex();
}
@Override
public boolean getApplyShorthand() {
return master.isApplyingShorthand();
}
@Override
public boolean getLogNotify() {
return master.isLogNotify();
}
@Override
public boolean getDebugPermissionChecks() {
return master.isDebugPermissionChecks();
}
@Override
public boolean getEnableOps() {
return master.isOpsEnabled();
}
@Override
public boolean getCommandsAllowOp() {
return master.isCommandsAllowOp();
}
@Override
public boolean getAutoOp() {
return master.isAutoOp();
}
@Override
public String getVaultServer() {
return master.getVaultServer();
}
@Override
public boolean getVaultIncludeGlobal() {
return master.isVaultIncludingGlobal();
}
@SuppressWarnings("deprecation")
@Override
public MySQLConfiguration getDatabaseValues() {
return getDatastoreConfig();
}
@Override
public DatastoreConfiguration getDatastoreConfig() {
return master.getDatabaseValues();
}
@Override
public String getStorageMethod() {
return master.getStorageMethod();
}
@Override
public boolean getSplitStorage() {
return master.isSplitStorage();
}
@Override
public Map<String, String> getSplitStorageOptions() {
return master.getSplitStorageOptions();
}
}
@@ -0,0 +1,137 @@
/*
* 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.implementation.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.Log;
import me.lucko.luckperms.api.LogEntry;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.UUID;
import static me.lucko.luckperms.api.implementation.internal.Utils.checkName;
/**
* Provides a link between {@link Log} and {@link me.lucko.luckperms.data.Log}
*/
@AllArgsConstructor
public class LogLink implements Log {
private final me.lucko.luckperms.data.Log master;
@Override
public SortedSet<LogEntry> getContent() {
return master.getContent();
}
@Override
public SortedSet<LogEntry> getRecent() {
return master.getRecent();
}
@Override
public SortedMap<Integer, LogEntry> getRecent(int pageNo) {
return master.getRecent(pageNo);
}
@Override
public int getRecentMaxPages() {
return master.getRecentMaxPages();
}
@Override
public SortedSet<LogEntry> getRecent(@NonNull UUID actor) {
return master.getRecent(actor);
}
@Override
public SortedMap<Integer, LogEntry> getRecent(int pageNo, @NonNull UUID actor) {
return master.getRecent(pageNo, actor);
}
@Override
public int getRecentMaxPages(@NonNull UUID actor) {
return master.getRecentMaxPages(actor);
}
@Override
public SortedSet<LogEntry> getUserHistory(@NonNull UUID uuid) {
return master.getUserHistory(uuid);
}
@Override
public SortedMap<Integer, LogEntry> getUserHistory(int pageNo, @NonNull UUID uuid) {
return master.getUserHistory(pageNo, uuid);
}
@Override
public int getUserHistoryMaxPages(@NonNull UUID uuid) {
return master.getUserHistoryMaxPages(uuid);
}
@Override
public SortedSet<LogEntry> getGroupHistory(@NonNull String name) {
return master.getGroupHistory(checkName(name));
}
@Override
public SortedMap<Integer, LogEntry> getGroupHistory(int pageNo, @NonNull String name) {
return master.getGroupHistory(pageNo, checkName(name));
}
@Override
public int getGroupHistoryMaxPages(@NonNull String name) {
return master.getGroupHistoryMaxPages(checkName(name));
}
@Override
public SortedSet<LogEntry> getTrackHistory(@NonNull String name) {
return master.getTrackHistory(checkName(name));
}
@Override
public SortedMap<Integer, LogEntry> getTrackHistory(int pageNo, @NonNull String name) {
return master.getTrackHistory(pageNo, checkName(name));
}
@Override
public int getTrackHistoryMaxPages(@NonNull String name) {
return master.getTrackHistoryMaxPages(checkName(name));
}
@Override
public SortedSet<LogEntry> getSearch(@NonNull String query) {
return master.getSearch(query);
}
@Override
public SortedMap<Integer, LogEntry> getSearch(int pageNo, @NonNull String query) {
return master.getSearch(pageNo, query);
}
@Override
public int getSearchMaxPages(@NonNull String query) {
return master.getSearchMaxPages(query);
}
}
@@ -0,0 +1,299 @@
/*
* 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.implementation.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.contexts.Contexts;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.*;
import static me.lucko.luckperms.api.implementation.internal.Utils.*;
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
/**
* Provides a link between {@link PermissionHolder} and {@link me.lucko.luckperms.core.PermissionHolder}
*/
@SuppressWarnings({"unused", "deprecation"})
@AllArgsConstructor
public class PermissionHolderLink implements PermissionHolder {
@NonNull
private final me.lucko.luckperms.core.PermissionHolder master;
@Override
public String getObjectName() {
return master.getObjectName();
}
@Override
public SortedSet<Node> getPermissions() {
return Collections.unmodifiableSortedSet(master.getPermissions(false));
}
@Override
public Set<Node> getEnduringPermissions() {
return Collections.unmodifiableSet(master.getNodes());
}
@Override
public Set<Node> getTransientPermissions() {
return Collections.unmodifiableSet(master.getTransientNodes());
}
@Override
public Set<Node> getAllNodes() {
return Collections.unmodifiableSet(master.getAllNodes(Collections.emptyList(), Contexts.allowAll()));
}
@Override
public Map<String, Boolean> getNodes() {
return exportToLegacy(master.getNodes());
}
@Override
public Tristate hasPermission(@NonNull Node node) {
return master.hasPermission(node, false);
}
@Override
public Tristate hasTransientPermission(@NonNull Node node) {
return master.hasPermission(node, true);
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b) {
return master.hasPermission(node, b);
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server) {
return master.hasPermission(node, b, checkServer(server));
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world) {
return master.hasPermission(node, b, checkServer(server), world);
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull boolean temporary) {
return master.hasPermission(node, b, temporary);
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull boolean temporary) {
return master.hasPermission(node, b, checkServer(server), temporary);
}
@Override
public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world, @NonNull boolean temporary) {
return master.hasPermission(node, b, checkServer(server), world, temporary);
}
@Override
public Tristate inheritsPermission(@NonNull Node node) {
return master.inheritsPermission(node);
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b) {
return master.inheritsPermission(node, b);
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server) {
return master.inheritsPermission(node, b, checkServer(server));
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world) {
return master.inheritsPermission(node, b, checkServer(server), world);
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull boolean temporary) {
return master.inheritsPermission(node, b, temporary);
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull boolean temporary) {
return master.inheritsPermission(node, b, checkServer(server), temporary);
}
@Override
public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world, @NonNull boolean temporary) {
return master.inheritsPermission(node, b, checkServer(server), world, temporary);
}
@Override
public void setPermission(@NonNull Node node) throws ObjectAlreadyHasException {
master.setPermission(node);
}
@Override
public void setTransientPermission(@NonNull Node node) throws ObjectAlreadyHasException {
master.setTransientPermission(node);
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value);
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull String server) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value, checkServer(server));
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull String server, @NonNull String world) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value, checkServer(server), world);
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull long expireAt) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value, checkTime(expireAt));
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull String server, @NonNull long expireAt) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value, checkServer(server), checkTime(expireAt));
}
@Override
public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull String server, @NonNull String world, @NonNull long expireAt) throws ObjectAlreadyHasException {
master.setPermission(checkNode(node), value, checkServer(server), world, checkTime(expireAt));
}
@Override
public void unsetPermission(@NonNull Node node) throws ObjectLacksException {
master.unsetPermission(node);
}
@Override
public void unsetTransientPermission(@NonNull Node node) throws ObjectLacksException {
master.unsetTransientPermission(node);
}
@Override
public void unsetPermission(@NonNull String node, @NonNull boolean temporary) throws ObjectLacksException {
master.unsetPermission(checkNode(node), temporary);
}
@Override
public void unsetPermission(@NonNull String node) throws ObjectLacksException {
master.unsetPermission(checkNode(node));
}
@Override
public void unsetPermission(@NonNull String node, @NonNull String server) throws ObjectLacksException {
master.unsetPermission(checkNode(node), checkServer(server));
}
@Override
public void unsetPermission(@NonNull String node, @NonNull String server, @NonNull String world) throws ObjectLacksException {
master.unsetPermission(checkNode(node), checkServer(server), world);
}
@Override
public void unsetPermission(@NonNull String node, @NonNull String server, @NonNull boolean temporary) throws ObjectLacksException {
master.unsetPermission(checkNode(node), checkServer(server), temporary);
}
@Override
public void unsetPermission(@NonNull String node, @NonNull String server, @NonNull String world, @NonNull boolean temporary) throws ObjectLacksException {
master.unsetPermission(checkNode(node), checkServer(server), world, temporary);
}
@Override
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups, List<String> possibleNodes) {
return master.getLocalPermissions(server, world, excludedGroups, possibleNodes);
}
@Override
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups) {
return master.getLocalPermissions(server, world, excludedGroups);
}
@Override
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups, List<String> possibleNodes) {
return master.getLocalPermissions(server, excludedGroups, possibleNodes);
}
@Override
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups) {
return master.getLocalPermissions(server, excludedGroups);
}
@Override
public Map<String, Boolean> getPermissions(String server, String world, Map<String, String> extraContext, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups) {
if (extraContext == null) {
extraContext = new HashMap<>();
}
if (server != null && !server.equals("")) {
extraContext.put("server", server);
}
if (world != null && !world.equals("")) {
extraContext.put("world", world);
}
return master.exportNodes(new Contexts(extraContext, includeGlobal, includeGlobal, applyGroups, true, true), possibleNodes);
}
@Override
public Map<Map.Entry<String, Boolean>, Long> getTemporaryNodes() {
Map<Map.Entry<String, Boolean>, Long> m = new HashMap<>();
for (Node node : master.getTemporaryNodes()) {
m.put(new AbstractMap.SimpleEntry<>(node.getKey(), node.getValue()), node.getExpiryUnixTime());
}
return m;
}
@Override
public Set<Node> getTemporaryPermissionNodes() {
return master.getTemporaryNodes();
}
@Override
public Map<String, Boolean> getPermanentNodes() {
return exportToLegacy(master.getPermanentNodes());
}
@Override
public Set<Node> getPermanentPermissionNodes() {
return master.getPermanentNodes();
}
@Override
public void auditTemporaryPermissions() {
master.auditTemporaryPermissions();
}
}
@@ -0,0 +1,116 @@
/*
* 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.implementation.internal;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import static me.lucko.luckperms.api.implementation.internal.Utils.checkGroup;
/**
* Provides a link between {@link Track} and {@link me.lucko.luckperms.tracks.Track}
*/
@EqualsAndHashCode(of = {"name"})
@SuppressWarnings("unused")
public class TrackLink implements Track {
@Getter(AccessLevel.PACKAGE)
private final me.lucko.luckperms.tracks.Track master;
@Getter
private final String name;
public TrackLink(@NonNull me.lucko.luckperms.tracks.Track master) {
this.master = master;
this.name = master.getName();
}
@Override
public List<String> getGroups() {
return master.getGroups();
}
@Override
public int getSize() {
return master.getSize();
}
@Override
public String getNext(@NonNull Group current) throws ObjectLacksException {
checkGroup(current);
return master.getNext(((GroupLink) current).getMaster());
}
@Override
public String getPrevious(@NonNull Group current) throws ObjectLacksException {
checkGroup(current);
return master.getPrevious(((GroupLink) current).getMaster());
}
@Override
public void appendGroup(@NonNull Group group) throws ObjectAlreadyHasException {
checkGroup(group);
master.appendGroup(((GroupLink) group).getMaster());
}
@Override
public void insertGroup(@NonNull Group group, @NonNull int position) throws ObjectAlreadyHasException, IndexOutOfBoundsException {
checkGroup(group);
master.insertGroup(((GroupLink) group).getMaster(), position);
}
@Override
public void removeGroup(@NonNull Group group) throws ObjectLacksException {
checkGroup(group);
master.removeGroup(((GroupLink) group).getMaster());
}
@Override
public void removeGroup(@NonNull String group) throws ObjectLacksException {
master.removeGroup(group);
}
@Override
public boolean containsGroup(@NonNull Group group) {
checkGroup(group);
return master.containsGroup(((GroupLink) group).getMaster());
}
@Override
public boolean containsGroup(@NonNull String group) {
return master.containsGroup(group);
}
@Override
public void clearGroups() {
master.clearGroups();
}
}
Loaded 100 of 310 files, more files were not shown because too many files have changed in this diff. Show more