Compare commits

..
298 Commits
Author SHA1 Message Date
Luck 8725ace739 LuckPerms v5 2019-11-23 18:21:32 +00:00
Andre_601 0d9106185c Add note about checking console to storage errors (#1678) 2019-11-23 18:19:19 +00:00
Luck 7449f6f9af Update patreon link 2019-11-23 18:18:25 +00:00
Luck 2316b6806e Cleanup in StackTracePrinter 2019-11-23 17:43:56 +00:00
Luck 94418d3648 Log thread in verbose events 2019-11-23 17:26:48 +00:00
Luck 479b2d026c Remove sql schema migrations 2019-11-23 14:15:30 +00:00
Luck 8e9683b33f Fix compile 2019-11-23 14:10:17 +00:00
Luck 6481bac045 Fix license violations 2019-11-23 13:21:11 +00:00
Luck 86aadf2cf8 A few more small API changes 2019-11-23 12:59:40 +00:00
Luck 95d2832884 A few more small API changes 2019-11-23 12:52:26 +00:00
Luck 213b2fcb44 Downgrade okhttp & okio 2019-11-19 18:09:14 +00:00
Luck c4bd657826 Changes to messaging service setup 2019-11-19 15:18:47 +00:00
Luck a5e15b8a29 More work 2019-11-18 21:19:59 +00:00
Luck 7a37fcd792 Implement a simple compiler (lexer + parser) for verbose filters
Removes the dependency on the Nashorn runtime.
2019-11-14 22:58:29 +00:00
Luck 81cbe02a9c Move some things around a bit 2019-11-14 19:43:57 +00:00
Luck 79c10c986e Web editor changes 2019-11-12 12:12:53 +00:00
Luck c836cce59b Moreeee stuff 2019-11-09 22:50:10 +00:00
Luck 287c0f7f7a All the cleanup 2019-11-09 22:34:12 +00:00
Luck dc52807a46 Fix issues with *-combined file storage methods (#1793) 2019-11-04 19:26:53 +00:00
Luck 916e3dbb0b Revert bad text refactoring, bump version to 3.0.2 2019-10-15 13:58:20 +01:00
Luck 4b0574710e Implement new compressed json import/export format
The old "command list" style is now only supported for import.
2019-10-14 17:25:37 +01:00
Luck 7764a04d46 More work 2019-10-13 15:04:03 +01:00
Luck 9438df787a Changes to option keys 2019-10-12 00:27:53 +01:00
Luck fd954d8293 More work 2019-10-06 21:34:24 +01:00
Luck 72dec16f54 Context parsing changes 2019-09-21 08:30:14 +01:00
Luck 40218563e1 Cut down on the number of command aliases 2019-09-04 22:34:25 +01:00
Luck 0251f2add9 Cleanup some stuff 2019-09-04 22:29:36 +01:00
Luck f0e42c6db6 Allow context calculators to define "potential contexts", and use these for tab completions 2019-09-04 22:08:24 +01:00
Luck 4b793d1f14 More work 2019-09-04 20:58:46 +01:00
Luck 61e5da928a Fix various runtime errors 2019-08-29 22:07:12 +01:00
Luck 419707aa5f Cleanup web clients 2019-08-26 20:37:33 +01:00
Luck 8b970c21fc Remove default assignments
For real this time
2019-08-26 19:33:43 +01:00
Luck 7a31edea09 Extensions 2019-08-26 19:31:55 +01:00
Luck b286faa1c5 Change API package to net.luckperms 2019-08-26 18:06:45 +01:00
Luck 5e2f45ebd0 Web editor changes, towards #1703 2019-08-26 15:03:30 +01:00
Luck eff93c788b Log action serialization changes 2019-08-26 14:04:49 +01:00
Luck 4667ffc681 Allow data query order to be specified via the API 2019-08-26 14:04:49 +01:00
Luck bafada4f17 Context & action log changes 2019-08-26 14:04:50 +01:00
Luck 5b97d01363 Permission holder refactoring 2019-08-26 14:02:39 +01:00
Luck 3474c66c1c Big API refactor
- removed a bunch of ugly / badly designed methods and APIs
- refactored 'Contexts' --> 'QueryOptions'
- Removed the FullySatisfiedContexts hack and replaced it with a sane API
- Made PermissionHolder (in the API) less ugly and horrible
- removed lots of deprecated / duplicated API functionality
and much more...
2019-08-26 14:02:44 +01:00
Luck 8f8c916be3 API: remove storage interface 2019-08-04 11:27:31 +01:00
Luck a823290d66 API: remove uuid cache 2019-08-04 11:27:27 +01:00
Luck 5577e3f590 Jedis requires SLF4J (#1579) 2019-07-14 09:11:54 +01:00
Luck ffe6c24b53 Properly remove "minecraft:" prefixed brigadier aliases 2019-06-03 20:15:29 +01:00
Luck 4e4982a98d Create FUNDING.yml 2019-05-27 10:40:12 +01:00
Luck 7f4f9bb917 Fix build 2019-05-20 23:09:02 +01:00
Luck 8d8024ba5e Fix group changes via the API not properly invalidating caches (#1534) 2019-05-20 10:42:48 +01:00
Luck 2e16b15b0e Change Sender#getNameWithLocation behaviour 2019-05-14 20:32:35 +01:00
Luck 1ebed37297 Remove use-server-properties-name option
This was removed from Minecraft 1.14, and isn't something I feel was ever really necessary to support.
2019-05-11 23:17:59 +01:00
Luck ff37ad176b Update text adapters to latest version (#1525) 2019-05-11 23:12:55 +01:00
Luck d0c5d89e91 Update to expect Velocity shading text 3
This reverts the reflection workaround implemented in f49446011a
2019-05-07 13:59:44 +01:00
Luck f49446011a Update to text 3 2019-05-07 00:23:40 +01:00
Luck d762a0aaa6 Reduce new instance creation further in TristateResult.Factory 2019-04-28 15:35:46 +01:00
Luck 2dc211a91e Don't account for wildcard/default permissions when running require-sender-group-membership-to-modify checks (#1512) 2019-04-24 18:40:27 +01:00
Luck 2c62de9658 Refactor storage type config read 2019-04-23 21:57:43 +01:00
Luck 494ab6787f Update okhttp 2019-04-23 20:45:02 +01:00
Luck b81e8a40a4 Refactor VaultHookManager 2019-04-22 10:27:29 +01:00
Luck 2fd2f4fedb Ignore exception if Brigadier is not supported by the server (#1506)
This error occurs when another plugin/the server shades the brigadier library without relocation on pre 1.13 MC versions.
2019-04-22 09:24:05 +01:00
Luck 493e5d08be Finish refactoring 2019-04-22 09:15:46 +01:00
Chinese Marc 62a834e145 Fix build (#1509) 2019-04-21 21:49:13 +01:00
Luck 241f13c8f1 Package renames 2019-04-20 18:10:31 +01:00
Luck 98ea255667 Refactor blank message sending 2019-04-19 09:46:45 +01:00
Luck 420ec2bf1a Don't attempt to read a boolean 'value' from parent/chatmeta/meta entries in file based storage files (#1505) 2019-04-18 23:14:23 +01:00
Luck 364a494ac6 Fix making changes to group subjects via the Sponge API (#1495) 2019-04-18 22:57:53 +01:00
Luck 821d1cb8dd Fallback to utf8 encoding if utf8mb4 isn't supported (#1497) 2019-04-17 18:44:34 +01:00
Luck 544ffbad19 Add missing javadocs to ConfigKeys 2019-04-06 18:22:19 +01:00
Luck 4fa6cd2577 Add configuration option to perform a post-traversal sort according to the inheritance (weight) rules 2019-04-06 18:20:30 +01:00
Luck 37d1f5efab Improve behaviour of userInGroup and userHasPermission Vault calls 2019-04-03 10:12:24 +01:00
Luck 7cd8e8bf5b Fix NPE in Vault contextForLookup method
Fixes CodeCrafter47/BungeeTabListPlus#415
2019-04-03 10:01:18 +01:00
Luck 8eed4558f4 Release API v4.4 2019-04-02 16:36:22 +01:00
Luck 62ca2d9c79 Implement special handling in the LP Vault implementation for NPC players (#1470) 2019-04-01 15:09:58 +01:00
Luck c7a0d7026c Update API build script 2019-04-01 14:00:46 +01:00
Luck ce74813ce5 Fallback to node/context ordering in InheritanceComparator, refactor graph traverser classes 2019-03-14 15:23:26 +00:00
Luck d1511e43f2 Fix build 2019-03-10 19:19:46 +00:00
Luck 6ef749c76a Update some dependencies 2019-03-08 23:11:32 +00:00
Luck 8846932cb6 Refactor the HolderType enum 2019-03-08 20:19:08 +00:00
Luck 12b861db3f Update PermissionHolderSubjectData#save code 2019-03-08 19:56:07 +00:00
Luck 0a50df6557 Code style: move private constructors for singleton classes to the top of the file 2019-03-05 12:36:09 +00:00
Luck 3726f6de41 Use a separate fork join pool for cache loading operations 2019-03-05 12:35:29 +00:00
Luck d1ca7684d6 Refactor AbstractJavaScheduler to make use of a cached thread pool 2019-03-05 12:32:16 +00:00
Luck 512b621a7a Refactor Dependency class a bit 2019-03-03 16:46:20 +00:00
Luck 2cf919a17a Bump hikari version 2019-03-03 12:01:15 +00:00
Luck 46072eb465 Attempt to detect and warn about CraftBukkit + offline mode problems (#1439) 2019-02-21 14:14:00 +00:00
Luck ae63a42c2e Slightly optimize regex and wildcard processors 2019-02-21 12:37:23 +00:00
Luck 8773ec07ab Include processor & cause in verbose hover message 2019-02-19 23:30:11 +00:00
Luck 287cc308d6 Fix parsing log entry types (#1438) 2019-02-19 14:17:33 +00:00
Luck beeb4fa169 Fix DuplicateRemovalFunction javadocs 2019-02-19 14:09:26 +00:00
Luck 4ef3d50965 Properly implement ContextManager#unregisterCalculator (#1422) 2019-02-09 11:50:00 +00:00
Luck dae64fc8c4 Cleanup some of the Sponge permission holder implementation code 2019-02-07 15:35:09 +00:00
Luck 215031a1f3 Close messaging service before storage
Fixes https://www.spigotmc.org/threads/174259/page-129#post-3302827
2019-02-07 12:38:24 +00:00
Luck 85d2f0b51f Add method to unregister context calculators (#1422) 2019-02-07 12:24:23 +00:00
Luck d91355e4d6 Remove some unused code 2019-02-04 20:35:39 +00:00
Luck 1a690dabd7 Implement NodeMap without using Guava's Multimap util (#1416) 2019-02-04 20:35:20 +00:00
Luck 526448ce40 Don't try to set unicode connection properties for PostgreSQL (#1134) 2019-02-04 19:36:53 +00:00
Luck 43d04a97f5 Correctly implement Bukkit/Nukkit isPermissionSet method, inline with the behaviour in PermissibleBase (#1403) 2019-01-31 01:14:38 +00:00
Luck 307614e704 Cleanup import statements 2019-01-31 00:53:42 +00:00
Luck f6c0794691 Return more detailed information about exactly how a permission check result was determined 2019-01-31 00:45:56 +00:00
Luck 83db00aef8 Better null checking in HikariConnectionFactory (#1408) 2019-01-30 16:24:30 +00:00
untuned 22252fa46d Update MIT license text to allow GitHub detection (#1400) 2019-01-28 10:46:05 +00:00
Luck 7b8426977a Switch text dependency back to 1.11 (#1404) 2019-01-28 10:39:08 +00:00
Luck d9912cb93f Update some dependencies 2019-01-27 22:51:05 +00:00
Luck 5db999f995 Only form data buf once in Bukkit PluginMessage messenger 2019-01-23 12:12:33 +00:00
Luck b744e35ad8 Fix typo in Vault exception message 2019-01-18 23:21:23 +00:00
Andre_601 b6769811a2 Fix some small typos (#1389) 2019-01-18 09:47:03 +00:00
Luck 1d9fc568e4 Fix calling default methods on Event interfaces (#1386) 2019-01-16 14:43:55 +00:00
Luck 3c0d1ba7a1 Ensure caches are invalidated when Bukkit/Nukkit's Permission#getChildren map is modified (#1378) 2019-01-13 16:58:31 +00:00
Luck 78a74510cf Fix Sponge and Velocity build scripts 2019-01-12 13:39:07 +00:00
Luck d3ae3324fa Allow the bytebin url to be configured 2019-01-12 12:02:16 +00:00
Luck 4b97c9419e Finish updating commodore
woops
2019-01-07 21:29:28 +00:00
Luck db830a0bef Buildscript changes 2019-01-07 21:25:11 +00:00
Luck 797c195424 unInject -> uninject 2019-01-07 20:45:47 +00:00
Luck 4788290615 Rename Vault implementation classes 2019-01-07 20:44:52 +00:00
Luck d0c016f6b7 Cleanup with way permissibles are monitored on Bukkit/Nukkit
- The removal of the call to recalculatePermissions should fix CMEs on startup, in particular with Vault.
- Monitored permissibles are now uninjected when the plugin disables.
2019-01-07 20:21:36 +00:00
Luck 9b1c73ed23 Implement use of a Maven Central mirror for dependency downloads
People keep telling me that LP's use of Maven Central for downloading dependencies is not allowed / inappropriate / abusive. I disagree but I'm bored of hearing it. Using a mirror will mean that all of the load is taken off of Central, and is instead absorbed by my servers + (mostly) Cloudflare.

- The mirror is (currently) hosted at https://nexus.lucko.me/repository/maven-central/
- The prospect of the mirror becoming compromised is not a concern. LuckPerms compares the downloaded content against a checksum before saving it.
- The prospect of the mirror going offline is also not a concern. We will fallback to Maven Central if a connection cannot be made to the mirror.
2019-01-07 16:56:16 +00:00
Luck 048768007d Change the way static contexts are displayed in /lp info 2019-01-07 15:44:54 +00:00
Luck ec7a5321a6 Some misc refactoring / code cleanup 2019-01-07 15:08:13 +00:00
Luck c396323308 Log exceptions thrown by BufferedRequest tasks 2019-01-05 23:06:57 +00:00
Luck 6fc2321fad Refactor PlayerLoginProcessEvent
This is technically a breaking change, but I'm fairly sure I'm the only person using this event. It's quite obscure ;p
2019-01-02 13:54:55 +00:00
Luck a0d04790a5 Update text-adapter-bungeecord to 1.0.2 (#1362) 2019-01-01 15:33:18 +00:00
Luck c4154c09da Remove SQL indexes on the permission field 2018-12-23 21:56:51 +00:00
Luck 8eed3131f2 Fix sending component messages on older CB/S releases (#1344) 2018-12-23 16:52:00 +00:00
Luck e5c4b710f6 Fix CME in Bukkit refreshAutoOp
cc @Exloki
2018-12-22 17:04:32 +00:00
Luck 2ccffc6e6d Fix error message when event handlers throw an exception 2018-12-22 17:03:51 +00:00
Luck fc69002c86 Fix wrong checksum for text-adapter-bukkit 2018-12-19 14:36:20 +00:00
Luck e3a6db5f97 Refactor ProgressLogger slightly 2018-12-19 10:39:48 +00:00
Luck 6d8077ffd0 Use text-adapter-bukkit for sending Components to Bukkit objects 2018-12-19 10:29:22 +00:00
Luck 784161d66d Update okhttp and okio versions 2018-12-19 10:06:36 +00:00
Jonathan Frederick 115f793733 Make gradlew script executable by default (#1338) 2018-12-19 09:24:44 +00:00
Luck 2cb5e437fd Switch default MySQL/MariaDB charset from utf8 to utf8mb4
https://medium.com/@adamhooper/in-mysql-never-use-utf8-use-utf8mb4-11761243e434
Relates to #1337
2018-12-18 16:02:25 +00:00
Luck 8c57c2b46d Remove static imports 2018-12-18 12:51:26 +00:00
Luck 879a88a398 Account for 'allow-invalid-usernames' setting in API calls 2018-12-18 12:50:52 +00:00
Luck 7e50c3c777 Update Gradle to 5.0 2018-12-15 22:24:17 +00:00
Luck 4b1cf51530 replace LoadingCache with more simple LoadingMap alternative when no auto expiry is needed 2018-12-14 18:37:56 +00:00
Luck de24817d9c Some node equality changes 2018-12-14 17:27:34 +00:00
Luck 085e7af681 Small cleanup in Contexts class 2018-12-10 15:33:57 +00:00
Luck 1aabd7610e Tweak PlayerSaveResult javadoc 2018-12-10 15:33:38 +00:00
Luck ef31db1431 Improve /op and /deop command matching 2018-12-10 15:33:04 +00:00
Luck 757e9d6be6 Add API method to get known permissions & improve the way PermissionDescriptions are migrated from existing Sponge services when LP enables 2018-12-07 14:07:54 +00:00
Luck b3a028e3ca Refactor AbstractConnectionListener for the addition of Velocity support 2018-12-07 13:36:38 +00:00
Luck e222e4e98c Missing nullability annotations 2018-12-07 13:33:05 +00:00
Luck 1213e58240 Depend on a specific Velocity snapshot version
Fixes #1319
Fixes VelocityPowered/Velocity#159
2018-12-06 14:04:31 +00:00
Luck b7ff0824b9 Optimize context set manipulation 2018-12-06 14:02:41 +00:00
Luck 7b5917660c Implement LoadingMap using Guava's ForwardingMap utility 2018-11-28 12:35:38 +00:00
Luck 1544487e92 Convert permissions to lowercase inside the cache
Slight optimization, toLowerCase is a relatively expensive call in the scheme of permission checks.
2018-11-24 13:09:26 +00:00
Luck c19ef84116 Optimize ImmutableContextSet#equals by comparing the hashcodes (constant time lookup) 2018-11-24 01:25:02 +00:00
Luck e8c4a55dc3 Cache the most recent lookup for permission/meta data in AbstractCachedData.
This avoids a (somewhat) costly lookup operation involving Contexts comparison. It aims to be effective on the basis that lookup calls within the same period of time are likely to target the same context (and therefore have the same result).
2018-11-24 01:17:42 +00:00
Luck 97d6aaed5c Experiment with different cache implementation in PermissionCalculator
Caffeine seems to just fallback to a ConcurrentHashMap based implementation in this case anyway.
2018-11-24 00:15:56 +00:00
Luck fe77834cef Optimize LookupSetting storage/manipulation within Contexts
Fixes some performance issues resulting from bad use / implementation of ImmutableEnumSets
2018-11-23 23:58:49 +00:00
Luck 2da6298c53 Update references to the project website 2018-11-22 15:25:39 +00:00
Luck e111270aed Add api-version option to Bukkit plugin.yml file
This doesn't make any functional change, LP doesn't use any of the remapped Material APIs. It only saves on the amount of remapping CB tries to perform when loading the plugin.
2018-11-22 15:19:12 +00:00
Luck e07f8c0fbe Don't send 1.13 tab completions to players without access to any LP commands (#1310) 2018-11-22 15:07:55 +00:00
Luck 90246afd03 Some misc refactoring 2018-11-22 14:51:20 +00:00
Luck 9809e591ad Reorganise some packages 2018-11-10 23:16:28 +00:00
Luck 26973461e7 Don't show negated group membership permissions in the output to 'user info' and 'group listmembers' 2018-11-10 22:42:54 +00:00
Luck 759ec5d499 Attempt to parse uuid from username string in Vault hook 2018-11-10 20:23:40 +00:00
Luck 58ab3c325c misc tidying up 2018-11-10 20:21:08 +00:00
Luck 44c8c67803 Update README.md 2018-11-06 16:36:34 +00:00
Luck acb56d683a Add missing since tag to MetaStackFactory 2018-11-06 15:42:59 +00:00
Luck 5dda522a62 Add option to deduplicate prefix/suffix stacks (#1285) 2018-11-06 14:29:15 +00:00
Luck 79091c726b Update readme badges 2018-11-06 13:28:05 +00:00
Luck e5be06e07b Use the newly added API method to retrieve Velocity implementation name / version 2018-11-06 13:18:58 +00:00
Luck f63992e209 Return a more informative error for invalid verbose filters 2018-11-06 13:16:07 +00:00
Luck 9988011308 Improve the way meta lookups are caught & reported to the verbose handler 2018-11-06 13:15:30 +00:00
Luck 8584a9b72c Sponge Subject lookup methods without a contexts param should default to current contexts, not global (#1279) 2018-11-02 22:39:02 +00:00
Luck 42c8cb1354 Use the fragment identifier instead of query parameters to convey the editor/verbose/treeview data id
This fixes the issue Multicraft panels have with displaying ? characters in console. (absolute quality)
2018-10-28 22:32:02 +00:00
Luck aaeaf5cfa0 Nicer format for verbose meta logging 2018-10-28 21:56:42 +00:00
Luck 45b4e1463f Match the type in verbose filters 2018-10-28 15:18:02 +00:00
Luck be92a67544 Increase verbose stacktrace truncation length for web outputs 2018-10-28 12:40:56 +00:00
Luck 5e0b8ebdf6 Include meta lookup events in verbose output 2018-10-28 12:31:47 +00:00
Luck 9d4ccd33e1 Update commodore for tab complete fix (#1257) 2018-10-26 20:21:00 +01:00
Luck f5c42c70e5 Catch Throwable instead of Exception when calling context calculators
Related to:  lucko/ExtraContexts#4
2018-10-15 22:32:52 +01:00
Luck dcc4656e5e Update buildscripts for Sponge Ore deployment 2018-10-15 22:30:36 +01:00
MrMicky ee2de3cff1 Some minor code cleanup (#1262) 2018-10-09 18:00:53 +01:00
Luck f96518b8e4 misc tidying 2018-10-07 19:48:20 +01:00
Luck dac59966aa Setup gradle license format check 2018-09-24 13:52:59 +01:00
Luck 8115fbaa98 Refactor storage system 2018-09-23 21:49:49 +01:00
Luck 8b97439ffc Use the correct permission check method when forming tree views 2018-09-23 19:53:37 +01:00
Luck fa83986250 Refactor Constraint/Comparison impls for bulkupdate 2018-09-23 19:53:16 +01:00
Luck e1b16465f8 Fix race condition in BufferedRequest 2018-09-23 19:52:42 +01:00
Luck 57619dacb1 Update commodore to 1.1 2018-09-23 15:40:33 +01:00
Luck 64e54d89eb Refactor buildscript determinePatchVersion function 2018-09-23 15:20:22 +01:00
Luck aa4139f0b7 Release v4.3.0 2018-09-23 15:04:15 +01:00
Luck e2f1c1e16b Remove specific dependency on Sponge API 8 in the mod info file (#1221) 2018-09-23 15:02:02 +01:00
Luck 1e7ef15e54 Fix class cast exception in NodeTypeKey#getTypeName (#1230) 2018-09-23 14:38:27 +01:00
Luck 1cc156d6f6 Fix buildscript deployment config for Sonatype 2018-09-23 14:30:09 +01:00
Imortalshard 1445a3faec Fix typo in the description of /lp export (#1229) 2018-09-23 11:28:48 +01:00
Luck 1cf90692cf fix typo 2018-09-21 21:53:06 +01:00
Luck 5656bea3f9 Update for latest Velocity changes 2018-09-21 21:36:44 +01:00
Luck 8e344cea76 Cleanup imports 2018-09-20 21:17:28 +01:00
Luck 5b1229c882 Fix slf4j loading (#1224) 2018-09-20 21:17:00 +01:00
Luck 834649b390 Improve Uuids#parse
thanks @kashike
2018-09-20 15:30:22 +01:00
Luck d28170cc3f Operations to add new nodes with differing values should just override existing entries, instead of failing with the ALREADY_HAS result (#1198) 2018-09-20 11:25:31 +01:00
Luck 04e511026d Detach from permissible objects with a 1 tick delay after player quit to allow plugins listening on monitor to still access data (#1220) 2018-09-20 11:07:20 +01:00
Luck 11a3ecbba0 Fix NPE when loading subject data on Sponge (#1222) 2018-09-20 10:51:00 +01:00
Luck 51b7bb93e2 Don't trigger Vault primary thread checks whilst the server is starting up 2018-09-20 10:44:04 +01:00
Luck 9fd2028d9f Update for velocity API changes 2018-09-19 21:47:22 +01:00
Luck 75f0f40d70 NonNull annotations should be on the same line in interfaces 2018-09-19 21:12:54 +01:00
Luck 3941c77826 Move from findbugs jsr305 to checker-qual 2018-09-19 20:40:25 +01:00
Luck 4987ca3ba2 Update gradle wrapper and buildscript plugins 2018-09-19 19:41:47 +01:00
Jesse Boyd 5fa481337a Fix Nukkit permissible null handling - fixes #1191 (#1213) 2018-09-12 08:58:55 +01:00
Luck dd78e0e271 Separate formatted vs plain display name methods in User/Group
Continues from 3c773e6823 & #1210
2018-09-10 16:54:16 +01:00
Max Lee 3c773e6823 Use neutral color to display potentially colored names - fixes #1170 (#1210) 2018-09-10 16:41:14 +01:00
Luck 54a9ff9256 Fix compile 2018-09-09 11:31:17 +01:00
Luck eca6b09b18 Refactor config keys 2018-09-05 20:49:37 +01:00
Luck b7f8ca6658 Add 'require-sender-group-membership-to-modify' config option (#1140) 2018-09-05 15:49:29 +01:00
Luck ffdeadac8a Add flag to prevent users from being added/removed to/from the first group on a track (#1151) 2018-09-05 15:15:15 +01:00
Luck 9e769904bf Expose TemporaryMergeBehaviour in the API (#1189) 2018-09-05 11:11:45 +01:00
Luck 8d79ec6b07 Rename "update task" --> "sync task" 2018-09-04 21:11:03 +01:00
Luck 3a123f9fa1 Avoid running full "update tasks" unless they're absolutely needed. Process Vault API "set" requests immediately instead of in the background 2018-09-04 21:02:40 +01:00
Luck f0c0328919 Refactor MetaAccumulator to be a little more sane 2018-09-04 20:33:22 +01:00
Luck 274286032a Update banner in readme 2018-09-03 13:56:49 +01:00
Luck 76517374a2 Only allow import and export commands to interact with files in the data directory (#1193) 2018-09-02 22:20:29 +01:00
Luck 2da027f3b5 Revert MySQL driver update 2018-09-02 20:04:26 +01:00
Luck fd712f131f Update some dependency versions 2018-09-02 16:36:28 +01:00
Luck 38613e5f03 Update gitignore 2018-08-31 20:27:13 +01:00
Luck ec9060ba80 Update messenger log prefixes 2018-08-31 20:22:31 +01:00
Luck 502d57e744 Optimize event generation & other misc improvements 2018-08-27 22:11:03 +01:00
Luck c59f2ab37a Don't call NodeAddEvent when adding the default group (#1177) 2018-08-27 22:06:49 +01:00
Luck 066189b486 Send a more informative message when the bulkupdate command is used from in-game 2018-08-27 18:25:57 +01:00
Luck 37d4f92c33 Update README 2018-08-27 09:37:41 +01:00
Luck 55220e9d10 Add support for Velocity 2018-08-26 22:24:46 +01:00
Luck bd41286076 Fix build 2018-08-26 18:45:33 +01:00
Luck d84484c81c Optimize event generation and posting 2018-08-26 10:28:04 +01:00
Luck fec87d4c6a Update event to 3.0.0 2018-08-16 20:01:26 +01:00
Luck 68ec6e2a37 Include license file in the jar 2018-08-14 10:56:07 +01:00
Luck a784ad435f Fix applying group web editor changes (#1148) 2018-08-13 22:44:10 +01:00
Luck cc9bb34873 Update kyori/event dependency 2018-08-13 20:03:57 +01:00
Luck 2ddae5a96c Avoid UnsupportedEncodingException in LilyPad messenger 2018-08-12 10:40:26 +01:00
Luck 40ad489c56 Update build instructions in the README file 2018-08-12 10:27:21 +01:00
Luck 56c55d71fe Improve the way Vault lookups for offline players are handled (#1150)
1) The behaviour of online player lookups is unchanged - this only affects offline player data lookups.
2) If a 'offline player' request is made from an async task, it is executed normally. (the data is loaded)
3) If a 'offline player' request that cannot be immediately fulfilled is made from the main server thread, an exception is thrown.

The exception thrown as a result of 3) can be disabled in the config. In this case, the query is performed anyway. The main server thread will block until the request is complete.
2018-08-11 19:02:57 +01:00
Luck 56df15caf8 Add bukkit-legacy build back to the main project 2018-08-11 18:11:30 +01:00
Luck 03720665b3 Move to gradle 2018-08-10 20:39:29 +01:00
Luck 445429b510 Update text & asm dependencies (fixes #1142)
Updates for:
https://github.com/KyoriPowered/text/commit/6a7fda4e80c48884ba957ffaadd9219cead7962d
2018-08-10 00:09:34 +01:00
Luck c698587d53 Update text dependency 2018-08-09 22:43:41 +01:00
Luck b8466beee5 Completely rework event system
* Event instances are now generated dynamically at runtime. The performance hit of creating proxies at runtime is negligible in this case.

* A better EventBus implementation is now being used internally, API contracts are unaffected.
2018-08-09 22:39:33 +01:00
Luck efa666445f Initial support for Brigadier (1.13 commands) on Bukkit servers 2018-08-08 23:42:25 +01:00
Luck 59c7d77525 Load a up-to-date copy of group data before applying web editor changes 2018-08-08 09:00:35 +01:00
Luck 553da9baf6 Give some form of feedback when trying to applyedits no changes instead of no feedback at all (#1136) 2018-08-08 08:58:58 +01:00
Luck 486ddb3d42 Don't include any database properties by default (#1134) 2018-08-05 21:59:48 +01:00
Luck 381922fc02 Don't schedule a delayed load task on startup (#1130) 2018-08-05 21:51:53 +01:00
Luck 4c891f0819 Fix uppercase inconsistencies when saving users to SQL storage types (#1119)
This was causing issues when user data was saved, without UUID data being saved beforehand.

This commit fixes the way the inconsistency was introduced, and ensures that inconsistent data is made consistent in the future. (when players next login)
2018-07-30 11:22:50 -07:00
Luck 4b3d11ccab More SQL escaping (#1091 & #1126)
Follows from c16630c32b
2018-07-29 17:14:48 -07:00
Luck b1ab465991 Misc cleanup 2018-07-29 17:12:05 -07:00
Luck 952e41ad3d A few API javadoc improvements 2018-07-27 23:45:16 -07:00
Luck ae3adf23c8 Fail silently when plugins use reflection to add to dummy permissibles (#1117) 2018-07-24 21:21:05 -07:00
Luck c3cdf387c2 Fix NPE in GroupManager migration (#1118) 2018-07-24 21:03:14 -07:00
Luck 054f0c2c19 Don't add spaces when formatting 'concise' durations 2018-07-24 20:59:49 -07:00
Luck 2f7fce2109 Change name of Sql messenger table for compat with changes in the previous commit 2018-07-15 22:49:09 -07:00
Luck 07469599bc Rewrite MessagingService message encoding, conform to new plugin message channel requirements
* This change isn't backwards compatible with previous builds, this version (& onwards) won't be able to "communicate" with old versions, and vice versa.

* MC 1.13 requires plugin message channel names to be namespaced, so 'lpuc' has been changed to 'luckperms:update'

* The channel names for Redis/Lily types have also changed, I've been wanting to change the encoded format to something a bit saner for a while, and this seemed like a good time. Changing the channel names a) keeps things consistent and b) means I don't have to worry about old versions interpreting the new format.
2018-07-15 22:42:37 -07:00
Luck 08869da96e misc cleanup 2018-07-13 17:51:30 -07:00
Luck 7540a6eb70 Send more appropriate message when no users/groups match the editor type (#1096) 2018-07-13 17:51:21 -07:00
Luck fa2d9357b8 Allow FileWatcher locations to be registered after initial start 2018-07-12 17:10:07 -07:00
Luck 247a40b65f Fix /lp search for groups when using separated file storage (#1094) 2018-07-12 16:35:32 -07:00
Luck 01ffe6ad5a Use synchronized wrapper for NodeMap backings 2018-07-12 09:50:10 -07:00
Luck da3c2a073a cleanup build scripts a bit 2018-07-11 13:09:54 -07:00
Luck c16630c32b Escape groups keyword in SQL queries to (hopefully) fix compat with newer versions of MySQL (#1091) 2018-07-11 13:09:20 -07:00
Luck bf64f465a8 Re-implement Bukkit 1.7.10 support 2018-07-01 15:31:28 +01:00
Luck c1e0b874d8 Add helpful message for users on first startup 2018-07-01 15:07:25 +01:00
Luck c780266139 Add setprefix, setsuffix, settempprefix, settempsuffix commands (#840) 2018-06-27 17:31:30 +01:00
Luck 08454d58d0 Refactor the way contexts are cached on all platforms (#1071)
Should fix memory leak issues on BungeeCord
2018-06-27 00:17:53 +01:00
Luck ee13540d78 Specify explicit global context in generated LP commands when default contexts have been set (#1062) 2018-06-26 14:39:18 +01:00
Luck b4ff54ffc8 Apply Sponge implicit wildcards after Bukkit style .* wildcards 2018-06-24 21:44:12 +01:00
Luck 6f96d9c7d1 Fix NPE on Nukkit load (#1059) 2018-06-19 23:40:13 +01:00
Luck 5b66436519 Ensure the backing of LPSubscriptionValueMaps is a WeakHashMap (#1058) 2018-06-19 23:35:19 +01:00
Luck 379eb00b69 Cleanup various message localisations, limit the size of the PermissionRegistry 2018-06-19 22:27:47 +01:00
Luck 2036127612 Cleanup action log formatting and pagination
This is technically a breaking change to the API, but I'm fairly certain hardly anyone is using these methods (the pagination functionality in the API is pretty useless)

Can always add them back if it becomes an issue
2018-06-18 16:08:18 +01:00
Luck 957a918bd6 Fix loading on BungeeCord (#1054) 2018-06-17 09:49:38 +01:00
Luck 6b305972ac Fix sponge build script 2018-06-16 18:41:53 +01:00
Luck b8c06904ab Make logging messages a bit less obnoxious
* Removed the ascii text from the startup output
* Log messages (but not command output) is now sent through the standard server logger, and isn't colored
2018-06-16 16:59:59 +01:00
Luck 6baa472567 Fix context cache invalidation 2018-06-15 19:07:24 +01:00
Luck 9c449def57 Update some dependency versions 2018-06-13 20:29:00 +01:00
Luck e4acc133a9 remove some unnecessary interfaces 2018-06-12 18:18:38 +01:00
Luck 8b181b877b Nukkit stores attachments in a set, not a list (#1046) 2018-06-11 17:07:56 +01:00
Luck 194790110d Fix node comparison for identical nodes except the value 2018-06-07 19:58:55 +01:00
Luck c0cd197bd0 Don't allow players to be added to SubscriptionValueMaps 2018-06-07 17:01:25 +01:00
Luck 30ce269873 Disable hikari leak detection (#1033) 2018-06-05 20:33:23 +01:00
Luck 4d7be13c16 Don't reload Sponge persisted subjects when a save is pending 2018-06-03 20:46:50 +01:00
Luck 8cf0f7da5f Improve buffering code 2018-06-03 19:36:55 +01:00
Luck bcb4e5ca64 cleanup various comparators 2018-05-31 23:41:37 +01:00
Luck 07b003c77a Make the dummy attachment a bit more compatible
still MassiveCore lol
2018-05-31 01:01:29 +01:00
Luck f4e4f727dd More workarounds to support MassiveCore's modification of attachment permissions via reflection 2018-05-31 00:51:33 +01:00
Luck 644c53a074 Add workaround for plugins adding/removing/modifying permission attachments via reflection (#1024)
who knows why they're doing it, it's not even beneficial for performance...
2018-05-30 13:17:41 +01:00
Luck c66622bd09 Fix regex permissions not really working properly (#1021) 2018-05-29 14:45:21 +01:00
Luck adf0589184 Print a more informative error when the port is missing from the address arg (#1022) 2018-05-29 12:40:39 +01:00
Luck b7de0e6901 Provide an even more detailed warning message when other uuids are present for a username
We can use the data we have about the UUID and the platform LP is running on to infer more information about what the problem (potentially) is.
2018-05-25 17:05:26 +01:00
Luck a90e59ec97 Fix cache invalidation when group data changes (#1010) 2018-05-21 18:48:47 +01:00
Luck f4882c1c14 Cache the creation of Sponge proxy subject classes (#1005) 2018-05-17 18:19:45 +01:00
Luck ed3b5a3cf1 Lazily load contexts cache for Sponge subjects (#1005) 2018-05-17 18:12:20 +01:00
Luck 45e2b7b12f Fix saving node attributes on non-YAML file storage types (#999) 2018-05-16 19:30:05 +01:00
Luck 1e73986c60 Allow world rewrite options to apply in (some) Vault lookups (#990) 2018-05-16 19:04:09 +01:00
Luck 20f992110d Refactor meta stack element creation, add 'from_group' & 'not_from_group' elements 2018-05-16 18:46:25 +01:00
Luck 18f09f9862 Various performance optimizations 2018-05-15 00:08:23 +01:00
Luck a0be1c7c48 Fix issue with Bukkit attachment permissions never being removed (#991) 2018-05-13 14:06:23 +01:00
DoNotSpamPls 5d34661a15 Readme fixes (#993) 2018-05-12 16:40:54 +01:00
Luck 1639879106 Reduce the number of config lookups required when calculating contexts 2018-05-12 01:51:38 +01:00
Luck a927ca659f Reduce the throughput on the contexts cache in ContextManager (#929) 2018-05-12 01:34:34 +01:00
Luck 804c884d8b Update configurate to fix issues with legacy guava compat 2018-05-06 19:57:50 +01:00
Luck 51f215b8ac Add PlayerDataSaveEvent 2018-05-06 18:21:14 +01:00
820 changed files with 31090 additions and 31998 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
patreon: luckdev
+23 -110
View File
@@ -1,40 +1,14 @@
# Created by https://www.gitignore.io/
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/
*.iws
/out/
### Gradle & IntelliJ ###
.gradle/
/.idea/
build/
out/
run/
*.iml
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
### Eclipse ###
.metadata
bin/
tmp/
@@ -46,73 +20,29 @@ local.properties
.settings/
.loadpath
.recommenders
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
.apt_generated/
.project
.classpath
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### macOS ###
*.DS_Store
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
@@ -120,7 +50,6 @@ Icon
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
@@ -128,37 +57,21 @@ Temporary Items
.apdisk
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
### Windows ###
# Windows image file caches
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
ehthumbs_vista.db
*.stackdump
[Dd]esktop.ini
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### Java ###
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
+2 -2
View File
@@ -19,8 +19,8 @@ LuckPerms loosely follows the [Google Java Style Guide](https://google.github.io
If you're considering submitting a substantial pull request, please open an issue so we can discuss the change before starting work on the contribution. Most pull requests are happily accepted, but larger changes may have an inpact on the maintainability of the project, and require more consideration.
#### Project Layout
The project is split up into 5 seperate modules.
The project is split up into a few seperate modules.
* **API** - The public, semantically versioned API used by other plugins wishing to integrate with and retrieve data from LuckPerms. This module (for the most part) does not contain any implementation itself, and is provided by the plugin.
* **Common** - The common module contains most of the code which implements the respective LuckPerms plugins. This abstract module reduces duplicated code throughout the project.
* **Bukkit, BungeeCord & Sponge** - Each use the common module to implement plugins on the respective server platforms.
* **Bukkit, BungeeCord, Sponge, Nukkit & Velocity** - Each use the common module to implement plugins on the respective server platforms.
+22
View File
@@ -0,0 +1,22 @@
This file is part of LuckPerms, licensed under the MIT License.
Copyright (c) lucko (Luck) <luck@lucko.me>
Copyright (c) contributors
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.
+2 -2
View File
@@ -1,4 +1,4 @@
The MIT License.
MIT License
Copyright (c) lucko (Luck) <luck@lucko.me>
Copyright (c) contributors
@@ -19,4 +19,4 @@ 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.
SOFTWARE.
+12 -12
View File
@@ -1,5 +1,9 @@
![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/) [![Javadocs](https://javadoc.io/badge/me.lucko.luckperms/luckperms-api.svg)](https://javadoc.io/doc/me.lucko.luckperms/luckperms-api) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/me.lucko.luckperms/luckperms-api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/me.lucko.luckperms/luckperms-api)
![alt text](https://i.imgur.com/ToguFkQ.png "Banner")
# LuckPerms
[![Build Status](https://ci.lucko.me/job/LuckPerms/badge/icon)](https://ci.lucko.me/job/LuckPerms/)
[![Javadocs](https://javadoc.io/badge/me.lucko.luckperms/luckperms-api.svg)](https://javadoc.io/doc/me.lucko.luckperms/luckperms-api)
[![Maven Central](https://img.shields.io/maven-metadata/v/https/repo1.maven.org/maven2/me/lucko/luckperms/luckperms-api/maven-metadata.xml.svg?label=maven%20central&colorB=brightgreen)](https://search.maven.org/artifact/me.lucko.luckperms/luckperms-api)
[![Discord](https://img.shields.io/discord/241667244927483904.svg?logo=discord&label=)](https://discord.gg/luckperms)
LuckPerms is an advanced permissions implementation aiming to be a fast, reliable and flexible alternative to existing permission plugins. The project's main goals are centered around high performance and a wide feature set, filling the gaps of functionality and building upon existing features found in other plugins.
@@ -9,26 +13,25 @@ Still not convinced? More information can be found on the wiki, under: [Why Luck
## Useful Links
The latest **downloads** can be found on the [project's homepage](https://luckperms.github.io/).
The latest **downloads** can be found on the [project's homepage](https://luckperms.net/).
More information about the project & how to use the plugin can be found in the [wiki](https://github.com/lucko/LuckPerms/wiki).
## Building
LuckPerms uses Maven to handle dependencies.
LuckPerms uses Gradle to handle dependencies & building.
#### Requirements
* Java 8 JDK or newer
* Maven 3.3.x or newer (the older versions will not work.)
* Git
#### Compiling from source
```sh
git clone https://github.com/lucko/LuckPerms.git
cd LuckPerms/
mvn clean package
./gradlew build
```
You can find the output jars in the `target` directories.
You can find the output jars in the `build/libs` directories.
## Contributing
#### Pull Requests
@@ -37,14 +40,11 @@ If you make any changes or improvements to the plugin which you think would be b
LuckPerms loosely follows the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html). Generally, try to copy the style of code found in the class you're editing.
#### Project Layout
The project is split up into 5 seperate modules.
The project is split up into a few separate modules.
* **API** - The public, semantically versioned API used by other plugins wishing to integrate with and retrieve data from LuckPerms. This module (for the most part) does not contain any implementation itself, and is provided by the plugin.
* **Common** - The common module contains most of the code which implements the respective LuckPerms plugins. This abstract module reduces duplicated code throughout the project.
* **Bukkit, BungeeCord, Sponge & Nukkit** - Each use the common module to implement plugins on the respective server platforms.
* **Bukkit, BungeeCord, Sponge, Nukkit & Velocity** - Each use the common module to implement plugins on the respective server platforms.
## License
LuckPerms is licensed under the permissive MIT license. Please see [`LICENSE.txt`](https://github.com/lucko/LuckPerms/blob/master/LICENSE.txt) for more info.
## Thanks
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").
+98
View File
@@ -0,0 +1,98 @@
group = 'net.luckperms'
project.version = '5.0'
dependencies {
compileOnly 'org.checkerframework:checker-qual:2.5.5'
}
// Only used occasionally for deployment - not needed for normal builds.
/*
if (project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')) {
apply plugin: 'signing'
javadoc {
title = 'LuckPerms API (v' + project.ext.apiVersion + ')'
options.encoding = 'UTF-8'
options.charSet = 'UTF-8'
options.links(
'https://docs.oracle.com/javase/8/docs/api/'
)
options.addStringOption('Xdoclint:none', '-quiet')
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier 'javadoc'
from javadoc.destinationDir
}
task sourcesJar(type: Jar) {
classifier 'sources'
from sourceSets.main.allSource
}
artifacts {
archives javadocJar
archives sourcesJar
}
signing {
useGpgCmd()
sign configurations.archives
}
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2/') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
pom {
project {
name 'LuckPerms API'
description 'An advanced permissions plugin for Bukkit/Spigot, BungeeCord, Sponge, Nukkit and Velocity.'
url 'https://luckperms.net'
licenses {
license {
name 'MIT'
url 'https://opensource.org/licenses/MIT'
}
}
developers {
developer {
name 'Luck'
email 'git@lucko.me'
url 'https://github.com/lucko'
}
}
scm {
connection 'scm:git:https://github.com/lucko/LuckPerms.git'
developerConnection 'scm:git:git@github.com:lucko/LuckPerms.git'
url 'https://github.com/lucko/LuckPerms'
}
ciManagement {
system 'Jenkins'
url 'https://ci.lucko.me/job/LuckPerms'
}
issueManagement {
system 'GitHub'
url 'https://github.com/lucko/LuckPerms/issues'
}
}
}
}
}
}
}
*/
-96
View File
@@ -1,96 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
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>4.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-api</artifactId>
<build>
<finalName>LuckPerms-API-${release.version}</finalName>
<resources>
<resource>
<directory>../</directory>
<filtering>false</filtering>
<includes>
<include>LICENSE.txt</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>deployment</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<links>
<link>https://google.github.io/guava/releases/21.0/api/docs/</link>
</links>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<!-- guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
<scope>provided</scope>
</dependency>
<!-- jsr305 -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -1,130 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.Map;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nonnull;
/**
* Represents a type of chat meta
*
* @since 3.2
*/
public enum ChatMetaType {
/**
* Represents a prefix
*/
PREFIX("prefix") {
@Override
public boolean matches(@Nonnull Node node) {
return Objects.requireNonNull(node, "node").isPrefix();
}
@Nonnull
@Override
public Map.Entry<Integer, String> getEntry(@Nonnull Node node) {
return Objects.requireNonNull(node, "node").getPrefix();
}
},
/**
* Represents a suffix
*/
SUFFIX("suffix") {
@Override
public boolean matches(@Nonnull Node node) {
return Objects.requireNonNull(node, "node").isSuffix();
}
@Nonnull
@Override
public Map.Entry<Integer, String> getEntry(@Nonnull Node node) {
return Objects.requireNonNull(node, "node").getSuffix();
}
};
private final String str;
ChatMetaType(String str) {
this.str = str;
}
/**
* Returns if the passed node matches the type
*
* @param node the node to test
* @return true if the node has the same type
*/
public abstract boolean matches(@Nonnull Node node);
/**
* Returns if the passed node should be ignored when searching for meta of this type
*
* @param node the node to test
* @return true if the node does not share the same type
*/
public boolean shouldIgnore(@Nonnull Node node) {
return !matches(node);
}
/**
* Maps the corresponding entry from the given node
*
* @param node the node to retrieve the entry from
* @return the entry
* @throws IllegalStateException if the node does not share the same type
*/
@Nonnull
public abstract Map.Entry<Integer, String> getEntry(@Nonnull Node node);
@Override
public String toString() {
return this.str;
}
/**
* Parses a ChatMetaType from the given node.
*
* @param node the node
* @return the parsed chat meta type
* @since 3.4
*/
@Nonnull
public static Optional<ChatMetaType> ofNode(@Nonnull Node node) {
if (node.isPrefix()) {
return Optional.of(PREFIX);
} else if (node.isSuffix()) {
return Optional.of(SUFFIX);
} else {
return Optional.empty();
}
}
}
@@ -1,353 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api;
import com.google.common.collect.ImmutableSet;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* Encapsulates the {@link ContextSet contexts} and {@link LookupSetting settings} for
* a permission or meta lookup.
*
* <p>This class is immutable.</p>
*
* @since 2.11
*/
@Immutable
public class Contexts {
/**
* The context key used to denote the subjects server
*/
public static final String SERVER_KEY = "server";
/**
* The context key used to denote the subjects world
*/
public static final String WORLD_KEY = "world";
/**
* The default {@link LookupSetting}s.
*/
private static final EnumSet<LookupSetting> DEFAULT_SETTINGS = EnumSet.of(
LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER,
LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD,
LookupSetting.RESOLVE_INHERITANCE,
LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER,
LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD
);
/**
* A 'global' or default contexts instance.
*
* <p>Formed of an empty {@link ContextSet} and all inclusion and
* inheritance {@link LookupSetting}s applied.</p>
*/
private static final Contexts GLOBAL = new Contexts(ImmutableContextSet.empty(), ImmutableSet.copyOf(DEFAULT_SETTINGS));
/**
* Gets the {@link FullySatisfiedContexts} instance.
*
* @return a context that will satisfy all contextual requirements.
*/
@Nonnull
public static Contexts allowAll() {
return FullySatisfiedContexts.getInstance();
}
/**
* Returns a 'global' or default contexts instance.
*
* <p>Formed of an empty {@link ContextSet} and all inclusion and
* inheritance {@link LookupSetting}s applied.</p>
*
* @return the global contexts
* @since 3.3
*/
@Nonnull
public static Contexts global() {
return GLOBAL;
}
/**
* Creates a new {@link Contexts} instance.
*
* @param contextSet the context set
* @param includeNodesSetWithoutServer the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER}
* @param includeNodesSetWithoutWorld the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD}
* @param resolveInheritance the value of {@link LookupSetting#RESOLVE_INHERITANCE}
* @param applyParentsWithoutServer the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER}
* @param applyParentsWithoutWorld the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD}
* @param isOp the value of {@link LookupSetting#IS_OP}
* @return a new instance
*/
@Nonnull
public static Contexts of(@Nonnull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
Objects.requireNonNull(contextSet, "contextSet");
EnumSet<LookupSetting> settings = formSettings(
includeNodesSetWithoutServer,
includeNodesSetWithoutWorld,
resolveInheritance,
applyParentsWithoutServer,
applyParentsWithoutWorld,
isOp
);
if (contextSet.isEmpty() && DEFAULT_SETTINGS.equals(settings)) {
return GLOBAL;
}
return new Contexts(contextSet.makeImmutable(), ImmutableSet.copyOf(settings));
}
/**
* Creates a new {@link Contexts} instance.
*
* @param contextSet the context set
* @param settings the settings
* @return a new instance
*/
public static Contexts of(@Nonnull ContextSet contextSet, @Nonnull Set<LookupSetting> settings) {
Objects.requireNonNull(contextSet, "contextSet");
Objects.requireNonNull(settings, "settings");
EnumSet<LookupSetting> settingsCopy = EnumSet.copyOf(settings);
if (contextSet.isEmpty() && DEFAULT_SETTINGS.equals(settingsCopy)) {
return GLOBAL;
}
return new Contexts(contextSet.makeImmutable(), ImmutableSet.copyOf(settingsCopy));
}
/**
* The contexts that apply for this lookup
*/
private final ImmutableContextSet contextSet;
/**
* The settings for this lookup
*/
private final ImmutableSet<LookupSetting> settings;
// cache hashcode - this class is immutable, and is used as an index in the permission cache.
private final int hashCode;
/**
* Creates a new {@link Contexts} instance.
*
* @param contextSet the context set
* @param includeNodesSetWithoutServer the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER}
* @param includeNodesSetWithoutWorld the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD}
* @param resolveInheritance the value of {@link LookupSetting#RESOLVE_INHERITANCE}
* @param applyParentsWithoutServer the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER}
* @param applyParentsWithoutWorld the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD}
* @param isOp the value of {@link LookupSetting#IS_OP}
* @deprecated in favour of {@link #of(ContextSet, boolean, boolean, boolean, boolean, boolean, boolean)}
*/
@Deprecated
public Contexts(@Nonnull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
this.contextSet = Objects.requireNonNull(contextSet, "contextSet").makeImmutable();
this.settings = ImmutableSet.copyOf(formSettings(
includeNodesSetWithoutServer,
includeNodesSetWithoutWorld,
resolveInheritance,
applyParentsWithoutServer,
applyParentsWithoutWorld,
isOp
));
this.hashCode = calculateHashCode();
}
protected Contexts(@Nonnull ImmutableContextSet contextSet, @Nonnull ImmutableSet<LookupSetting> settings) {
this.contextSet = contextSet;
this.settings = settings;
this.hashCode = calculateHashCode();
}
/**
* Gets the {@link ContextSet} which represent these {@link Contexts}.
*
* @return an immutable context from this instance
* @since 2.13
*/
@Nonnull
public ContextSet getContexts() {
return this.contextSet;
}
/**
* Gets the set of {@link LookupSetting}s which represent these {@link Contexts}.
*
* @return the settings
* @since 4.2
*/
@Nonnull
public Set<LookupSetting> getSettings() {
return this.settings;
}
/**
* Gets if the given {@link LookupSetting} is set.
*
* @param setting the setting
* @return the value
* @since 4.2
*/
public boolean hasSetting(@Nonnull LookupSetting setting) {
return this.settings.contains(setting);
}
/**
* Gets the value of {@link LookupSetting#IS_OP}.
*
* @return the value
* @see LookupSetting#IS_OP
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
*/
@Deprecated
public boolean isOp() {
return hasSetting(LookupSetting.IS_OP);
}
/**
* Gets the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER}.
*
* @return the value
* @see LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
*/
@Deprecated
public boolean isIncludeGlobal() {
return hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER);
}
/**
* Gets the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD}.
*
* @return the value
* @see LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
*/
@Deprecated
public boolean isIncludeGlobalWorld() {
return hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD);
}
/**
* Gets the value of {@link LookupSetting#RESOLVE_INHERITANCE}.
*
* @return the value
* @see LookupSetting#RESOLVE_INHERITANCE
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
*/
@Deprecated
public boolean isApplyGroups() {
return hasSetting(LookupSetting.RESOLVE_INHERITANCE);
}
/**
* Gets the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER}.
*
* @return the value
* @see LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
*/
@Deprecated
public boolean isApplyGlobalGroups() {
return hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER);
}
/**
* Gets the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD}.
*
* @return the value
* @see LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
*/
@Deprecated
public boolean isApplyGlobalWorldGroups() {
return hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD);
}
@Nonnull
@Override
public String toString() {
return "Contexts(contextSet=" + this.contextSet + ", settings=" + this.settings + ")";
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (o == allowAll()) return false;
if (!(o instanceof Contexts)) return false;
final Contexts that = (Contexts) o;
return this.contextSet.equals(that.contextSet) && this.settings.equals(that.settings);
}
private int calculateHashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.contextSet.hashCode();
result = result * PRIME + this.settings.hashCode();
return result;
}
@Override
public int hashCode() {
return this.hashCode;
}
private static EnumSet<LookupSetting> formSettings(boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
EnumSet<LookupSetting> settings = EnumSet.noneOf(LookupSetting.class);
if (includeNodesSetWithoutServer) {
settings.add(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER);
}
if (includeNodesSetWithoutWorld) {
settings.add(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD);
}
if (resolveInheritance) {
settings.add(LookupSetting.RESOLVE_INHERITANCE);
}
if (applyParentsWithoutServer) {
settings.add(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER);
}
if (applyParentsWithoutWorld) {
settings.add(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD);
}
if (isOp) {
settings.add(LookupSetting.IS_OP);
}
return settings;
}
}
@@ -1,83 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api;
import com.google.common.collect.ImmutableSet;
import me.lucko.luckperms.api.caching.CachedData;
import me.lucko.luckperms.api.caching.MetaContexts;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import javax.annotation.Nonnull;
/**
* A special instance of {@link Contexts}, which when passed to:
*
* <p></p>
* <ul>
* <li>{@link CachedData#getPermissionData(Contexts)}</li>
* <li>{@link CachedData#getMetaData(Contexts)}</li>
* <li>{@link CachedData#getMetaData(MetaContexts)}</li>
* </ul>
*
* <p>... will always satisfy all contextual requirements.</p>
*
* <p>This effectively allows you to do lookups which ignore context.</p>
*
* @since 3.3
*/
public final class FullySatisfiedContexts extends Contexts {
// singleton
private static final FullySatisfiedContexts INSTANCE = new FullySatisfiedContexts();
@Nonnull
public static Contexts getInstance() {
return INSTANCE;
}
private FullySatisfiedContexts() {
super(ImmutableContextSet.empty(), ImmutableSet.copyOf(Contexts.global().getSettings()));
}
@Nonnull
@Override
public String toString() {
return "FullySatisfiedContexts()";
}
@Override
public boolean equals(Object o) {
// this class is a singleton, so we can use object comparison to check equality.
return o == this;
}
@Override
public int hashCode() {
// just use the system hashcode - we need to override the hashcode impl in super
return System.identityHashCode(this);
}
}
@@ -1,106 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api;
import me.lucko.luckperms.api.context.ContextSet;
import java.util.Optional;
import java.util.OptionalLong;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* A relationship between a {@link PermissionHolder} and a permission.
*
* @param <T> the identifier type of the holder
* @since 2.17
*/
@Immutable
public interface HeldPermission<T> {
/**
* Gets the holder of the permission
*
* @return the holder
*/
@Nonnull
T getHolder();
/**
* Gets the permission being held
*
* @return the permission
*/
@Nonnull
String getPermission();
/**
* Gets the value of the permission
*
* @return the value
*/
boolean getValue();
/**
* Gets the server where the permission is held
*
* @return the server
*/
@Nonnull
Optional<String> getServer();
/**
* Gets the world where the permission is held
*
* @return the world
*/
@Nonnull
Optional<String> getWorld();
/**
* Gets the time in unix time when the permission will expire
*
* @return the expiry time
*/
OptionalLong getExpiry();
/**
* Gets the extra context for the permission.
*
* @return the extra context
*/
ContextSet getContexts();
/**
* Converts this permission into a Node
*
* @return a Node copy of this permission
*/
@Nonnull
Node asNode();
}
@@ -1,122 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.Map;
import javax.annotation.Nonnull;
/**
* Wrapper around parts of the LuckPerms configuration file
*/
public interface LPConfiguration {
/**
* Gets the name of this server
*
* @return the name of this server
*/
@Nonnull
String getServer();
/**
* Gets if the users on this server will have their global permissions applied
*
* @return if the users on this server will have their global permissions applied
*/
boolean getIncludeGlobalPerms();
/**
* Gets if the users on this server will have their global world permissions applied
*
* @return if the users on this server will have their global world permissions applied
* @since 2.9
*/
boolean getIncludeGlobalWorldPerms();
/**
* Gets if the platform is applying global groups
*
* @return true if the platform is applying global groups
* @since 2.9
*/
boolean getApplyGlobalGroups();
/**
* Gets if the platform is applying global world groups
*
* @return true if the platform is applying global world groups
* @since 2.9
*/
boolean getApplyGlobalWorldGroups();
/**
* Gets the storage method string from the configuration
*
* @return the storage method string from the configuration
*/
@Nonnull
String getStorageMethod();
/**
* Gets true if split storage is enabled
*
* @return true if split storage is enabled
* @since 2.7
*/
boolean getSplitStorage();
/**
* Gets a map of split storage options
*
* @return a map of split storage options, where the key is the storage section, and the value is the storage
* method. For example: key = user, value = json
* @since 2.7
*/
@Nonnull
Map<String, String> getSplitStorageOptions();
@Nonnull
Unsafe unsafe();
interface Unsafe {
/**
* Gets an Object from the config.
*
* <p>This method is nested under {@link Unsafe} because the keys
* and return types may change between versions without warning.</p>
*
* @param key the key, as defined as a field name in
* the "ConfigKeys" class.
* @return the corresponding object, if one is present
* @throws IllegalArgumentException if the key isn't known
*/
@Nonnull
Object getObject(String key);
}
}
@@ -1,232 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* Represents the internal LuckPerms log.
*
* <p>The returned instance provides a copy of the data at the time of retrieval.</p>
*
* <p>Any changes made to log entries will only apply to this instance of the log.
* You can add to the log using the {@link Storage}, and then request an updated copy.</p>
*
* <p>All methods are thread safe, and return immutable and thread safe collections.</p>
*/
@Immutable
public interface Log {
/**
* Get the content of the log
*
* @return a {@link SortedSet} of all of the {@link LogEntry} objects in this {@link Log}
*/
@Nonnull
SortedSet<LogEntry> getContent();
/**
* Get the content of the log
*
* @return all content in this log
*/
@Nonnull
SortedSet<LogEntry> getRecent();
/**
* Gets the recent content separated by page
*
* @param pageNo the page number
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getRecentMaxPages()}
*/
@Nonnull
SortedMap<Integer, LogEntry> getRecent(int pageNo);
/**
* Gets the max page number for the recent pages.
*
* @return the max page number allowed in the {@link #getRecent(int)} method
*/
int getRecentMaxPages();
/**
* Gets the recent content for a given actor
*
* @param actor the uuid of the actor to filter by
* @return all content in this log where is actor = uuid
*/
@Nonnull
SortedSet<LogEntry> getRecent(@Nonnull UUID actor);
/**
* Gets the recent content for a given actor, separated by page
*
* @param pageNo the page number
* @param actor the uuid of the actor to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getRecentMaxPages(UUID)}
*/
@Nonnull
SortedMap<Integer, LogEntry> getRecent(int pageNo, @Nonnull UUID actor);
/**
* Gets the max page number for the recent pages.
*
* @param actor the actor to filter by
* @return the max page number allowed in the {@link #getRecent(int, UUID)} method
*/
int getRecentMaxPages(@Nonnull UUID actor);
/**
* Gets the log content for a given user
*
* @param uuid the uuid to filter by
* @return all content in this log where the user = uuid
*/
@Nonnull
SortedSet<LogEntry> getUserHistory(@Nonnull UUID uuid);
/**
* Gets the log content for a given user, separated by page
*
* @param pageNo the page number
* @param uuid the uuid of the acted user to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getUserHistoryMaxPages(UUID)}
*/
@Nonnull
SortedMap<Integer, LogEntry> getUserHistory(int pageNo, @Nonnull UUID uuid);
/**
* Gets the max page number for the user history pages.
*
* @param uuid the uuid to filter by
* @return the max page number allowed in the {@link #getUserHistory(int, UUID)} method
*/
int getUserHistoryMaxPages(@Nonnull UUID uuid);
/**
* Gets the log content for a given group
*
* @param name the name to filter by
* @return all content in this log where the group = name
*/
@Nonnull
SortedSet<LogEntry> getGroupHistory(@Nonnull String name);
/**
* Gets the log content for a given group, separated by page
*
* @param pageNo the page number
* @param name the name of the acted group to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getGroupHistoryMaxPages(String)}
*/
@Nonnull
SortedMap<Integer, LogEntry> getGroupHistory(int pageNo, @Nonnull String name);
/**
* Gets the max page number for the group history pages.
*
* @param name the name to filter by
* @return the max page number allowed in the {@link #getGroupHistory(int, String)} method
*/
int getGroupHistoryMaxPages(@Nonnull String name);
/**
* Gets the log content for a given track
*
* @param name the name to filter by
* @return all content in this log where the track = name
*/
@Nonnull
SortedSet<LogEntry> getTrackHistory(@Nonnull String name);
/**
* Gets the log content for a given track, separated by page
*
* @param pageNo the page number
* @param name the name of the acted track to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getTrackHistoryMaxPages(String)}
*/
@Nonnull
SortedMap<Integer, LogEntry> getTrackHistory(int pageNo, @Nonnull String name);
/**
* Gets the max page number for the track history pages.
*
* @param name the name to filter by
* @return the max page number allowed in the {@link #getTrackHistory(int, String)} method
*/
int getTrackHistoryMaxPages(@Nonnull String name);
/**
* Gets the log content for a given search query
*
* @param query the query to filter by
* @return all content in this log where the content matches query
*/
@Nonnull
SortedSet<LogEntry> getSearch(@Nonnull String query);
/**
* Gets the log content for a given search query, separated by page
*
* @param pageNo the page number
* @param query the query to filter by
* @return the page content
* @throws IllegalArgumentException if the pageNo is less than 1
* @throws IllegalStateException if the log doesn't contain enough entries to populate the page. See {@link #getSearchMaxPages(String)}}
*/
@Nonnull
SortedMap<Integer, LogEntry> getSearch(int pageNo, @Nonnull String query);
/**
* Gets the max page number for the search query pages.
*
* @param query the query to filter by
* @return the max page number allowed in the {@link #getSearch(int, String)} method
*/
int getSearchMaxPages(@Nonnull String query);
}
@@ -1,505 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.api.context.ContextCalculator;
import me.lucko.luckperms.api.context.ContextManager;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.event.EventBus;
import me.lucko.luckperms.api.manager.GroupManager;
import me.lucko.luckperms.api.manager.TrackManager;
import me.lucko.luckperms.api.manager.UserManager;
import me.lucko.luckperms.api.messenger.MessengerProvider;
import me.lucko.luckperms.api.metastacking.MetaStackFactory;
import me.lucko.luckperms.api.platform.PlatformInfo;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* The LuckPerms API.
*
* <p>This interface is the base of the entire API package. All API functions
* are accessed via this interface.</p>
*
* <p>An instance can be obtained via {@link LuckPerms#getApi()}, or the platforms
* Services Manager.</p>
*/
public interface LuckPermsApi {
/**
* Gets information about the platform LuckPerms is running on.
*
* @return the platform info
* @since 4.0
*/
@Nonnull
PlatformInfo getPlatformInfo();
/**
* Gets the {@link UserManager}, responsible for managing
* {@link User} instances.
*
* <p>This manager can be used to retrieve instances of {@link User} by uuid
* or name, or query all loaded users.</p>
*
* <p>The {@link #getStorage() storage} instance should be used to
* load/create/save users.</p>
*
* @return the user manager
* @since 4.0
*/
@Nonnull
UserManager getUserManager();
/**
* Gets the {@link GroupManager}, responsible for managing
* {@link Group} instances.
*
* <p>This manager can be used to retrieve instances of {@link Group} by
* name, or query all loaded groups.</p>
*
* <p>The {@link #getStorage() storage} instance should be used to
* load/create/save/delete groups.</p>
*
* @return the group manager
* @since 4.0
*/
@Nonnull
GroupManager getGroupManager();
/**
* Gets the {@link TrackManager}, responsible for managing
* {@link Track} instances.
*
* <p>This manager can be used to retrieve instances of {@link Track} by
* name, or query all loaded tracks.</p>
*
* <p>The {@link #getStorage() storage} instance should be used to
* load/create/save/delete tracks.</p>
*
* @return the track manager
* @since 4.0
*/
@Nonnull
TrackManager getTrackManager();
/**
* Schedules the execution of an update task, and returns an encapsulation
* of the task as a {@link CompletableFuture}.
*
* <p>The exact actions performed in an update task remains an
* implementation detail of the plugin, however, as a minimum, it is
* expected to perform a full reload of user, group and track data, and
* ensure that any changes are fully applied and propagated.</p>
*
* @return a future
* @since 4.0
*/
@Nonnull
CompletableFuture<Void> runUpdateTask();
/**
* Gets the {@link EventBus}, used for subscribing to internal LuckPerms
* events.
*
* @return the event bus
* @since 3.0
*/
@Nonnull
EventBus getEventBus();
/**
* Gets a representation of the plugins configuration
*
* @return the configuration
*/
@Nonnull
LPConfiguration getConfiguration();
/**
* Gets an object representing the plugins primary {@link Storage} backend.
*
* <p>The instance propagates calls to the internal DAO (Data Access Object),
* and applies any changes to the storage provider.</p>
*
* @return a storage instance
* @since 2.14
*/
@Nonnull
Storage getStorage();
/**
* Gets the {@link MessagingService}, if present.
*
* <p>The MessagingService is used to dispatch updates throughout a network
* of servers running the plugin.</p>
*
* <p>Not all instances of LuckPerms will have a messaging service setup and
* configured, but it is recommended that all users of the API account for
* and make use of this.</p>
*
* @return the messaging service instance, if present.
*/
@Nonnull
Optional<MessagingService> getMessagingService();
/**
* Registers a {@link MessengerProvider} for use by the platform.
*
* <p>Note that the mere action of registering a provider doesn't
* necessarily mean that it will be used.</p>
*
* @param messengerProvider the messenger provider.
* @since 4.1
*/
void registerMessengerProvider(@Nonnull MessengerProvider messengerProvider);
/**
* Gets the {@link ActionLogger}.
*
* <p>The action logger is responsible for saving and broadcasting defined
* actions occurring on the platform.</p>
*
* @return the action logger
* @since 4.1
*/
ActionLogger getActionLogger();
/**
* Gets a {@link UuidCache}.
*
* <p>The uuid cache provides read access to the internal LuckPerms uuid
* mapping system.</p>
*
* @return the uuid cache
* @deprecated this feature is now handled internally - and the API returns a
* No-op implementation of this class.
*/
@Nonnull
@Deprecated
UuidCache getUuidCache();
/**
* Gets the {@link ContextManager}.
*
* <p>The context manager manages {@link ContextCalculator}s, and calculates
* applicable contexts for a given type.</p>
*
* @return the context manager
* @since 4.0
*/
ContextManager getContextManager();
/**
* Gets the {@link NodeFactory}.
*
* <p>The node factory provides methods for building {@link Node} instances.</p>
*
* @return the node factory
*/
@Nonnull
NodeFactory getNodeFactory();
/**
* Gets the {@link MetaStackFactory}.
*
* <p>The metastack factory provides methods for retrieving
* {@link me.lucko.luckperms.api.metastacking.MetaStackElement}s and constructing
* {@link me.lucko.luckperms.api.metastacking.MetaStackDefinition}s.</p>
*
* @return the meta stack factory
* @since 3.2
*/
@Nonnull
MetaStackFactory getMetaStackFactory();
/*
* The following methods are provided only for convenience, and offer no
* additional functionality.
*
* They are implemented as "default" methods, using the manager and factory
* instances provided by the methods above.
*/
/**
* 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
*/
@Nullable
default User getUser(@Nonnull UUID uuid) {
return getUserManager().getUser(uuid);
}
/**
* Gets a wrapped user object from the user storage.
*
* @param uuid the uuid of the user to get
* @return an optional {@link User} object
* @throws NullPointerException if the uuid is null
*/
@Nonnull
default Optional<User> getUserSafe(@Nonnull UUID uuid) {
return getUserManager().getUserOpt(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
*/
@Nullable
default User getUser(@Nonnull String name) {
return getUserManager().getUser(name);
}
/**
* Gets a wrapped user object from the user storage.
*
* @param name the username of the user to get
* @return an optional {@link User} object
* @throws NullPointerException if the name is null
*/
@Nonnull
default Optional<User> getUserSafe(@Nonnull String name) {
return getUserManager().getUserOpt(name);
}
/**
* Gets a set of all loaded users.
*
* @return a {@link Set} of {@link User} objects
*/
@Nonnull
default Set<User> getUsers() {
return getUserManager().getLoadedUsers();
}
/**
* 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
*/
default boolean isUserLoaded(@Nonnull UUID uuid) {
return getUserManager().isLoaded(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
*/
default void cleanupUser(@Nonnull User user) {
getUserManager().cleanupUser(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
*/
@Nullable
default Group getGroup(@Nonnull String name) {
return getGroupManager().getGroup(name);
}
/**
* Gets a wrapped group object from the group storage.
*
* <p>This method does not return null, unlike {@link #getGroup}</p>
*
* @param name the name of the group to get
* @return an optional {@link Group} object
* @throws NullPointerException if the name is null
*/
@Nonnull
default Optional<Group> getGroupSafe(@Nonnull String name) {
return getGroupManager().getGroupOpt(name);
}
/**
* Gets a set of all loaded groups.
*
* @return a {@link Set} of {@link Group} objects
*/
@Nonnull
default Set<Group> getGroups() {
return getGroupManager().getLoadedGroups();
}
/**
* 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
*/
default boolean isGroupLoaded(@Nonnull String name) {
return getGroupManager().isLoaded(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
*/
@Nullable
default Track getTrack(@Nonnull String name) {
return getTrackManager().getTrack(name);
}
/**
* Gets a wrapped track object from the track storage.
*
* <p>This method does not return null, unlike {@link #getTrack}</p>
*
* @param name the name of the track to get
* @return an optional {@link Track} object
* @throws NullPointerException if the name is null
*/
@Nonnull
default Optional<Track> getTrackSafe(@Nonnull String name) {
return getTrackManager().getTrackOpt(name);
}
/**
* Gets a set of all loaded tracks.
*
* @return a {@link Set} of {@link Track} objects
*/
@Nonnull
default Set<Track> getTracks() {
return getTrackManager().getLoadedTracks();
}
/**
* 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
*/
default boolean isTrackLoaded(@Nonnull String name) {
return getTrackManager().isLoaded(name);
}
/**
* Returns a new LogEntry Builder instance
*
* @return a new builder
* @since 4.0
*/
@Nonnull
default LogEntry.Builder newLogEntryBuilder() {
return getActionLogger().newEntryBuilder();
}
/**
* 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
*/
@Nonnull
default Node.Builder buildNode(@Nonnull String permission) throws IllegalArgumentException {
return getNodeFactory().newBuilder(permission);
}
/**
* Register a custom context calculator to the server
*
* @param calculator 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.
*/
default void registerContextCalculator(@Nonnull ContextCalculator<?> calculator) {
getContextManager().registerCalculator(calculator);
}
/**
* Gets a calculated context instance for the user using the rules of the platform.
*
* <p> These values are calculated using the options in the configuration, and the provided calculators.
*
* @param user the user to get contexts for
* @return an optional containing contexts. Will return empty if the user is not online.
*/
@Nonnull
default Optional<Contexts> getContextForUser(@Nonnull User user) {
return getContextManager().lookupApplicableContexts(user);
}
/**
* Gets set of contexts applicable to a player using the platforms {@link ContextCalculator}s.
*
* @param player the player to calculate for. Must be the player instance for the platform.
* @return a set of contexts.
* @since 2.17
*/
@Nonnull
default ContextSet getContextForPlayer(@Nonnull Object player) {
return getContextManager().getApplicableContext(player);
}
/**
* Gets a Contexts instance for the player using the platforms {@link ContextCalculator}s.
*
* @param player the player to calculate for. Must be the player instance for the platform.
* @return a set of contexts.
* @since 3.3
*/
@Nonnull
default Contexts getContextsForPlayer(@Nonnull Object player) {
return getContextManager().getApplicableContexts(player);
}
}
@@ -1,715 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api;
import com.google.common.base.Preconditions;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.nodetype.NodeType;
import me.lucko.luckperms.api.nodetype.NodeTypeKey;
import me.lucko.luckperms.api.nodetype.types.DisplayNameType;
import me.lucko.luckperms.api.nodetype.types.InheritanceType;
import me.lucko.luckperms.api.nodetype.types.MetaType;
import me.lucko.luckperms.api.nodetype.types.PrefixType;
import me.lucko.luckperms.api.nodetype.types.SuffixType;
import me.lucko.luckperms.api.nodetype.types.WeightType;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* Represents a LuckPerms "node".
*
* <p>The {@link Node} class encapsulates more than just permission assignments.
* Nodes are used to store data about inherited groups, as well as assigned
* prefixes, suffixes and meta values.</p>
*
* <p>Combining these various states into one object (a "node") means that a
* holder only has to have one type of data set (a set of nodes) in order to
* take on various properties.</p>
*
* <p>It is recommended that users of the API make use of {@link Stream}s
* to manipulate data and obtain the required information.</p>
*
* <p>This interface provides a number of methods to read the attributes of the
* node, as well as methods to query and extract additional state and properties
* from these settings.</p>
*
* <p>Nodes have the following attributes:</p>
* <p></p>
* <ul>
* <li>{@link #getPermission() permission} - the actual permission string</li>
* <li>{@link #getValue() value} - the value of the node (false for negated)</li>
* <li>{@link #isOverride() override} - if the node is marked as having special priority over other nodes</li>
* <li>{@link #getServer() server} - the specific server where this node should apply</li>
* <li>{@link #getWorld() world} - the specific world where this node should apply</li>
* <li>{@link #getContexts() context} - the additional contexts required for this node to apply </li>
* <li>{@link #getExpiry() expiry} - the time when this node should expire</li>
* </ul>
*
* <p>The 'permission' property of a {@link Node} is also used in some cases to represent state
* beyond a granted permission. This state is encapsulated by extra {@link NodeType} data which
* can be obtained from this instance using {@link #getTypeData(NodeTypeKey)}.</p>
*
* <p>Type data is mapped by {@link NodeTypeKey}s, which are usually stored as static members of the
* corresponding {@link NodeType} class under the <code>KEY</code> field.</p>
*
* <p>The current types are:</p>
* <p></p>
* <ul>
* <li>normal - just a regular permission</li>
* <li>{@link InheritanceType} - an "inheritance node" marks that the holder should inherit data from another group</li>
* <li>{@link PrefixType} - represents an assigned prefix</li>
* <li>{@link SuffixType} - represents an assigned suffix</li>
* <li>{@link MetaType} - represents an assigned meta option</li>
* <li>{@link WeightType} - marks the weight of the object holding this node</li>
* <li>{@link DisplayNameType} - marks the display name of the object holding this node</li>
* </ul>
*
* <p>The core node state must be immutable in all implementations.</p>
*
* @see NodeFactory for obtaining and constructing instances.
* @since 2.6
*/
@Immutable
public interface Node {
/**
* Gets the permission string this node encapsulates.
*
* <p>The exact value of this string may vary for nodes which aren't regular
* permission settings.</p>
*
* @return the actual permission node
*/
@Nonnull
String getPermission();
/**
* Gets the value of the node.
*
* <p>A negated setting would result in a value of <code>false</code>.</p>
*
* @return the nodes value
*/
boolean getValue();
/**
* Gets the value of this node as a {@link Tristate}.
*
* @return the value of this node as a Tristate
*/
@Nonnull
default Tristate getTristate() {
return Tristate.fromBoolean(getValue());
}
/**
* Gets if the node is negated.
*
* <p>This is the inverse of the {@link #getValue() value}.</p>
*
* @return true if the node is negated
*/
default boolean isNegated() {
return !getValue();
}
/**
* Gets if this node is set to override explicitly.
*
* <p>This value does not persist across saves, and is therefore only
* useful for transient nodes.</p>
*
* @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
*/
@Nonnull
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
*/
@Nonnull
Optional<String> getWorld();
/**
* Gets if this node is server specific.
*
* @return true if this node is server specific
*/
boolean isServerSpecific();
/**
* Gets if this node is server specific.
*
* @return true if this node is server specific
*/
boolean isWorldSpecific();
/**
* Gets if this node applies globally, and therefore has no specific context.
*
* @return true if this node applies globally, and has no specific context
* @since 3.1
*/
boolean appliesGlobally();
/**
* Gets if this node has any specific context in order for it to apply.
*
* @return true if this node has specific context
* @since 3.1
*/
boolean hasSpecificContext();
/**
* Gets if this node should apply in the given context
*
* @param contextSet the context set
* @return true if the node should apply
* @since 2.13
*/
boolean shouldApplyWithContext(@Nonnull ContextSet contextSet);
/**
* Resolves any shorthand parts of this node and returns the full list of
* resolved nodes.
*
* <p>The list will not contain the exact permission itself.</p>
*
* @return a list of full nodes
*/
@Nonnull
List<String> resolveShorthand();
/**
* Gets if this node is assigned temporarily.
*
* @return true if this node will expire in the future
*/
boolean isTemporary();
/**
* Gets if this node is permanent (will not expire).
*
* @return true if this node will not expire
*/
default boolean isPermanent() {
return !isTemporary();
}
/**
* Gets the unix timestamp (in seconds) when this node will expire.
*
* @return the time in Unix time when this node will expire
* @throws IllegalStateException if the node is not temporary
*/
long getExpiryUnixTime() throws IllegalStateException;
/**
* Gets the date when this node will expire.
*
* @return the {@link Date} when this node will expire
* @throws IllegalStateException if the node is not temporary
*/
@Nonnull
Date getExpiry() throws IllegalStateException;
/**
* Gets the number of seconds until this permission will expire.
*
* <p>Will return a negative value if the node has already expired.</p>
*
* @return the number of seconds until this permission will expire
* @throws IllegalStateException if the node is not temporary
*/
long getSecondsTilExpiry() throws IllegalStateException;
/**
* Gets if the node has expired.
*
* <p>This returns false if the node is not temporary.</p>
*
* @return true if this node has expired
*/
boolean hasExpired();
/**
* Gets the extra contexts required for this node to apply.
*
* @return the extra contexts required for this node to apply
* @since 2.13
*/
@Nonnull
ContextSet getContexts();
/**
* The same as {@link #getContexts()}, but also includes context pairs for
* "server" and "world" keys if present.
*
* @return the full contexts required for this node to apply
* @since 3.1
* @see Contexts#SERVER_KEY
* @see Contexts#WORLD_KEY
*/
@Nonnull
ContextSet getFullContexts();
/**
* Gets if this node is a wildcard permission.
*
* @return true if this node is a wildcard permission
*/
boolean isWildcard();
/**
* Gets the level of this wildcard.
*
* <p>The node <code>luckperms.*</code> has a wildcard level of 1.</p>
* <p>The node <code>luckperms.user.permission.*</code> has a wildcard level of 3.</p>
*
* <p>Nodes with a higher wildcard level are more specific and have priority over
* less specific nodes (nodes with a lower wildcard level).</p>
*
* @return the wildcard level
* @throws IllegalStateException if this is not a wildcard
*/
int getWildcardLevel() throws IllegalStateException;
/**
* Gets if this node has any extra {@link NodeType} data attached to it.
*
* @return if this node has any type data
* @since 4.2
*/
boolean hasTypeData();
/**
* Gets the type data corresponding to the given <code>key</code>, if present.
*
* @param key the key
* @param <T> the {@link NodeType} type
* @return the data, if present
* @since 4.2
*/
<T extends NodeType> Optional<T> getTypeData(NodeTypeKey<T> key);
/**
* Gets the type data corresponding to the given <code>key</code>, throwing an exception
* if no data is present.
*
* @param key the key
* @param <T> the {@link NodeType} type
* @return the data
* @throws IllegalStateException if data isn't present
* @since 4.2
*/
default <T extends NodeType> T typeData(NodeTypeKey<T> key) throws IllegalStateException {
return getTypeData(key)
.orElseThrow(() ->
new IllegalStateException("Node '" + getPermission() + "' does not have the '" + key.getTypeName() + "' type.")
);
}
/**
* Gets if this node has {@link InheritanceType} type data.
*
* @return true if this is a inheritance (group) node.
*/
default boolean isGroupNode() {
return getTypeData(InheritanceType.KEY).isPresent();
}
/**
* Gets the name of the inherited group if this node has {@link InheritanceType} type data,
* throwing an exception if the data is not present.
*
* @return the name of the group
* @throws IllegalStateException if this node doesn't have {@link InheritanceType} data
*/
@Nonnull
default String getGroupName() throws IllegalStateException {
return typeData(InheritanceType.KEY).getGroupName();
}
/**
* Gets if this node has {@link MetaType} type data.
*
* @return true if this is a meta node.
*/
default boolean isMeta() {
return getTypeData(MetaType.KEY).isPresent();
}
/**
* Gets the meta entry if this node has {@link MetaType} type data,
* throwing an exception if the data is not present.
*
* @return the meta entry
* @throws IllegalStateException if this node doesn't have {@link MetaType} data
*/
@Nonnull
default Map.Entry<String, String> getMeta() throws IllegalStateException {
return typeData(MetaType.KEY);
}
/**
* Gets if this node has {@link PrefixType} type data.
*
* @return true if this node is a prefix node
*/
default boolean isPrefix() {
return getTypeData(PrefixType.KEY).isPresent();
}
/**
* Gets the prefix entry if this node has {@link PrefixType} type data,
* throwing an exception if the data is not present.
*
* @return the meta entry
* @throws IllegalStateException if this node doesn't have {@link PrefixType} data
*/
@Nonnull
default Map.Entry<Integer, String> getPrefix() throws IllegalStateException {
return typeData(PrefixType.KEY).getAsEntry();
}
/**
* Gets if this node has {@link SuffixType} type data.
*
* @return true if this node is a suffix node
*/
default boolean isSuffix() {
return getTypeData(SuffixType.KEY).isPresent();
}
/**
* Gets the suffix entry if this node has {@link SuffixType} type data,
* throwing an exception if the data is not present.
*
* @return the meta entry
* @throws IllegalStateException if this node doesn't have {@link SuffixType} data
*/
@Nonnull
default Map.Entry<Integer, String> getSuffix() throws IllegalStateException {
return typeData(SuffixType.KEY).getAsEntry();
}
/**
* Gets 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 StandardNodeEquality#EXACT
*/
@Override
boolean equals(Object obj);
/**
* Gets if this Node is equal to another node as defined by the given
* {@link StandardNodeEquality} predicate.
*
* @param other the other node
* @param equalityPredicate the predicate
* @return true if this node is considered equal
* @since 4.1
*/
boolean standardEquals(Node other, StandardNodeEquality equalityPredicate);
/**
* Gets if this Node is equal to another node as defined by the given
* {@link NodeEqualityPredicate}.
*
* @param other the other node
* @param equalityPredicate the predicate
* @return true if this node is considered equal
* @since 4.1
*/
default boolean equals(Node other, NodeEqualityPredicate equalityPredicate) {
return equalityPredicate.areEqual(this, other);
}
/**
* 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
* @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)}
* @see StandardNodeEquality#IGNORE_VALUE
*/
@Deprecated
default boolean equalsIgnoringValue(@Nonnull Node other) {
return equals(other, StandardNodeEquality.IGNORE_VALUE);
}
/**
* 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
* @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)}
* @see StandardNodeEquality#IGNORE_EXPIRY_TIME_AND_VALUE
*/
@Deprecated
default boolean almostEquals(@Nonnull Node other) {
return equals(other, StandardNodeEquality.IGNORE_EXPIRY_TIME_AND_VALUE);
}
/**
* 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
* @deprecated in favour of {@link #equals(Node, NodeEqualityPredicate)}
* @see StandardNodeEquality#IGNORE_VALUE_OR_IF_TEMPORARY
*/
@Deprecated
default boolean equalsIgnoringValueOrTemp(@Nonnull Node other) {
return equals(other, StandardNodeEquality.IGNORE_VALUE_OR_IF_TEMPORARY);
}
/**
* Constructs a new builder initially containing the current properties of
* this node.
*
* @return a new builder
* @since 4.1
*/
Builder toBuilder();
/**
* Builds a Node instance
*/
interface Builder {
/**
* Copies the attributes from the given node and applies them to this
* builder.
*
* <p>Note that this copies all attributes <strong>except</strong> the
* permission itself.</p>
*
* @param node the node to copy from
* @return the builder
* @since 4.2
*/
Builder copyFrom(@Nonnull Node node);
/**
* Sets the value of negated for the node.
*
* @param negated the value
* @return the builder
* @see Node#isNegated()
*/
@Nonnull
Builder setNegated(boolean negated);
/**
* Sets the value of the node.
*
* @param value the value
* @return the builder
* @see Node#getValue()
*/
@Nonnull
Builder setValue(boolean value);
/**
* Sets the override property for the node.
*
* <p>Warning: this value does not persist, and disappears when the holder is re-loaded.
* It is therefore only useful for transient nodes.</p>
*
* @param override the override state
* @return the builder
* @see Node#isOverride()
*/
@Nonnull
Builder setOverride(boolean override);
/**
* Sets the time when the node should expire.
*
* <p>The parameter passed to this method must be the unix timestamp
* (in seconds) when the node should expire.</p>
*
* @param expiryUnixTimestamp the expiry timestamp (unix seconds)
* @return the builder
* @see Node#getExpiryUnixTime()
*/
@Nonnull
Builder setExpiry(long expiryUnixTimestamp);
/**
* Sets the time when the node should expire.
*
* <p>The expiry timestamp is calculated relative to the current
* system time.</p>
*
* @param duration how long the node should be added for
* @param unit the unit <code>duration</code> is measured in
* @return the builder
* @since 4.2
*/
@Nonnull
default Builder setExpiry(long duration, TimeUnit unit) {
Preconditions.checkArgument(duration > 0, "duration must be positive");
long seconds = Objects.requireNonNull(unit, "unit").toSeconds(duration);
long timeNow = System.currentTimeMillis() / 1000L;
return setExpiry(timeNow + seconds);
}
/**
* Marks that the node being built should never expire.
*
* @return the builder
* @since 4.2
*/
@Nonnull
Builder clearExpiry();
/**
* Sets the world value for the node.
*
* @param world the world value
* @return the builder
* @see Node#getWorld()
*/
@Nonnull
Builder setWorld(@Nullable String world);
/**
* Sets the server value for the node.
*
* @param server the world value
* @return the builder
* @see Node#getServer()
*/
@Nonnull
Builder setServer(@Nullable String server);
/**
* Appends an extra context onto the node.
*
* @param key the context key
* @param value the context value
* @return the builder
* @see ContextSet
* @see Node#getContexts()
*/
@Nonnull
Builder withExtraContext(@Nonnull String key, @Nonnull String value);
/**
* Appends extra contexts onto the node.
*
* @param map a map of contexts
* @return the builder
* @see ContextSet
* @see Node#getContexts()
*/
@Nonnull
Builder withExtraContext(@Nonnull Map<String, String> map);
/**
* Appends extra contexts onto the node.
*
* @param context a set of contexts
* @return the builder
* @see ContextSet
* @see Node#getContexts()
*/
@Nonnull
Builder withExtraContext(@Nonnull Set<Map.Entry<String, String>> context);
/**
* Appends an extra context onto the node.
*
* @param entry the context
* @return the builder
* @see ContextSet
* @see Node#getContexts()
*/
@Nonnull
Builder withExtraContext(@Nonnull Map.Entry<String, String> entry);
/**
* Appends extra contexts onto the node.
*
* @param contextSet a context set
* @return the builder
* @see ContextSet
* @see Node#getContexts()
*/
@Nonnull
Builder withExtraContext(@Nonnull ContextSet contextSet);
/**
* Sets the extra contexts for the node.
*
* @param contextSet a context set
* @return the builder
* @see ContextSet
* @see Node#getContexts()
* @since 4.2
*/
@Nonnull
Builder setExtraContext(@Nonnull ContextSet contextSet);
/**
* Creates a {@link Node} instance from the builder.
*
* @return a new node instance
*/
@Nonnull
Node build();
}
}
@@ -1,53 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 javax.annotation.Nonnull;
/**
* A rule for determining if two nodes are equal.
*
* <p>Generally, individual instances of this interface should fulfil the same
* requirements as the {@link Object#equals(Object)} contract.</p>
*
* <p>Some standard implementations are provided by
* {@link StandardNodeEquality}.</p>
*
* @since 4.1
*/
@FunctionalInterface
public interface NodeEqualityPredicate {
/**
* Returns if the two nodes are equal
*
* @param o1 the first node
* @param o2 the second node
* @return true if equal
*/
boolean areEqual(@Nonnull Node o1, @Nonnull Node o2);
}
@@ -1,127 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 javax.annotation.Nonnull;
/**
* Assists with constructing {@link Node} instances.
*
* @since 2.17
*/
public interface NodeFactory {
/**
* Creates a new node builder from a given base permission string
*
* @param permission the permission
* @return a node builder instance
* @throws NullPointerException if the permission is null
*/
@Nonnull
Node.Builder newBuilder(@Nonnull String permission);
/**
* Creates a node builder instance from an existing node
*
* @param other the other node
* @return a node builder instance
* @throws NullPointerException if the other node is null
*/
@Nonnull
Node.Builder newBuilderFromExisting(@Nonnull Node other);
/**
* Creates a node builder from a group
*
* @param group the group
* @return a node builder instance
* @throws NullPointerException if the group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
* @since 3.1
*/
@Nonnull
Node.Builder makeGroupNode(@Nonnull Group group);
/**
* Creates a node builder from a group
*
* @param groupName the name of the group
* @return a node builder instance
* @throws NullPointerException if the groupName is null
* @since 4.0
*/
@Nonnull
Node.Builder makeGroupNode(@Nonnull String groupName);
/**
* Creates a node builder from a key value pair
*
* @param key the key
* @param value the value
* @return a node builder instance
* @throws NullPointerException if the key or value is null
*/
@Nonnull
Node.Builder makeMetaNode(@Nonnull String key, @Nonnull String value);
/**
* Creates a node builder for the given chat meta type
*
* @param type the type
* @param priority the priority
* @param value the value for the prefix/suffix
* @return a node builder instance
* @throws NullPointerException if the type or value is null
* @since 3.2
*/
@Nonnull
Node.Builder makeChatMetaNode(@Nonnull ChatMetaType type, int priority, @Nonnull String value);
/**
* Creates a node builder from a prefix string and priority
*
* @param priority the priority
* @param prefix the prefix string
* @return a node builder instance
* @throws NullPointerException if the prefix is null
*/
@Nonnull
Node.Builder makePrefixNode(int priority, @Nonnull String prefix);
/**
* Creates a node builder from a prefix string and priority
*
* @param priority the priority
* @param suffix the suffix string
* @return a node builder instance
* @throws NullPointerException if the suffix is null
*/
@Nonnull
Node.Builder makeSuffixNode(int priority, @Nonnull String suffix);
}
@@ -1,548 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
import me.lucko.luckperms.api.caching.CachedData;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
/**
* An object which holds permissions.
*
* <p>Any changes made to permission holding objects will be lost unless the
* instance is saved back to the {@link Storage}.</p>
*/
public interface PermissionHolder {
/**
* Gets the objects name.
*
* <p>{@link User#getUuid()}, {@link User#getName()} or {@link Group#getName()} should normally be used instead of
* this method.</p>
*
* @return the identifier for this object. Either a uuid string or name.
*/
@Nonnull
String getObjectName();
/**
* Gets a friendly name for this holder, to be displayed in command output, etc.
*
* <p>This will <strong>always</strong> return a value, eventually falling back to {@link #getObjectName()} if no
* other "friendlier" identifiers are present.</p>
*
* @return a friendly identifier for this holder
* @since 3.2
*/
@Nonnull
String getFriendlyName();
/**
* Gets the holders {@link CachedData} cache.
*
* @return the holders cached data.
* @since 3.2
*/
@Nonnull
CachedData getCachedData();
/**
* Refreshes and applies any changes to the cached holder data.
*
* <p>Calling this method is unnecessary in most cases. Cache updates are handled
* behind the scenes by the implementation.</p>
*
* @return the task future
* @since 4.0
*/
@Nonnull
CompletableFuture<Void> refreshCachedData();
/**
* Gets the backing multimap containing every permission this holder has.
*
* <p>This method <b>does not</b> resolve inheritance rules, and returns a
* view of what's 'in the file'.</p>
*
* @return the holders own permissions
* @since 3.3
*/
@Nonnull
ImmutableSetMultimap<ImmutableContextSet, Node> getNodes();
/**
* Gets the backing multimap containing every transient permission this holder has.
*
* <p>This method <b>does not</b> resolve inheritance rules.</p>
*
* <p>Transient permissions only exist for the duration of the session.</p>
*
* @return the holders own permissions
* @since 3.3
*/
@Nonnull
ImmutableSetMultimap<ImmutableContextSet, Node> getTransientNodes();
/**
* Gets a flattened/squashed view of the holders permissions.
*
* <p>This list is constructed using the {@link Multimap#values()} method
* of both the transient and enduring backing multimaps.</p>
*
* <p>This means that it <b>may contain</b> duplicate entries.</p>
*
* <p>Use {@link #getPermissions()} for a view without duplicates.</p>
*
* @return a list of the holders own nodes.
* @since 3.3
*/
@Nonnull
List<Node> getOwnNodes();
/**
* Gets a sorted set of all held permissions.
*
* @return an immutable set of permissions in priority order
* @since 2.6
*/
@Nonnull
SortedSet<? extends Node> getPermissions();
/**
* Similar to {@link #getPermissions()}, except without transient permissions.
*
* <p>Unlike transient permissions, enduring permissions will be saved to storage, and exist after the session.</p>
*
* @return a set of nodes
* @since 2.6
*/
@Nonnull
Set<? extends Node> getEnduringPermissions();
/**
* Similar to {@link #getPermissions()}, except without enduring permissions.
*
* <p>Transient permissions only exist for the duration of the session.</p>
*
* @return a set of nodes
* @since 2.6
*/
@Nonnull
Set<? extends Node> getTransientPermissions();
/**
* Processes the nodes and returns the non-temporary ones.
*
* @return a set of permanent nodes
* @since 2.6
*/
@Nonnull
Set<Node> getPermanentPermissionNodes();
/**
* Processes the nodes and returns the temporary ones.
*
* @return a set of temporary nodes
* @since 2.6
*/
@Nonnull
Set<Node> getTemporaryPermissionNodes();
/**
* Recursively resolves this holders permissions.
*
* <p>The returned list will contain every inherited
* node the holder has, in the order that they were inherited in.</p>
*
* <p>This means the list will contain duplicates.</p>
*
* @param contexts the contexts for the lookup
* @return a list of nodes
* @since 3.3
*/
@Nonnull
List<LocalizedNode> resolveInheritances(Contexts contexts);
/**
* Recursively resolves this holders permissions.
*
* <p>The returned list will contain every inherited
* node the holder has, in the order that they were inherited in.</p>
*
* <p>This means the list will contain duplicates.</p>
*
* <p>Unlike {@link #resolveInheritances(Contexts)}, this method does not
* filter by context, at all.</p>
*
* @return a list of nodes
* @since 3.3
*/
@Nonnull
List<LocalizedNode> resolveInheritances();
/**
* Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context
*
* <p>Unlike {@link #getAllNodesFiltered(Contexts)}, this method will not filter individual nodes. The context is only
* used to determine which groups should apply.</p>
*
* <p>Nodes are sorted into priority order.</p>
*
* @param contexts the context for the lookup
* @return a mutable sorted set of permissions
* @throws NullPointerException if the context is null
* @since 2.11
*/
@Nonnull
SortedSet<LocalizedNode> getAllNodes(@Nonnull Contexts contexts);
/**
* Gets a mutable sorted set of the nodes that this object has and inherits.
*
* <p>Unlike {@link #getAllNodes(Contexts)}, this method does not filter by context, at all.</p>
*
* <p>Nodes are sorted into priority order.</p>
*
* @return a mutable sorted set of permissions
* @throws NullPointerException if the context is null
* @since 3.3
*/
@Nonnull
SortedSet<LocalizedNode> getAllNodes();
/**
* Gets a mutable set of the nodes that this object has and inherits, filtered by context.
*
* <p>Unlike {@link #getAllNodes(Contexts)}, this method WILL filter individual nodes, and only return ones that fully
* meet the context provided.</p>
*
* @param contexts the context for the lookup
* @return a mutable set of permissions
* @throws NullPointerException if the context is null
* @since 2.11
*/
@Nonnull
Set<LocalizedNode> getAllNodesFiltered(@Nonnull Contexts contexts);
/**
* Converts the output of {@link #getAllNodesFiltered(Contexts)}, and expands shorthand permissions.
*
* @param contexts the context for the lookup
* @param lowerCase if the keys should be made lowercase whilst being exported
* @return a mutable map of permissions
*/
@Nonnull
Map<String, Boolean> exportNodes(@Nonnull Contexts contexts, boolean lowerCase);
/**
* Removes temporary permissions that have expired
*/
void auditTemporaryPermissions();
/**
* Checks to see if the object has a certain permission
*
* @param node the node to check for
* @param equalityPredicate how to determine if a node matches
* @return a Tristate for the holders permission status for the node
* @throws NullPointerException if the node is null
* @since 4.1
*/
@Nonnull
Tristate hasPermission(@Nonnull Node node, @Nonnull NodeEqualityPredicate equalityPredicate);
/**
* Checks to see if the object has a certain permission
*
* @param node the node to check for
* @param equalityPredicate how to determine if a node matches
* @return a Tristate for the holders permission status for the node
* @throws NullPointerException if the node is null
* @since 4.1
*/
@Nonnull
Tristate hasTransientPermission(@Nonnull Node node, @Nonnull NodeEqualityPredicate equalityPredicate);
/**
* Checks to see if the object inherits a certain permission
*
* @param node the node to check for
* @param equalityPredicate how to determine if a node matches
* @return a Tristate for the holders inheritance status for the node
* @throws NullPointerException if the node is null
* @since 4.1
*/
@Nonnull
Tristate inheritsPermission(@Nonnull Node node, @Nonnull NodeEqualityPredicate equalityPredicate);
/**
* 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
*/
@Nonnull
Tristate hasPermission(@Nonnull 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
*/
@Nonnull
Tristate hasTransientPermission(@Nonnull Node node);
/**
* Checks 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
*/
@Nonnull
Tristate inheritsPermission(@Nonnull Node node);
/**
* Check to see if this holder inherits another group directly
*
* @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.
* @since 4.0
*/
boolean inheritsGroup(@Nonnull Group group);
/**
* Check to see if this holder inherits another group directly
*
* @param group The group to check membership of
* @param contextSet the context set to filter by
* @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.
* @since 4.0
*/
boolean inheritsGroup(@Nonnull Group group, @Nonnull ContextSet contextSet);
/**
* Sets a permission for the object
*
* @param node The node to be set
* @return the result of the operation
* @throws NullPointerException if the node is null
* @since 4.0
*/
@Nonnull
DataMutateResult setPermission(@Nonnull Node node);
/**
* 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>
*
* <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>
*
* <p>For unsetting a transient permission, see {@link #unsetTransientPermission(Node)}</p>
*
* @param node The node to be set
* @return the result of the operation
* @throws NullPointerException if the node is null
* @since 4.0
*/
@Nonnull
DataMutateResult setTransientPermission(@Nonnull Node node);
/**
* Unsets a permission for the object
*
* @param node The node to be unset
* @return the result of the operation
* @throws NullPointerException if the node is null
* @since 4.0
*/
@Nonnull
DataMutateResult unsetPermission(@Nonnull Node node);
/**
* Unsets a transient permission for the object
*
* @param node The node to be unset
* @return the result of the operation
* @throws NullPointerException if the node is null
* @since 4.0
*/
@Nonnull
DataMutateResult unsetTransientPermission(@Nonnull Node node);
/**
* Clears any nodes from the holder which pass the predicate
*
* @param test the predicate to test for nodes which should be removed
* @since 3.2
*/
void clearMatching(@Nonnull Predicate<Node> test);
/**
* Clears any transient nodes from the holder which pass the predicate
*
* @param test the predicate to test for nodes which should be removed
* @since 3.2
*/
void clearMatchingTransient(@Nonnull Predicate<Node> test);
/**
* Clears all nodes held by the object
*
* @since 2.17
*/
void clearNodes();
/**
* Clears all nodes held by the object in a specific context
*
* @param contextSet the contexts to filter by
* @since 3.2
*/
void clearNodes(@Nonnull ContextSet contextSet);
/**
* Clears all parent groups
*
* @since 2.17
*/
void clearParents();
/**
* Clears all parent groups in a specific context
*
* @param contextSet the contexts to filter by
* @since 3.2
*/
void clearParents(@Nonnull ContextSet contextSet);
/**
* Clears all meta held by the object
*
* @since 2.17
*/
void clearMeta();
/**
* Clears all meta held by the object in a specific context
*
* @param contextSet the contexts to filter by
* @since 3.2
*/
void clearMeta(@Nonnull ContextSet contextSet);
/**
* Clears all transient permissions the holder has.
*/
void clearTransientNodes();
/**
* Sets a permission for the object
*
* @param node The node to be set
* @return the result of the operation
* @throws NullPointerException if the node is null
* @since 3.1
* @deprecated now forwards to {@link #setPermission(Node)}.
*/
@Nonnull
@Deprecated
default DataMutateResult setPermissionUnchecked(@Nonnull Node node) {
return setPermission(node);
}
/**
* Sets a transient permission for the object
*
* @param node The node to be set
* @return the result of the operation
* @throws NullPointerException if the node is null
* @since 3.1
* @deprecated now forwards to {@link #setTransientPermission(Node)}
*/
@Nonnull
@Deprecated
default DataMutateResult setTransientPermissionUnchecked(@Nonnull Node node) {
return setTransientPermission(node);
}
/**
* Unsets a permission for the object
*
* @param node The node to be unset
* @throws NullPointerException if the node is null
* @return the result of the operation
* @since 3.1
* @deprecated now forwards to {@link #unsetPermission(Node)}
*/
@Nonnull
@Deprecated
default DataMutateResult unsetPermissionUnchecked(@Nonnull Node node) {
return unsetPermission(node);
}
/**
* Unsets a transient permission for the object
*
* @param node The node to be unset
* @throws NullPointerException if the node is null
* @return the result of the operation
* @since 3.1
* @deprecated now forwards to {@link #unsetTransientPermission(Node)}
*/
@Nonnull
@Deprecated
default DataMutateResult unsetTransientPermissionUnchecked(@Nonnull Node node) {
return unsetTransientPermission(node);
}
}
@@ -1,78 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 javax.annotation.Nonnull;
/**
* Standard {@link NodeEqualityPredicate}s.
*
* @since 4.1
*/
public enum StandardNodeEquality implements NodeEqualityPredicate {
/**
* Represents an exact match.
*
* <p>All attributes of the nodes must match for them to be considered
* equal.</p>
*/
EXACT,
/**
* All attributes must match, except for
* {@link Node#getValue() value}, which is ignored.
*/
IGNORE_VALUE,
/**
* All attributes must match, except for the
* {@link Node#getExpiry() expiry time}, which is ignored.
*
* <p>Note that with this setting, whether a node is temporary or not is
* still considered.</p>
*/
IGNORE_EXPIRY_TIME,
/**
* All attributes must match, except for
* {@link Node#getValue() value} and the
* {@link Node#getExpiry() expiry time}, which are ignored.
*/
IGNORE_EXPIRY_TIME_AND_VALUE,
/**
* All attributes must match, except for
* {@link Node#getValue() value} and the if the node is
* {@link Node#isTemporary() temporary}, which are ignored.
*/
IGNORE_VALUE_OR_IF_TEMPORARY;
@Override
public boolean areEqual(@Nonnull Node o1, @Nonnull Node o2) {
return o1.standardEquals(o2, this);
}
}
@@ -1,359 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.manager.GroupManager;
import me.lucko.luckperms.api.manager.TrackManager;
import me.lucko.luckperms.api.manager.UserManager;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* A means of loading and saving permission data to/from the backend.
*
* @since 2.14
*/
public interface Storage {
/**
* Get the name of the storage implementation.
*
* @return the name of the implementation
*/
@Nonnull
String getName();
/**
* Gets whether the storage instance is allowing logins on the platform.
*
* @return true if logins are enabled
* @deprecated as this method always returns true.
*/
@Deprecated
boolean isAcceptingLogins();
/**
* Saves an action to storage
*
* @param entry the log entry to be saved
* @return true if the operation completed successfully.
* @throws NullPointerException if entry is null
* @deprecated in favour of {@link ActionLogger#submit(LogEntry)}.
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> logAction(@Nonnull LogEntry entry);
/**
* Loads and returns the entire log from storage
*
* @return a log instance, could be null if loading failed
* @deprecated in favour of {@link ActionLogger#getLog()}
*/
@Nonnull
@Deprecated
CompletableFuture<Log> getLog();
/**
* Loads a user's data from the main storage into the plugins local storage.
*
* @param uuid the uuid of the user to load
* @param username the users username, or null if it is not known.
* @return if the operation completed successfully
* @throws NullPointerException if uuid is null
* @deprecated in favour of {@link UserManager#loadUser(UUID, String)}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> loadUser(@Nonnull UUID uuid, @Nullable String username);
/**
* Loads a user's data from the main storage into the plugins local storage.
*
* @param uuid the uuid of the user to load
* @return if the operation completed successfully
* @throws NullPointerException if uuid is null
* @deprecated in favour of {@link UserManager#loadUser(UUID)}
*/
@Nonnull
@Deprecated
default CompletableFuture<Boolean> loadUser(@Nonnull UUID uuid) {
return loadUser(uuid, null);
}
/**
* Saves a user object back to storage.
*
* <p>You should call this after you make any changes to a user.</p>
*
* @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.
* @deprecated in favour of {@link UserManager#saveUser(User)}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> saveUser(@Nonnull User user);
/**
* Gets a set all "unique" user UUIDs.
*
* <p>"Unique" meaning the user isn't just a member of the "default" group.</p>
*
* @return a set of uuids, or null if the operation failed.
* @deprecated in favour of {@link UserManager#getUniqueUsers()}
*/
@Nonnull
@Deprecated
CompletableFuture<Set<UUID>> getUniqueUsers();
/**
* Searches for a list of users with a given permission.
*
* @param permission the permission to search for
* @return a list of held permissions, or null if the operation failed
* @throws NullPointerException if the permission is null
* @since 2.17
* @deprecated in favour of {@link UserManager#getWithPermission(String)}
*/
@Nonnull
@Deprecated
CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(@Nonnull String permission);
/**
* Creates and loads a group into the plugins local storage
*
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
* @deprecated in favour of {@link GroupManager#createAndLoadGroup(String)}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> createAndLoadGroup(@Nonnull String name);
/**
* Loads a group into the plugins local storage.
*
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
* @deprecated in favour of {@link GroupManager#loadGroup(String)}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> loadGroup(@Nonnull String name);
/**
* Loads all groups from the storage into memory
*
* @return true if the operation completed successfully.
* @deprecated in favour of {@link GroupManager#loadAllGroups()}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> loadAllGroups();
/**
* Saves a group back to storage.
*
* <p>You should call this after you make any changes to a group.</p>
*
* @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.
* @deprecated in favour of {@link GroupManager#saveGroup(Group)}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> saveGroup(@Nonnull Group group);
/**
* Permanently deletes a group from storage.
*
* @param group the group to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
* @deprecated in favour of {@link GroupManager#deleteGroup(Group)}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> deleteGroup(@Nonnull Group group);
/**
* Searches for a list of groups with a given permission.
*
* @param permission the permission to search for
* @return a list of held permissions, or null if the operation failed
* @throws NullPointerException if the permission is null
* @since 2.17
* @deprecated in favour of {@link GroupManager#getWithPermission(String)}
*/
@Nonnull
@Deprecated
CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(@Nonnull String permission);
/**
* Creates and loads a track into the plugins local storage
*
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
* @deprecated in favour of {@link TrackManager#createAndLoadTrack(String)}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> createAndLoadTrack(@Nonnull String name);
/**
* Loads a track into the plugins local storage.
*
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
* @deprecated in favour of {@link TrackManager#loadTrack(String)}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> loadTrack(@Nonnull String name);
/**
* Loads all tracks from the storage into memory
*
* @return true if the operation completed successfully.
* @deprecated in favour of {@link TrackManager#loadAllTracks()}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> loadAllTracks();
/**
* Saves a track back to storage. You should call this after you make any changes to a track.
*
* @param track the track to save
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
* @deprecated in favour of {@link TrackManager#saveTrack(Track)}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> saveTrack(@Nonnull Track track);
/**
* Permanently deletes a track from storage
*
* @param track the track to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
* @deprecated in favour of {@link TrackManager#deleteTrack(Track)}
*/
@Nonnull
@Deprecated
CompletableFuture<Boolean> deleteTrack(@Nonnull Track track);
/**
* Saves UUID caching data to the global cache
*
* @param username the users username
* @param uuid the users mojang unique id
* @return true if the operation completed successfully.
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
* @deprecated in favour of {@link UserManager#savePlayerData(UUID, String)}
*/
@Nonnull
CompletableFuture<Boolean> saveUUIDData(@Nonnull String username, @Nonnull 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
* @deprecated in favour of {@link UserManager#lookupUuid(String)}
*/
@Nonnull
CompletableFuture<UUID> getUUID(@Nonnull String username);
/**
* Gets a username from a UUID
*
* @param uuid the corresponding uuid
* @return a name string, could be null
* @throws NullPointerException if either parameters are null
* @since 2.17
* @deprecated in favour of {@link UserManager#lookupUsername(UUID)}
*/
@Nonnull
@Deprecated
CompletableFuture<String> getName(@Nonnull UUID uuid);
/**
* Returns an executor which will run all passed runnables on the
* main server thread.
*
* <p>This method is deprecated as plugins should create and use their own
* executor instances.</p>
*
* @return an executor instance
* @deprecated as plugins should create their own executors
*/
@Nonnull
@Deprecated
Executor getSyncExecutor();
/**
* Returns an executor which will run all passed runnables asynchronously
* using the platforms scheduler and thread pools.
*
* <p>This method is deprecated as plugins should create and use their own
* executor instances.</p>
*
* @return an executor instance
* @deprecated as plugins should create their own executors
*/
@Nonnull
@Deprecated
Executor getAsyncExecutor();
}
@@ -1,425 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.caching;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.PermissionHolder;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
/**
* Holds cached permission and meta lookup data for a {@link PermissionHolder}.
*
* <p>All calls will account for inheritance, as well as any default data
* provided by the platform. This calls are heavily cached and are therefore
* fast.</p>
*
* <p>For meta, both methods accepting {@link Contexts} and {@link MetaContexts}
* are provided. The only difference is that the latter allows you to define
* how the meta stack should be structured internally. Where {@link Contexts}
* are passed, the values from the configuration are used.</p>
*
* @since 4.0
*/
public interface CachedData {
/**
* Gets PermissionData from the cache, given a specified context.
*
* @param contexts the contexts to get the permission data in
* @return a permission data instance
* @throws NullPointerException if contexts is null
*/
@Nonnull
PermissionData getPermissionData(@Nonnull Contexts contexts);
/**
* Gets MetaData from the cache, given a specified context.
*
* @param contexts the contexts to get the permission data in
* @return a meta data instance
* @throws NullPointerException if contexts is null
* @since 3.2
*/
@Nonnull
MetaData getMetaData(@Nonnull MetaContexts contexts);
/**
* Gets MetaData from the cache, given a specified context.
*
* @param contexts the contexts to get the permission data in
* @return a meta data instance
* @throws NullPointerException if contexts is null
*/
@Nonnull
MetaData getMetaData(@Nonnull Contexts contexts);
/**
* Calculates permission data, bypassing the cache.
*
* <p>The result of this operation is calculated each time the method is called.
* The result is not added to the internal cache.</p>
*
* <p>It is therefore highly recommended to use {@link #getPermissionData(Contexts)} instead.</p>
*
* <p>The use cases of this method are more around constructing one-time
* instances of {@link PermissionData}, without adding the result to the cache.</p>
*
* @param contexts the contexts to get permission data in
* @return a permission data instance
* @throws NullPointerException if contexts is null
*/
@Nonnull
PermissionData calculatePermissions(@Nonnull Contexts contexts);
/**
* Calculates meta data, bypassing the cache.
*
* <p>The result of this operation is calculated each time the method is called.
* The result is not added to the internal cache.</p>
*
* <p>It is therefore highly recommended to use {@link #getMetaData(MetaContexts)} instead.</p>
*
* <p>The use cases of this method are more around constructing one-time
* instances of {@link MetaData}, without adding the result to the cache.</p>
*
* @param contexts the contexts to get meta data in
* @return a meta data instance
* @throws NullPointerException if contexts is null
* @since 3.2
*/
@Nonnull
MetaData calculateMeta(@Nonnull MetaContexts contexts);
/**
* Calculates meta data, bypassing the cache.
*
* <p>The result of this operation is calculated each time the method is called.
* The result is not added to the internal cache.</p>
*
* <p>It is therefore highly recommended to use {@link #getMetaData(Contexts)} instead.</p>
*
* <p>The use cases of this method are more around constructing one-time
* instances of {@link MetaData}, without adding the result to the cache.</p>
*
* @param contexts the contexts to get meta data in
* @return a meta data instance
* @throws NullPointerException if contexts is null
*/
@Nonnull
MetaData calculateMeta(@Nonnull Contexts contexts);
/**
* (Re)calculates permission data for a given context.
*
* <p>This method returns immediately in all cases. The (re)calculation is
* performed asynchronously and applied to the cache in the background.</p>
*
* <p>If there was a previous {@link PermissionData} instance associated with
* the given {@link Contexts}, then that instance will continue to be returned by
* {@link #getPermissionData(Contexts)} until the recalculation is completed.</p>
*
* <p>If there was no value calculated and cached prior to the call of this
* method, then one will be calculated.</p>
*
* @param contexts the contexts to recalculate in.
* @throws NullPointerException if contexts is null
*/
void recalculatePermissions(@Nonnull Contexts contexts);
/**
* (Re)calculates meta data for a given context.
*
* <p>This method returns immediately in all cases. The (re)calculation is
* performed asynchronously and applied to the cache in the background.</p>
*
* <p>If there was a previous {@link MetaData} instance associated with
* the given {@link MetaContexts}, then that instance will continue to be returned by
* {@link #getMetaData(MetaContexts)} until the recalculation is completed.</p>
*
* <p>If there was no value calculated and cached prior to the call of this
* method, then one will be calculated.</p>
*
* @param contexts the contexts to recalculate in.
* @throws NullPointerException if contexts is null
* @since 3.2
*/
void recalculateMeta(@Nonnull MetaContexts contexts);
/**
* (Re)calculates meta data for a given context.
*
* <p>This method returns immediately in all cases. The (re)calculation is
* performed asynchronously and applied to the cache in the background.</p>
*
* <p>If there was a previous {@link MetaData} instance associated with
* the given {@link Contexts}, then that instance will continue to be returned by
* {@link #getMetaData(Contexts)} until the recalculation is completed.</p>
*
* <p>If there was no value calculated and cached prior to the call of this
* method, then one will be calculated.</p>
*
* @param contexts the contexts to recalculate in.
* @throws NullPointerException if contexts is null
*/
void recalculateMeta(@Nonnull Contexts contexts);
/**
* (Re)loads permission data for a given context.
*
* <p>Unlike {@link #recalculatePermissions(Contexts)}, this method immediately
* invalidates any previous {@link PermissionData} values contained within the cache,
* and then schedules a task to reload a new {@link PermissionData} instance to
* replace the one which was invalidated.</p>
*
* <p>The invalidation happens immediately during the execution of this method.
* The result of the re-computation encapsulated by the future.</p>
*
* <p>Subsequent calls to {@link #getPermissionData(Contexts)} will block until
* the result of this operation is complete.</p>
*
* <p>If there was no value calculated and cached prior to the call of this
* method, then one will be calculated.</p>
*
* <p>This method returns a Future so users can optionally choose to wait
* until the recalculation has been performed.</p>
*
* @param contexts the contexts to reload in.
* @throws NullPointerException if contexts is null
* @return a future
* @since 4.0
*/
@Nonnull
CompletableFuture<? extends PermissionData> reloadPermissions(@Nonnull Contexts contexts);
/**
* (Re)loads meta data for a given context.
*
* <p>Unlike {@link #recalculateMeta(MetaContexts)}, this method immediately
* invalidates any previous {@link MetaData} values contained within the cache,
* and then schedules a task to reload a new {@link MetaData} instance to
* replace the one which was invalidated.</p>
*
* <p>The invalidation happens immediately during the execution of this method.
* The result of the re-computation encapsulated by the future.</p>
*
* <p>Subsequent calls to {@link #getMetaData(MetaContexts)} will block until
* the result of this operation is complete.</p>
*
* <p>If there was no value calculated and cached prior to the call of this
* method, then one will be calculated.</p>
*
* <p>This method returns a Future so users can optionally choose to wait
* until the recalculation has been performed.</p>
*
* @param contexts the contexts to reload in.
* @throws NullPointerException if contexts is null
* @return a future
* @since 4.0
*/
@Nonnull
CompletableFuture<? extends MetaData> reloadMeta(@Nonnull MetaContexts contexts);
/**
* (Re)loads meta data for a given context.
*
* <p>Unlike {@link #recalculateMeta(Contexts)}, this method immediately
* invalidates any previous {@link MetaData} values contained within the cache,
* and then schedules a task to reload a new {@link MetaData} instance to
* replace the one which was invalidated.</p>
*
* <p>The invalidation happens immediately during the execution of this method.
* The result of the re-computation encapsulated by the future.</p>
*
* <p>Subsequent calls to {@link #getMetaData(Contexts)} will block until
* the result of this operation is complete.</p>
*
* <p>If there was no value calculated and cached prior to the call of this
* method, then one will be calculated.</p>
*
* <p>This method returns a Future so users can optionally choose to wait
* until the recalculation has been performed.</p>
*
* @param contexts the contexts to reload in.
* @throws NullPointerException if contexts is null
* @return a future
* @since 4.0
*/
@Nonnull
CompletableFuture<? extends MetaData> reloadMeta(@Nonnull Contexts contexts);
/**
* Recalculates permission data for all known contexts.
*
* <p>This method returns immediately. The recalculation is performed
* asynchronously and applied to the cache in the background.</p>
*
* <p>The previous {@link PermissionData} instances will continue to be returned
* by {@link #getPermissionData(Contexts)} until the recalculation is completed.</p>
*/
void recalculatePermissions();
/**
* Recalculates meta data for all known contexts.
*
* <p>This method returns immediately. The recalculation is performed
* asynchronously and applied to the cache in the background.</p>
*
* <p>The previous {@link MetaData} instances will continue to be returned
* by {@link #getMetaData(MetaContexts)} and {@link #getMetaData(Contexts)}
* until the recalculation is completed.</p>
*/
void recalculateMeta();
/**
* Reloads permission data for all known contexts.
*
* <p>Unlike {@link #recalculatePermissions()}, this method immediately
* invalidates all previous {@link PermissionData} values contained within the cache,
* and then schedules a task to reload a new {@link PermissionData} instances to
* replace the ones which were invalidated.</p>
*
* <p>The invalidation happens immediately during the execution of this method.
* The result of the re-computation encapsulated by the future.</p>
*
* <p>Subsequent calls to {@link #getPermissionData(Contexts)} will block until
* the result of this operation is complete.</p>
*
* <p>This method returns a Future so users can optionally choose to wait
* until the recalculation has been performed.</p>
*
* @return a future
* @since 4.0
*/
@Nonnull
CompletableFuture<Void> reloadPermissions();
/**
* Reloads meta data for all known contexts.
*
* <p>Unlike {@link #recalculateMeta()}, this method immediately
* invalidates all previous {@link MetaData} values contained within the cache,
* and then schedules a task to reload a new {@link MetaData} instances to
* replace the ones which were invalidated.</p>
*
* <p>The invalidation happens immediately during the execution of this method.
* The result of the re-computation encapsulated by the future.</p>
*
* <p>Subsequent calls to {@link #getMetaData(MetaContexts)} and
* {@link #getMetaData(Contexts)} will block until the result of this operation
* is complete.</p>
*
* <p>This method returns a Future so users can optionally choose to wait
* until the recalculation has been performed.</p>
*
* @return a future
* @since 4.0
*/
@Nonnull
CompletableFuture<Void> reloadMeta();
/**
* Pre-calculates and caches {@link PermissionData} and {@link MetaData}
* instances for the given contexts.
*
* <p>If the cache already contains a value for the given context,
* no action is taken.</p>
*
* <p>This method blocks until the calculation is completed.</p>
*
* @param contexts a set of contexts
* @throws NullPointerException if contexts is null
*/
default void preCalculate(@Nonnull Set<Contexts> contexts) {
contexts.forEach(this::preCalculate);
}
/**
* Pre-calculates and caches {@link PermissionData} and {@link MetaData}
* instances for a given context.
*
* <p>If the cache already contains a value for the given context,
* no action is taken.</p>
*
* <p>This method blocks until the calculation is completed.</p>
*
* @param contexts the contexts to pre-calculate for
* @throws NullPointerException if contexts is null
*/
void preCalculate(@Nonnull Contexts contexts);
/**
* Invalidates any cached {@link PermissionData} instances mapped to the given
* {@link Contexts}.
*
* @param contexts the contexts to invalidate for
* @since 4.0
*/
void invalidatePermissions(@Nonnull Contexts contexts);
/**
* Invalidates any cached {@link MetaData} instances mapped to the given
* {@link MetaContexts}.
*
* @param contexts the contexts to invalidate for
* @since 4.0
*/
void invalidateMeta(@Nonnull MetaContexts contexts);
/**
* Invalidates any cached {@link MetaData} instances mapped to the given
* {@link Contexts}.
*
* @param contexts the contexts to invalidate for
* @since 4.0
*/
void invalidateMeta(@Nonnull Contexts contexts);
/**
* Invalidates all cached {@link PermissionData} instances.
*
* @since 4.2
*/
void invalidatePermissions();
/**
* Invalidates all cached {@link MetaData} instances.
*
* @since 4.2
*/
void invalidateMeta();
/**
* Invalidates all of the underlying Permission calculators.
*
* <p>Can be called to allow for an update in defaults.</p>
*/
void invalidatePermissionCalculators();
}
@@ -1,45 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.caching;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Group;
/**
* Holds cached permission and meta lookup data for a {@link Group}.
*
* <p>All calls will account for inheritance, as well as any default data provided
* by the platform. This calls are heavily cached and are therefore fast.</p>
*
* <p>For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that
* the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the
* values from the configuration are used.</p>
*
* @since 4.0
*/
public interface GroupData extends CachedData {
}
@@ -1,123 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.caching;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* Encapsulates the options and settings for a meta lookup.
*
* <p>Consists of a standard {@link Contexts} element, plus options to define how
* the meta stack should be constructed.</p>
*
* @since 3.2
*/
@Immutable
public final class MetaContexts {
/**
* Creates a new meta contexts instance
*
* @param contexts the standard contexts for the query
* @param prefixStackDefinition the prefix stack definition to be used
* @param suffixStackDefinition the suffix stack definition to be used
* @return the new instance
*/
public static MetaContexts of(@Nonnull Contexts contexts, @Nonnull MetaStackDefinition prefixStackDefinition, @Nonnull MetaStackDefinition suffixStackDefinition) {
return new MetaContexts(contexts, prefixStackDefinition, suffixStackDefinition);
}
private final Contexts contexts;
private final MetaStackDefinition prefixStackDefinition;
private final MetaStackDefinition suffixStackDefinition;
// cache hashcode - this class is immutable, and is used as an index in the permission cache.
private final int hashCode;
/**
* Creates a new meta contexts instance
*
* @param contexts the standard contexts for the query
* @param prefixStackDefinition the prefix stack definition to be used
* @param suffixStackDefinition the suffix stack definition to be used
*/
public MetaContexts(@Nonnull Contexts contexts, @Nonnull MetaStackDefinition prefixStackDefinition, @Nonnull MetaStackDefinition suffixStackDefinition) {
this.contexts = Objects.requireNonNull(contexts, "contexts");
this.prefixStackDefinition = Objects.requireNonNull(prefixStackDefinition, "prefixStackDefinition");
this.suffixStackDefinition = Objects.requireNonNull(suffixStackDefinition, "suffixStackDefinition");
this.hashCode = calculateHashCode();
}
@Nonnull
public Contexts getContexts() {
return this.contexts;
}
@Nonnull
public MetaStackDefinition getPrefixStackDefinition() {
return this.prefixStackDefinition;
}
@Nonnull
public MetaStackDefinition getSuffixStackDefinition() {
return this.suffixStackDefinition;
}
@Override
@Nonnull
public String toString() {
return "MetaContexts(" +
"contexts=" + this.getContexts() + ", " +
"prefixStackDefinition=" + this.getPrefixStackDefinition() + ", " +
"suffixStackDefinition=" + this.getSuffixStackDefinition() +
")";
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof MetaContexts)) return false;
final MetaContexts that = (MetaContexts) o;
return this.contexts.equals(that.contexts) &&
this.prefixStackDefinition.equals(that.prefixStackDefinition) &&
this.suffixStackDefinition.equals(that.suffixStackDefinition);
}
private int calculateHashCode() {
return Objects.hash(this.contexts, this.prefixStackDefinition, this.suffixStackDefinition);
}
@Override
public int hashCode() {
return this.hashCode;
}
}
@@ -1,45 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.caching;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.User;
/**
* Holds cached permission and meta lookup data for a {@link User}.
*
* <p>All calls will account for inheritance, as well as any default data provided by
* the platform. This calls are heavily cached and are therefore fast.</p>
*
* <p>For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that
* the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the
* values from the configuration are used.</p>
*
* @since 2.13
*/
public interface UserData extends CachedData {
}
@@ -1,50 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 javax.annotation.Nonnull;
/**
* Calculates whether contexts are applicable to a {@link T subject}.
*
* @param <T> the subject type. Is ALWAYS the player class of the platform.
* @since 2.13
*/
@FunctionalInterface
public interface ContextCalculator<T> {
/**
* Gives the subject all of the applicable contexts they meet
*
* @param subject the subject to add contexts to
* @param accumulator a map of contexts to add to
* @return the map
* @since 2.13
*/
@Nonnull
MutableContextSet giveApplicableContext(@Nonnull T subject, @Nonnull MutableContextSet accumulator);
}
@@ -1,377 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.context;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.SetMultimap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.Spliterator;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* An immutable implementation of {@link ContextSet}.
*
* @since 2.16
*/
@Immutable
public final class ImmutableContextSet extends AbstractContextSet implements ContextSet {
private static final ImmutableContextSet EMPTY = new ImmutableContextSet(ImmutableSetMultimap.of());
/**
* Creates an {@link ImmutableContextSet.Builder}.
*
* @return a new ImmutableContextSet builder
* @since 4.1
*/
@Nonnull
public static Builder builder() {
return new Builder();
}
/**
* Creates an {@link ImmutableContextSet} from a context pair.
*
* @param key the key
* @param value the value
* @return a new ImmutableContextSet containing one context pair
* @throws NullPointerException if key or value is null
*/
@Nonnull
public static ImmutableContextSet singleton(@Nonnull String key, @Nonnull String value) {
return new ImmutableContextSet(ImmutableSetMultimap.of(sanitizeKey(key), sanitizeValue(value)));
}
/**
* Creates an {@link ImmutableContextSet} from two context pairs.
*
* @param key1 the first key
* @param value1 the first value
* @param key2 the second key
* @param value2 the second value
* @return a new ImmutableContextSet containing the two pairs
* @throws NullPointerException if any of the keys or values are null
* @since 3.1
*/
@Nonnull
public static ImmutableContextSet of(@Nonnull String key1, @Nonnull String value1, @Nonnull String key2, @Nonnull String value2) {
return new ImmutableContextSet(ImmutableSetMultimap.of(
sanitizeKey(key1),
sanitizeValue(value1),
sanitizeKey(key2),
sanitizeValue(value2)
));
}
/**
* Creates an {@link ImmutableContextSet} from an existing {@link Iterable} of {@link Map.Entry}s.
*
* @param iterable the iterable to copy from
* @return a new ImmutableContextSet representing the pairs in the iterable
* @throws NullPointerException if the iterable is null
*/
@Nonnull
public static ImmutableContextSet fromEntries(@Nonnull Iterable<? extends Map.Entry<String, String>> iterable) {
Objects.requireNonNull(iterable, "iterable");
ImmutableContextSet.Builder builder = builder();
for (Map.Entry<String, String> entry : iterable) {
builder.add(entry);
}
return builder.build();
}
/**
* Creates an {@link ImmutableContextSet} from an existing {@link Map}.
*
* @param map the map to copy from
* @return a new ImmutableContextSet representing the pairs from the map
* @throws NullPointerException if the map is null
*/
@Nonnull
public static ImmutableContextSet fromMap(@Nonnull Map<String, String> map) {
return fromEntries(Objects.requireNonNull(map, "map").entrySet());
}
/**
* Creates an {@link ImmutableContextSet} from an existing {@link Multimap}.
*
* @param multimap the multimap to copy from
* @return a new ImmutableContextSet representing the pairs in the multimap
* @throws NullPointerException if the multimap is null
* @since 2.16
*/
@Nonnull
public static ImmutableContextSet fromMultimap(@Nonnull Multimap<String, String> multimap) {
return fromEntries(Objects.requireNonNull(multimap, "multimap").entries());
}
/**
* Creates an new {@link ImmutableContextSet} from an existing {@link Set}.
*
* <p>Only really useful for converting between mutable and immutable types.</p>
*
* @param contextSet the context set to copy from
* @return a new ImmutableContextSet with the same content and the one provided
* @throws NullPointerException if contextSet is null
*/
@Nonnull
public static ImmutableContextSet fromSet(@Nonnull ContextSet contextSet) {
return Objects.requireNonNull(contextSet, "contextSet").makeImmutable();
}
/**
* Returns an empty {@link ImmutableContextSet}.
*
* @return an empty ImmutableContextSet
*/
@Nonnull
public static ImmutableContextSet empty() {
return EMPTY;
}
private final ImmutableSetMultimap<String, String> map;
private final int hashCode;
ImmutableContextSet(ImmutableSetMultimap<String, String> contexts) {
this.map = contexts;
this.hashCode = this.map.hashCode();
}
@Override
protected SetMultimap<String, String> backing() {
return this.map;
}
@Override
protected void copyTo(SetMultimap<String, String> other) {
other.putAll(this.map);
}
@Override
public boolean isImmutable() {
return true;
}
@Nonnull
@Override
@Deprecated // This set is already immutable!
public ImmutableContextSet makeImmutable() {
return this;
}
@Nonnull
@Override
public MutableContextSet mutableCopy() {
return MutableContextSet.fromSet(this);
}
@Nonnull
@Override
public Set<Map.Entry<String, String>> toSet() {
return this.map.entries();
}
@Nonnull
@Override
@Deprecated
public Map<String, String> toMap() {
ImmutableMap.Builder<String, String> m = ImmutableMap.builder();
for (Map.Entry<String, String> e : this.map.entries()) {
m.put(e.getKey(), e.getValue());
}
return m.build();
}
@Nonnull
@Override
public Multimap<String, String> toMultimap() {
return this.map;
}
@Nonnull
@Override
public Iterator<Map.Entry<String, String>> iterator() {
return this.map.entries().iterator();
}
@Override
public Spliterator<Map.Entry<String, String>> spliterator() {
return this.map.entries().spliterator();
}
@Override
public int hashCode() {
return this.hashCode;
}
@Override
public String toString() {
return "ImmutableContextSet(contexts=" + this.map + ")";
}
/**
* A builder for {@link ImmutableContextSet}.
*
* @since 4.1
*/
public static final class Builder {
private ImmutableSetMultimap.Builder<String, String> builder;
private Builder() {
}
private synchronized ImmutableSetMultimap.Builder<String, String> builder() {
if (this.builder == null) {
this.builder = ImmutableSetMultimap.builder();
}
return this.builder;
}
private void put(String key, String value) {
builder().put(key, value);
}
/**
* Adds a context to the set.
*
* @param key the key to add
* @param value the value to add
* @return the builder
* @throws NullPointerException if the key or value is null
* @see MutableContextSet#add(String, String)
*/
@Nonnull
public Builder add(@Nonnull String key, @Nonnull String value) {
put(sanitizeKey(key), sanitizeValue(value));
return this;
}
/**
* Adds a context to the set.
*
* @param entry the entry to add
* @return the builder
* @throws NullPointerException if the entry is null
* @see MutableContextSet#add(Map.Entry)
*/
@Nonnull
public Builder add(@Nonnull Map.Entry<String, String> entry) {
Objects.requireNonNull(entry, "entry");
add(entry.getKey(), entry.getValue());
return this;
}
/**
* Adds the contexts contained in the given {@link Iterable} to the set.
*
* @param iterable an iterable of key value context pairs
* @return the builder
* @throws NullPointerException if iterable is null
* @see MutableContextSet#addAll(Iterable)
*/
@Nonnull
public Builder addAll(@Nonnull Iterable<? extends Map.Entry<String, String>> iterable) {
for (Map.Entry<String, String> e : Objects.requireNonNull(iterable, "iterable")) {
add(e);
}
return this;
}
/**
* Adds the contexts contained in the given {@link Map} to the set.
*
* @param map the map to add from
* @return the builder
* @throws NullPointerException if the map is null
* @see MutableContextSet#addAll(Map)
*/
@Nonnull
public Builder addAll(@Nonnull Map<String, String> map) {
addAll(Objects.requireNonNull(map, "map").entrySet());
return this;
}
/**
* Adds the contexts contained in the given {@link Multimap} to the set.
*
* @param multimap the multimap to add from
* @return the builder
* @throws NullPointerException if the map is null
* @since 3.4
* @see MutableContextSet#addAll(Multimap)
*/
@Nonnull
public Builder addAll(@Nonnull Multimap<String, String> multimap) {
addAll(Objects.requireNonNull(multimap, "multimap").entries());
return this;
}
/**
* Adds of of the contexts in another {@link ContextSet} to the set.
*
* @param contextSet the set to add from
* @return the builder
* @throws NullPointerException if the contextSet is null
* @see MutableContextSet#addAll(ContextSet)
*/
@Nonnull
public Builder addAll(@Nonnull ContextSet contextSet) {
Objects.requireNonNull(contextSet, "contextSet");
if (contextSet instanceof AbstractContextSet) {
AbstractContextSet other = ((AbstractContextSet) contextSet);
if (!other.isEmpty()) {
builder().putAll(other.backing());
}
} else {
addAll(contextSet.toMultimap());
}
return this;
}
/**
* Creates a {@link ImmutableContextSet} from the values previously
* added to the builder.
*
* @return an {@link ImmutableContextSet} from the builder
*/
@Nonnull
public ImmutableContextSet build() {
if (this.builder == null) {
return empty();
} else {
return new ImmutableContextSet(this.builder.build());
}
}
}
}
@@ -1,365 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.context;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.Spliterator;
import javax.annotation.Nonnull;
/**
* A mutable implementation of {@link ContextSet}.
*
* @since 2.16
*/
public final class MutableContextSet extends AbstractContextSet implements ContextSet {
/**
* Creates a {@link MutableContextSet} from a context pair.
*
* @param key the key
* @param value the value
* @return a new MutableContextSet containing one context pair
* @throws NullPointerException if key or value is null
*/
@Nonnull
public static MutableContextSet singleton(@Nonnull String key, @Nonnull String value) {
Objects.requireNonNull(key, "key");
Objects.requireNonNull(value, "value");
MutableContextSet set = MutableContextSet.create();
set.add(key, value);
return set;
}
/**
* Creates a {@link MutableContextSet} from two context pairs.
*
* @param key1 the first key
* @param value1 the first value
* @param key2 the second key
* @param value2 the second value
* @return a new MutableContextSet containing the two pairs
* @throws NullPointerException if any of the keys or values are null
* @since 3.1
*/
@Nonnull
public static MutableContextSet of(@Nonnull String key1, @Nonnull String value1, @Nonnull String key2, @Nonnull String value2) {
Objects.requireNonNull(key1, "key1");
Objects.requireNonNull(value1, "value1");
Objects.requireNonNull(key2, "key2");
Objects.requireNonNull(value2, "value2");
MutableContextSet set = create();
set.add(key1, value1);
set.add(key2, value2);
return set;
}
/**
* Creates a {@link MutableContextSet} from an existing {@link Iterable} of {@link Map.Entry}s.
*
* @param iterable the iterable to copy from
* @return a new MutableContextSet representing the pairs in the iterable
* @throws NullPointerException if the iterable is null
*/
@Nonnull
public static MutableContextSet fromEntries(@Nonnull Iterable<? extends Map.Entry<String, String>> iterable) {
Objects.requireNonNull(iterable, "iterable");
MutableContextSet set = create();
set.addAll(iterable);
return set;
}
/**
* Creates a {@link MutableContextSet} from an existing {@link Map}.
*
* @param map the map to copy from
* @return a new MutableContextSet representing the pairs from the map
* @throws NullPointerException if the map is null
*/
@Nonnull
public static MutableContextSet fromMap(@Nonnull Map<String, String> map) {
Objects.requireNonNull(map, "map");
MutableContextSet set = create();
set.addAll(map);
return set;
}
/**
* Creates a {@link MutableContextSet} from an existing {@link Multimap}.
*
* @param multimap the multimap to copy from
* @return a new MutableContextSet representing the pairs in the multimap
* @throws NullPointerException if the multimap is null
* @since 2.16
*/
@Nonnull
public static MutableContextSet fromMultimap(@Nonnull Multimap<String, String> multimap) {
Objects.requireNonNull(multimap, "multimap");
MutableContextSet set = create();
set.addAll(multimap);
return set;
}
/**
* Creates a new {@link MutableContextSet} from an existing {@link Set}.
*
* <p>Only really useful for converting between mutable and immutable types.</p>
*
* @param contextSet the context set to copy from
* @return a new MutableContextSet with the same content and the one provided
* @throws NullPointerException if contextSet is null
*/
@Nonnull
public static MutableContextSet fromSet(@Nonnull ContextSet contextSet) {
Objects.requireNonNull(contextSet, "contextSet");
if (contextSet instanceof ImmutableContextSet) {
SetMultimap<String, String> map = ((ImmutableContextSet) contextSet).backing();
return new MutableContextSet(map);
} else if (contextSet instanceof MutableContextSet) {
return contextSet.mutableCopy();
} else {
MutableContextSet set = create();
set.addAll(contextSet);
return set;
}
}
/**
* Creates a new empty MutableContextSet.
*
* @return a new MutableContextSet
*/
@Nonnull
public static MutableContextSet create() {
return new MutableContextSet();
}
private final SetMultimap<String, String> map;
public MutableContextSet() {
this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create());
}
private MutableContextSet(SetMultimap<String, String> other) {
this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create(other));
}
@Override
protected SetMultimap<String, String> backing() {
return this.map;
}
@Override
protected void copyTo(SetMultimap<String, String> other) {
synchronized (this.map) {
other.putAll(this.map);
}
}
@Override
public boolean isImmutable() {
return false;
}
@Nonnull
@Override
public ImmutableContextSet makeImmutable() {
// if the map is empty, don't create a new instance
if (this.map.isEmpty()) {
return ImmutableContextSet.empty();
}
synchronized (this.map) {
return new ImmutableContextSet(ImmutableSetMultimap.copyOf(this.map));
}
}
@Nonnull
@Override
public MutableContextSet mutableCopy() {
synchronized (this.map) {
return new MutableContextSet(this.map);
}
}
@Nonnull
@Override
public Set<Map.Entry<String, String>> toSet() {
synchronized (this.map) {
// map.entries() returns immutable Map.Entry instances, so we can just call copyOf
return ImmutableSet.copyOf(this.map.entries());
}
}
@Nonnull
@Override
@Deprecated
public Map<String, String> toMap() {
ImmutableMap.Builder<String, String> m = ImmutableMap.builder();
synchronized (this.map) {
for (Map.Entry<String, String> e : this.map.entries()) {
m.put(e.getKey(), e.getValue());
}
}
return m.build();
}
@Nonnull
@Override
public Multimap<String, String> toMultimap() {
synchronized (this.map) {
return ImmutableSetMultimap.copyOf(this.map);
}
}
@Nonnull
@Override
public Iterator<Map.Entry<String, String>> iterator() {
return toSet().iterator();
}
@Override
public Spliterator<Map.Entry<String, String>> spliterator() {
return toSet().spliterator();
}
/**
* Adds a context to this set.
*
* @param key the key to add
* @param value the value to add
* @throws NullPointerException if the key or value is null
*/
public void add(@Nonnull String key, @Nonnull String value) {
this.map.put(sanitizeKey(key), sanitizeValue(value));
}
/**
* Adds a context to this set.
*
* @param entry the entry to add
* @throws NullPointerException if the entry is null
*/
public void add(@Nonnull Map.Entry<String, String> entry) {
Objects.requireNonNull(entry, "entry");
add(entry.getKey(), entry.getValue());
}
/**
* Adds the contexts contained in the given {@link Iterable} to this set.
*
* @param iterable an iterable of key value context pairs
* @throws NullPointerException if iterable is null
*/
public void addAll(@Nonnull Iterable<? extends Map.Entry<String, String>> iterable) {
for (Map.Entry<String, String> e : Objects.requireNonNull(iterable, "iterable")) {
add(e);
}
}
/**
* Adds the contexts contained in the given {@link Map} to this set.
*
* @param map the map to add from
* @throws NullPointerException if the map is null
*/
public void addAll(@Nonnull Map<String, String> map) {
addAll(Objects.requireNonNull(map, "map").entrySet());
}
/**
* Adds the contexts contained in the given {@link Multimap} to this set.
*
* @param multimap the multimap to add from
* @throws NullPointerException if the map is null
* @since 3.4
*/
public void addAll(@Nonnull Multimap<String, String> multimap) {
addAll(Objects.requireNonNull(multimap, "multimap").entries());
}
/**
* Adds of of the contexts in another {@link ContextSet} to this set.
*
* @param contextSet the set to add from
* @throws NullPointerException if the contextSet is null
*/
public void addAll(@Nonnull ContextSet contextSet) {
Objects.requireNonNull(contextSet, "contextSet");
if (contextSet instanceof AbstractContextSet) {
AbstractContextSet other = ((AbstractContextSet) contextSet);
synchronized (this.map) {
other.copyTo(this.map);
}
} else {
addAll(contextSet.toMultimap());
}
}
/**
* Removes a context from this set.
*
* @param key the key to remove
* @param value the value to remove
* @throws NullPointerException if the key or value is null
*/
public void remove(@Nonnull String key, @Nonnull String value) {
this.map.remove(sanitizeKey(key), sanitizeValue(value));
}
/**
* Removes all contexts from this set with the given key.
*
* @param key the key to remove
* @throws NullPointerException if the key is null
*/
public void removeAll(@Nonnull String key) {
this.map.removeAll(sanitizeKey(key));
}
/**
* Removes all contexts from the set.
*/
public void clear() {
this.map.clear();
}
@Override
public String toString() {
return "MutableContextSet(contexts=" + this.map + ")";
}
}
@@ -1,44 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.nodetype;
import me.lucko.luckperms.api.Node;
/**
* Superinterface for extended {@link Node} types.
*
* <p>The 'permission' property of a {@link Node} is also used in some cases to represent state
* beyond a granted permission. This state is encapsulated by extra {@link NodeType} data which
* can be obtained from this instance using {@link Node#getTypeData(NodeTypeKey)}.</p>
*
* <p>Type data is mapped by {@link NodeTypeKey}s, which are usually stored as static members of the
* corresponding {@link NodeType} class under the <code>KEY</code> field.</p>
*
* @since 4.2
*/
public interface NodeType {
}
@@ -1,56 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.nodetype;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import javax.annotation.Nonnull;
/**
* Marks an instance used as a key for a {@link NodeType}.
*
* <p>A single instance of this interface is created and stored statically for
* each sub-interface of {@link NodeType}.</p>
*
* @param <N> the type of the {@link NodeType} being indexed by this key
* @since 4.2
*/
public interface NodeTypeKey<N extends NodeType> {
/**
* Gets the {@link Class#getSimpleName() class name} of the represented type.
*
* @return the name of the represented type
*/
@Nonnull
default String getTypeName() {
ParameterizedType thisType = (ParameterizedType) getClass().getGenericSuperclass();
Type nodeType = thisType.getActualTypeArguments()[0];
return ((Class) nodeType).getSimpleName();
}
}
@@ -1,57 +0,0 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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.platform;
import javax.annotation.Nonnull;
/**
* Represents a type of platform which LuckPerms can run on.
*
* @since 2.7
*/
public enum PlatformType {
BUKKIT("Bukkit"),
BUNGEE("Bungee"),
SPONGE("Sponge"),
NUKKIT("Nukkit");
private final String friendlyName;
PlatformType(String friendlyName) {
this.friendlyName = friendlyName;
}
/**
* Gets a readable name for the platform type.
*
* @return a readable name
*/
@Nonnull
public String getFriendlyName() {
return this.friendlyName;
}
}
@@ -0,0 +1,209 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 net.luckperms.api;
import net.luckperms.api.actionlog.ActionLogger;
import net.luckperms.api.context.ContextCalculator;
import net.luckperms.api.context.ContextManager;
import net.luckperms.api.event.EventBus;
import net.luckperms.api.messaging.MessagingService;
import net.luckperms.api.messenger.MessengerProvider;
import net.luckperms.api.metastacking.MetaStackDefinition;
import net.luckperms.api.metastacking.MetaStackElement;
import net.luckperms.api.metastacking.MetaStackFactory;
import net.luckperms.api.model.group.Group;
import net.luckperms.api.model.group.GroupManager;
import net.luckperms.api.model.user.User;
import net.luckperms.api.model.user.UserManager;
import net.luckperms.api.node.NodeBuilderRegistry;
import net.luckperms.api.platform.Platform;
import net.luckperms.api.platform.PluginMetadata;
import net.luckperms.api.track.Track;
import net.luckperms.api.track.TrackManager;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
/**
* The LuckPerms API.
*
* <p>The API allows other plugins on the server to read and modify LuckPerms
* data, change behaviour of the plugin, listen to certain events, and integrate
* LuckPerms into other plugins and systems.</p>
*
* <p>This interface represents the base of the API package. All functions are
* accessed via this interface.</p>
*
* <p>To start using the API, you need to obtain an instance of this interface.
* These are registered by the LuckPerms plugin to the platforms Services
* Manager. This is the preferred method for obtaining an instance.</p>
*
* <p>For ease of use, and for platforms without a Service Manager, an instance
* can also be obtained from the static singleton accessor in
* {@link LuckPermsProvider}.</p>
*/
public interface LuckPerms {
/**
* Gets the name of this server.
*
* <p>This is defined in the LuckPerms configuration file, and is used for
* server specific permission handling.</p>
*
* <p>The default server name is "global".</p>
*
* @return the server name
*/
@NonNull String getServerName();
/**
* Gets the {@link UserManager}, responsible for managing
* {@link User} instances.
*
* <p>This manager can be used to retrieve instances of {@link User} by uuid
* or name, or query all loaded users.</p>
*
* @return the user manager
*/
@NonNull UserManager getUserManager();
/**
* Gets the {@link GroupManager}, responsible for managing
* {@link Group} instances.
*
* <p>This manager can be used to retrieve instances of {@link Group} by
* name, or query all loaded groups.</p>
*
* @return the group manager
*/
@NonNull GroupManager getGroupManager();
/**
* Gets the {@link TrackManager}, responsible for managing
* {@link Track} instances.
*
* <p>This manager can be used to retrieve instances of {@link Track} by
* name, or query all loaded tracks.</p>
*
* @return the track manager
*/
@NonNull TrackManager getTrackManager();
/**
* Gets the {@link Platform}, which represents the server platform the
* plugin is running on.
*
* @return the platform
*/
@NonNull Platform getPlatform();
/**
* Gets the {@link PluginMetadata}, responsible for providing metadata about
* the LuckPerms plugin currently running.
*
* @return the plugin metadata
*/
@NonNull PluginMetadata getPluginMetadata();
/**
* Gets the {@link EventBus}, used for subscribing to internal LuckPerms
* events.
*
* @return the event bus
*/
@NonNull EventBus getEventBus();
/**
* Gets the {@link MessagingService}, used to dispatch updates throughout a
* network of servers running the plugin.
*
* <p>Not all instances of LuckPerms will have a messaging service setup and
* configured.</p>
*
* @return the messaging service instance, if present.
*/
@NonNull Optional<MessagingService> getMessagingService();
/**
* Gets the {@link ActionLogger}, responsible for saving and broadcasting
* defined actions occurring on the platform.
*
* @return the action logger
*/
@NonNull ActionLogger getActionLogger();
/**
* Gets the {@link ContextManager}, responsible for managing
* {@link ContextCalculator}s, and calculating applicable contexts.
*
* @return the context manager
*/
@NonNull ContextManager getContextManager();
/**
* Gets the {@link NodeBuilderRegistry}.
*
* @return the node builder registry
*/
@NonNull NodeBuilderRegistry getNodeBuilderRegistry();
/**
* Gets the {@link MetaStackFactory}.
*
* <p>The metastack factory provides methods for retrieving
* {@link MetaStackElement}s and constructing
* {@link MetaStackDefinition}s.</p>
*
* @return the meta stack factory
*/
@NonNull MetaStackFactory getMetaStackFactory();
/**
* Schedules the execution of an update task, and returns an encapsulation
* of the task as a {@link CompletableFuture}.
*
* <p>The exact actions performed in an update task remains an
* implementation detail of the plugin, however, as a minimum, it is
* expected to perform a full reload of user, group and track data, and
* ensure that any changes are fully applied and propagated.</p>
*
* @return a future
*/
@NonNull CompletableFuture<Void> runUpdateTask();
/**
* Registers a {@link MessengerProvider} for use by the platform.
*
* <p>Note that the mere action of registering a provider doesn't
* necessarily mean that it will be used.</p>
*
* @param messengerProvider the messenger provider.
*/
void registerMessengerProvider(@NonNull MessengerProvider messengerProvider);
}
@@ -23,25 +23,21 @@
* SOFTWARE.
*/
package me.lucko.luckperms;
package net.luckperms.api;
import me.lucko.luckperms.api.LuckPermsApi;
import java.util.Optional;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Provides static access to the {@link LuckPermsApi}.
* Provides static access to the {@link LuckPerms} service.
*
* <p>Ideally, the ServiceManager for the platform should be used to obtain an instance,
* however, this provider can be used if you need static access.</p>
* <p>Ideally, the ServiceManager for the platform should be used to obtain an
* instance, however, this provider can be used if you need static access.</p>
*/
public final class LuckPerms {
private static LuckPermsApi instance = null;
public final class LuckPermsProvider {
private static LuckPerms instance = null;
/**
* Gets an instance of the {@link LuckPermsApi},
* Gets an instance of the {@link LuckPerms} service,
* throwing {@link IllegalStateException} if an instance is not yet loaded.
*
* <p>Will never return null.</p>
@@ -49,45 +45,22 @@ public final class LuckPerms {
* @return an api instance
* @throws IllegalStateException if the api is not loaded
*/
@Nonnull
public static LuckPermsApi getApi() {
public static @NonNull LuckPerms get() {
if (instance == null) {
throw new IllegalStateException("API is not loaded.");
throw new IllegalStateException("The LuckPerms API is not loaded.");
}
return instance;
}
/**
* Gets an instance of {@link LuckPermsApi}, if it is loaded.
*
* <p>Unlike {@link LuckPerms#getApi}, this method will not throw an
* {@link IllegalStateException} if an instance is not yet loaded, rather return
* an empty {@link Optional}.
*
* @return an optional api instance
*/
@Nonnull
public static Optional<LuckPermsApi> getApiSafe() {
return Optional.ofNullable(instance);
static void register(LuckPerms instance) {
LuckPermsProvider.instance = instance;
}
/**
* Registers an instance of the {@link LuckPermsApi} with this provider.
*
* @param instance the instance
*/
static void registerProvider(LuckPermsApi instance) {
LuckPerms.instance = instance;
static void unregister() {
LuckPermsProvider.instance = null;
}
/**
* Removes the current instance from this provider.
*/
static void unregisterProvider() {
LuckPerms.instance = null;
}
private LuckPerms() {
private LuckPermsProvider() {
throw new UnsupportedOperationException("This class cannot be instantiated.");
}
@@ -23,73 +23,51 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api;
package net.luckperms.api.actionlog;
import net.luckperms.api.LuckPermsProvider;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.time.Instant;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* Represents a logged action.
*
* @see ActionLogger#newEntryBuilder() for creating an instance
*/
@Immutable
public interface LogEntry extends Comparable<LogEntry> {
public interface Action extends Comparable<Action> {
/**
* Gets the time in unix seconds when the action occurred.
* Gets a {@link Action.Builder}
*
* @return a new builder
*/
static @NonNull Builder builder() {
return LuckPermsProvider.get().getActionLogger().actionBuilder();
}
/**
* Gets the time when the action occurred.
*
* @return the timestamp
*/
long getTimestamp();
@NonNull Instant getTimestamp();
/**
* Gets the id of the object which performed the action.
* Gets the source of the action.
*
* <p>This is the players uuid in most cases.</p>
*
* @return the actor id
* @return the source
*/
@Nonnull
UUID getActor();
@NonNull Source getSource();
/**
* Gets the name describing the actor.
* Gets the target of the action.
*
* @return the name of the actor
* @return the target
*/
@Nonnull
String getActorName();
/**
* Gets the type of action.
*
* @return the action type
*/
@Nonnull
Type getType();
/**
* Gets the uuid of the object which was acted upon.
*
* <p>Will only return a value for {@link Type#USER} entries.</p>
*
* @return the uuid of acted object
*/
@Nonnull
Optional<UUID> getActed();
/**
* Gets the name describing the object which was acted upon
*
* @return the name of the acted object
*/
@Nonnull
String getActedName();
@NonNull Target getTarget();
/**
* Returns a string describing the action which took place.
@@ -99,49 +77,65 @@ public interface LogEntry extends Comparable<LogEntry> {
*
* @return the action
*/
@Nonnull
String getAction();
@NonNull String getDescription();
/**
* Represents the type of a {@link LogEntry}.
*
* @since 3.3
* Represents the source of an action.
*/
enum Type {
USER('U'),
GROUP('G'),
TRACK('T');
interface Source {
private final char code;
/**
* Gets the source unique id.
*
* @return the source unique id
*/
@NonNull UUID getUniqueId();
Type(char code) {
this.code = code;
}
/**
* Gets the source name.
*
* @return the source name
*/
@NonNull String getName();
public char getCode() {
return this.code;
}
}
@Nonnull
public static Type valueOf(char code) {
switch (code) {
case 'U':
case 'u':
return USER;
case 'G':
case 'g':
return GROUP;
case 'T':
case 't':
return TRACK;
default:
throw new IllegalArgumentException("Unknown code: " + code);
}
/**
* Represents the target of an action.
*/
interface Target {
/**
* Gets the target unique id.
*
* @return the target unique id
*/
@NonNull Optional<UUID> getUniqueId();
/**
* Gets the target name.
*
* @return the target name
*/
@NonNull String getName();
/**
* Gets the target type.
*
* @return the target type
*/
@NonNull Type getType();
/**
* Represents the type of a {@link Target}.
*/
enum Type {
USER, GROUP, TRACK
}
}
/**
* Builds a LogEntry instance
* Builds an {@link Action} instance
*/
interface Builder {
@@ -150,78 +144,64 @@ public interface LogEntry extends Comparable<LogEntry> {
*
* @param timestamp the timestamp
* @return the builder
* @see LogEntry#getTimestamp()
* @see Action#getTimestamp()
*/
@Nonnull
Builder setTimestamp(long timestamp);
@NonNull Builder timestamp(@NonNull Instant timestamp);
/**
* Sets the actor of the entry.
*
* @param actor the actor
* @return the builder
* @see LogEntry#getActor()
*/
@Nonnull
Builder setActor(@Nonnull UUID actor);
@NonNull Builder source(@NonNull UUID actor);
/**
* Sets the actor name of the entry.
*
* @param actorName the actor name
* @return the builder
* @see LogEntry#getActorName()
*/
@Nonnull
Builder setActorName(@Nonnull String actorName);
@NonNull Builder sourceName(@NonNull String actorName);
/**
* Sets the type of the entry.
*
* @param type the type
* @return the builder
* @see LogEntry#getType()
*/
@Nonnull
Builder setType(@Nonnull Type type);
@NonNull Builder targetType(Action.Target.Type type);
/**
* Sets the acted object for the entry.
*
* @param acted the acted object
* @return the builder
* @see LogEntry#getActed()
*/
@Nonnull
Builder setActed(@Nullable UUID acted);
@NonNull Builder target(@Nullable UUID acted);
/**
* Sets the acted name for the entry.
*
* @param actedName the acted name
* @return the builder
* @see LogEntry#getActedName()
*/
@Nonnull
Builder setActedName(@Nonnull String actedName);
@NonNull Builder targetName(@NonNull String actedName);
/**
* Sets the action of the entry.
*
* @param action the action
* @return the builder
* @see LogEntry#getAction()
*/
@Nonnull
Builder setAction(@Nonnull String action);
@NonNull Builder description(@NonNull String action);
/**
* Creates a {@link LogEntry} instance from the builder.
* Creates a {@link Action} instance from the builder.
*
* @return a new log entry instance
*/
@Nonnull
LogEntry build();
@NonNull Action build();
}
@@ -0,0 +1,84 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 net.luckperms.api.actionlog;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.SortedSet;
import java.util.UUID;
/**
* Represents the internal LuckPerms log.
*
* <p>The returned instance provides a copy of the data at the time of retrieval.</p>
*
* <p>Any changes made to log entries will only apply to this instance of the log.
* You can add to the log using the {@link ActionLogger}, and then request an updated copy.</p>
*
* <p>All methods are thread safe, and return immutable and thread safe collections.</p>
*/
public interface ActionLog {
/**
* Gets the {@link Action}s that make up this log.
*
* @return the content
*/
@NonNull SortedSet<Action> getContent();
/**
* Gets the entries in the log performed by the given actor.
*
* @param actor the uuid of the actor to filter by
* @return the content for the given actor
*/
@NonNull SortedSet<Action> getContent(@NonNull UUID actor);
/**
* Gets the log content for a given user
*
* @param uniqueId the uuid to filter by
* @return all content in this log where the user = uuid
*/
@NonNull SortedSet<Action> getUserHistory(@NonNull UUID uniqueId);
/**
* Gets the log content for a given group
*
* @param name the name to filter by
* @return all content in this log where the group = name
*/
@NonNull SortedSet<Action> getGroupHistory(@NonNull String name);
/**
* Gets the log content for a given track
*
* @param name the name to filter by
* @return all content in this log where the track = name
*/
@NonNull SortedSet<Action> getTrackHistory(@NonNull String name);
}
@@ -23,35 +23,32 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api;
package net.luckperms.api.actionlog;
import net.luckperms.api.messaging.MessagingService;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
/**
* Represents the object responsible for handling action logging.
*
* @since 4.1
*/
public interface ActionLogger {
/**
* Returns a new {@link LogEntry.Builder} instance
* Returns a new {@link Action.Builder} instance
*
* @return a new builder
*/
@Nonnull
LogEntry.Builder newEntryBuilder();
Action.@NonNull Builder actionBuilder();
/**
* Gets a {@link Log} instance from the plugin storage.
* Gets a {@link ActionLog} instance from the plugin storage.
*
* @return a log instance
* @see Storage#getLog()
*/
@Nonnull
CompletableFuture<Log> getLog();
@NonNull CompletableFuture<ActionLog> getLog();
/**
* Submits a log entry to the plugin to be handled.
@@ -60,7 +57,7 @@ public interface ActionLogger {
* it.</p>
*
* <p>It is therefore roughly equivalent to calling
* {@link #submitToStorage(LogEntry)} and {@link #broadcastAction(LogEntry)},
* {@link #submitToStorage(Action)} and {@link #broadcastAction(Action)},
* however, using this method is preferred to making the calls individually.</p>
*
* <p>If you want to submit a log entry but don't know which method to pick,
@@ -69,19 +66,15 @@ public interface ActionLogger {
* @param entry the entry to submit
* @return a future which will complete when the action is done
*/
@Nonnull
CompletableFuture<Void> submit(@Nonnull LogEntry entry);
@NonNull CompletableFuture<Void> submit(@NonNull Action entry);
/**
* Submits a log entry to the plugins storage handler.
*
* <p>Performs the same action as {@link Storage#logAction(LogEntry)}.</p>
*
* @param entry the entry to submit
* @return a future which will complete when the action is done
*/
@Nonnull
CompletableFuture<Void> submitToStorage(@Nonnull LogEntry entry);
@NonNull CompletableFuture<Void> submitToStorage(@NonNull Action entry);
/**
* Submits a log entry to the plugins log broadcasting handler.
@@ -92,7 +85,6 @@ public interface ActionLogger {
* @param entry the entry to submit
* @return a future which will complete when the action is done
*/
@Nonnull
CompletableFuture<Void> broadcastAction(@Nonnull LogEntry entry);
@NonNull CompletableFuture<Void> broadcastAction(@NonNull Action entry);
}
@@ -23,25 +23,22 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.caching;
package net.luckperms.api.cacheddata;
import me.lucko.luckperms.api.Contexts;
import net.luckperms.api.query.QueryOptions;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Holds cached lookup data in a specific set of contexts.
*
* @since 4.1
* Holds cached lookup data for a given set of query options.
*/
public interface CachedDataContainer {
public interface CachedData {
/**
* Gets the contexts this container is holding data for.
* Gets the query options this container is holding data for.
*
* @return the contexts this container is caching
* @return the query options this container is caching
*/
@Nonnull
Contexts getContexts();
@NonNull QueryOptions getQueryOptions();
}
@@ -0,0 +1,212 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 net.luckperms.api.cacheddata;
import net.luckperms.api.model.PermissionHolder;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.concurrent.CompletableFuture;
/**
* Holds cached permission and meta lookup data for a {@link PermissionHolder}.
*
* <p>All calls will account for inheritance, as well as any default data
* provided by the platform. This calls are heavily cached and are therefore
* fast.</p>
*/
public interface CachedDataManager {
/**
* Gets the manager for {@link CachedPermissionData}.
*
* @return the permission data manager
*/
@NonNull Container<CachedPermissionData> permissionData();
/**
* Gets the manager for {@link CachedMetaData}.
*
* @return the meta data manager
*/
@NonNull Container<CachedMetaData> metaData();
/**
* Gets PermissionData from the cache, given a specified context.
*
* @param queryOptions the query options
* @return a permission data instance
* @throws NullPointerException if contexts is null
*/
@NonNull CachedPermissionData getPermissionData(@NonNull QueryOptions queryOptions);
/**
* Gets MetaData from the cache, given a specified context.
*
* @param queryOptions the query options
* @return a meta data instance
* @throws NullPointerException if contexts is null
*/
@NonNull CachedMetaData getMetaData(@NonNull QueryOptions queryOptions);
/**
* Invalidates all cached {@link CachedPermissionData} and {@link CachedMetaData}
* instances.
*/
void invalidate();
/**
* Invalidates all of the underlying Permission calculators.
*
* <p>Can be called to allow for an update in defaults.</p>
*/
void invalidatePermissionCalculators();
/**
* Manages a specific type of {@link CachedData cached data} within
* a {@link CachedDataManager} instance.
*
* @param <T> the data type
*/
interface Container<T extends CachedData> {
/**
* Gets {@link T data} from the cache.
*
* @param queryOptions the query options
* @return a data instance
* @throws NullPointerException if contexts is null
*/
@NonNull T get(@NonNull QueryOptions queryOptions);
/**
* Calculates {@link T data}, bypassing the cache.
*
* <p>The result of this operation is calculated each time the method is called.
* The result is not added to the internal cache.</p>
*
* <p>It is therefore highly recommended to use {@link #get(QueryOptions)} instead.</p>
*
* <p>The use cases of this method are more around constructing one-time
* instances of {@link T data}, without adding the result to the cache.</p>
*
* @param queryOptions the query options
* @return a data instance
* @throws NullPointerException if contexts is null
*/
@NonNull T calculate(@NonNull QueryOptions queryOptions);
/**
* (Re)calculates data for a given context.
*
* <p>This method returns immediately in all cases. The (re)calculation is
* performed asynchronously and applied to the cache in the background.</p>
*
* <p>If there was a previous data instance associated with
* the given {@link QueryOptions}, then that instance will continue to be returned by
* {@link #get(QueryOptions)} until the recalculation is completed.</p>
*
* <p>If there was no value calculated and cached prior to the call of this
* method, then one will be calculated.</p>
*
* @param queryOptions the query options
* @throws NullPointerException if contexts is null
*/
void recalculate(@NonNull QueryOptions queryOptions);
/**
* (Re)loads permission data for a given context.
*
* <p>Unlike {@link #recalculate(QueryOptions)}, this method immediately
* invalidates any previous data values contained within the cache,
* and then schedules a task to reload a new data instance to
* replace the one which was invalidated.</p>
*
* <p>The invalidation happens immediately during the execution of this method.
* The result of the re-computation encapsulated by the future.</p>
*
* <p>Subsequent calls to {@link #get(QueryOptions)} will block until
* the result of this operation is complete.</p>
*
* <p>If there was no value calculated and cached prior to the call of this
* method, then one will be calculated.</p>
*
* <p>This method returns a Future so users can optionally choose to wait
* until the recalculation has been performed.</p>
*
* @param queryOptions the query options.
* @return a future
* @throws NullPointerException if contexts is null
*/
@NonNull CompletableFuture<? extends T> reload(@NonNull QueryOptions queryOptions);
/**
* Recalculates data for all known contexts.
*
* <p>This method returns immediately. The recalculation is performed
* asynchronously and applied to the cache in the background.</p>
*
* <p>The previous data instances will continue to be returned
* by {@link #get(QueryOptions)} until the recalculation is completed.</p>
*/
void recalculate();
/**
* Reloads permission data for all known contexts.
*
* <p>Unlike {@link #recalculate()}, this method immediately
* invalidates all previous data values contained within the cache,
* and then schedules a task to reload new data instances to
* replace the ones which were invalidated.</p>
*
* <p>The invalidation happens immediately during the execution of this method.
* The result of the re-computation encapsulated by the future.</p>
*
* <p>Subsequent calls to {@link #get(QueryOptions)} will block until
* the result of this operation is complete.</p>
*
* <p>This method returns a Future so users can optionally choose to wait
* until the recalculation has been performed.</p>
*
* @return a future
*/
@NonNull CompletableFuture<Void> reload();
/**
* Invalidates any cached data instances mapped to the given context.
*
* @param queryOptions the queryOptions to invalidate for
*/
void invalidate(@NonNull QueryOptions queryOptions);
/**
* Invalidates all cached data instances.
*/
void invalidate();
}
}
@@ -23,58 +23,50 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.caching;
package net.luckperms.api.cacheddata;
import com.google.common.collect.ListMultimap;
import net.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Holds cached meta lookup data for a specific set of contexts.
*
* @since 2.13
*/
public interface MetaData extends CachedDataContainer {
public interface CachedMetaData extends CachedData {
/**
* Gets the contexts this container is holding data for.
* Gets a value for the given meta key.
*
* @return the contexts this container is caching
* @param key the key
* @return the value
*/
@Nonnull
MetaContexts getMetaContexts();
@Nullable String getMetaValue(String key);
/**
* Gets the user's highest priority prefix, or null if the user has no prefixes
*
* @return a prefix string, or null
*/
@Nullable String getPrefix();
/**
* Gets the user's highest priority suffix, or null if the user has no suffixes
*
* @return a suffix string, or null
*/
@Nullable String getSuffix();
/**
* Gets an immutable copy of the meta this user has.
*
* <p>A list multimap is used because when inherited values are included, each key can be
* mapped to multiple values.</p>
*
* <p>The first value to be accumulated (and used to represent the key in {@link #getMeta()} is at index 0
* in the list. Any additional values are stored in order of accumulation.</p>
*
* @return an immutable multimap of meta
* @since 3.3
*/
@Nonnull
ListMultimap<String, String> getMetaMultimap();
/**
* Gets an immutable copy of the meta this user has.
*
* <p>This map is formed by taking the entries in {@link #getMetaMultimap()}, and mapping each key
* to the value at index 0 in the corresponding list.</p>
*
* @return an immutable map of meta
*/
@Nonnull
Map<String, String> getMeta();
@NonNull Map<String, List<String>> getMeta();
/**
* Gets an immutable sorted map of all of the prefixes the user has, whereby the first value is the highest priority
@@ -82,8 +74,7 @@ public interface MetaData extends CachedDataContainer {
*
* @return a sorted map of prefixes
*/
@Nonnull
SortedMap<Integer, String> getPrefixes();
@NonNull SortedMap<Integer, String> getPrefixes();
/**
* Gets an immutable sorted map of all of the suffixes the user has, whereby the first value is the highest priority
@@ -91,41 +82,20 @@ public interface MetaData extends CachedDataContainer {
*
* @return a sorted map of suffixes
*/
@Nonnull
SortedMap<Integer, String> getSuffixes();
/**
* Gets the user's highest priority prefix, or null if the user has no prefixes
*
* @return a prefix string, or null
*/
@Nullable
String getPrefix();
/**
* Gets the user's highest priority suffix, or null if the user has no suffixes
*
* @return a suffix string, or null
*/
@Nullable
String getSuffix();
@NonNull SortedMap<Integer, String> getSuffixes();
/**
* Gets the definition used for the prefix stack
*
* @return the definition used for the prefix stack
* @since 3.2
*/
@Nonnull
MetaStackDefinition getPrefixStackDefinition();
@NonNull MetaStackDefinition getPrefixStackDefinition();
/**
* Gets the definition used for the suffix stack
*
* @return the definition used for the suffix stack
* @since 3.2
*/
@Nonnull
MetaStackDefinition getSuffixStackDefinition();
@NonNull MetaStackDefinition getSuffixStackDefinition();
}
@@ -23,20 +23,18 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.caching;
package net.luckperms.api.cacheddata;
import me.lucko.luckperms.api.Tristate;
import net.luckperms.api.util.Tristate;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Map;
import javax.annotation.Nonnull;
/**
* Holds cached permission lookup data for a specific set of contexts.
*
* @since 2.13
*/
public interface PermissionData extends CachedDataContainer {
public interface CachedPermissionData extends CachedData {
/**
* Gets a permission check result for the given permission node.
@@ -45,8 +43,7 @@ public interface PermissionData extends CachedDataContainer {
* @return a tristate result
* @throws NullPointerException if permission is null
*/
@Nonnull
Tristate getPermissionValue(@Nonnull String permission);
@NonNull Tristate checkPermission(@NonNull String permission);
/**
* Invalidates the underlying permission calculator cache.
@@ -60,7 +57,6 @@ public interface PermissionData extends CachedDataContainer {
*
* @return an immutable set of permissions
*/
@Nonnull
Map<String, Boolean> getImmutableBacking();
@NonNull Map<String, Boolean> getPermissionMap();
}
@@ -23,21 +23,27 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.listener;
package net.luckperms.api.context;
import java.util.Set;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Handles incoming connections on the platform
* Represents an individual context pair.
*/
public interface ConnectionListener {
public interface Context {
/**
* Gets the unique players which have connected to the server since it started.
* Gets the context key.
*
* @return the unique connections
* @return the key
*/
Set<UUID> getUniqueConnections();
@NonNull String getKey();
/**
* Gets the context value
*
* @return the value
*/
@NonNull String getValue();
}
@@ -0,0 +1,110 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 net.luckperms.api.context;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Objects;
import java.util.function.Function;
/**
* Calculates the contexts applicable for a contextual subject.
*
* <p>Implementations of this interface should satisfy the following
* requirements:</p>
* <ul>
* <li>Context lookups should be <i>fast</i>: lookup methods are likely to
* be invoked frequently, and should therefore be fast to execute. If
* determining the current contexts involves a particularly time consuming
* lookup (database queries, network requests, etc), then such results
* should be cached ahead of time.</li>
*
* <li>Context lookups should be <i>thread-safe</i>: lookups will sometimes
* be performed from "async" threads, and therefore should not access any
* part of the server only safe for access from a sync context. If
* necessary, such results should be determined ahead of time and stored in
* a thread-safe collection for retrieval later.</li>
*
* <li>Context lookups should <i>not query active contexts</i>: doing so is
* likely to result in a stack overflow, or thread deadlock. Care should be
* taken to avoid (indirect) calls to the same calculator.</li>
* </ul>
* <p></p>
*
* <p>Calculators should be registered using
* {@link ContextManager#registerCalculator(ContextCalculator)}.</p>
*/
@FunctionalInterface
public interface ContextCalculator<T> {
/**
* Creates a new {@link ContextCalculator} that provides a single context.
*
* @param key the key of the context provided by the calculator
* @param valueFunction the function used to compute the corresponding value
* for each query. A context will not be "accumulated"
* if the value returned is null.
* @param <T> the contextual type
* @return the resultant calculator
*/
static <T> @NonNull ContextCalculator<T> forSingleContext(@NonNull String key, @NonNull Function<T, String> valueFunction) {
Objects.requireNonNull(key, "key");
Objects.requireNonNull(valueFunction, "valueFunction");
return (target, consumer) -> {
String value = valueFunction.apply(target);
if (value != null) {
consumer.accept(key, value);
}
};
}
/**
* Submits any contexts this calculator determines to be applicable to
* the {@code target} contextual subject.
*
* <p>Care should be taken to ensure implementations of this method meet the
* general requirements for {@link ContextCalculator}, defined in the class
* doc.</p>
*
* @param target the target contextual subject for this operation
* @param consumer the {@link ContextConsumer} to submit contexts to
*/
void calculate(@NonNull T target, @NonNull ContextConsumer consumer);
/**
* Gets a {@link ContextSet}, containing some/all of the contexts this
* calculator could potentially submit.
*
* <p>The result of this call is primarily intended on providing
* suggestions to end users when defining permissions.</p>
*
* @return a set of potential contexts
*/
default ContextSet estimatePotentialContexts() {
return ImmutableContextSet.empty();
}
}
@@ -23,34 +23,42 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.primarygroup;
package net.luckperms.api.context;
import java.util.Optional;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Calculates and caches a User's "primary group"
* Functional interface that accepts context key value pairs.
*/
public interface PrimaryGroupHolder {
@FunctionalInterface
public interface ContextConsumer {
/**
* Gets the name of the primary group, or null.
* Accepts a context pair.
*
* @return the name of the primary group, or null.
* @param key the key
* @param value the value
*/
String getValue();
void accept(@NonNull String key, @NonNull String value);
/**
* Gets the primary group which is stored against the user's data.
* Accepts a context pair.
*
* @return the stored value
* @param context the context
*/
Optional<String> getStoredValue();
default void accept(@NonNull Context context) {
accept(context.getKey(), context.getValue());
}
/**
* Sets the primary group which is stored against the user's data.
* Accepts a context set.
*
* @param storedValue the new stored value
* @param contextSet the context set
*/
void setStoredValue(String storedValue);
default void accept(@NonNull ContextSet contextSet) {
for (Context entry : contextSet) {
accept(entry);
}
}
}
@@ -23,15 +23,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.context;
package net.luckperms.api.context;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.User;
import net.luckperms.api.model.user.User;
import net.luckperms.api.query.QueryMode;
import net.luckperms.api.query.QueryOptions;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Optional;
import javax.annotation.Nonnull;
/**
* Manages {@link ContextCalculator}s, and calculates applicable contexts for a
* given type.
@@ -44,12 +45,12 @@ import javax.annotation.Nonnull;
*
* <p></p>
* <ul>
* <li>{@code org.bukkit.entity.Player}</li>
* <li>{@code net.md_5.bungee.api.connection.ProxiedPlayer}</li>
* <li>{@code org.spongepowered.api.service.permission.Subject}</li>
* <li>{@code org.bukkit.entity.Player}</li>
* <li>{@code net.md_5.bungee.api.connection.ProxiedPlayer}</li>
* <li>{@code org.spongepowered.api.service.permission.Subject}</li>
* <li>{@code cn.nukkit.Player}</li>
* <li>{@code com.velocitypowered.api.proxy.Player}</li>
* </ul>
*
* @since 4.0
*/
public interface ContextManager {
@@ -59,116 +60,97 @@ public interface ContextManager {
* @param subject the subject
* @return the applicable context for the subject
*/
@Nonnull
ImmutableContextSet getApplicableContext(@Nonnull Object subject);
@NonNull ImmutableContextSet getContext(@NonNull Object subject);
/**
* Queries the ContextManager for current context values for the subject.
* Queries the ContextManager for current context values for the given User.
*
* <p>This will only return a value if the player corresponding to the
* {@link User} is online.</p>
*
* <p>If you need to obtain a {@link ImmutableContextSet} instance
* regardless, you should initially try this method, and then fallback on
* {@link #getStaticContext()}.</p>
*
* @param user the user
* @return the applicable context for the subject
*/
@NonNull Optional<ImmutableContextSet> getContext(@NonNull User user);
/**
* Gets the contexts from the static calculators in this manager.
*
* <p>Static calculators provide the same context for all subjects, and are
* marked as such when registered.</p>
*
* @return the current active static contexts
*/
@NonNull ImmutableContextSet getStaticContext();
/**
* Creates a new {@link QueryOptions.Builder}.
*
* @param mode the mode
* @return a new query options builder
*/
QueryOptions.@NonNull Builder queryOptionsBuilder(@NonNull QueryMode mode);
/**
* Obtains current {@link QueryOptions} for the subject.
*
* @param subject the subject
* @return the applicable context for the subject
* @return the query options for the subject
*/
@Nonnull
Contexts getApplicableContexts(@Nonnull Object subject);
@NonNull QueryOptions getQueryOptions(@NonNull Object subject);
/**
* Queries the ContextManager for current context values for the given User.
* Obtains current {@link QueryOptions} for the given User.
*
* <p>This will only return a value if the player corresponding to the
* {@link User} is online.</p>
*
* <p>If you need to be a {@link Contexts} instance regardless, you should
* initially try this method, and then fallback on {@link #getStaticContext()}.</p>
* <p>If you need to obtain a {@link QueryOptions} instance regardless, you should
* initially try this method, and then fallback on {@link #getStaticQueryOptions()}.</p>
*
* @param user the user
* @return the applicable context for the subject
* @return the query options for the subject
*/
@Nonnull
Optional<ImmutableContextSet> lookupApplicableContext(@Nonnull User user);
@NonNull Optional<QueryOptions> getQueryOptions(@NonNull User user);
/**
* Queries the ContextManager for current context values for the given User.
* Gets the static query options, using the registered static context calculators.
*
* <p>This will only return a value if the player corresponding to the
* {@link User} is online.</p>
*
* <p>If you need to be a {@link Contexts} instance regardless, you should
* initially try this method, and then fallback on {@link #getStaticContexts()}.</p>
*
* @param user the user
* @return the applicable context for the subject
* @return the current static query options
*/
@Nonnull
Optional<Contexts> lookupApplicableContexts(@Nonnull User user);
/**
* Gets the contexts from the static calculators in this manager.
*
* <p>Static calculators provide the same context for all subjects, and are
* marked as such when registered.</p>
*
* @return the current active static contexts
*/
@Nonnull
ImmutableContextSet getStaticContext();
/**
* Gets the contexts from the static calculators in this manager.
*
* <p>Static calculators provide the same context for all subjects, and are
* marked as such when registered.</p>
*
* @return the current active static contexts
*/
@Nonnull
Contexts getStaticContexts();
/**
* Forms a {@link Contexts} instance from an {@link ImmutableContextSet}.
*
* <p>This method relies on the plugins configuration to form the
* {@link Contexts} instance.</p>
*
* @param subject the reference subject
* @param contextSet the context set
* @return a contexts instance
*/
@Nonnull
Contexts formContexts(@Nonnull Object subject, @Nonnull ImmutableContextSet contextSet);
/**
* Forms a {@link Contexts} instance from an {@link ImmutableContextSet}.
*
* <p>This method relies on the plugins configuration to form the
* {@link Contexts} instance.</p>
*
* @param contextSet the context set
* @return a contexts instance
*/
@Nonnull
Contexts formContexts(@Nonnull ImmutableContextSet contextSet);
@NonNull QueryOptions getStaticQueryOptions();
/**
* Registers a context calculator with the manager.
*
* @param calculator the calculator
*/
void registerCalculator(@Nonnull ContextCalculator<?> calculator);
void registerCalculator(@NonNull ContextCalculator<?> calculator);
/**
* Registers a static context calculator with the manager.
*
* <p>Static calculators provide the same context for all subjects.</p>
* Unregisters a context calculator with the manager.
*
* @param calculator the calculator
*/
void registerStaticCalculator(@Nonnull StaticContextCalculator calculator);
void unregisterCalculator(@NonNull ContextCalculator<?> calculator);
/**
* Gets the {@link ContextSetFactory}, responsible for creating
* {@link ContextSet} instances.
*
* @return the context set factory
*/
@NonNull ContextSetFactory getContextSetFactory();
/**
* Invalidates the lookup cache for a given subject
*
* @param subject the subject
*/
void invalidateCache(@Nonnull Object subject);
void invalidateCache(@NonNull Object subject);
}
@@ -23,9 +23,9 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.context;
package net.luckperms.api.context;
import com.google.common.collect.Multimap;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Iterator;
import java.util.Map;
@@ -33,8 +33,6 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nonnull;
/**
* A set of contexts.
*
@@ -58,100 +56,8 @@ import javax.annotation.Nonnull;
* <p>Two default ContextSet implementations are provided.
* {@link MutableContextSet} allows the addition and removal of context keys
* after construction, and {@link ImmutableContextSet} does not.</p>
*
* @since 2.13
*/
public interface ContextSet extends Iterable<Map.Entry<String, String>> {
/**
* Creates an {@link ImmutableContextSet} from a context pair.
*
* @param key the key
* @param value the value
* @return a new ImmutableContextSet containing one context pair
* @throws NullPointerException if key or value is null
*/
@Nonnull
static ImmutableContextSet singleton(@Nonnull String key, @Nonnull String value) {
return ImmutableContextSet.singleton(key, value);
}
/**
* Creates an {@link ImmutableContextSet} from two context pairs.
*
* @param key1 the first key
* @param value1 the first value
* @param key2 the second key
* @param value2 the second value
* @return a new ImmutableContextSet containing the two pairs
* @throws NullPointerException if any of the keys or values are null
* @since 3.1
*/
@Nonnull
static ImmutableContextSet of(@Nonnull String key1, @Nonnull String value1, @Nonnull String key2, @Nonnull String value2) {
return ImmutableContextSet.of(key1, value1, key2, value2);
}
/**
* Creates an {@link ImmutableContextSet} from an existing {@link Iterable} of {@link Map.Entry}s.
*
* @param iterable the iterable to copy from
* @return a new ImmutableContextSet representing the pairs in the iterable
* @throws NullPointerException if the iterable is null
*/
@Nonnull
static ImmutableContextSet fromEntries(@Nonnull Iterable<? extends Map.Entry<String, String>> iterable) {
return ImmutableContextSet.fromEntries(iterable);
}
/**
* Creates an {@link ImmutableContextSet} from an existing {@link Map}.
*
* @param map the map to copy from
* @return a new ImmutableContextSet representing the pairs from the map
* @throws NullPointerException if the map is null
*/
@Nonnull
static ImmutableContextSet fromMap(@Nonnull Map<String, String> map) {
return ImmutableContextSet.fromMap(map);
}
/**
* Creates an {@link ImmutableContextSet} from an existing {@link Multimap}.
*
* @param multimap the multimap to copy from
* @return a new ImmutableContextSet representing the pairs in the multimap
* @throws NullPointerException if the multimap is null
* @since 2.16
*/
@Nonnull
static ImmutableContextSet fromMultimap(@Nonnull Multimap<String, String> multimap) {
return ImmutableContextSet.fromMultimap(multimap);
}
/**
* Creates an new {@link ImmutableContextSet} from an existing {@link Set}.
*
* <p>Only really useful for converting between mutable and immutable types.</p>
*
* @param contextSet the context set to copy from
* @return a new ImmutableContextSet with the same content and the one provided
* @throws NullPointerException if contextSet is null
*/
@Nonnull
static ImmutableContextSet fromSet(@Nonnull ContextSet contextSet) {
return ImmutableContextSet.fromSet(contextSet);
}
/**
* Returns an empty {@link ImmutableContextSet}.
*
* @return an empty ImmutableContextSet
*/
@Nonnull
static ImmutableContextSet empty() {
return ImmutableContextSet.empty();
}
public interface ContextSet extends Iterable<Context> {
/**
* Gets if this {@link ContextSet} is immutable.
@@ -170,8 +76,7 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
*
* @return an immutable representation of this set
*/
@Nonnull
ImmutableContextSet makeImmutable();
@NonNull ImmutableContextSet immutableCopy();
/**
* Creates a mutable copy of this {@link ContextSet}.
@@ -180,13 +85,11 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
* {@link #isImmutable() mutability} of this set.</p>
*
* @return a mutable ContextSet
* @since 2.16
*/
@Nonnull
MutableContextSet mutableCopy();
@NonNull MutableContextSet mutableCopy();
/**
* Returns a {@link Set} of {@link Map.Entry}s representing the current
* Returns a {@link Set} of {@link Context}s representing the current
* state of this {@link ContextSet}.
*
* <p>The returned set is immutable, and is a copy of the current set.
@@ -194,8 +97,18 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
*
* @return an immutable set
*/
@Nonnull
Set<Map.Entry<String, String>> toSet();
@NonNull Set<Context> toSet();
/**
* Returns a {@link Map} representing the current state of this
* {@link ContextSet}.
*
* <p>The returned set is immutable, and is a copy of the current set.
* (will not update live)</p>
*
* @return a map
*/
@NonNull Map<String, Set<String>> toMap();
/**
* Returns a {@link Map} <b>loosely</b> representing the current state of
@@ -207,29 +120,11 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
* <p>As a single context key can be mapped to multiple values, this method
* may not be a true representation of the set.</p>
*
* <p>If you need a representation of the set in a Java collection instance,
* use {@link #toSet()} or {@link #toMultimap()} followed by
* {@link Multimap#asMap()}.</p>
*
* @return an immutable map
* @deprecated because the resultant map may not contain all data in the ContextSet
*/
@Nonnull
@Deprecated
Map<String, String> toMap();
/**
* Returns a {@link Multimap} representing the current state of this
* {@link ContextSet}.
*
* <p>The returned multimap is immutable, and is a copy of the current set.
* (will not update live)</p>
*
* @return a multimap
* @since 2.16
*/
@Nonnull
Multimap<String, String> toMultimap();
@NonNull Map<String, String> toFlattenedMap();
/**
* Returns an {@link Iterator} over each of the context pairs in this set.
@@ -241,9 +136,8 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
*
* @return an iterator
*/
@Nonnull
@Override
Iterator<Map.Entry<String, String>> iterator();
@NonNull Iterator<Context> iterator();
/**
* Returns if the {@link ContextSet} contains at least one value for the
@@ -253,7 +147,7 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
* @return true if the set contains a value for the key
* @throws NullPointerException if the key is null
*/
boolean containsKey(@Nonnull String key);
boolean containsKey(@NonNull String key);
/**
* Returns a {@link Set} of the values mapped to the given key.
@@ -265,8 +159,7 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
* @return a set of values
* @throws NullPointerException if the key is null
*/
@Nonnull
Set<String> getValues(@Nonnull String key);
@NonNull Set<String> getValues(@NonNull String key);
/**
* Returns any value from this {@link ContextSet} matching the key, if present.
@@ -276,10 +169,8 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
*
* @param key the key to find values for
* @return an optional containing any match
* @since 3.1
*/
@Nonnull
default Optional<String> getAnyValue(@Nonnull String key) {
default @NonNull Optional<String> getAnyValue(@NonNull String key) {
return getValues(key).stream().findAny();
}
@@ -291,7 +182,7 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
* @return true if the set contains the context pair
* @throws NullPointerException if the key or value is null
*/
boolean has(@Nonnull String key, @Nonnull String value);
boolean contains(@NonNull String key, @NonNull String value);
/**
* Returns if the {@link ContextSet} contains a given context pairing.
@@ -300,9 +191,9 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
* @return true if the set contains the context pair
* @throws NullPointerException if the key or value is null
*/
default boolean has(@Nonnull Map.Entry<String, String> entry) {
default boolean contains(@NonNull Context entry) {
Objects.requireNonNull(entry, "entry");
return has(entry.getKey(), entry.getValue());
return contains(entry.getKey(), entry.getValue());
}
/**
@@ -315,33 +206,8 @@ public interface ContextSet extends Iterable<Map.Entry<String, String>> {
*
* @param other the other set to check
* @return true if all entries in this set are also in the other set
* @since 3.1
*/
default boolean isSatisfiedBy(@Nonnull ContextSet other) {
if (this == other) {
return true;
}
Objects.requireNonNull(other, "other");
if (this.isEmpty()) {
// this is empty, so is therefore always satisfied.
return true;
} else if (other.isEmpty()) {
// this set isn't empty, but the other one is
return false;
} else if (this.size() > other.size()) {
// this set has more unique entries than the other set, so there's no way this can be satisfied.
return false;
} else {
// neither are empty, we need to compare the individual entries
for (Map.Entry<String, String> context : toSet()) {
if (!other.has(context)) {
return false;
}
}
return true;
}
}
boolean isSatisfiedBy(@NonNull ContextSet other);
/**
* Returns if the {@link ContextSet} is empty.
@@ -0,0 +1,43 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 net.luckperms.api.context;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* A factory for creating {@link ContextSet}s.
*/
public interface ContextSetFactory {
ImmutableContextSet.@NonNull Builder immutableBuilder();
@NonNull ImmutableContextSet immutableOf(@NonNull String key, @NonNull String value);
@NonNull ImmutableContextSet immutableEmpty();
@NonNull MutableContextSet mutable();
}
@@ -23,17 +23,24 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.calculators;
package net.luckperms.api.context;
/**
* Extension of {@link CalculatorFactory} which keeps a record of produced
* calculators and provides a means to invalidate them all in bulk.
* Some default context keys used by the plugin.
*/
public interface PlatformCalculatorFactory extends CalculatorFactory {
public final class DefaultContextKeys {
private DefaultContextKeys() {
throw new AssertionError();
}
/**
* Invalidates all calculators build by this factory
* The context key used to denote the subjects server.
*/
void invalidateAll();
public static final String SERVER_KEY = "server";
/**
* The context key used to denote the subjects world.
*/
public static final String WORLD_KEY = "world";
}
@@ -0,0 +1,139 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 net.luckperms.api.context;
import net.luckperms.api.LuckPermsProvider;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Objects;
/**
* An immutable implementation of {@link ContextSet}.
*/
public interface ImmutableContextSet extends ContextSet {
/**
* Creates an {@link ImmutableContextSet.Builder}.
*
* @return a new ImmutableContextSet builder
*/
static @NonNull Builder builder() {
return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableBuilder();
}
/**
* Returns an empty {@link ImmutableContextSet}.
*
* @return an empty ImmutableContextSet
*/
static @NonNull ImmutableContextSet empty() {
return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableEmpty();
}
/**
* Creates an {@link ImmutableContextSet} from a context pair.
*
* @param key the key
* @param value the value
* @return a new ImmutableContextSet containing one context pair
* @throws NullPointerException if key or value is null
*/
static @NonNull ImmutableContextSet of(@NonNull String key, @NonNull String value) {
return LuckPermsProvider.get().getContextManager().getContextSetFactory().immutableOf(key, value);
}
/**
* @deprecated Already immutable!
*/
@Override
@Deprecated
@NonNull ImmutableContextSet immutableCopy();
/**
* A builder for {@link ImmutableContextSet}.
*/
interface Builder {
/**
* Adds a context to the set.
*
* @param key the key to add
* @param value the value to add
* @return the builder
* @throws NullPointerException if the key or value is null
* @see MutableContextSet#add(String, String)
*/
@NonNull Builder add(@NonNull String key, @NonNull String value);
/**
* Adds a context to the set.
*
* @param entry the entry to add
* @return the builder
* @throws NullPointerException if the entry is null
* @see MutableContextSet#add(Context)
*/
default @NonNull Builder add(@NonNull Context entry) {
Objects.requireNonNull(entry, "entry");
add(entry.getKey(), entry.getValue());
return this;
}
/**
* Adds the contexts contained in the given {@link Iterable} to the set.
*
* @param iterable an iterable of key value context pairs
* @return the builder
* @throws NullPointerException if iterable is null
* @see MutableContextSet#addAll(Iterable)
*/
default @NonNull Builder addAll(@NonNull Iterable<Context> iterable) {
for (Context e : Objects.requireNonNull(iterable, "iterable")) {
add(e);
}
return this;
}
/**
* Adds of of the contexts in another {@link ContextSet} to the set.
*
* @param contextSet the set to add from
* @return the builder
* @throws NullPointerException if the contextSet is null
* @see MutableContextSet#addAll(ContextSet)
*/
@NonNull Builder addAll(@NonNull ContextSet contextSet);
/**
* Creates a {@link ImmutableContextSet} from the values previously
* added to the builder.
*
* @return an {@link ImmutableContextSet} from the builder
*/
@NonNull ImmutableContextSet build();
}
}
@@ -0,0 +1,126 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 net.luckperms.api.context;
import net.luckperms.api.LuckPermsProvider;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Objects;
/**
* A mutable implementation of {@link ContextSet}.
*/
public interface MutableContextSet extends ContextSet {
/**
* Creates a new empty MutableContextSet.
*
* @return a new MutableContextSet
*/
static @NonNull MutableContextSet create() {
return LuckPermsProvider.get().getContextManager().getContextSetFactory().mutable();
}
/**
* Creates a {@link MutableContextSet} from a context pair.
*
* @param key the key
* @param value the value
* @return a new MutableContextSet containing one context pair
* @throws NullPointerException if key or value is null
*/
static @NonNull MutableContextSet of(@NonNull String key, @NonNull String value) {
Objects.requireNonNull(key, "key");
Objects.requireNonNull(value, "value");
MutableContextSet set = create();
set.add(key, value);
return set;
}
/**
* Adds a context to this set.
*
* @param key the key to add
* @param value the value to add
* @throws NullPointerException if the key or value is null
*/
void add(@NonNull String key, @NonNull String value);
/**
* Adds a context to this set.
*
* @param entry the entry to add
* @throws NullPointerException if the entry is null
*/
default void add(@NonNull Context entry) {
Objects.requireNonNull(entry, "entry");
add(entry.getKey(), entry.getValue());
}
/**
* Adds the contexts contained in the given {@link Iterable} to this set.
*
* @param iterable an iterable of key value context pairs
* @throws NullPointerException if iterable is null
*/
default void addAll(@NonNull Iterable<Context> iterable) {
for (Context e : Objects.requireNonNull(iterable, "iterable")) {
add(e);
}
}
/**
* Adds of of the contexts in another {@link ContextSet} to this set.
*
* @param contextSet the set to add from
* @throws NullPointerException if the contextSet is null
*/
void addAll(@NonNull ContextSet contextSet);
/**
* Removes a context from this set.
*
* @param key the key to remove
* @param value the value to remove
* @throws NullPointerException if the key or value is null
*/
void remove(@NonNull String key, @NonNull String value);
/**
* Removes all contexts from this set with the given key.
*
* @param key the key to remove
* @throws NullPointerException if the key is null
*/
void removeAll(@NonNull String key);
/**
* Removes all contexts from the set.
*/
void clear();
}
@@ -23,41 +23,53 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.context;
package net.luckperms.api.context;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Objects;
import java.util.function.Supplier;
/**
* Extension of {@link ContextCalculator} which provides the same context
* regardless of the subject.
*
* @since 4.0
*/
@FunctionalInterface
public interface StaticContextCalculator extends ContextCalculator<Object> {
/**
* Adds this calculators context to the given accumulator.
* Creates a new {@link StaticContextCalculator} that provides a single context.
*
* @param accumulator a map of contexts to add to
* @return the map
* @param key the key of the context provided by the calculator
* @param valueFunction the function used to compute the corresponding value
* for each query. A context will not be "accumulated"
* if the value returned is null.
* @return the resultant calculator
*/
@Nonnull
MutableContextSet giveApplicableContext(@Nonnull MutableContextSet accumulator);
/**
* Gives the subject all of the applicable contexts they meet
*
* @param subject the subject to add contexts to
* @param accumulator a map of contexts to add to
* @return the map
*/
@Nonnull
@Override
@Deprecated
default MutableContextSet giveApplicableContext(@Nullable Object subject, @Nonnull MutableContextSet accumulator) {
return giveApplicableContext(accumulator);
static StaticContextCalculator forSingleContext(String key, Supplier<String> valueFunction) {
Objects.requireNonNull(key, "key");
Objects.requireNonNull(valueFunction, "valueFunction");
return consumer -> {
String value = valueFunction.get();
if (value != null) {
consumer.accept(key, value);
}
};
}
/**
* Submits any contexts this calculator determines to be applicable.
*
* <p>Care should be taken to ensure implementations of this method meet the
* general requirements for {@link ContextCalculator}, defined in the class
* doc.</p>
*
* @param consumer the {@link ContextConsumer} to submit contexts to
*/
void calculate(@NonNull ContextConsumer consumer);
@Override
default void calculate(@NonNull Object target, @NonNull ContextConsumer consumer) {
calculate(consumer);
}
}
@@ -23,26 +23,24 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event;
package net.luckperms.api.event;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Set;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
/**
* The LuckPerms event bus.
*
* <p>Used to subscribe (or "listen") to LuckPerms events.</p>
*
* @since 3.0
*/
public interface EventBus {
/**
* Registers a new subscription to the given event.
*
* <p>The returned {@link EventHandler} instance encapsulates the subscription state. It has
* <p>The returned {@link EventSubscription} instance encapsulates the subscription state. It has
* methods which can be used to terminate the subscription, or view stats about the nature of
* the subscription.</p>
*
@@ -51,19 +49,18 @@ public interface EventBus {
* @param <T> the event class
* @return an event handler instance representing this subscription
*/
@Nonnull
<T extends LuckPermsEvent> EventHandler<T> subscribe(@Nonnull Class<T> eventClass, @Nonnull Consumer<? super T> handler);
@NonNull <T extends LuckPermsEvent> EventSubscription<T> subscribe(@NonNull Class<T> eventClass, @NonNull Consumer<? super T> handler);
/**
* Registers a new subscription to the given event.
*
* <p>The returned {@link EventHandler} instance encapsulates the subscription state. It has
* <p>The returned {@link EventSubscription} instance encapsulates the subscription state. It has
* methods which can be used to terminate the subscription, or view stats about the nature of
* the subscription.</p>
*
* <p>Unlike {@link #subscribe(Class, Consumer)}, this method accepts an additional parameter
* for {@code plugin}. This object must be a "plugin" instance on the platform, and is used to
* automatically {@link EventHandler#unregister() unregister} the subscription when the
* automatically {@link EventSubscription#close() unregister} the subscription when the
* corresponding plugin is disabled.</p>
*
* @param <T> the event class
@@ -72,8 +69,7 @@ public interface EventBus {
* @param handler the event handler
* @return an event handler instance representing this subscription
*/
@Nonnull
<T extends LuckPermsEvent> EventHandler<T> subscribe(Object plugin, @Nonnull Class<T> eventClass, @Nonnull Consumer<? super T> handler);
@NonNull <T extends LuckPermsEvent> EventSubscription<T> subscribe(Object plugin, @NonNull Class<T> eventClass, @NonNull Consumer<? super T> handler);
/**
* Gets a set of all registered handlers for a given event.
@@ -82,7 +78,6 @@ public interface EventBus {
* @param <T> the event class
* @return an immutable set of event handlers
*/
@Nonnull
<T extends LuckPermsEvent> Set<EventHandler<T>> getHandlers(@Nonnull Class<T> eventClass);
@NonNull <T extends LuckPermsEvent> Set<EventSubscription<T>> getSubscriptions(@NonNull Class<T> eventClass);
}
@@ -23,26 +23,25 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event;
package net.luckperms.api.event;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
/**
* Represents a subscription to a {@link LuckPermsEvent}.
*
* @param <T> the event class
*/
public interface EventHandler<T extends LuckPermsEvent> extends AutoCloseable {
public interface EventSubscription<T extends LuckPermsEvent> extends AutoCloseable {
/**
* Gets the class this handler is listening to
*
* @return the event class
*/
@Nonnull
Class<T> getEventClass();
@NonNull Class<T> getEventClass();
/**
* Returns true if this handler is active
@@ -52,29 +51,15 @@ public interface EventHandler<T extends LuckPermsEvent> extends AutoCloseable {
boolean isActive();
/**
* Unregisters this handler from the event bus
*
* @return true if the handler wasn't already unregistered
* Unregisters this handler from the event bus.
*/
boolean unregister();
@Override
void close();
/**
* Gets the event consumer responsible for handling the event
*
* @return the event consumer
*/
@Nonnull
Consumer<? super T> getConsumer();
/**
* Gets the number of times this handler has been called
*
* @return the number of times this handler has been called
*/
int getCallCount();
@Override
default void close() {
unregister();
}
@NonNull Consumer<? super T> getHandler();
}
@@ -23,16 +23,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event;
package net.luckperms.api.event;
import me.lucko.luckperms.api.LuckPermsApi;
import net.luckperms.api.LuckPerms;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* A superinterface for all LuckPerms events.
*
* @since 3.0
*/
public interface LuckPermsEvent {
@@ -41,7 +39,13 @@ public interface LuckPermsEvent {
*
* @return the api instance
*/
@Nonnull
LuckPermsApi getApi();
@NonNull LuckPerms getLuckPerms();
/**
* Gets the type of the event.
*
* @return the type of the event
*/
@NonNull Class<? extends LuckPermsEvent> getEventType();
}
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.cause;
package net.luckperms.api.event.cause;
/**
* The cause of a group/track creation
@@ -35,6 +35,11 @@ public enum CreationCause {
*/
COMMAND,
/**
* The creation was caused by the web editor
*/
WEB_EDITOR,
/**
* The creation was caused by an API call
*/
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.cause;
package net.luckperms.api.event.cause;
/**
* The cause of a group/track deletion
@@ -0,0 +1,47 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 net.luckperms.api.event.extension;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.extension.Extension;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when an {@link Extension} is loaded.
*/
public interface ExtensionLoadEvent extends LuckPermsEvent {
/**
* Gets the extension that was loaded.
*
* @return the extension
*/
@Param(0)
@NonNull Extension getExtension();
}
@@ -23,18 +23,17 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.group;
package net.luckperms.api.event.group;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.caching.GroupData;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.cacheddata.CachedDataManager;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.model.group.Group;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a groups {@link GroupData} is loaded.
*
* @since 4.0
* Called when a groups {@link CachedDataManager} is loaded.
*/
public interface GroupCacheLoadEvent extends LuckPermsEvent {
@@ -43,15 +42,15 @@ public interface GroupCacheLoadEvent extends LuckPermsEvent {
*
* @return the group
*/
@Nonnull
Group getGroup();
@Param(0)
@NonNull Group getGroup();
/**
* Gets the data that was loaded
*
* @return the loaded data
*/
@Nonnull
GroupData getLoadedData();
@Param(1)
@NonNull CachedDataManager getLoadedData();
}
@@ -23,13 +23,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.group;
package net.luckperms.api.event.group;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.cause.CreationCause;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.event.cause.CreationCause;
import net.luckperms.api.model.group.Group;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a group is created
@@ -41,15 +42,15 @@ public interface GroupCreateEvent extends LuckPermsEvent {
*
* @return the new group
*/
@Nonnull
Group getGroup();
@Param(0)
@NonNull Group getGroup();
/**
* Gets the cause of the creation
*
* @return the cause of the creation
*/
@Nonnull
CreationCause getCause();
@Param(1)
@NonNull CreationCause getCause();
}
@@ -23,18 +23,17 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.group;
package net.luckperms.api.event.group;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.caching.GroupData;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.cacheddata.CachedDataManager;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.model.group.Group;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a groups cached data is refreshed
*
* @since 4.0
*/
public interface GroupDataRecalculateEvent extends LuckPermsEvent {
@@ -43,15 +42,15 @@ public interface GroupDataRecalculateEvent extends LuckPermsEvent {
*
* @return the group
*/
@Nonnull
Group getGroup();
@Param(0)
@NonNull Group getGroup();
/**
* Gets the data that was recalculated
*
* @return the data
*/
@Nonnull
GroupData getData();
@Param(1)
@NonNull CachedDataManager getData();
}
@@ -23,16 +23,17 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.group;
package net.luckperms.api.event.group;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.cause.DeletionCause;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.event.cause.DeletionCause;
import net.luckperms.api.node.Node;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Set;
import javax.annotation.Nonnull;
/**
* Called when a group is deleted
*/
@@ -43,23 +44,23 @@ public interface GroupDeleteEvent extends LuckPermsEvent {
*
* @return the name of the deleted group
*/
@Nonnull
String getGroupName();
@Param(0)
@NonNull String getGroupName();
/**
* Gets an immutable copy of the groups existing data
*
* @return a copy of the groups existing data
*/
@Nonnull
Set<Node> getExistingData();
@Param(1)
@NonNull Set<Node> getExistingData();
/**
* Gets the cause of the deletion
*
* @return the cause of the deletion
*/
@Nonnull
DeletionCause getCause();
@Param(2)
@NonNull DeletionCause getCause();
}
@@ -23,9 +23,9 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.group;
package net.luckperms.api.event.group;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
/**
* Called when all groups have been loaded in from storage.
@@ -23,12 +23,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.group;
package net.luckperms.api.event.group;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.model.group.Group;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a group is loaded into memory from the storage.
@@ -42,7 +43,7 @@ public interface GroupLoadEvent extends LuckPermsEvent {
*
* @return the group that was loaded
*/
@Nonnull
Group getGroup();
@Param(0)
@NonNull Group getGroup();
}
@@ -23,13 +23,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.log;
package net.luckperms.api.event.log;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.event.type.Cancellable;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a log entry is about to be sent to notifiable players on the platform
@@ -41,22 +42,19 @@ public interface LogBroadcastEvent extends LuckPermsEvent, Cancellable {
*
* @return the log entry to be broadcasted
*/
@Nonnull
LogEntry getEntry();
@Param(0)
@NonNull Action getEntry();
/**
* Gets where the log entry originated from.
*
* @return the origin of the log
* @since 3.3
*/
@Nonnull
Origin getOrigin();
@Param(1)
@NonNull Origin getOrigin();
/**
* Represents where a log entry is from
*
* @since 3.3
*/
enum Origin {
@@ -23,20 +23,19 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.log;
package net.luckperms.api.event.log;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.event.type.Cancellable;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.UUID;
import javax.annotation.Nonnull;
/**
* Called when a log is about to be published to the network via the MessagingService
*
* @since 3.3
*/
public interface LogNetworkPublishEvent extends LuckPermsEvent, Cancellable {
@@ -45,15 +44,15 @@ public interface LogNetworkPublishEvent extends LuckPermsEvent, Cancellable {
*
* @return the id of the log entry being published
*/
@Nonnull
UUID getLogId();
@Param(0)
@NonNull UUID getLogId();
/**
* Gets the log entry to be published
*
* @return the log entry to be published
*/
@Nonnull
LogEntry getEntry();
@Param(1)
@NonNull Action getEntry();
}
@@ -23,14 +23,15 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.log;
package net.luckperms.api.event.log;
import me.lucko.luckperms.api.Entity;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.event.type.Cancellable;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.platform.PlatformEntity;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a log entry is about to be sent to specific notifiable object on
@@ -39,8 +40,6 @@ import javax.annotation.Nonnull;
* <p>This event is not called for players without the notify permission,
* but is called for objects which are ignoring log notifications (called with
* the cancelled flag set to true).</p>
*
* @since 4.1
*/
public interface LogNotifyEvent extends LuckPermsEvent, Cancellable {
@@ -49,24 +48,24 @@ public interface LogNotifyEvent extends LuckPermsEvent, Cancellable {
*
* @return the log entry to be sent
*/
@Nonnull
LogEntry getEntry();
@Param(0)
@NonNull Action getEntry();
/**
* Gets where the log entry originated from.
*
* @return the origin of the log
*/
@Nonnull
Origin getOrigin();
@Param(1)
@NonNull Origin getOrigin();
/**
* Gets the object to be notified.
*
* @return the object to notify
*/
@Nonnull
Entity getNotifiable();
@Param(2)
@NonNull PlatformEntity getNotifiable();
/**
* Represents where a log entry is from
@@ -23,13 +23,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.log;
package net.luckperms.api.event.log;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.event.type.Cancellable;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a log is about to be published to the storage file/table
@@ -41,7 +42,7 @@ public interface LogPublishEvent extends LuckPermsEvent, Cancellable {
*
* @return the log entry to be published
*/
@Nonnull
LogEntry getEntry();
@Param(0)
@NonNull Action getEntry();
}
@@ -23,19 +23,18 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.log;
package net.luckperms.api.event.log;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.actionlog.Action;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.UUID;
import javax.annotation.Nonnull;
/**
* Called when a log entry is received via the MessagingService
*
* @since 3.3
*/
public interface LogReceiveEvent extends LuckPermsEvent {
@@ -44,15 +43,15 @@ public interface LogReceiveEvent extends LuckPermsEvent {
*
* @return the id of the log entry being received
*/
@Nonnull
UUID getLogId();
@Param(0)
@NonNull UUID getLogId();
/**
* Gets the log entry being received
*
* @return the log entry being received
*/
@Nonnull
LogEntry getEntry();
@Param(1)
@NonNull Action getEntry();
}
@@ -23,11 +23,12 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.node;
package net.luckperms.api.event.node;
import me.lucko.luckperms.api.Node;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.node.Node;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a node is added to a holder
@@ -39,7 +40,7 @@ public interface NodeAddEvent extends NodeMutateEvent {
*
* @return the node that was added
*/
@Nonnull
Node getNode();
@Param(4)
@NonNull Node getNode();
}
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.node;
package net.luckperms.api.event.node;
/**
* Called when a holder has their nodes cleared
@@ -23,16 +23,20 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.node;
package net.luckperms.api.event.node;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.model.PermissionHolder;
import net.luckperms.api.model.data.DataType;
import net.luckperms.api.model.group.Group;
import net.luckperms.api.model.user.User;
import net.luckperms.api.node.Node;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Set;
import javax.annotation.Nonnull;
/**
* Called when a node is added to/removed from a user/group
*/
@@ -43,41 +47,53 @@ public interface NodeMutateEvent extends LuckPermsEvent {
*
* @return the event target
*/
@Nonnull
PermissionHolder getTarget();
@Param(0)
@NonNull PermissionHolder getTarget();
/**
* Gets the data type that was mutated.
*
* @return the data type
*/
@Param(1)
@NonNull DataType getDataType();
/**
* Gets an immutable copy of the holders data before the change
*
* @return the data before the change
*/
@Nonnull
Set<Node> getDataBefore();
@Param(2)
@NonNull Set<Node> getDataBefore();
/**
* Gets an immutable copy of the holders data after the change
*
* @return the data after the change
*/
@Nonnull
Set<Node> getDataAfter();
@Param(3)
@NonNull Set<Node> getDataAfter();
/**
* Gets whether the target of this event is a {@link me.lucko.luckperms.api.User}
* Gets whether the target of this event is a {@link User}
*
* <p>This is equivalent to checking if getTarget() instanceof User</p>
*
* @return if the event is targeting a user
*/
boolean isUser();
default boolean isUser() {
return getTarget() instanceof User;
}
/**
* Gets whether the target of this event is a {@link me.lucko.luckperms.api.Group}
* Gets whether the target of this event is a {@link Group}
*
* <p>This is equivalent to checking if getTarget() instanceof Group</p>
*
* @return if the event is targeting a group
*/
boolean isGroup();
default boolean isGroup() {
return getTarget() instanceof Group;
}
}
@@ -23,11 +23,12 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.node;
package net.luckperms.api.event.node;
import me.lucko.luckperms.api.Node;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.node.Node;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a node is removed from a holder
@@ -39,7 +40,7 @@ public interface NodeRemoveEvent extends NodeMutateEvent {
*
* @return the node that was removed
*/
@Nonnull
Node getNode();
@Param(4)
@NonNull Node getNode();
}
@@ -23,47 +23,46 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.nodetype.types;
package net.luckperms.api.event.player;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.nodetype.NodeType;
import me.lucko.luckperms.api.nodetype.NodeTypeKey;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.model.PlayerSaveResult;
import net.luckperms.api.model.user.UserManager;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.NonNull;
import javax.annotation.Nonnull;
import java.util.UUID;
/**
* A sub-type of {@link Node} used to store meta assignments.
* Called when player data is saved to the storage.
*
* @since 4.2
* <p>Data can be saved using {@link UserManager#savePlayerData(UUID, String)}.</p>
*/
public interface MetaType extends NodeType, Map.Entry<String, String> {
public interface PlayerDataSaveEvent extends LuckPermsEvent {
/**
* The key for this type.
*/
NodeTypeKey<MetaType> KEY = new NodeTypeKey<MetaType>(){};
/**
* Gets the meta key.
* Gets the unique ID that was saved.
*
* @return the meta key
* @return the uuid
*/
@Nonnull
String getKey();
@Param(0)
@NonNull UUID getUniqueId();
/**
* Gets the meta value.
* Gets the username that was saved.
*
* @return the meta value
* @return the username
*/
@Nonnull
String getValue();
@Param(1)
@NonNull String getUsername();
/**
* Gets the result of the operation.
*
* @return the result
*/
@Param(2)
@NonNull PlayerSaveResult getResult();
@Override
@Deprecated
default String setValue(String value) {
throw new UnsupportedOperationException();
}
}
@@ -23,50 +23,71 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.user;
package net.luckperms.api.event.player;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.model.user.User;
import net.luckperms.api.util.Result;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.UUID;
import javax.annotation.Nonnull;
/**
* Called when LuckPerms has finished processing a certain Player's connection.
* Called when LuckPerms has finished processing a Player's initial connection.
*
* <p>This event will always execute during the platforms async login/auth event.
* All handlers will be called instantly.</p>
* <p>This event will always execute during the platforms async connection
* event. The LuckPerms platform listener processing the connection will block
* while this event is posted.</p>
*
* <p>This, among other things, allows you to wait until permission data is loaded
* for a User during the BungeeCord 'LoginEvent', as event priorities are ignored
* by the current implementation.</p>
* <p>This, among other things, allows you to wait until permission data is
* loaded for a User during the BungeeCord 'LoginEvent', as event priorities are
* ignored by the current implementation.</p>
*
* @since 3.4
* <p>The implementation will make an attempt to ensure this event is called
* for all connections, even if the operation to load User data was not
* successful. Note that LuckPerms will usually cancel the platform connection
* event if data could not be loaded.</p>
*/
public interface UserLoginProcessEvent extends LuckPermsEvent {
public interface PlayerLoginProcessEvent extends LuckPermsEvent, Result {
/**
* Gets the UUID of the connection which was processed
*
* @return the uuid of the connection which was processed
*/
@Nonnull
UUID getUuid();
@Param(0)
@NonNull UUID getUniqueId();
/**
* Gets the username of the connection which was processed
*
* @return the username of the connection which was processed
*/
@Nonnull
String getUsername();
@Param(1)
@NonNull String getUsername();
/**
* Gets if the login was processed successfully.
*
* @return true if the login was successful
*/
@Override
default boolean wasSuccessful() {
return getUser() != null;
}
/**
* Gets the resultant User instance which was loaded.
*
* <p>Returns {@code null} if the login was not processed
* {@link #wasSuccessful() successfully.}</p>
*
* @return the user instance
*/
User getUser();
@Param(2)
@Nullable User getUser();
}
@@ -23,16 +23,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.source;
package net.luckperms.api.event.source;
import me.lucko.luckperms.api.Entity;
import net.luckperms.api.platform.PlatformEntity;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Represents an {@link Entity} which was the {@link Source} of something.
*
* @since 4.1
* Represents an {@link PlatformEntity} which was the {@link Source} of something.
*/
public interface EntitySource extends Source {
@@ -41,7 +39,6 @@ public interface EntitySource extends Source {
*
* @return the entity
*/
@Nonnull
Entity getEntity();
@NonNull PlatformEntity getEntity();
}
@@ -23,18 +23,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.source;
package net.luckperms.api.event.source;
import me.lucko.luckperms.api.Entity;
import net.luckperms.api.platform.PlatformEntity;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Represents the source of an event.
*
* <p>Could also be described as the "thing" that caused an event to occur.</p>
*
* @since 4.1
*/
public interface Source {
@@ -43,8 +41,7 @@ public interface Source {
*
* @return the type
*/
@Nonnull
Type getType();
@NonNull Type getType();
/**
* Represents a type of source
@@ -52,7 +49,7 @@ public interface Source {
enum Type {
/**
* Represents an {@link Entity} source
* Represents an {@link PlatformEntity} source
*
* @see EntitySource
*/
@@ -23,9 +23,9 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.sync;
package net.luckperms.api.event.sync;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
/**
* Called when the configuration is reloaded
@@ -23,9 +23,9 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.sync;
package net.luckperms.api.event.sync;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
/**
* Called when an sync task has been completed
@@ -23,15 +23,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.sync;
package net.luckperms.api.event.sync;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.type.Cancellable;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.UUID;
import javax.annotation.Nonnull;
/**
* Called before a received network sync task runs
*/
@@ -42,7 +43,7 @@ public interface PreNetworkSyncEvent extends LuckPermsEvent, Cancellable {
*
* @return the id of the sync request
*/
@Nonnull
UUID getSyncId();
@Param(0)
@NonNull UUID getSyncId();
}
@@ -23,10 +23,10 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.sync;
package net.luckperms.api.event.sync;
import me.lucko.luckperms.api.event.Cancellable;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.type.Cancellable;
import net.luckperms.api.event.LuckPermsEvent;
/**
* Called before a sync task runs
@@ -23,13 +23,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.track;
package net.luckperms.api.event.track;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.cause.CreationCause;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.event.cause.CreationCause;
import net.luckperms.api.track.Track;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a track is created
@@ -41,15 +42,15 @@ public interface TrackCreateEvent extends LuckPermsEvent {
*
* @return the new track
*/
@Nonnull
Track getTrack();
@Param(0)
@NonNull Track getTrack();
/**
* Gets the cause of the creation
*
* @return the cause of the creation
*/
@Nonnull
CreationCause getCause();
@Param(1)
@NonNull CreationCause getCause();
}
@@ -23,15 +23,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.track;
package net.luckperms.api.event.track;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.cause.DeletionCause;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.event.cause.DeletionCause;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.List;
import javax.annotation.Nonnull;
/**
* Called when a track is deleted
*/
@@ -42,23 +43,23 @@ public interface TrackDeleteEvent extends LuckPermsEvent {
*
* @return the name of the deleted track
*/
@Nonnull
String getTrackName();
@Param(0)
@NonNull String getTrackName();
/**
* Gets an immutable copy of the tracks existing data
*
* @return a copy of the tracks existing data
*/
@Nonnull
List<String> getExistingData();
@Param(1)
@NonNull List<String> getExistingData();
/**
* Gets the cause of the deletion
*
* @return the cause of the deletion
*/
@Nonnull
DeletionCause getCause();
@Param(2)
@NonNull DeletionCause getCause();
}
@@ -23,9 +23,9 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.track;
package net.luckperms.api.event.track;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
/**
* Called when all tracks have been loaded in from storage.
@@ -23,12 +23,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.track;
package net.luckperms.api.event.track;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.track.Track;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a track is loaded into memory from the storage.
@@ -42,7 +43,7 @@ public interface TrackLoadEvent extends LuckPermsEvent {
*
* @return the track that was loaded
*/
@Nonnull
Track getTrack();
@Param(0)
@NonNull Track getTrack();
}
@@ -23,9 +23,11 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.track.mutate;
package net.luckperms.api.event.track.mutate;
import javax.annotation.Nonnull;
import net.luckperms.api.event.util.Param;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a group is added to a track
@@ -37,7 +39,7 @@ public interface TrackAddGroupEvent extends TrackMutateEvent {
*
* @return the group that was added
*/
@Nonnull
String getGroup();
@Param(3)
@NonNull String getGroup();
}
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.track.mutate;
package net.luckperms.api.event.track.mutate;
/**
* Called when a track is cleared
@@ -23,15 +23,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.track.mutate;
package net.luckperms.api.event.track.mutate;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.track.Track;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.List;
import javax.annotation.Nonnull;
/**
* Called when a track is changed
*/
@@ -42,23 +43,23 @@ public interface TrackMutateEvent extends LuckPermsEvent {
*
* @return the track that was mutated
*/
@Nonnull
Track getTrack();
@Param(0)
@NonNull Track getTrack();
/**
* Gets an immutable copy of the tracks data before the change
*
* @return the data before the change
*/
@Nonnull
List<String> getDataBefore();
@Param(1)
@NonNull List<String> getStateBefore();
/**
* Gets an immutable copy of the tracks data after the change
*
* @return the data after the change
*/
@Nonnull
List<String> getDataAfter();
@Param(2)
@NonNull List<String> getStateAfter();
}
@@ -23,9 +23,11 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.track.mutate;
package net.luckperms.api.event.track.mutate;
import javax.annotation.Nonnull;
import net.luckperms.api.event.util.Param;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a group is removed from a track
@@ -37,7 +39,7 @@ public interface TrackRemoveGroupEvent extends TrackMutateEvent {
*
* @return the group that was removed
*/
@Nonnull
String getGroup();
@Param(3)
@NonNull String getGroup();
}
@@ -23,12 +23,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event;
package net.luckperms.api.event.type;
import net.luckperms.api.event.util.Param;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nonnull;
/**
* Represents an event that can be cancelled
*/
@@ -39,24 +41,22 @@ public interface Cancellable {
*
* @return the cancellation
*/
@Nonnull
AtomicBoolean getCancellationState();
@Param(-1)
@NonNull AtomicBoolean cancellationState();
/**
* Returns true if the event is currently cancelled.
*
* @return if the event is cancelled
* @since 4.1
*/
default boolean isCancelled() {
return getCancellationState().get();
return cancellationState().get();
}
/**
* Returns true if the event is not currently cancelled.
*
* @return if the event is not cancelled
* @since 4.1
*/
default boolean isNotCancelled() {
return !isCancelled();
@@ -67,10 +67,9 @@ public interface Cancellable {
*
* @param cancelled the new state
* @return the previous state
* @since 4.1
*/
default boolean setCancelled(boolean cancelled) {
return getCancellationState().getAndSet(cancelled);
return cancellationState().getAndSet(cancelled);
}
}
@@ -23,16 +23,15 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event;
package net.luckperms.api.event.type;
import me.lucko.luckperms.api.event.source.Source;
import net.luckperms.api.event.source.Source;
import net.luckperms.api.event.util.Param;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Represents an event with a {@link Source}.
*
* @since 4.1
*/
public interface Sourced {
@@ -44,7 +43,6 @@ public interface Sourced {
*
* @return the source
*/
@Nonnull
Source getSource();
@NonNull @Param(-1) Source getSource();
}
@@ -23,16 +23,17 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.user;
package net.luckperms.api.event.user;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.cacheddata.CachedDataManager;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.model.user.User;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a users {@link me.lucko.luckperms.api.caching.UserData} is loaded.
* Called when a users {@link CachedDataManager} is loaded.
*/
public interface UserCacheLoadEvent extends LuckPermsEvent {
@@ -41,15 +42,15 @@ public interface UserCacheLoadEvent extends LuckPermsEvent {
*
* @return the user
*/
@Nonnull
User getUser();
@Param(0)
@NonNull User getUser();
/**
* Gets the data that was loaded
*
* @return the loaded data
*/
@Nonnull
UserData getLoadedData();
@Param(1)
@NonNull CachedDataManager getLoadedData();
}
@@ -23,13 +23,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.user;
package net.luckperms.api.event.user;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.cacheddata.CachedDataManager;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.model.user.User;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a users cached data is refreshed
@@ -41,15 +42,15 @@ public interface UserDataRecalculateEvent extends LuckPermsEvent {
*
* @return the user
*/
@Nonnull
User getUser();
@Param(0)
@NonNull User getUser();
/**
* Gets the data that was recalculated
*
* @return the data
*/
@Nonnull
UserData getData();
@Param(1)
@NonNull CachedDataManager getData();
}
@@ -23,14 +23,15 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.user;
package net.luckperms.api.event.user;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.UUID;
import javax.annotation.Nonnull;
/**
* Called when the user logs into the network for the first time.
*
@@ -49,15 +50,15 @@ public interface UserFirstLoginEvent extends LuckPermsEvent {
*
* @return the uuid of the user
*/
@Nonnull
UUID getUuid();
@Param(0)
@NonNull UUID getUniqueId();
/**
* Gets the username of the user
*
* @return the username of the user
*/
@Nonnull
String getUsername();
@Param(1)
@NonNull String getUsername();
}
@@ -23,12 +23,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.user;
package net.luckperms.api.event.user;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.model.user.User;
import javax.annotation.Nonnull;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a user is loaded into memory from the storage.
@@ -40,7 +41,7 @@ public interface UserLoadEvent extends LuckPermsEvent {
*
* @return the user that was loaded
*/
@Nonnull
User getUser();
@Param(0)
@NonNull User getUser();
}
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.user.track;
package net.luckperms.api.event.user.track;
/**
* Represents the type of action performed in a {@link UserTrackEvent}
@@ -23,7 +23,9 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.user.track;
package net.luckperms.api.event.user.track;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a user is demoted down a track.
@@ -32,4 +34,8 @@ package me.lucko.luckperms.api.event.user.track;
*/
public interface UserDemoteEvent extends UserTrackEvent {
@Override
default @NonNull TrackAction getAction() {
return TrackAction.DEMOTION;
}
}
@@ -23,7 +23,9 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.user.track;
package net.luckperms.api.event.user.track;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Called when a user is promoted up a track.
@@ -32,4 +34,8 @@ package me.lucko.luckperms.api.event.user.track;
*/
public interface UserPromoteEvent extends UserTrackEvent {
@Override
default @NonNull TrackAction getAction() {
return TrackAction.PROMOTION;
}
}
@@ -23,17 +23,18 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.user.track;
package net.luckperms.api.event.user.track;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Sourced;
import net.luckperms.api.event.LuckPermsEvent;
import net.luckperms.api.event.util.Param;
import net.luckperms.api.event.type.Sourced;
import net.luckperms.api.model.user.User;
import net.luckperms.api.track.Track;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Optional;
import javax.annotation.Nonnull;
/**
* Called when a user interacts with a track through a promotion or demotion
*/
@@ -44,24 +45,23 @@ public interface UserTrackEvent extends LuckPermsEvent, Sourced {
*
* @return the track involved in the event
*/
@Nonnull
Track getTrack();
@Param(0)
@NonNull Track getTrack();
/**
* Gets the user who was promoted or demoted
*
* @return the user involved in the event
*/
@Nonnull
User getUser();
@Param(1)
@NonNull User getUser();
/**
* Gets the action performed
*
* @return the action performed
*/
@Nonnull
TrackAction getAction();
@NonNull TrackAction getAction();
/**
* Gets the group the user was promoted/demoted from.
@@ -70,15 +70,15 @@ public interface UserTrackEvent extends LuckPermsEvent, Sourced {
*
* @return the group the user was promoted/demoted from
*/
@Nonnull
Optional<String> getGroupFrom();
@Param(2)
@NonNull Optional<String> getGroupFrom();
/**
* Gets the group the user was promoted/demoted to
*
* @return the group the user was promoted/demoted to
*/
@Nonnull
Optional<String> getGroupTo();
@Param(3)
@NonNull Optional<String> getGroupTo();
}
@@ -0,0 +1,49 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 net.luckperms.api.event.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Represents the position of a parameter within an event.
*
* <p>This is an implementation detail and should not be relied upon.</p>
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Param {
/**
* Gets the index of the parameter.
*
* @return the index
*/
int value();
}
@@ -0,0 +1,50 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* 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 net.luckperms.api.extension;
import net.luckperms.api.LuckPerms;
/**
* Represents a simple extension "plugin" for LuckPerms.
*
* <p>Yes, that's right. A plugin for a plugin.</p>
*
* <p>Extensions should either declare a no-arg constructor, or a constructor
* that accepts a single {@link LuckPerms} parameter as it's only argument.</p>
*/
public interface Extension {
/**
* Loads the extension.
*/
void load();
/**
* Unloads the extension.
*/
void unload();
}
@@ -23,44 +23,40 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api;
package net.luckperms.api.extension;
import me.lucko.luckperms.api.caching.GroupData;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.OptionalInt;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
/**
* An inheritable holder of permission data.
* Manages extensions.
*/
public interface Group extends PermissionHolder {
public interface ExtensionManager {
/**
* Get the name of the group
* Loads the given extension.
*
* @return the name of the group
* @param extension the extension to load
*/
@Nonnull
String getName();
void loadExtension(Extension extension);
/**
* Gets the weight of this group, if present.
* Loads the extension at the given path.
*
* @return the group weight
* @since 2.17
* @param path the path to the extension
* @return the extension
* @throws IOException if the extension could not be loaded
*/
@Nonnull
OptionalInt getWeight();
@NonNull Extension loadExtension(Path path) throws IOException;
/**
* Gets the groups's {@link GroupData} cache.
* Gets a collection of all loaded extensions.
*
* @return the groups cached data.
* @since 4.0
* @return the loaded extensions
*/
@Nonnull
@Override
GroupData getCachedData();
@NonNull Collection<Extension> getLoadedExtensions();
}
Loaded 100 of 820 files, more files were not shown because too many files have changed in this diff. Show more