Compare commits

...
112 Commits
Author SHA1 Message Date
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
497 changed files with 5683 additions and 4188 deletions

No files matched your search

+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.
+5 -1
View File
@@ -1,5 +1,9 @@
![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://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)
# 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.
+10 -5
View File
@@ -1,12 +1,13 @@
project.version = '4.3'
project.version = '4.4'
dependencies {
compileOnly 'com.google.guava:guava:19.0'
compileOnly 'org.checkerframework:checker-qual:2.5.5'
}
// disabled by default
if (false && project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')) {
// Only used occasionally for deployment - not needed for normal builds.
/*
if (project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')) {
apply plugin: 'signing'
javadoc {
@@ -48,11 +49,15 @@ if (false && project.hasProperty('sonatypeUsername') && project.hasProperty('son
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://github.com/lucko/LuckPerms'
url 'https://luckperms.github.io'
licenses {
license {
@@ -73,7 +78,6 @@ if (false && project.hasProperty('sonatypeUsername') && project.hasProperty('son
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 {
@@ -91,3 +95,4 @@ if (false && project.hasProperty('sonatypeUsername') && project.hasProperty('son
}
}
}
*/
@@ -25,14 +25,11 @@
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 org.checkerframework.checker.nullness.qual.NonNull;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;
@@ -57,9 +54,9 @@ public class Contexts {
public static final String WORLD_KEY = "world";
/**
* The default {@link LookupSetting}s.
* The default {@link LookupSetting}s as a flag.
*/
private static final EnumSet<LookupSetting> DEFAULT_SETTINGS = EnumSet.of(
private static final byte DEFAULT_SETTINGS_FLAG = LookupSetting.createFlag(
LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER,
LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD,
LookupSetting.RESOLVE_INHERITANCE,
@@ -73,7 +70,7 @@ public class Contexts {
* <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));
private static final Contexts GLOBAL = new Contexts(ImmutableContextSet.empty(), DEFAULT_SETTINGS_FLAG);
/**
* Gets the {@link FullySatisfiedContexts} instance.
@@ -111,7 +108,7 @@ public class Contexts {
*/
public static @NonNull 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(
byte settingsFlag = LookupSetting.createFlag(
includeNodesSetWithoutServer,
includeNodesSetWithoutWorld,
resolveInheritance,
@@ -119,18 +116,10 @@ public class Contexts {
applyParentsWithoutWorld,
isOp
);
if (contextSet.isEmpty() && DEFAULT_SETTINGS.equals(settings)) {
if (contextSet.isEmpty() && DEFAULT_SETTINGS_FLAG == settingsFlag) {
return GLOBAL;
}
return new Contexts(contextSet.makeImmutable(), ImmutableSet.copyOf(settings));
}
private static EnumSet<LookupSetting> asEnumSet(Set<LookupSetting> settings) {
if (settings instanceof EnumSet<?>) {
return ((EnumSet<LookupSetting>) settings);
} else {
return EnumSet.copyOf(settings);
}
return new Contexts(contextSet.makeImmutable(), settingsFlag);
}
/**
@@ -144,12 +133,12 @@ public class Contexts {
Objects.requireNonNull(contextSet, "contextSet");
Objects.requireNonNull(settings, "settings");
EnumSet<LookupSetting> settingsCopy = asEnumSet(settings);
if (contextSet.isEmpty() && DEFAULT_SETTINGS.equals(settingsCopy)) {
byte settingsFlag = LookupSetting.createFlag(settings);
if (contextSet.isEmpty() && DEFAULT_SETTINGS_FLAG == settingsFlag) {
return GLOBAL;
}
return new Contexts(contextSet.makeImmutable(), ImmutableSet.copyOf(settingsCopy));
return new Contexts(contextSet.makeImmutable(), settingsFlag);
}
/**
@@ -160,7 +149,7 @@ public class Contexts {
/**
* The settings for this lookup
*/
private final ImmutableSet<LookupSetting> settings;
private final byte settingsFlag;
// cache hashcode - this class is immutable, and is used as an index in the permission cache.
private final int hashCode;
@@ -180,25 +169,25 @@ public class Contexts {
@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(
this.settingsFlag = LookupSetting.createFlag(
includeNodesSetWithoutServer,
includeNodesSetWithoutWorld,
resolveInheritance,
applyParentsWithoutServer,
applyParentsWithoutWorld,
isOp
));
);
this.hashCode = calculateHashCode();
}
protected Contexts(@NonNull ImmutableContextSet contextSet, @NonNull ImmutableSet<LookupSetting> settings) {
protected Contexts(@NonNull ImmutableContextSet contextSet, byte settingsFlag) {
this.contextSet = contextSet;
this.settings = settings;
this.settingsFlag = settingsFlag;
this.hashCode = calculateHashCode();
}
/**
* Gets the {@link ContextSet} which represent these {@link Contexts}.
* Gets the {@link ContextSet set of context pairs} for this {@link Contexts} instance.
*
* @return an immutable context from this instance
* @since 2.13
@@ -208,13 +197,51 @@ public class Contexts {
}
/**
* Gets the set of {@link LookupSetting}s which represent these {@link Contexts}.
* Gets the set of {@link LookupSetting}s for this {@link Contexts} instance.
*
* @return the settings
* @since 4.2
*/
public @NonNull Set<LookupSetting> getSettings() {
return this.settings;
return LookupSetting.createSetFromFlag(this.settingsFlag);
}
/**
* Creates a copy of this {@link Contexts} instance, but with the
* {@link ContextSet set of context pairs} replaced by the given set.
*
* @param contextSet the context set
* @return a new contexts instance representing the new settings
* @since 4.4
*/
public @NonNull Contexts setContexts(@NonNull ContextSet contextSet) {
ImmutableContextSet cs = Objects.requireNonNull(contextSet, "contextSet").makeImmutable();
if (this.contextSet.equals(cs)) {
return this;
}
return new Contexts(cs, this.settingsFlag);
}
/**
* Creates a copy of this {@link Contexts} instance, but with the
* {@link LookupSetting}s replaced by the given settings.
*
* @param settings the lookup settings
* @return a new contexts instance representing the new settings
* @since 4.4
*/
public @NonNull Contexts setSettings(@NonNull Set<LookupSetting> settings) {
Objects.requireNonNull(settings, "settings");
byte settingsFlag = LookupSetting.createFlag(settings);
if (this.settingsFlag == settingsFlag) {
return this;
}
if (DEFAULT_SETTINGS_FLAG == settingsFlag && this.contextSet.isEmpty()) {
return GLOBAL;
}
return new Contexts(this.contextSet, settingsFlag);
}
/**
@@ -225,7 +252,7 @@ public class Contexts {
* @since 4.2
*/
public boolean hasSetting(@NonNull LookupSetting setting) {
return this.settings.contains(setting);
return LookupSetting.isSet(this.settingsFlag, setting);
}
/**
@@ -302,7 +329,7 @@ public class Contexts {
@Override
public @NonNull String toString() {
return "Contexts(contextSet=" + this.contextSet + ", settings=" + this.settings + ")";
return "Contexts(contextSet=" + this.contextSet + ", settings=" + LookupSetting.createSetFromFlag(this.settingsFlag) + ")";
}
@Override
@@ -311,14 +338,14 @@ public class Contexts {
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);
return this.contextSet.equals(that.contextSet) && this.settingsFlag == that.settingsFlag;
}
private int calculateHashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.contextSet.hashCode();
result = result * PRIME + this.settings.hashCode();
result = result * PRIME + this.settingsFlag;
return result;
}
@@ -327,27 +354,4 @@ public class Contexts {
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;
}
}
@@ -25,8 +25,6 @@
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;
@@ -59,7 +57,7 @@ public final class FullySatisfiedContexts extends Contexts {
}
private FullySatisfiedContexts() {
super(ImmutableContextSet.empty(), ImmutableSet.copyOf(Contexts.global().getSettings()));
super(ImmutableContextSet.empty(), LookupSetting.createFlag(Contexts.global().getSettings()));
}
@Override
@@ -80,14 +80,14 @@ public interface HeldPermission<T> {
*
* @return the expiry time
*/
OptionalLong getExpiry();
@NonNull OptionalLong getExpiry();
/**
* Gets the extra context for the permission.
*
* @return the extra context
*/
ContextSet getContexts();
@NonNull ContextSet getContexts();
/**
* Converts this permission into a Node
@@ -102,6 +102,35 @@ public interface LogEntry extends Comparable<LogEntry> {
enum Type {
USER('U'), GROUP('G'), TRACK('T');
/**
* Parses a {@link Type} from a string.
*
* @param type the string
* @return a type
* @throws IllegalArgumentException if a type could not be parsed
* @since 4.4
*/
public static @NonNull Type parse(String type) {
try {
return valueOf(type);
} catch (IllegalArgumentException e) {
// ignore
}
try {
return valueOf(type.charAt(0));
} catch (IllegalArgumentException e) {
// ignore
}
throw new IllegalArgumentException("Unknown type: " + type);
}
/**
* Returns a {@link Type} by its code.
*
* @param code the code - see {@link Type#getCode()}.
* @return a type
* @throws IllegalArgumentException if a type could not be resolved
*/
public static @NonNull Type valueOf(char code) {
switch (code) {
case 'U':
@@ -25,6 +25,9 @@
package me.lucko.luckperms.api;
import java.util.EnumSet;
import java.util.Set;
/**
* The various lookup setting flags for {@link Contexts}.
*
@@ -60,5 +63,62 @@ public enum LookupSetting {
/**
* If global or non-world-specific group memberships should be applied
*/
APPLY_PARENTS_SET_WITHOUT_WORLD
APPLY_PARENTS_SET_WITHOUT_WORLD;
/* bitwise utility methods */
static boolean isSet(byte b, LookupSetting setting) {
return ((b >> setting.ordinal()) & 1) == 1;
}
static byte createFlag(LookupSetting... settings) {
byte b = 0;
for (LookupSetting setting : settings) {
b |= (1 << setting.ordinal());
}
return b;
}
static byte createFlag(Set<LookupSetting> settings) {
byte b = 0;
for (LookupSetting setting : settings) {
b |= (1 << setting.ordinal());
}
return b;
}
static Set<LookupSetting> createSetFromFlag(byte b) {
EnumSet<LookupSetting> settings = EnumSet.noneOf(LookupSetting.class);
for (LookupSetting setting : LookupSetting.values()) {
if (((b >> setting.ordinal()) & 1) == 1) {
settings.add(setting);
}
}
return settings;
}
static byte createFlag(boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
byte b = 0;
if (includeNodesSetWithoutServer) {
b |= (1 << LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER.ordinal());
}
if (includeNodesSetWithoutWorld) {
b |= (1 << LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD.ordinal());
}
if (resolveInheritance) {
b |= (1 << LookupSetting.RESOLVE_INHERITANCE.ordinal());
}
if (applyParentsWithoutServer) {
b |= (1 << LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER.ordinal());
}
if (applyParentsWithoutWorld) {
b |= (1 << LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD.ordinal());
}
if (isOp) {
b |= (1 << LookupSetting.IS_OP.ordinal());
}
return b;
}
}
@@ -40,6 +40,7 @@ import me.lucko.luckperms.api.platform.PlatformInfo;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@@ -210,6 +211,14 @@ public interface LuckPermsApi {
*/
@NonNull ContextManager getContextManager();
/**
* Gets a {@link Collection} of all known permission strings.
*
* @return a collection of the known permissions
* @since 4.4
*/
@NonNull Collection<String> getKnownPermissions();
/**
* Gets the {@link NodeFactory}.
*
@@ -430,17 +430,6 @@ public interface Node {
@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}.
@@ -450,9 +439,7 @@ public interface Node {
* @return true if this node is considered equal
* @since 4.1
*/
default boolean equals(Node other, NodeEqualityPredicate equalityPredicate) {
return equalityPredicate.areEqual(this, other);
}
boolean equals(Node other, NodeEqualityPredicate equalityPredicate);
/**
* Similar to {@link Node#equals(Object)}, except doesn't take note of the
@@ -41,7 +41,10 @@ import org.checkerframework.checker.nullness.qual.NonNull;
public interface NodeEqualityPredicate {
/**
* Returns if the two nodes are equal
* Returns if the two nodes are equal.
*
* <p>This method should avoid making calls to {@link Node#equals(Node, NodeEqualityPredicate)}
* with {@code this} as the second argument, directly or otherwise.</p>
*
* @param o1 the first node
* @param o2 the second node
@@ -30,6 +30,7 @@ import me.lucko.luckperms.api.manager.UserManager;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
@@ -56,10 +57,16 @@ public interface PlayerSaveResult {
* @param status the status to check for
* @return if the result includes the status
*/
boolean includes(@NonNull Status status);
default boolean includes(@NonNull Status status) {
Objects.requireNonNull(status, "status");
return getStatus().contains(status);
}
/**
* Gets the old username involved in the result
* Gets the old username involved in the result.
*
* <p>Returns null when the result doesn't {@link #includes(Status) include} the
* {@link Status#USERNAME_UPDATED} status.</p>
*
* @return the old username
* @see Status#USERNAME_UPDATED
@@ -67,7 +74,10 @@ public interface PlayerSaveResult {
@Nullable String getOldUsername();
/**
* Gets the other uuids involved in the result
* Gets the other uuids involved in the result.
*
* <p>Returns null when the result doesn't {@link #includes(Status) include} the
* {@link Status#OTHER_UUIDS_PRESENT_FOR_USERNAME} status.</p>
*
* @return the other uuids
* @see Status#OTHER_UUIDS_PRESENT_FOR_USERNAME
@@ -73,6 +73,6 @@ public enum StandardNodeEquality implements NodeEqualityPredicate {
@Override
public boolean areEqual(@NonNull Node o1, @NonNull Node o2) {
return o1.standardEquals(o2, this);
return o1.equals(o2, this);
}
}
@@ -26,7 +26,6 @@
package me.lucko.luckperms.api.context;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.SetMultimap;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -67,23 +66,6 @@ abstract class AbstractContextSet implements ContextSet {
return backing().size();
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof ContextSet)) return false;
final ContextSet that = (ContextSet) o;
final Multimap<String, String> otherContexts;
if (that instanceof AbstractContextSet) {
otherContexts = ((AbstractContextSet) that).backing();
} else {
otherContexts = that.toMultimap();
}
return backing().equals(otherContexts);
}
@Override
public int hashCode() {
return backing().hashCode();
@@ -47,6 +47,8 @@ import java.util.Optional;
* <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
@@ -148,13 +150,12 @@ public interface ContextManager {
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
* @since 4.4
*/
void registerStaticCalculator(@NonNull StaticContextCalculator calculator);
void unregisterCalculator(@NonNull ContextCalculator<?> calculator);
/**
* Invalidates the lookup cache for a given subject
@@ -213,6 +213,28 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
return this.map.entries().spliterator();
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof ContextSet)) return false;
final ContextSet that = (ContextSet) o;
// fast(er) path for ImmutableContextSet comparisons
if (that instanceof ImmutableContextSet) {
ImmutableContextSet immutableThat = (ImmutableContextSet) that;
if (this.hashCode != immutableThat.hashCode) return false;
}
final Multimap<String, String> thatBacking;
if (that instanceof AbstractContextSet) {
thatBacking = ((AbstractContextSet) that).backing();
} else {
thatBacking = that.toMultimap();
}
return backing().equals(thatBacking);
}
@Override
public int hashCode() {
return this.hashCode;
@@ -345,6 +345,22 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
this.map.clear();
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof ContextSet)) return false;
final ContextSet that = (ContextSet) o;
final Multimap<String, String> thatBacking;
if (that instanceof AbstractContextSet) {
thatBacking = ((AbstractContextSet) that).backing();
} else {
thatBacking = that.toMultimap();
}
return backing().equals(thatBacking);
}
@Override
public String toString() {
return "MutableContextSet(contexts=" + this.map + ")";
@@ -43,4 +43,12 @@ public interface LuckPermsEvent {
*/
@NonNull LuckPermsApi getApi();
/**
* Gets the type of the event.
*
* @return the type of the event
* @since 4.4
*/
@NonNull Class<? extends LuckPermsEvent> getEventType();
}
@@ -23,29 +23,36 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.user;
package me.lucko.luckperms.api.event.player;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.LuckPermsEvent;
import me.lucko.luckperms.api.event.Param;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.UUID;
/**
* 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>
*
* @since 4.4
*/
public interface UserLoginProcessEvent extends LuckPermsEvent {
public interface PlayerLoginProcessEvent extends LuckPermsEvent {
/**
* Gets the UUID of the connection which was processed
@@ -61,11 +68,23 @@ public interface UserLoginProcessEvent extends LuckPermsEvent {
*/
@NonNull @Param(1) String getUsername();
/**
* Gets if the login was processed successfully.
*
* @return true if the login was successful
*/
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
*/
@NonNull @Param(2) User getUser();
@Nullable @Param(2) User getUser();
}
@@ -0,0 +1,111 @@
/*
* 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.metastacking;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
/**
* Functional interface which removes duplicate entries from a list.
*
* <p>Used by LuckPerms to remove duplicate entries from a MetaStack.</p>
*
* @since 4.4
*/
public interface DuplicateRemovalFunction {
/**
* Removes duplicates from the given list, according to the behaviour
* of the function.
*
* @param list the entries
* @param <T> the type of entries
*/
<T> void processDuplicates(@NonNull List<T> list);
/**
* A {@link DuplicateRemovalFunction} that does not remove duplicates.
*/
DuplicateRemovalFunction RETAIN_ALL = new DuplicateRemovalFunction() {
@Override
public <T> void processDuplicates(@NonNull List<T> list) {
}
@Override
public String toString() {
return "DuplicateRemovalFunction#RETAIN_ALL";
}
};
/**
* A {@link DuplicateRemovalFunction} that retains only the first occurrence.
*/
DuplicateRemovalFunction FIRST_ONLY = new DuplicateRemovalFunction() {
@SuppressWarnings("Java8CollectionRemoveIf")
@Override
public <T> void processDuplicates(@NonNull List<T> list) {
Set<T> seen = new HashSet<>();
for (ListIterator<T> it = list.listIterator(); it.hasNext(); ) {
T next = it.next();
if (!seen.add(next)) {
it.remove();
}
}
}
@Override
public String toString() {
return "DuplicateRemovalFunction#FIRST_ONLY";
}
};
/**
* A {@link DuplicateRemovalFunction} that retains only the last occurrence.
*/
DuplicateRemovalFunction LAST_ONLY = new DuplicateRemovalFunction() {
@Override
public <T> void processDuplicates(@NonNull List<T> list) {
Set<T> seen = new HashSet<>();
for (ListIterator<T> it = list.listIterator(list.size()); it.hasPrevious(); ) {
T next = it.previous();
if (!seen.add(next)) {
it.remove();
}
}
}
@Override
public String toString() {
return "DuplicateRemovalFunction#LAST_ONLY";
}
};
}
@@ -49,6 +49,15 @@ public interface MetaStackDefinition {
*/
@NonNull List<MetaStackElement> getElements();
/**
* Gets the duplicate removal function, applied to the entries before
* formatting takes place.
*
* @return the duplicate removal function
* @since 4.4
*/
@NonNull DuplicateRemovalFunction getDuplicateRemovalFunction();
/**
* Gets the spacer string added before any stack elements
*
@@ -64,6 +64,22 @@ public interface MetaStackFactory {
* @param endSpacer the spacer to be included at the end of the stacks output
* @return the new stack definition instance
*/
@NonNull MetaStackDefinition createDefinition(@NonNull List<MetaStackElement> elements, @NonNull String startSpacer, @NonNull String middleSpacer, @NonNull String endSpacer);
default @NonNull MetaStackDefinition createDefinition(@NonNull List<MetaStackElement> elements, @NonNull String startSpacer, @NonNull String middleSpacer, @NonNull String endSpacer) {
return createDefinition(elements, DuplicateRemovalFunction.RETAIN_ALL, startSpacer, middleSpacer, endSpacer);
}
/**
* Creates a new {@link MetaStackDefinition} with the given properties.
*
* @param elements the elements to be included in the stack.
* @param duplicateRemovalFunction the duplicate removal function
* @param startSpacer the spacer to be included at the start of the stacks output
* @param middleSpacer the spacer to be included between stack elements
* @param endSpacer the spacer to be included at the end of the stacks output
* @return the new stack definition instance
* @since 4.4
*/
@NonNull MetaStackDefinition createDefinition(@NonNull List<MetaStackElement> elements, @NonNull DuplicateRemovalFunction duplicateRemovalFunction, @NonNull String startSpacer, @NonNull String middleSpacer, @NonNull String endSpacer);
}
+30 -18
View File
@@ -1,9 +1,22 @@
buildscript {
repositories {
maven { url 'https://plugins.gradle.org/m2' }
}
dependencies {
classpath 'gradle.plugin.net.minecrell:licenser:0.4.1'
}
}
defaultTasks 'licenseFormat', 'build'
subprojects {
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'net.minecrell.licenser'
group = 'me.lucko.luckperms'
version = '4.3-SNAPSHOT'
version = '4.4-SNAPSHOT'
sourceCompatibility = 1.8
targetCompatibility = 1.8
@@ -18,35 +31,34 @@ subprojects {
def determinePatchVersion = {
// get the name of the last tag
def lastTag = new ByteArrayOutputStream()
def tagInfo = new ByteArrayOutputStream()
exec {
commandLine 'git', 'describe', '--tags', '--abbrev=0', '@^'
standardOutput = lastTag
commandLine 'git', 'describe', '--tags'
standardOutput = tagInfo
}
tagInfo = tagInfo.toString()
// get a list of the commits since the last tag
def commitsSinceLastTag = new ByteArrayOutputStream()
exec {
commandLine 'git', 'log', '--oneline', lastTag.toString().trim() + '..@'
standardOutput = commitsSinceLastTag
if (!tagInfo.contains('-')) {
return 0
}
// calculate what the patch version should be
return Integer.toString(commitsSinceLastTag.toString().split("\n").length)
return tagInfo.split("-")[1]
}
project.ext.majorVersion = '4'
project.ext.minorVersion = '3'
project.ext.minorVersion = '4'
project.ext.patchVersion = determinePatchVersion()
project.ext.fullVersion = project.ext.majorVersion + '.' + project.ext.minorVersion + '.' + project.ext.patchVersion
license {
header = rootProject.file('HEADER.txt')
include '**/*.java'
newLine = true
}
repositories {
//mavenLocal()
mavenCentral()
maven {
name 'luck-repo'
url 'https://repo.lucko.me/'
}
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
maven { url 'https://repo.lucko.me/' }
}
}
-7
View File
@@ -2,13 +2,6 @@ plugins {
id 'com.github.johnrengelman.shadow' version '2.0.4'
}
repositories {
maven {
name 'spigot-repo'
url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/'
}
}
dependencies {
compile project(path: ':bukkit', configuration: 'shadow')
compile 'com.google.code.gson:gson:2.7'
+5 -6
View File
@@ -3,17 +3,16 @@ plugins {
}
repositories {
maven {
name 'spigot-repo'
url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/'
}
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
maven { url 'https://libraries.minecraft.net/' }
}
dependencies {
compile project(':common')
compileOnly 'org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT'
compileOnly 'me.lucko:commodore:1.0'
compileOnly 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT'
compileOnly'net.kyori:text-adapter-bukkit:1.0.2'
compileOnly 'me.lucko:commodore:1.3'
compileOnly('net.milkbowl.vault:VaultAPI:1.6') {
exclude(module: 'bukkit')
}
@@ -26,16 +26,14 @@
package me.lucko.luckperms.bukkit;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.bukkit.compat.BukkitJsonMessageHandler;
import me.lucko.luckperms.bukkit.compat.CraftBukkitUtil;
import me.lucko.luckperms.bukkit.compat.SpigotJsonMessageHandler;
import me.lucko.luckperms.common.command.CommandManager;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.sender.SenderFactory;
import me.lucko.luckperms.common.utils.TextUtils;
import me.lucko.luckperms.common.util.TextUtils;
import net.kyori.text.Component;
import net.kyori.text.serializer.ComponentSerializers;
import net.kyori.text.adapter.bukkit.TextAdapter;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
@@ -45,13 +43,9 @@ import org.bukkit.entity.Player;
import java.util.UUID;
public class BukkitSenderFactory extends SenderFactory<CommandSender> {
private final BukkitJsonMessageHandler bukkitHandler;
private final SpigotJsonMessageHandler spigotHandler;
public BukkitSenderFactory(LuckPermsPlugin plugin) {
super(plugin);
this.bukkitHandler = new BukkitJsonMessageHandler();
this.spigotHandler = isSpigot() ? new SpigotJsonMessageHandler() : null;
}
@Override
@@ -59,7 +53,7 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> {
if (sender instanceof Player) {
return sender.getName();
}
return CommandManager.CONSOLE_NAME;
return Sender.CONSOLE_NAME;
}
@Override
@@ -67,7 +61,7 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> {
if (sender instanceof Player) {
return ((Player) sender).getUniqueId();
}
return CommandManager.CONSOLE_UUID;
return Sender.CONSOLE_UUID;
}
@Override
@@ -85,22 +79,11 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> {
@Override
protected void sendMessage(CommandSender sender, Component message) {
if (CraftBukkitUtil.isChatCompatible() && sender instanceof Player) {
Player player = (Player) sender;
String json = ComponentSerializers.JSON.serialize(message);
// Try Bukkit.
if (this.bukkitHandler.sendJsonMessage(player, json)) {
return;
}
// Try Spigot.
if (this.spigotHandler != null && this.spigotHandler.sendJsonMessage(player, json)) {
return;
}
TextAdapter.sendComponent(sender, message);
} else {
// Fallback to legacy format
sendMessage(sender, TextUtils.toLegacy(message));
}
// Fallback to legacy format
sendMessage(sender, TextUtils.toLegacy(message));
}
@Override
@@ -116,15 +99,6 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> {
return sender.hasPermission(node);
}
private static boolean isSpigot() {
try {
Class.forName("net.md_5.bungee.chat.ComponentSerializer");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
private static final class SyncMessengerAgent implements Runnable {
private final CommandSender sender;
private final String message;
@@ -28,36 +28,36 @@ package me.lucko.luckperms.bukkit;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LuckPermsApi;
import me.lucko.luckperms.api.event.user.UserDataRecalculateEvent;
import me.lucko.luckperms.bukkit.calculators.BukkitCalculatorFactory;
import me.lucko.luckperms.bukkit.calculator.BukkitCalculatorFactory;
import me.lucko.luckperms.bukkit.compat.LuckPermsBrigadier;
import me.lucko.luckperms.bukkit.contexts.BukkitContextManager;
import me.lucko.luckperms.bukkit.contexts.WorldCalculator;
import me.lucko.luckperms.bukkit.context.BukkitContextManager;
import me.lucko.luckperms.bukkit.context.WorldCalculator;
import me.lucko.luckperms.bukkit.inject.permissible.LPPermissible;
import me.lucko.luckperms.bukkit.inject.permissible.PermissibleInjector;
import me.lucko.luckperms.bukkit.inject.permissible.PermissibleMonitoringInjector;
import me.lucko.luckperms.bukkit.inject.server.InjectorDefaultsMap;
import me.lucko.luckperms.bukkit.inject.server.InjectorPermissionMap;
import me.lucko.luckperms.bukkit.inject.server.InjectorSubscriptionMap;
import me.lucko.luckperms.bukkit.inject.server.LPDefaultsMap;
import me.lucko.luckperms.bukkit.inject.server.LPPermissionMap;
import me.lucko.luckperms.bukkit.inject.server.LPSubscriptionMap;
import me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener;
import me.lucko.luckperms.bukkit.listeners.BukkitPlatformListener;
import me.lucko.luckperms.bukkit.messaging.BukkitMessagingFactory;
import me.lucko.luckperms.bukkit.model.permissible.LPPermissible;
import me.lucko.luckperms.bukkit.model.permissible.PermissibleInjector;
import me.lucko.luckperms.bukkit.model.permissible.PermissibleMonitoringInjector;
import me.lucko.luckperms.bukkit.model.server.InjectorDefaultsMap;
import me.lucko.luckperms.bukkit.model.server.InjectorPermissionMap;
import me.lucko.luckperms.bukkit.model.server.InjectorSubscriptionMap;
import me.lucko.luckperms.bukkit.model.server.LPDefaultsMap;
import me.lucko.luckperms.bukkit.model.server.LPPermissionMap;
import me.lucko.luckperms.bukkit.model.server.LPSubscriptionMap;
import me.lucko.luckperms.bukkit.vault.VaultHookManager;
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
import me.lucko.luckperms.common.api.delegates.model.ApiUser;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.api.implementation.ApiUser;
import me.lucko.luckperms.common.calculator.CalculatorFactory;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
import me.lucko.luckperms.common.dependencies.Dependency;
import me.lucko.luckperms.common.event.AbstractEventBus;
import me.lucko.luckperms.common.managers.group.StandardGroupManager;
import me.lucko.luckperms.common.managers.track.StandardTrackManager;
import me.lucko.luckperms.common.managers.user.StandardUserManager;
import me.lucko.luckperms.common.messaging.MessagingFactory;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.model.manager.group.StandardGroupManager;
import me.lucko.luckperms.common.model.manager.track.StandardTrackManager;
import me.lucko.luckperms.common.model.manager.user.StandardUserManager;
import me.lucko.luckperms.common.plugin.AbstractLuckPermsPlugin;
import me.lucko.luckperms.common.plugin.util.AbstractConnectionListener;
import me.lucko.luckperms.common.sender.Sender;
@@ -123,7 +123,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
@Override
protected Set<Dependency> getGlobalDependencies() {
EnumSet<Dependency> dependencies = EnumSet.of(Dependency.TEXT, Dependency.CAFFEINE, Dependency.OKIO, Dependency.OKHTTP, Dependency.EVENT);
EnumSet<Dependency> dependencies = EnumSet.of(Dependency.TEXT, Dependency.TEXT_ADAPTER_BUKKIT, Dependency.CAFFEINE, Dependency.OKIO, Dependency.OKHTTP, Dependency.EVENT);
if (isBrigadierSupported()) {
dependencies.add(Dependency.COMMODORE);
}
@@ -189,7 +189,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
new InjectorSubscriptionMap(this),
new InjectorPermissionMap(this),
new InjectorDefaultsMap(this),
new PermissibleMonitoringInjector(this)
new PermissibleMonitoringInjector(this, PermissibleMonitoringInjector.Mode.INJECT)
};
for (Runnable injector : injectors) {
@@ -266,7 +266,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
getApiProvider().getEventBus().subscribe(UserDataRecalculateEvent.class, event -> {
User user = ApiUser.cast(event.getUser());
Optional<Player> player = getBootstrap().getPlayer(user.getUuid());
player.ifPresent(this::refreshAutoOp);
player.ifPresent(p -> refreshAutoOp(p, false));
});
}
@@ -297,7 +297,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
// uninject from players
for (Player player : this.bootstrap.getServer().getOnlinePlayers()) {
try {
PermissibleInjector.unInject(player, false);
PermissibleInjector.uninject(player, false);
} catch (Exception e) {
e.printStackTrace();
}
@@ -317,6 +317,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
InjectorSubscriptionMap.uninject();
InjectorPermissionMap.uninject();
InjectorDefaultsMap.uninject();
new PermissibleMonitoringInjector(this, PermissibleMonitoringInjector.Mode.UNINJECT).run();
// unhook vault
if (this.vaultHookManager != null) {
@@ -324,16 +325,25 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
}
}
public void refreshAutoOp(Player player) {
public void refreshAutoOp(Player player, boolean callerIsSync) {
if (getConfiguration().get(ConfigKeys.AUTO_OP)) {
User user = getUserManager().getIfLoaded(player.getUniqueId());
if (user == null) {
player.setOp(false);
if (callerIsSync) {
player.setOp(false);
} else {
this.bootstrap.getScheduler().executeSync(() -> player.setOp(false));
}
return;
}
Map<String, Boolean> permData = user.getCachedData().getPermissionData(this.contextManager.getApplicableContexts(player)).getImmutableBacking();
player.setOp(permData.getOrDefault("luckperms.autoop", false));
boolean value = permData.getOrDefault("luckperms.autoop", false);
if (callerIsSync) {
player.setOp(value);
} else {
this.bootstrap.getScheduler().executeSync(() -> player.setOp(value));
}
}
}
@@ -23,24 +23,22 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.calculators;
package me.lucko.luckperms.bukkit.calculator;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LookupSetting;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.bukkit.processors.ChildProcessor;
import me.lucko.luckperms.bukkit.processors.DefaultsProcessor;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.calculators.PermissionCalculator;
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
import me.lucko.luckperms.common.cacheddata.CacheMetadata;
import me.lucko.luckperms.common.calculator.CalculatorFactory;
import me.lucko.luckperms.common.calculator.PermissionCalculator;
import me.lucko.luckperms.common.calculator.processor.MapProcessor;
import me.lucko.luckperms.common.calculator.processor.PermissionProcessor;
import me.lucko.luckperms.common.calculator.processor.RegexProcessor;
import me.lucko.luckperms.common.calculator.processor.WildcardProcessor;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.model.HolderType;
import me.lucko.luckperms.common.processors.MapProcessor;
import me.lucko.luckperms.common.processors.PermissionProcessor;
import me.lucko.luckperms.common.processors.RegexProcessor;
import me.lucko.luckperms.common.processors.WildcardProcessor;
public class BukkitCalculatorFactory implements CalculatorFactory {
private final LPBukkitPlugin plugin;
@@ -50,7 +48,7 @@ public class BukkitCalculatorFactory implements CalculatorFactory {
}
@Override
public PermissionCalculator build(Contexts contexts, PermissionCalculatorMetadata metadata) {
public PermissionCalculator build(Contexts contexts, CacheMetadata metadata) {
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
processors.add(new MapProcessor());
@@ -23,12 +23,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.processors;
package me.lucko.luckperms.bukkit.calculator;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.processors.AbstractPermissionProcessor;
import me.lucko.luckperms.common.processors.PermissionProcessor;
import me.lucko.luckperms.common.calculator.processor.AbstractPermissionProcessor;
import me.lucko.luckperms.common.calculator.processor.PermissionProcessor;
import me.lucko.luckperms.common.calculator.result.TristateResult;
import java.util.Collections;
import java.util.Map;
@@ -38,6 +39,8 @@ import java.util.concurrent.ConcurrentHashMap;
* Permission Processor for Bukkits "child" permission system.
*/
public class ChildProcessor extends AbstractPermissionProcessor implements PermissionProcessor {
private static final TristateResult.Factory RESULT_FACTORY = new TristateResult.Factory(ChildProcessor.class);
private final LPBukkitPlugin plugin;
private Map<String, Boolean> childPermissions = Collections.emptyMap();
@@ -46,8 +49,8 @@ public class ChildProcessor extends AbstractPermissionProcessor implements Permi
}
@Override
public Tristate hasPermission(String permission) {
return Tristate.fromNullableBoolean(this.childPermissions.get(permission));
public TristateResult hasPermission(String permission) {
return RESULT_FACTORY.result(Tristate.fromNullableBoolean(this.childPermissions.get(permission)));
}
@Override
@@ -61,4 +64,9 @@ public class ChildProcessor extends AbstractPermissionProcessor implements Permi
}
this.childPermissions = builder;
}
@Override
public void invalidate() {
refresh();
}
}
@@ -23,11 +23,12 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.processors;
package me.lucko.luckperms.bukkit.calculator;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.processors.PermissionProcessor;
import me.lucko.luckperms.common.calculator.processor.PermissionProcessor;
import me.lucko.luckperms.common.calculator.result.TristateResult;
import org.bukkit.permissions.Permission;
@@ -35,6 +36,8 @@ import org.bukkit.permissions.Permission;
* Permission Processor for Bukkits "default" permission system.
*/
public class DefaultsProcessor implements PermissionProcessor {
private static final TristateResult.Factory RESULT_FACTORY = new TristateResult.Factory(DefaultsProcessor.class);
private final LPBukkitPlugin plugin;
private final boolean isOp;
@@ -44,13 +47,16 @@ public class DefaultsProcessor implements PermissionProcessor {
}
@Override
public Tristate hasPermission(String permission) {
public TristateResult hasPermission(String permission) {
Tristate t = this.plugin.getDefaultPermissionMap().lookupDefaultPermission(permission, this.isOp);
if (t != Tristate.UNDEFINED) {
return t;
return RESULT_FACTORY.result(t, "default permission map");
}
Permission defPerm = this.plugin.getPermissionMap().get(permission);
return defPerm == null ? Tristate.UNDEFINED : Tristate.fromBoolean(defPerm.getDefault().getValue(this.isOp));
if (defPerm == null) {
return TristateResult.UNDEFINED;
}
return RESULT_FACTORY.result(Tristate.fromBoolean(defPerm.getDefault().getValue(this.isOp)), "permission map");
}
}
@@ -1,113 +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.bukkit.compat;
import org.bukkit.entity.Player;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class BukkitJsonMessageHandler {
private static boolean setup = false;
private static boolean triedAndFailed = false;
private static Method GET_HANDLE_METHOD;
private static Field PLAYER_CONNECTION_FIELD;
private static Method SEND_PACKET_METHOD;
private static Constructor<?> PACKET_CHAT_CONSTRUCTOR;
private static Method SERIALIZE_METHOD;
private static void setup(Object player) throws Exception {
Class<?> craftPlayerClass = player.getClass();
GET_HANDLE_METHOD = craftPlayerClass.getDeclaredMethod("getHandle");
Object handleObject = GET_HANDLE_METHOD.invoke(player);
Class<?> handleClass = handleObject.getClass();
PLAYER_CONNECTION_FIELD = handleClass.getDeclaredField("playerConnection");
Object playerConnectionObject = PLAYER_CONNECTION_FIELD.get(handleObject);
Method[] playerConnectionMethods = playerConnectionObject.getClass().getDeclaredMethods();
for (Method m : playerConnectionMethods) {
if (m.getName().equals("sendPacket")) {
SEND_PACKET_METHOD = m;
break;
}
}
Class<?> packetChatClass = CraftBukkitUtil.nmsClass("PacketPlayOutChat");
Constructor[] packetConstructors = packetChatClass.getDeclaredConstructors();
for (Constructor c : packetConstructors) {
Class<?>[] parameters = c.getParameterTypes();
if (parameters.length == 1 && parameters[0].getName().endsWith("IChatBaseComponent")) {
PACKET_CHAT_CONSTRUCTOR = c;
break;
}
}
Class<?> baseComponentClass = CraftBukkitUtil.nmsClass("IChatBaseComponent");
Class<?> chatSerializerClass;
if (baseComponentClass.getClasses().length > 0) {
chatSerializerClass = baseComponentClass.getClasses()[0];
} else {
// 1.7 class is here instead.
chatSerializerClass = CraftBukkitUtil.nmsClass("ChatSerializer");
}
SERIALIZE_METHOD = chatSerializerClass.getDeclaredMethod("a", String.class);
}
private static synchronized boolean trySetup(Object player) {
if (setup) return true;
if (triedAndFailed) return false;
try {
setup(player);
setup = true;
return true;
} catch (Throwable e) {
triedAndFailed = true;
return false;
}
}
public boolean sendJsonMessage(Player player, String json) {
if (!trySetup(player)) {
return false;
}
try {
Object connection = PLAYER_CONNECTION_FIELD.get(GET_HANDLE_METHOD.invoke(player));
SEND_PACKET_METHOD.invoke(connection, PACKET_CHAT_CONSTRUCTOR.newInstance(SERIALIZE_METHOD.invoke(null, json)));
return true;
} catch (Exception e) {
return false;
}
}
}
@@ -28,10 +28,12 @@ package me.lucko.luckperms.bukkit.compat;
import org.bukkit.Bukkit;
public final class CraftBukkitUtil {
private static final String SERVER_VERSION = getServerVersion();
private static final boolean CHAT_COMPATIBLE = !SERVER_VERSION.startsWith(".v1_7_");
private CraftBukkitUtil() {}
private static String getServerVersion() {
private static final String SERVER_PACKAGE_VERSION = getServerPackageVersion();
private static final boolean CHAT_COMPATIBLE = !SERVER_PACKAGE_VERSION.startsWith(".v1_7_");
private static String getServerPackageVersion() {
Class<?> server = Bukkit.getServer().getClass();
if (!server.getSimpleName().equals("CraftServer")) {
return ".";
@@ -50,7 +52,7 @@ public final class CraftBukkitUtil {
}
public static String nms(String className) {
return "net.minecraft.server" + SERVER_VERSION + className;
return "net.minecraft.server" + SERVER_PACKAGE_VERSION + className;
}
public static Class<?> nmsClass(String className) throws ClassNotFoundException {
@@ -58,13 +60,10 @@ public final class CraftBukkitUtil {
}
public static String obc(String className) {
return "org.bukkit.craftbukkit" + SERVER_VERSION + className;
return "org.bukkit.craftbukkit" + SERVER_PACKAGE_VERSION + className;
}
public static Class<?> obcClass(String className) throws ClassNotFoundException {
return Class.forName(obc(className));
}
private CraftBukkitUtil() {}
}
@@ -40,8 +40,13 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import me.lucko.commodore.Commodore;
import me.lucko.commodore.CommodoreProvider;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.sender.Sender;
import org.bukkit.command.Command;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandSendEvent;
import org.bukkit.plugin.PluginManager;
import java.io.BufferedReader;
import java.io.InputStream;
@@ -53,6 +58,7 @@ import java.util.zip.GZIPInputStream;
public class LuckPermsBrigadier {
public static void register(LPBukkitPlugin plugin, Command pluginCommand) throws Exception {
// register completions with commodore
Commodore commodore = CommodoreProvider.getCommodore(plugin.getBootstrap());
try (InputStream is = plugin.getBootstrap().getResourceStream("luckperms-brigadier.json.gz")) {
if (is == null) {
@@ -65,6 +71,29 @@ public class LuckPermsBrigadier {
commodore.register(pluginCommand, command);
}
}
// add event listener to prevent completions from being send to players without permission
// to use any LP commands.
PluginManager pluginManager = plugin.getBootstrap().getServer().getPluginManager();
pluginManager.registerEvents(new PermissionListener(plugin, pluginCommand), plugin.getBootstrap());
}
private static final class PermissionListener implements Listener {
private final LPBukkitPlugin plugin;
private final Command pluginCommand;
private PermissionListener(LPBukkitPlugin plugin, Command pluginCommand) {
this.plugin = plugin;
this.pluginCommand = pluginCommand;
}
@EventHandler
public void onCommandSend(PlayerCommandSendEvent e) {
Sender playerAsSender = this.plugin.getSenderFactory().wrap(e.getPlayer());
if (!this.plugin.getCommandManager().hasPermissionForAny(playerAsSender)) {
e.getCommands().removeAll(Commodore.getAliases(this.pluginCommand));
}
}
}
private static ArgumentBuilder deserialize(JsonObject data) {
@@ -23,9 +23,8 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.contexts;
package me.lucko.luckperms.bukkit.context;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import me.lucko.luckperms.api.Contexts;
@@ -33,9 +32,11 @@ import me.lucko.luckperms.api.LookupSetting;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.contexts.ContextManager;
import me.lucko.luckperms.common.contexts.ContextsCache;
import me.lucko.luckperms.common.contexts.ContextsSupplier;
import me.lucko.luckperms.common.context.ContextManager;
import me.lucko.luckperms.common.context.ContextsCache;
import me.lucko.luckperms.common.context.ContextsSupplier;
import me.lucko.luckperms.common.util.CaffeineFactory;
import me.lucko.luckperms.common.util.LoadingMap;
import org.bukkit.entity.Player;
@@ -45,11 +46,10 @@ import java.util.concurrent.TimeUnit;
public class BukkitContextManager extends ContextManager<Player> {
// cache the creation of ContextsCache instances for online players with no expiry
private final LoadingCache<Player, ContextsCache<Player>> onlineSubjectCaches = Caffeine.newBuilder()
.build(key -> new ContextsCache<>(key, this));
private final LoadingMap<Player, ContextsCache<Player>> onlineSubjectCaches = LoadingMap.of(key -> new ContextsCache<>(key, this));
// cache the creation of ContextsCache instances for offline players with a 1m expiry
private final LoadingCache<Player, ContextsCache<Player>> offlineSubjectCaches = Caffeine.newBuilder()
private final LoadingCache<Player, ContextsCache<Player>> offlineSubjectCaches = CaffeineFactory.newBuilder()
.expireAfterAccess(1, TimeUnit.MINUTES)
.build(key -> {
ContextsCache<Player> cache = this.onlineSubjectCaches.getIfPresent(key);
@@ -64,7 +64,7 @@ public class BukkitContextManager extends ContextManager<Player> {
}
public void onPlayerQuit(Player player) {
this.onlineSubjectCaches.invalidate(player);
this.onlineSubjectCaches.remove(player);
}
@Override
@@ -99,12 +99,13 @@ public class BukkitContextManager extends ContextManager<Player> {
@Override
public Contexts formContexts(Player subject, ImmutableContextSet contextSet) {
EnumSet<LookupSetting> settings = this.plugin.getConfiguration().get(ConfigKeys.LOOKUP_SETTINGS);
Contexts contexts = this.plugin.getConfiguration().get(ConfigKeys.GLOBAL_CONTEXTS);
if (subject.isOp()) {
settings = EnumSet.copyOf(settings);
EnumSet<LookupSetting> settings = EnumSet.copyOf(contexts.getSettings());
settings.add(LookupSetting.IS_OP);
contexts = contexts.setSettings(settings);
}
return Contexts.of(contextSet, settings);
return contexts.setContexts(contextSet);
}
}
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.contexts;
package me.lucko.luckperms.bukkit.context;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.context.ContextCalculator;
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.dummy;
package me.lucko.luckperms.bukkit.inject.dummy;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.Permission;
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.dummy;
package me.lucko.luckperms.bukkit.inject.dummy;
import org.bukkit.Server;
import org.bukkit.command.Command;
@@ -23,17 +23,19 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.permissible;
package me.lucko.luckperms.bukkit.inject.permissible;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.bukkit.calculator.DefaultsProcessor;
import me.lucko.luckperms.common.calculator.result.TristateResult;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.contexts.ContextsSupplier;
import me.lucko.luckperms.common.context.ContextsSupplier;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.common.verbose.CheckOrigin;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissibleBase;
@@ -136,8 +138,17 @@ public class LPPermissible extends PermissibleBase {
throw new NullPointerException("permission");
}
Tristate ts = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission, CheckOrigin.PLATFORM_LOOKUP_CHECK);
return ts != Tristate.UNDEFINED || Permission.DEFAULT_PERMISSION.getValue(isOp());
TristateResult result = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission, PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK);
if (result.result() == Tristate.UNDEFINED) {
return false;
}
// ignore matches made from looking up in the permission map (replicate bukkit behaviour)
if (result.processorClass() == DefaultsProcessor.class && "permission map".equals(result.cause())) {
return false;
}
return true;
}
@Override
@@ -146,16 +157,7 @@ public class LPPermissible extends PermissibleBase {
throw new NullPointerException("permission");
}
Tristate ts = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission.getName(), CheckOrigin.PLATFORM_LOOKUP_CHECK);
if (ts != Tristate.UNDEFINED) {
return true;
}
if (!this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUKKIT_DEFAULT_PERMISSIONS)) {
return Permission.DEFAULT_PERMISSION.getValue(isOp());
} else {
return permission.getDefault().getValue(isOp());
}
return isPermissionSet(permission.getName());
}
@Override
@@ -164,7 +166,7 @@ public class LPPermissible extends PermissibleBase {
throw new NullPointerException("permission");
}
Tristate ts = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission, CheckOrigin.PLATFORM_PERMISSION_CHECK);
Tristate ts = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission, PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result();
return ts != Tristate.UNDEFINED ? ts.asBoolean() : Permission.DEFAULT_PERMISSION.getValue(isOp());
}
@@ -174,15 +176,15 @@ public class LPPermissible extends PermissibleBase {
throw new NullPointerException("permission");
}
Tristate ts = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission.getName(), CheckOrigin.PLATFORM_PERMISSION_CHECK);
Tristate ts = this.user.getCachedData().getPermissionData(this.contextsSupplier.getContexts()).getPermissionValue(permission.getName(), PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result();
if (ts != Tristate.UNDEFINED) {
return ts.asBoolean();
}
if (!this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUKKIT_DEFAULT_PERMISSIONS)) {
return Permission.DEFAULT_PERMISSION.getValue(isOp());
} else {
if (this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUKKIT_DEFAULT_PERMISSIONS)) {
return permission.getDefault().getValue(isOp());
} else {
return Permission.DEFAULT_PERMISSION.getValue(isOp());
}
}
@@ -23,12 +23,12 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.permissible;
package me.lucko.luckperms.bukkit.inject.permissible;
import com.google.common.base.Preconditions;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.bukkit.model.dummy.DummyPlugin;
import me.lucko.luckperms.bukkit.inject.dummy.DummyPlugin;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.factory.NodeFactory;
@@ -23,14 +23,15 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.permissible;
package me.lucko.luckperms.bukkit.inject.permissible;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.bukkit.model.dummy.DummyPermissibleBase;
import me.lucko.luckperms.bukkit.inject.dummy.DummyPermissibleBase;
import me.lucko.luckperms.common.calculator.result.TristateResult;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.verbose.CheckOrigin;
import me.lucko.luckperms.common.verbose.VerboseHandler;
import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.Permission;
@@ -47,7 +48,7 @@ import java.util.Set;
* Method calls are forwarded to the delegate permissible.
*/
public class MonitoredPermissibleBase extends PermissibleBase {
private final LuckPermsPlugin plugin;
final LuckPermsPlugin plugin;
private final PermissibleBase delegate;
private final String name;
@@ -64,14 +65,10 @@ public class MonitoredPermissibleBase extends PermissibleBase {
this.delegate = delegate;
this.name = name;
this.initialised = true;
// since we effectively cancel the execution of this call in the super
// constructor we need to call it again.
recalculatePermissions();
}
private void logCheck(CheckOrigin origin, String permission, boolean result) {
this.plugin.getVerboseHandler().offerCheckData(origin, this.name, ContextSet.empty(), permission, Tristate.fromBoolean(result));
private void logCheck(PermissionCheckEvent.Origin origin, String permission, boolean result) {
this.plugin.getVerboseHandler().offerPermissionCheckEvent(origin, this.name, ContextSet.empty(), permission, TristateResult.of(Tristate.fromBoolean(result)));
this.plugin.getPermissionRegistry().offer(permission);
}
@@ -86,7 +83,7 @@ public class MonitoredPermissibleBase extends PermissibleBase {
}
final boolean result = this.delegate.isPermissionSet(permission);
logCheck(CheckOrigin.PLATFORM_LOOKUP_CHECK, permission, result);
logCheck(PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK, permission, result);
return result;
}
@@ -97,7 +94,7 @@ public class MonitoredPermissibleBase extends PermissibleBase {
}
final boolean result = this.delegate.isPermissionSet(permission);
logCheck(CheckOrigin.PLATFORM_LOOKUP_CHECK, permission.getName(), result);
logCheck(PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK, permission.getName(), result);
return result;
}
@@ -108,7 +105,7 @@ public class MonitoredPermissibleBase extends PermissibleBase {
}
final boolean result = this.delegate.hasPermission(permission);
logCheck(CheckOrigin.PLATFORM_PERMISSION_CHECK, permission, result);
logCheck(PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK, permission, result);
return result;
}
@@ -119,7 +116,7 @@ public class MonitoredPermissibleBase extends PermissibleBase {
}
final boolean result = this.delegate.hasPermission(permission);
logCheck(CheckOrigin.PLATFORM_PERMISSION_CHECK, permission.getName(), result);
logCheck(PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK, permission.getName(), result);
return result;
}
@@ -23,10 +23,10 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.permissible;
package me.lucko.luckperms.bukkit.inject.permissible;
import me.lucko.luckperms.bukkit.compat.CraftBukkitUtil;
import me.lucko.luckperms.bukkit.model.dummy.DummyPermissibleBase;
import me.lucko.luckperms.bukkit.inject.dummy.DummyPermissibleBase;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissibleBase;
@@ -42,6 +42,7 @@ import java.util.List;
* checks made by plugins.
*/
public final class PermissibleInjector {
private PermissibleInjector() {}
/**
* All permission checks made on standard Bukkit objects are effectively proxied to a
@@ -120,7 +121,7 @@ public final class PermissibleInjector {
* @param dummy if the replacement permissible should be a dummy.
* @throws Exception propagates any exceptions which were thrown during uninjection
*/
public static void unInject(Player player, boolean dummy) throws Exception {
public static void uninject(Player player, boolean dummy) throws Exception {
// gets the players current permissible.
PermissibleBase permissible = (PermissibleBase) HUMAN_ENTITY_PERMISSIBLE_FIELD.get(player);
@@ -151,6 +152,4 @@ public final class PermissibleInjector {
}
}
private PermissibleInjector() {}
}
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.permissible;
package me.lucko.luckperms.bukkit.inject.permissible;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.bukkit.compat.CraftBukkitUtil;
@@ -43,8 +43,15 @@ import java.util.Objects;
public class PermissibleMonitoringInjector implements Runnable {
private final LPBukkitPlugin plugin;
public PermissibleMonitoringInjector(LPBukkitPlugin plugin) {
public enum Mode {
INJECT, UNINJECT
}
private final Mode mode;
public PermissibleMonitoringInjector(LPBukkitPlugin plugin, Mode mode) {
this.plugin = plugin;
this.mode = mode;
}
@Override
@@ -68,14 +75,24 @@ public class PermissibleMonitoringInjector implements Runnable {
}
}
private MonitoredPermissibleBase wrap(PermissibleBase permBase, String name) {
private PermissibleBase transform(PermissibleBase permBase, String name) {
Objects.requireNonNull(permBase, "permBase");
// don't bother injecting if already setup.
if (this.mode == Mode.INJECT && permBase instanceof MonitoredPermissibleBase && ((MonitoredPermissibleBase) permBase).plugin == this.plugin) {
return null;
}
// unwrap any previous injection
if (permBase instanceof MonitoredPermissibleBase) {
permBase = ((MonitoredPermissibleBase) permBase).getDelegate();
}
// if the mode is uninject, just return the unwrapped PermissibleBase
if (this.mode == Mode.UNINJECT) {
return permBase;
}
// create a monitored instance which delegates to the previous PermissibleBase
return new MonitoredPermissibleBase(this.plugin, permBase, name);
}
@@ -93,10 +110,13 @@ public class PermissibleMonitoringInjector implements Runnable {
// get the PermissibleBase instance
PermissibleBase permBase = (PermissibleBase) permField.get(consoleSender);
// create a monitored instance which delegates to the previous PermissibleBase
MonitoredPermissibleBase newPermBase = wrap(permBase, "internal/console");
// create a new instance which delegates to the previous PermissibleBase
PermissibleBase newPermBase = transform(permBase, "internal/console");
if (newPermBase == null) {
return;
}
// inject the monitored instance
// inject the new instance
permField.set(consoleSender, newPermBase);
}
@@ -117,10 +137,13 @@ public class PermissibleMonitoringInjector implements Runnable {
permBase = new PermissibleBase(new CommandBlockServerOperator());
}
// create a monitored instance which delegates to the previous PermissibleBase
MonitoredPermissibleBase newPermBase = wrap(permBase, "internal/commandblock");
// create a new instance which delegates to the previous PermissibleBase
PermissibleBase newPermBase = transform(permBase, "internal/commandblock");
if (newPermBase == null) {
return;
}
// inject the monitored instance
// inject the new instance
permField.set(null, newPermBase);
}
@@ -140,10 +163,13 @@ public class PermissibleMonitoringInjector implements Runnable {
Field permField = entityClass.getDeclaredField("perm");
permField.setAccessible(true);
// create a monitored instance which delegates to the previous PermissibleBase
MonitoredPermissibleBase newPermBase = wrap(permBase, "internal/entity");
// create a new instance which delegates to the previous PermissibleBase
PermissibleBase newPermBase = transform(permBase, "internal/entity");
if (newPermBase == null) {
return;
}
// inject the monitored instance
// inject the new instance
permField.set(null, newPermBase);
}
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.server;
package me.lucko.luckperms.bukkit.inject.server;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.server;
package me.lucko.luckperms.bukkit.inject.server;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.server;
package me.lucko.luckperms.bukkit.inject.server;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.server;
package me.lucko.luckperms.bukkit.inject.server;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.ImmutableList;
@@ -33,7 +33,7 @@ import com.google.common.collect.Maps;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.buffers.Cache;
import me.lucko.luckperms.common.buffer.Cache;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.PluginManager;
@@ -95,6 +95,8 @@ public final class LPDefaultsMap implements Map<Boolean, Set<Permission>> {
private void invalidate(boolean op) {
getCache(op).invalidate();
this.plugin.getUserManager().invalidateAllPermissionCalculators();
this.plugin.getGroupManager().invalidateAllPermissionCalculators();
}
/**
@@ -176,6 +178,13 @@ public final class LPDefaultsMap implements Map<Boolean, Set<Permission>> {
invalidate(this.op);
return ret;
}
@Override
public boolean remove(@NonNull Object object) {
boolean ret = super.remove(object);
invalidate(this.op);
return ret;
}
}
}
@@ -23,34 +23,35 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.server;
package me.lucko.luckperms.bukkit.inject.server;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.ForwardingMap;
import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.treeview.PermissionRegistry;
import me.lucko.luckperms.common.util.LoadingMap;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.PluginManager;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
/**
* A replacement map for the 'permissions' instance in Bukkit's SimplePluginManager.
*
* This instance allows LuckPerms to intercept calls to
* {@link PluginManager#addPermission(Permission)} and record permissions in the
* {@link PermissionRegistry}.
* {@link PermissionRegistry}. It also lets us monitor changes to child permission
* relationships.
*
* It also allows us to pre-determine child permission relationships.
*
@@ -58,15 +59,23 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public final class LPPermissionMap extends ForwardingMap<String, Permission> {
private static final Field PERMISSION_CHILDREN_FIELD;
static {
try {
PERMISSION_CHILDREN_FIELD = Permission.class.getDeclaredField("children");
PERMISSION_CHILDREN_FIELD.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new ExceptionInInitializerError(e);
}
}
// Uses perm.getName().toLowerCase(java.util.Locale.ENGLISH); to determine the key
private final Map<String, Permission> delegate = new ConcurrentHashMap<>();
// cache from permission --> children
private final LoadingCache<String, Map<String, Boolean>> trueChildPermissions = Caffeine.newBuilder()
.build(new ChildPermissionResolver(true));
private final LoadingCache<String, Map<String, Boolean>> falseChildPermissions = Caffeine.newBuilder()
.build(new ChildPermissionResolver(false));
private final Map<String, Map<String, Boolean>> trueChildPermissions = LoadingMap.of(new ChildPermissionResolver(true));
private final Map<String, Map<String, Boolean>> falseChildPermissions = LoadingMap.of(new ChildPermissionResolver(false));
/**
* The plugin instance
@@ -83,8 +92,10 @@ public final class LPPermissionMap extends ForwardingMap<String, Permission> {
}
private void update() {
this.trueChildPermissions.invalidateAll();
this.falseChildPermissions.invalidateAll();
this.trueChildPermissions.clear();
this.falseChildPermissions.clear();
this.plugin.getUserManager().invalidateAllPermissionCalculators();
this.plugin.getGroupManager().invalidateAllPermissionCalculators();
}
@Override
@@ -98,7 +109,7 @@ public final class LPPermissionMap extends ForwardingMap<String, Permission> {
Objects.requireNonNull(value, "value");
this.plugin.getPermissionRegistry().insert(key);
Permission ret = super.put(key, value);
Permission ret = super.put(key, inject(value));
update();
return ret;
}
@@ -110,32 +121,21 @@ public final class LPPermissionMap extends ForwardingMap<String, Permission> {
}
}
@Override
public Permission putIfAbsent(String key, Permission value) {
Objects.requireNonNull(key, "key");
Objects.requireNonNull(value, "value");
this.plugin.getPermissionRegistry().insert(key);
Permission ret = super.putIfAbsent(key, value);
update();
return ret;
}
// null-safe - the plugin manager uses hashmap
@Override
public Permission remove(@Nullable Object object) {
if (object == null) {
return null;
}
return super.remove(object);
return uninject(super.remove(object));
}
@Override
public boolean remove(Object key, Object value) {
return key != null && value != null && super.remove(key, value);
return key != null && value != null && super.remove(key, uninject(((Permission) value)));
}
// check for null
@Override
public boolean containsKey(@Nullable Object key) {
return key != null && super.containsKey(key);
@@ -154,7 +154,7 @@ public final class LPPermissionMap extends ForwardingMap<String, Permission> {
return super.get(key);
}
private final class ChildPermissionResolver implements CacheLoader<String, Map<String, Boolean>> {
private final class ChildPermissionResolver implements Function<String, Map<String, Boolean>> {
private final boolean value;
private ChildPermissionResolver(boolean value) {
@@ -162,7 +162,7 @@ public final class LPPermissionMap extends ForwardingMap<String, Permission> {
}
@Override
public Map<String, Boolean> load(@NonNull String key) {
public Map<String, Boolean> apply(@NonNull String key) {
Map<String, Boolean> children = new HashMap<>();
resolveChildren(children, Collections.singletonMap(key, this.value), false);
children.remove(key, this.value);
@@ -190,4 +190,81 @@ public final class LPPermissionMap extends ForwardingMap<String, Permission> {
}
}
private Permission inject(Permission permission) {
if (permission == null) {
return null;
}
try {
//noinspection unchecked
Map<String, Boolean> children = (Map<String, Boolean>) PERMISSION_CHILDREN_FIELD.get(permission);
while (children instanceof PermissionNotifyingChildrenMap) {
children = ((PermissionNotifyingChildrenMap) children).delegate;
}
PermissionNotifyingChildrenMap notifyingChildren = new PermissionNotifyingChildrenMap(children);
PERMISSION_CHILDREN_FIELD.set(permission, notifyingChildren);
} catch (Exception e) {
e.printStackTrace();
}
return permission;
}
private Permission uninject(Permission permission) {
if (permission == null) {
return null;
}
try {
//noinspection unchecked
Map<String, Boolean> children = (Map<String, Boolean>) PERMISSION_CHILDREN_FIELD.get(permission);
while (children instanceof PermissionNotifyingChildrenMap) {
children = ((PermissionNotifyingChildrenMap) children).delegate;
}
PERMISSION_CHILDREN_FIELD.set(permission, children);
} catch (Exception e) {
e.printStackTrace();
}
return permission;
}
private final class PermissionNotifyingChildrenMap extends ForwardingMap<String, Boolean> {
private final Map<String, Boolean> delegate;
PermissionNotifyingChildrenMap(Map<String, Boolean> delegate) {
this.delegate = delegate;
}
@Override
protected Map<String, Boolean> delegate() {
return this.delegate;
}
@Override
public Boolean put(@NonNull String key, @NonNull Boolean value) {
Boolean ret = super.put(key, value);
LPPermissionMap.this.update();
return ret;
}
@Override
public void putAll(@NonNull Map<? extends String, ? extends Boolean> map) {
super.putAll(map);
LPPermissionMap.this.update();
}
@Override
public Boolean remove(@NonNull Object object) {
Boolean ret = super.remove(object);
LPPermissionMap.this.update();
return ret;
}
@Override
public void clear() {
super.clear();
LPPermissionMap.this.update();
}
}
}
@@ -23,13 +23,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.model.server;
package me.lucko.luckperms.bukkit.inject.server;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
@@ -177,8 +177,8 @@ public final class LPSubscriptionMap extends HashMap<String, Map<Permissible, Bo
// if the key is a player, check their LPPermissible first
if (isPlayer) {
Permissible p = (Permissible) key;
if (p.isPermissionSet(this.permission)) {
return p.hasPermission(this.permission);
if (p.hasPermission(this.permission)) {
return true;
}
}
@@ -191,8 +191,8 @@ public final class LPSubscriptionMap extends HashMap<String, Map<Permissible, Bo
// then try the permissible, if we haven't already
if (!isPlayer && key instanceof Permissible) {
Permissible p = (Permissible) key;
if (p.isPermissionSet(this.permission)) {
return p.hasPermission(this.permission);
if (p.hasPermission(this.permission)) {
return true;
}
}
@@ -220,7 +220,7 @@ public final class LPSubscriptionMap extends HashMap<String, Map<Permissible, Bo
public @NonNull Set<Permissible> keySet() {
// gather players (LPPermissibles)
Set<Permissible> players = LPSubscriptionMap.this.plugin.getBootstrap().getServer().getOnlinePlayers().stream()
.filter(player -> player.isPermissionSet(this.permission))
.filter(player -> player.hasPermission(this.permission) || player.isPermissionSet(this.permission))
.collect(Collectors.toSet());
// then combine the players with the backing map
@@ -26,8 +26,8 @@
package me.lucko.luckperms.bukkit.listeners;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.bukkit.model.permissible.LPPermissible;
import me.lucko.luckperms.bukkit.model.permissible.PermissibleInjector;
import me.lucko.luckperms.bukkit.inject.permissible.LPPermissible;
import me.lucko.luckperms.bukkit.inject.permissible.PermissibleInjector;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.User;
@@ -50,12 +50,32 @@ import java.util.concurrent.TimeUnit;
public class BukkitConnectionListener extends AbstractConnectionListener implements Listener {
private final LPBukkitPlugin plugin;
private final boolean detectedCraftBukkitOfflineMode;
private final Set<UUID> deniedAsyncLogin = Collections.synchronizedSet(new HashSet<>());
private final Set<UUID> deniedLogin = Collections.synchronizedSet(new HashSet<>());
public BukkitConnectionListener(LPBukkitPlugin plugin) {
super(plugin);
this.plugin = plugin;
// check for craftbukkit + offline mode combination
String version = plugin.getBootstrap().getServer().getVersion();
boolean onlineMode = plugin.getBootstrap().getServer().getOnlineMode();
if (!onlineMode && version.startsWith("git-Bukkit-")) {
printCraftBukkitOfflineModeError();
this.detectedCraftBukkitOfflineMode = true;
} else {
this.detectedCraftBukkitOfflineMode = false;
}
}
private void printCraftBukkitOfflineModeError() {
this.plugin.getLogger().warn("It appears that your server is running CraftBukkit and configured in offline (cracked) mode.");
this.plugin.getLogger().warn("Due to a CraftBukkit limitation, LuckPerms cannot function correctly in this setup.");
this.plugin.getLogger().warn("To resolve this, please either a) upgrade from CraftBukkit to Spigot or Paper, or b) enable online-mode.");
this.plugin.getLogger().warn("For more info, please see: https://github.com/lucko/LuckPerms/wiki/Installation#craftbukkit-and-offline-mode");
}
@EventHandler(priority = EventPriority.LOW)
@@ -86,8 +106,8 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
- setting up cached data. */
try {
User user = loadUser(e.getUniqueId(), e.getName());
this.plugin.getEventFactory().handleUserLoginProcess(e.getUniqueId(), e.getName(), user);
recordConnection(e.getUniqueId());
this.plugin.getEventFactory().handlePlayerLoginProcess(e.getUniqueId(), e.getName(), user);
} catch (Exception ex) {
this.plugin.getLogger().severe("Exception occurred whilst loading data for " + e.getUniqueId() + " - " + e.getName());
ex.printStackTrace();
@@ -95,6 +115,7 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
// deny the connection
this.deniedAsyncLogin.add(e.getUniqueId());
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_DATABASE_ERROR.asString(this.plugin.getLocaleManager()));
this.plugin.getEventFactory().handlePlayerLoginProcess(e.getUniqueId(), e.getName(), null);
}
}
@@ -133,9 +154,17 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
this.deniedLogin.add(player.getUniqueId());
if (!getUniqueConnections().contains(player.getUniqueId())) {
this.plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getName() +
" doesn't have data pre-loaded, they have never been processed during pre-login in this session." +
" - denying login.");
if (this.detectedCraftBukkitOfflineMode) {
printCraftBukkitOfflineModeError();
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_STATE_ERROR_CB_OFFLINE_MODE.asString(this.plugin.getLocaleManager()));
return;
}
} else {
this.plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getName() +
" doesn't currently have data pre-loaded, but they have been processed before in this session." +
@@ -164,7 +193,7 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
return;
}
this.plugin.refreshAutoOp(player);
this.plugin.refreshAutoOp(player, true);
}
@EventHandler(priority = EventPriority.MONITOR)
@@ -193,7 +222,7 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
this.plugin.getBootstrap().getServer().getScheduler().runTaskLaterAsynchronously(this.plugin.getBootstrap(), () -> {
// Remove the custom permissible
try {
PermissibleInjector.unInject(player, true);
PermissibleInjector.uninject(player, true);
} catch (Exception ex) {
ex.printStackTrace();
}
@@ -75,8 +75,8 @@ public class BukkitPlatformListener implements Listener {
s = s.substring(1);
}
if (s.startsWith("minecraft:")) {
s = s.substring("minecraft:".length());
if (s.contains(":")) {
s = s.substring(s.indexOf(':') + 1);
}
if (s.equals("op") || s.startsWith("op ") || s.equals("deop") || s.startsWith("deop ")) {
@@ -95,7 +95,7 @@ public class BukkitPlatformListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onWorldChange(PlayerChangedWorldEvent e) {
this.plugin.getContextManager().invalidateCache(e.getPlayer());
this.plugin.refreshAutoOp(e.getPlayer());
this.plugin.refreshAutoOp(e.getPlayer(), true);
}
}
@@ -69,6 +69,10 @@ public class PluginMessageMessenger implements Messenger, PluginMessageListener
@Override
public void sendOutgoingMessage(@NonNull OutgoingMessage outgoingMessage) {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF(outgoingMessage.asEncodedString());
byte[] data = out.toByteArray();
new BukkitRunnable() {
@Override
public void run() {
@@ -78,11 +82,6 @@ public class PluginMessageMessenger implements Messenger, PluginMessageListener
return;
}
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF(outgoingMessage.asEncodedString());
byte[] data = out.toByteArray();
p.sendPluginMessage(PluginMessageMessenger.this.plugin.getBootstrap(), CHANNEL, data);
cancel();
}
@@ -25,14 +25,15 @@
package me.lucko.luckperms.bukkit.migration;
import me.lucko.luckperms.common.utils.ProgressLogger;
import me.lucko.luckperms.common.utils.Uuids;
import me.lucko.luckperms.common.util.ProgressLogger;
import me.lucko.luckperms.common.util.Uuids;
import org.bukkit.Bukkit;
import java.util.UUID;
public final class BukkitUuids {
private BukkitUuids() {}
public static UUID lookupUuid(ProgressLogger log, String s) {
UUID uuid = Uuids.parse(s);
@@ -50,6 +51,4 @@ public final class BukkitUuids {
return uuid;
}
private BukkitUuids() {}
}
@@ -35,9 +35,11 @@ import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.common.command.CommandResult;
import me.lucko.luckperms.common.command.abstraction.SubCommand;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.User;
@@ -45,9 +47,9 @@ import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.node.model.NodeTypes;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.Iterators;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.ProgressLogger;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.Predicates;
import me.lucko.luckperms.common.util.ProgressLogger;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -59,8 +61,6 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import static me.lucko.luckperms.common.command.access.CommandPermission.MIGRATION;
public class MigrationBPermissions extends SubCommand<Object> {
private static final Field UCONFIG_FIELD;
static {
@@ -73,12 +73,12 @@ public class MigrationBPermissions extends SubCommand<Object> {
}
public MigrationBPermissions(LocaleManager locale) {
super(CommandSpec.MIGRATION_COMMAND.localize(locale), "bpermissions", MIGRATION, Predicates.alwaysFalse());
super(CommandSpec.MIGRATION_COMMAND.localize(locale), "bpermissions", CommandPermission.MIGRATION, Predicates.alwaysFalse());
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
ProgressLogger log = new ProgressLogger("bPermissions");
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "bPermissions");
log.addListener(plugin.getConsoleSender());
log.addListener(sender);
@@ -116,10 +116,10 @@ public class MigrationBPermissions extends SubCommand<Object> {
return CommandResult.FAILURE;
}
AtomicInteger userLoadCount = new AtomicInteger(0);
users.forEach(s -> {
world.loadOne(s, CalculableType.USER);
log.logProgress("Forcefully loaded {} users so far.", userLoadCount.incrementAndGet());
});
for (String user : users) {
world.loadOne(user, CalculableType.USER);
log.logProgress("Forcefully loaded {} users so far.", userLoadCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
}
}
log.log("Forcefully loaded all users.");
@@ -169,7 +169,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
plugin.getStorage().saveUser(lpUser);
plugin.getUserManager().cleanup(lpUser);
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet());
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
});
log.log("Migrated " + userCount.get() + " users in world " + world.getName() + ".");
@@ -34,6 +34,7 @@ import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.model.UserIdentifier;
@@ -41,10 +42,10 @@ import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.node.model.NodeTypes;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.Iterators;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.ProgressLogger;
import me.lucko.luckperms.common.utils.Uuids;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.Predicates;
import me.lucko.luckperms.common.util.ProgressLogger;
import me.lucko.luckperms.common.util.Uuids;
import org.anjocaido.groupmanager.GlobalGroups;
import org.anjocaido.groupmanager.GroupManager;
@@ -70,7 +71,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
ProgressLogger log = new ProgressLogger("GroupManager");
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "GroupManager");
log.addListener(plugin.getConsoleSender());
log.addListener(sender);
@@ -210,7 +211,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
}
}
log.logProgress("Migrated {} users so far in world " + world, userWorldCount.incrementAndGet());
log.logProgress("Migrated {} users so far in world " + world, userWorldCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
});
log.log("Migrated " + userWorldCount.get() + " users in world " + world);
});
@@ -250,7 +251,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user);
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet());
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
});
log.log("Migrated " + userCount.get() + " users.");
@@ -34,15 +34,16 @@ import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.Iterators;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.ProgressLogger;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.Predicates;
import me.lucko.luckperms.common.util.ProgressLogger;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
@@ -59,7 +60,7 @@ public class MigrationPermissionsBukkit extends SubCommand<Object> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
ProgressLogger log = new ProgressLogger("PermissionsBukkit");
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "PermissionsBukkit");
log.addListener(plugin.getConsoleSender());
log.addListener(sender);
@@ -114,7 +115,7 @@ public class MigrationPermissionsBukkit extends SubCommand<Object> {
plugin.getUserManager().cleanup(lpUser);
plugin.getStorage().saveUser(lpUser);
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet());
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
});
log.log("Migrated " + userCount.get() + " users.");
@@ -34,6 +34,7 @@ import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.Track;
@@ -42,9 +43,9 @@ import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.node.model.NodeTypes;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.Iterators;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.ProgressLogger;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.Predicates;
import me.lucko.luckperms.common.util.ProgressLogger;
import org.bukkit.Bukkit;
@@ -90,10 +91,9 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
super(CommandSpec.MIGRATION_COMMAND.localize(locale), "permissionsex", CommandPermission.MIGRATION, Predicates.alwaysFalse());
}
@SuppressWarnings("deprecation")
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
ProgressLogger log = new ProgressLogger("PermissionsEx");
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "PermissionsEx");
log.addListener(plugin.getConsoleSender());
log.addListener(sender);
@@ -176,7 +176,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
plugin.getUserManager().cleanup(lpUser);
plugin.getStorage().saveUser(lpUser);
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet());
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
});
log.log("Migrated " + userCount.get() + " users.");
@@ -186,7 +186,6 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
private static Map<String, List<String>> getPermanentPermissions(PermissionEntity entity) {
try {
//noinspection unchecked
PermissionsData data = (PermissionsData) GET_DATA_METHOD.invoke(entity);
return data.getPermissionsMap();
} catch (IllegalAccessException | InvocationTargetException e) {
@@ -37,19 +37,21 @@ import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.common.command.CommandResult;
import me.lucko.luckperms.common.command.abstraction.SubCommand;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.storage.StorageType;
import me.lucko.luckperms.common.utils.Iterators;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.ProgressLogger;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.Predicates;
import me.lucko.luckperms.common.util.ProgressLogger;
import org.bukkit.Bukkit;
@@ -68,17 +70,15 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import static me.lucko.luckperms.common.command.access.CommandPermission.MIGRATION;
// Only supports the latest versions of the PP API. (it seems to change randomly almost every release)
public class MigrationPowerfulPerms extends SubCommand<Object> {
public MigrationPowerfulPerms(LocaleManager locale) {
super(CommandSpec.MIGRATION_POWERFULPERMS.localize(locale), "powerfulperms", MIGRATION, Predicates.not(5));
super(CommandSpec.MIGRATION_POWERFULPERMS.localize(locale), "powerfulperms", CommandPermission.MIGRATION, Predicates.not(5));
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
ProgressLogger log = new ProgressLogger("PowerfulPerms");
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "PowerfulPerms");
log.addListener(plugin.getConsoleSender());
log.addListener(sender);
@@ -265,7 +265,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
plugin.getUserManager().cleanup(user);
plugin.getStorage().saveUser(user);
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet());
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
});
log.log("Migrated " + userCount.get() + " users.");
@@ -34,6 +34,7 @@ import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.Track;
@@ -42,9 +43,9 @@ import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.node.model.NodeTypes;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.Iterators;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.ProgressLogger;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.Predicates;
import me.lucko.luckperms.common.util.ProgressLogger;
import org.bukkit.Bukkit;
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
@@ -70,7 +71,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
ProgressLogger log = new ProgressLogger("zPermissions");
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "zPermissions");
log.addListener(plugin.getConsoleSender());
log.addListener(sender);
@@ -182,7 +183,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
plugin.getUserManager().cleanup(user);
plugin.getStorage().saveUser(user);
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet());
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
});
log.log("Migrated " + userCount.get() + " users.");
@@ -32,15 +32,15 @@ import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.caching.type.MetaAccumulator;
import me.lucko.luckperms.common.caching.type.MetaCache;
import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator;
import me.lucko.luckperms.common.cacheddata.type.MetaCache;
import me.lucko.luckperms.common.command.CommandManager;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.node.model.NodeTypes;
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
import net.milkbowl.vault.chat.Chat;
@@ -60,19 +60,19 @@ import java.util.UUID;
* which they simply cannot be, as LP utilises databases for data storage. Server admins
* willing to take the risk of lagging their server can disable these exceptions in the config file.
*/
public class VaultChatHook extends AbstractVaultChat {
public class LuckPermsVaultChat extends AbstractVaultChat {
// the plugin instance
private final LPBukkitPlugin plugin;
// the vault permission implementation
private final VaultPermissionHook permissionHook;
private final LuckPermsVaultPermission vaultPermission;
VaultChatHook(LPBukkitPlugin plugin, VaultPermissionHook permissionHook) {
super(permissionHook);
LuckPermsVaultChat(LPBukkitPlugin plugin, LuckPermsVaultPermission vaultPermission) {
super(vaultPermission);
this.plugin = plugin;
this.permissionHook = permissionHook;
this.worldMappingFunction = world -> permissionHook.isIgnoreWorld() ? null : world;
this.vaultPermission = vaultPermission;
this.worldMappingFunction = world -> vaultPermission.isIgnoreWorld() ? null : world;
}
@Override
@@ -84,10 +84,10 @@ public class VaultChatHook extends AbstractVaultChat {
public String getUserChatPrefix(String world, UUID uuid) {
Objects.requireNonNull(uuid, "uuid");
User user = this.permissionHook.lookupUser(uuid);
Contexts contexts = this.permissionHook.contextForLookup(user, world);
PermissionHolder user = this.vaultPermission.lookupUser(uuid);
Contexts contexts = this.vaultPermission.contextForLookup(uuid, world);
MetaCache metaData = user.getCachedData().getMetaData(contexts);
String ret = metaData.getPrefix();
String ret = metaData.getPrefix(MetaCheckEvent.Origin.THIRD_PARTY_API);
if (log()) {
logMsg("#getUserChatPrefix: %s - %s - %s", user.getPlainDisplayName(), contexts.getContexts().toMultimap(), ret);
}
@@ -98,10 +98,10 @@ public class VaultChatHook extends AbstractVaultChat {
public String getUserChatSuffix(String world, UUID uuid) {
Objects.requireNonNull(uuid, "uuid");
User user = this.permissionHook.lookupUser(uuid);
Contexts contexts = this.permissionHook.contextForLookup(user, world);
PermissionHolder user = this.vaultPermission.lookupUser(uuid);
Contexts contexts = this.vaultPermission.contextForLookup(uuid, world);
MetaCache metaData = user.getCachedData().getMetaData(contexts);
String ret = metaData.getSuffix();
String ret = metaData.getSuffix(MetaCheckEvent.Origin.THIRD_PARTY_API);
if (log()) {
logMsg("#getUserChatSuffix: %s - %s - %s", user.getPlainDisplayName(), contexts.getContexts().toMultimap(), ret);
}
@@ -112,7 +112,10 @@ public class VaultChatHook extends AbstractVaultChat {
public void setUserChatPrefix(String world, UUID uuid, String prefix) {
Objects.requireNonNull(uuid, "uuid");
User user = this.permissionHook.lookupUser(uuid);
PermissionHolder user = this.vaultPermission.lookupUser(uuid);
if (user instanceof Group) {
throw new UnsupportedOperationException("Unable to modify the permissions of NPC players");
}
setChatMeta(user, ChatMetaType.PREFIX, prefix, world);
}
@@ -120,7 +123,10 @@ public class VaultChatHook extends AbstractVaultChat {
public void setUserChatSuffix(String world, UUID uuid, String suffix) {
Objects.requireNonNull(uuid, "uuid");
User user = this.permissionHook.lookupUser(uuid);
PermissionHolder user = this.vaultPermission.lookupUser(uuid);
if (user instanceof Group) {
throw new UnsupportedOperationException("Unable to modify the permissions of NPC players");
}
setChatMeta(user, ChatMetaType.SUFFIX, suffix, world);
}
@@ -129,10 +135,10 @@ public class VaultChatHook extends AbstractVaultChat {
Objects.requireNonNull(uuid, "uuid");
Objects.requireNonNull(key, "key");
User user = this.permissionHook.lookupUser(uuid);
Contexts contexts = this.permissionHook.contextForLookup(user, world);
PermissionHolder user = this.vaultPermission.lookupUser(uuid);
Contexts contexts = this.vaultPermission.contextForLookup(uuid, world);
MetaCache metaData = user.getCachedData().getMetaData(contexts);
String ret = metaData.getMeta().get(key);
String ret = metaData.getMeta(MetaCheckEvent.Origin.THIRD_PARTY_API).get(key);
if (log()) {
logMsg("#getUserMeta: %s - %s - %s - %s", user.getPlainDisplayName(), contexts.getContexts().toMultimap(), key, ret);
}
@@ -144,7 +150,10 @@ public class VaultChatHook extends AbstractVaultChat {
Objects.requireNonNull(uuid, "uuid");
Objects.requireNonNull(key, "key");
User user = this.permissionHook.lookupUser(uuid);
PermissionHolder user = this.vaultPermission.lookupUser(uuid);
if (user instanceof Group) {
throw new UnsupportedOperationException("Unable to modify the permissions of NPC players");
}
setMeta(user, key, value, world);
}
@@ -155,9 +164,9 @@ public class VaultChatHook extends AbstractVaultChat {
if (group == null) {
return null;
}
Contexts contexts = this.permissionHook.contextForLookup(null, world);
Contexts contexts = this.vaultPermission.contextForLookup(null, world);
MetaCache metaData = group.getCachedData().getMetaData(contexts);
String ret = metaData.getPrefix();
String ret = metaData.getPrefix(MetaCheckEvent.Origin.THIRD_PARTY_API);
if (log()) {
logMsg("#getGroupPrefix: %s - %s - %s", group.getName(), contexts.getContexts().toMultimap(), ret);
}
@@ -171,9 +180,9 @@ public class VaultChatHook extends AbstractVaultChat {
if (group == null) {
return null;
}
Contexts contexts = this.permissionHook.contextForLookup(null, world);
Contexts contexts = this.vaultPermission.contextForLookup(null, world);
MetaCache metaData = group.getCachedData().getMetaData(contexts);
String ret = metaData.getSuffix();
String ret = metaData.getSuffix(MetaCheckEvent.Origin.THIRD_PARTY_API);
if (log()) {
logMsg("#getGroupSuffix: %s - %s - %s", group.getName(), contexts.getContexts().toMultimap(), ret);
}
@@ -208,9 +217,9 @@ public class VaultChatHook extends AbstractVaultChat {
if (group == null) {
return null;
}
Contexts contexts = this.permissionHook.contextForLookup(null, world);
Contexts contexts = this.vaultPermission.contextForLookup(null, world);
MetaCache metaData = group.getCachedData().getMetaData(contexts);
String ret = metaData.getMeta().get(key);
String ret = metaData.getMeta(MetaCheckEvent.Origin.THIRD_PARTY_API).get(key);
if (log()) {
logMsg("#getGroupMeta: %s - %s - %s - %s", group.getName(), contexts.getContexts().toMultimap(), key, ret);
}
@@ -254,7 +263,7 @@ public class VaultChatHook extends AbstractVaultChat {
holder.removeIf(type::matches);
if (value == null) {
this.permissionHook.holderSave(holder);
this.vaultPermission.holderSave(holder);
return;
}
@@ -264,11 +273,11 @@ public class VaultChatHook extends AbstractVaultChat {
int priority = metaAccumulator.getChatMeta(type).keySet().stream().mapToInt(e -> e).max().orElse(0) + 10;
Node.Builder chatMetaNode = NodeFactory.buildChatMetaNode(type, priority, value);
chatMetaNode.setServer(this.permissionHook.getVaultServer());
chatMetaNode.setServer(this.vaultPermission.getVaultServer());
chatMetaNode.setWorld(world);
holder.setPermission(chatMetaNode.build()); // assume success
this.permissionHook.holderSave(holder);
this.vaultPermission.holderSave(holder);
}
private void setMeta(PermissionHolder holder, String key, Object value, String world) {
@@ -279,7 +288,7 @@ public class VaultChatHook extends AbstractVaultChat {
holder.removeIf(n -> n.isMeta() && n.getMeta().getKey().equals(key));
if (value == null) {
this.permissionHook.holderSave(holder);
this.vaultPermission.holderSave(holder);
return;
}
@@ -290,11 +299,11 @@ public class VaultChatHook extends AbstractVaultChat {
metaNode = NodeFactory.buildMetaNode(key, value.toString());
}
metaNode.setServer(this.permissionHook.getVaultServer());
metaNode.setServer(this.vaultPermission.getVaultServer());
metaNode.setWorld(world);
holder.setPermission(metaNode.build()); // assume success
this.permissionHook.holderSave(holder);
this.vaultPermission.holderSave(holder);
}
private Contexts createContextForWorldSet(String world) {
@@ -302,7 +311,7 @@ public class VaultChatHook extends AbstractVaultChat {
if (world != null && !world.equals("") && !world.equalsIgnoreCase("global")) {
context.add(Contexts.WORLD_KEY, world.toLowerCase());
}
context.add(Contexts.SERVER_KEY, this.permissionHook.getVaultServer());
return Contexts.of(context.build(), this.permissionHook.isIncludeGlobal(), true, true, true, true, false);
context.add(Contexts.SERVER_KEY, this.vaultPermission.getVaultServer());
return Contexts.of(context.build(), this.vaultPermission.isIncludeGlobal(), true, true, true, true, false);
}
}
@@ -33,14 +33,17 @@ import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.caching.type.PermissionCache;
import me.lucko.luckperms.common.cacheddata.type.PermissionCache;
import me.lucko.luckperms.common.command.CommandManager;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.HolderType;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.verbose.CheckOrigin;
import me.lucko.luckperms.common.util.Uuids;
import me.lucko.luckperms.common.verbose.event.MetaCheckEvent;
import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent;
import net.milkbowl.vault.permission.Permission;
@@ -49,7 +52,6 @@ import org.bukkit.entity.Player;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
/**
@@ -65,12 +67,12 @@ import java.util.UUID;
* which they simply cannot be, as LP utilises databases for data storage. Server admins
* willing to take the risk of lagging their server can disable these exceptions in the config file.
*/
public class VaultPermissionHook extends AbstractVaultPermission {
public class LuckPermsVaultPermission extends AbstractVaultPermission {
// the plugin instance
private final LPBukkitPlugin plugin;
public VaultPermissionHook(LPBukkitPlugin plugin) {
public LuckPermsVaultPermission(LPBukkitPlugin plugin) {
this.plugin = plugin;
this.worldMappingFunction = world -> isIgnoreWorld() ? null : world;
}
@@ -94,8 +96,14 @@ public class VaultPermissionHook extends AbstractVaultPermission {
return onlinePlayer.getUniqueId();
}
// account for plugins that for some reason think it's valid to pass the uuid as a string.
UUID uuid = Uuids.parse(player);
if (uuid != null) {
return uuid;
}
// are we on the main thread?
if (!plugin.getBootstrap().isServerStarting() && Bukkit.isPrimaryThread() && !this.plugin.getConfiguration().get(ConfigKeys.VAULT_UNSAFE_LOOKUPS)) {
if (!this.plugin.getBootstrap().isServerStarting() && Bukkit.isPrimaryThread() && !this.plugin.getConfiguration().get(ConfigKeys.VAULT_UNSAFE_LOOKUPS)) {
throw new RuntimeException(
"The operation to lookup a UUID for '" + player + "' was cancelled by LuckPerms. This is NOT a bug. \n" +
"The lookup request was made on the main server thread. It is not safe to execute a request to \n" +
@@ -108,7 +116,7 @@ public class VaultPermissionHook extends AbstractVaultPermission {
}
// lookup a username from the database
UUID uuid = this.plugin.getStorage().getPlayerUuid(player.toLowerCase()).join();
uuid = this.plugin.getStorage().getPlayerUuid(player.toLowerCase()).join();
if (uuid == null) {
uuid = this.plugin.getBootstrap().lookupUuid(player).orElse(null);
}
@@ -121,7 +129,7 @@ public class VaultPermissionHook extends AbstractVaultPermission {
return uuid;
}
public User lookupUser(UUID uuid) {
public PermissionHolder lookupUser(UUID uuid) {
Objects.requireNonNull(uuid, "uuid");
// loaded already?
@@ -130,12 +138,27 @@ public class VaultPermissionHook extends AbstractVaultPermission {
return user;
}
// if the uuid is version 2, assume it is an NPC
// see: https://github.com/lucko/LuckPerms/issues/1470
// and https://github.com/lucko/LuckPerms/issues/1470#issuecomment-475403162
if (uuid.version() == 2) {
String npcGroupName = this.plugin.getConfiguration().get(ConfigKeys.VAULT_NPC_GROUP);
Group npcGroup = this.plugin.getGroupManager().getIfLoaded(npcGroupName);
if (npcGroup == null) {
npcGroup = this.plugin.getGroupManager().getIfLoaded(NodeFactory.DEFAULT_GROUP_NAME);
if (npcGroup == null) {
throw new IllegalStateException("unable to get default group");
}
}
return npcGroup;
}
// are we on the main thread?
if (!plugin.getBootstrap().isServerStarting() && Bukkit.isPrimaryThread() && !this.plugin.getConfiguration().get(ConfigKeys.VAULT_UNSAFE_LOOKUPS)) {
if (!this.plugin.getBootstrap().isServerStarting() && Bukkit.isPrimaryThread() && !this.plugin.getConfiguration().get(ConfigKeys.VAULT_UNSAFE_LOOKUPS)) {
throw new RuntimeException(
"The operation to load user data for '" + uuid + "' was cancelled by LuckPerms. This is NOT a bug. \n" +
"The lookup request was made on the main server thread. It is not safe to execute a request to \n" +
"load username data from the database in this context. \n" +
"load data for offline players from the database in this context. \n" +
"If you are a plugin author, please consider making your request asynchronously. \n" +
"Alternatively, server admins can disable this catch by setting 'vault-unsafe-lookups' to true \n" +
"in the LP config, but should consider the consequences (lag) before doing so."
@@ -158,11 +181,11 @@ public class VaultPermissionHook extends AbstractVaultPermission {
Objects.requireNonNull(uuid, "uuid");
Objects.requireNonNull(permission, "permission");
User user = lookupUser(uuid);
Contexts contexts = contextForLookup(user, world);
PermissionHolder user = lookupUser(uuid);
Contexts contexts = contextForLookup(uuid, world);
PermissionCache permissionData = user.getCachedData().getPermissionData(contexts);
Tristate result = permissionData.getPermissionValue(permission, CheckOrigin.INTERNAL);
Tristate result = permissionData.getPermissionValue(permission, PermissionCheckEvent.Origin.THIRD_PARTY_API).result();
if (log()) {
logMsg("#userHasPermission: %s - %s - %s - %s", user.getPlainDisplayName(), contexts.getContexts().toMultimap(), permission, result);
}
@@ -174,7 +197,10 @@ public class VaultPermissionHook extends AbstractVaultPermission {
Objects.requireNonNull(uuid, "uuid");
Objects.requireNonNull(permission, "permission");
User user = lookupUser(uuid);
PermissionHolder user = lookupUser(uuid);
if (user instanceof Group) {
throw new UnsupportedOperationException("Unable to modify the permissions of NPC players");
}
return holderAddPermission(user, permission, world);
}
@@ -183,7 +209,10 @@ public class VaultPermissionHook extends AbstractVaultPermission {
Objects.requireNonNull(uuid, "uuid");
Objects.requireNonNull(permission, "permission");
User user = lookupUser(uuid);
PermissionHolder user = lookupUser(uuid);
if (user instanceof Group) {
throw new UnsupportedOperationException("Unable to modify the permissions of NPC players");
}
return holderRemovePermission(user, permission, world);
}
@@ -212,8 +241,8 @@ public class VaultPermissionHook extends AbstractVaultPermission {
public String[] userGetGroups(String world, UUID uuid) {
Objects.requireNonNull(uuid, "uuid");
User user = lookupUser(uuid);
ContextSet contexts = contextForLookup(user, world).getContexts();
PermissionHolder user = lookupUser(uuid);
ContextSet contexts = contextForLookup(uuid, world).getContexts();
String[] ret = user.enduringData().immutable().values().stream()
.filter(Node::isGroupNode)
@@ -238,13 +267,18 @@ public class VaultPermissionHook extends AbstractVaultPermission {
public String userGetPrimaryGroup(String world, UUID uuid) {
Objects.requireNonNull(uuid, "uuid");
User user = lookupUser(uuid);
String value = user.getPrimaryGroup().getValue();
PermissionHolder user = lookupUser(uuid);
if (user instanceof Group) { // npc
return this.plugin.getConfiguration().get(ConfigKeys.VAULT_NPC_GROUP);
}
String value = ((User) user).getPrimaryGroup().getValue();
Group group = getGroup(value);
if (group != null) {
value = group.getPlainDisplayName();
}
this.plugin.getVerboseHandler().offerMetaCheckEvent(MetaCheckEvent.Origin.THIRD_PARTY_API, user.getPlainDisplayName(), ContextSet.empty(), "primarygroup", value);
if (log()) {
logMsg("#userGetPrimaryGroup: %s - %s - %s", user.getPlainDisplayName(), world, value);
}
@@ -265,7 +299,7 @@ public class VaultPermissionHook extends AbstractVaultPermission {
Contexts contexts = contextForLookup(null, world);
PermissionCache permissionData = group.getCachedData().getPermissionData(contexts);
Tristate result = permissionData.getPermissionValue(permission, CheckOrigin.INTERNAL);
Tristate result = permissionData.getPermissionValue(permission, PermissionCheckEvent.Origin.THIRD_PARTY_API).result();
if (log()) {
logMsg("#groupHasPermission: %s - %s - %s - %s", group.getName(), contexts.getContexts().toMultimap(), permission, result);
}
@@ -328,10 +362,10 @@ public class VaultPermissionHook extends AbstractVaultPermission {
}
// utility method for getting a contexts instance for a given vault lookup.
Contexts contextForLookup(User user, String world) {
Contexts contextForLookup(UUID uuid, String world) {
MutableContextSet context;
Player player = Optional.ofNullable(user).flatMap(u -> this.plugin.getBootstrap().getPlayer(u.getUuid())).orElse(null);
Player player = this.plugin.getBootstrap().getPlayer(uuid).orElse(null);
if (player != null) {
context = this.plugin.getContextManager().getApplicableContext(player).mutableCopy();
} else {
@@ -360,7 +394,14 @@ public class VaultPermissionHook extends AbstractVaultPermission {
}
}
return Contexts.of(context, isIncludeGlobal(), true, true, true, true, false);
boolean op = false;
if (player != null) {
op = player.isOp();
} else if (uuid.version() == 2) { // npc
op = this.plugin.getConfiguration().get(ConfigKeys.VAULT_NPC_OP_STATUS);
}
return Contexts.of(context, isIncludeGlobal(), true, true, true, true, op);
}
// utility methods for modifying the state of PermissionHolders
@@ -394,13 +435,13 @@ public class VaultPermissionHook extends AbstractVaultPermission {
}
boolean holderSave(PermissionHolder holder) {
if (holder.getType().isUser()) {
if (holder.getType() == HolderType.USER) {
User u = (User) holder;
// we don't need to join this call - the save operation
// can happen in the background.
this.plugin.getStorage().saveUser(u);
} else if (holder.getType().isGroup()) {
} else if (holder.getType() == HolderType.GROUP) {
Group g = (Group) holder;
// invalidate caches - they have potentially been affected by
@@ -37,8 +37,8 @@ import org.bukkit.plugin.ServicesManager;
* Handles hooking with the Vault API
*/
public class VaultHookManager {
private VaultChatHook chatHook = null;
private VaultPermissionHook permissionHook = null;
private LuckPermsVaultChat chat = null;
private LuckPermsVaultPermission permission = null;
/**
* Registers the LuckPerms implementation of {@link Permission} and {@link Chat} with
@@ -48,17 +48,17 @@ public class VaultHookManager {
*/
public void hook(LPBukkitPlugin plugin) {
try {
if (this.permissionHook == null) {
this.permissionHook = new VaultPermissionHook(plugin);
if (this.permission == null) {
this.permission = new LuckPermsVaultPermission(plugin);
}
if (this.chatHook == null) {
this.chatHook = new VaultChatHook(plugin, this.permissionHook);
if (this.chat == null) {
this.chat = new LuckPermsVaultChat(plugin, this.permission);
}
final ServicesManager sm = plugin.getBootstrap().getServer().getServicesManager();
sm.register(Permission.class, this.permissionHook, plugin.getBootstrap(), ServicePriority.High);
sm.register(Chat.class, this.chatHook, plugin.getBootstrap(), ServicePriority.High);
sm.register(Permission.class, this.permission, plugin.getBootstrap(), ServicePriority.High);
sm.register(Chat.class, this.chat, plugin.getBootstrap(), ServicePriority.High);
} catch (Exception e) {
e.printStackTrace();
@@ -73,14 +73,14 @@ public class VaultHookManager {
public void unhook(LPBukkitPlugin plugin) {
final ServicesManager sm = plugin.getBootstrap().getServer().getServicesManager();
if (this.permissionHook != null) {
sm.unregister(Permission.class, this.permissionHook);
this.permissionHook = null;
if (this.permission != null) {
sm.unregister(Permission.class, this.permission);
this.permission = null;
}
if (this.chatHook != null) {
sm.unregister(Chat.class, this.chatHook);
this.chatHook = null;
if (this.chat != null) {
sm.unregister(Chat.class, this.chat);
this.chat = null;
}
}
+18
View File
@@ -4,6 +4,7 @@
# | | | | / ` |__/ |__) |__ |__) |\/| /__` | #
# | |___ \__/ \__, | \ | |___ | \ | | .__/ | #
# | | #
# | https://luckperms.github.io | #
# | | #
# | SOURCE CODE: https://github.com/lucko/LuckPerms | #
# | WIKI: https://github.com/lucko/LuckPerms/wiki | #
@@ -300,6 +301,8 @@ log-notify: true
# - It is explained and documented in more detail on the wiki under "Prefix & Suffix Stacking".
#
# - The options are divided into separate sections for prefixes and suffixes.
# - The 'duplicates' setting refers to how duplicate elements are handled. Can be 'retain-all',
# 'first-only' or 'last-only'.
# - The value of 'start-spacer' is included at the start of the resultant prefix/suffix.
# - The value of 'end-spacer' is included at the end of the resultant prefix/suffix.
# - The value of 'middle-spacer' is included between each element in the resultant prefix/suffix.
@@ -333,12 +336,14 @@ meta-formatting:
prefix:
format:
- "highest"
duplicates: first-only
start-spacer: ""
middle-spacer: " "
end-spacer: ""
suffix:
format:
- "highest"
duplicates: first-only
start-spacer: ""
middle-spacer: " "
end-spacer: ""
@@ -496,6 +501,19 @@ commands-allow-op: true
# option to 'true.
vault-unsafe-lookups: false
# Controls which group LuckPerms should use for NPC players when handling Vault requests.
#
# - As NPCs aren't actually real players, LuckPerms does not load any user data for them. This
# becomes an issue when plugins want to check for their permissions using Vault.
# - As a solution, Vault checks for NPCs fallback to a group, which is defined below.
vault-npc-group: default
# Controls how LuckPerms should consider the OP status of NPC players when handing Vault requests.
#
# - If you want NPCs to have the same permissions as "normal" players, set this option to false.
# - If you want NPCs to have OP status, set this option to true.
vault-npc-op-status: false
# If the vault-server option below should be used.
#
# - When this option is set to false, the server value defined above under "server" is used.
+6 -1
View File
@@ -2,11 +2,16 @@ name: LuckPerms
version: ${pluginVersion}
description: A permissions plugin
author: Luck
website: https://github.com/lucko/LuckPerms
website: https://luckperms.github.io
main: me.lucko.luckperms.bukkit.LPBukkitBootstrap
load: STARTUP
# Mark the plugin as 1.13 compatible to avoid CB having to perform quite as much unnecessary
# remapping when the plugin is loaded. Note that despite what this setting might otherwise imply,
# LP is still compatible with pre-1.13 releases.
api-version: 1.13
# This means that all plugins that (soft-)depend on Vault, depend on LuckPerms too.
# It in turn fixes issues where plugins using Vault cache the provided instance
# when their plugin enables, or when they check for the presence of a service
+2 -1
View File
@@ -5,7 +5,8 @@ plugins {
dependencies {
compile project(':common')
compileOnly 'net.md-5:bungeecord-api:1.12-SNAPSHOT'
compileOnly 'net.md-5:bungeecord-api:1.13-SNAPSHOT'
compileOnly 'net.kyori:text-adapter-bungeecord:1.0.2'
compileOnly 'com.imaginarycode.minecraft:RedisBungee:0.4'
// migration plugins
@@ -27,7 +27,7 @@ package me.lucko.luckperms.bungee;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask;
import me.lucko.luckperms.common.utils.Iterators;
import me.lucko.luckperms.common.util.Iterators;
import net.md_5.bungee.api.scheduler.ScheduledTask;
@@ -27,16 +27,15 @@ package me.lucko.luckperms.bungee;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.bungee.event.TristateCheckEvent;
import me.lucko.luckperms.common.command.CommandManager;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.sender.SenderFactory;
import me.lucko.luckperms.common.utils.TextUtils;
import me.lucko.luckperms.common.util.TextUtils;
import net.kyori.text.Component;
import net.kyori.text.serializer.ComponentSerializers;
import net.kyori.text.adapter.bungeecord.TextAdapter;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.chat.ComponentSerializer;
import java.util.UUID;
@@ -50,7 +49,7 @@ public class BungeeSenderFactory extends SenderFactory<CommandSender> {
if (sender instanceof ProxiedPlayer) {
return sender.getName();
}
return CommandManager.CONSOLE_NAME;
return Sender.CONSOLE_NAME;
}
@Override
@@ -58,7 +57,7 @@ public class BungeeSenderFactory extends SenderFactory<CommandSender> {
if (sender instanceof ProxiedPlayer) {
return ((ProxiedPlayer) sender).getUniqueId();
}
return CommandManager.CONSOLE_UUID;
return Sender.CONSOLE_UUID;
}
@Override
@@ -68,7 +67,7 @@ public class BungeeSenderFactory extends SenderFactory<CommandSender> {
@Override
protected void sendMessage(CommandSender sender, Component message) {
sender.sendMessage(ComponentSerializer.parse(ComponentSerializers.JSON.serialize(message)));
TextAdapter.sendComponent(sender, message);
}
@Override
@@ -27,25 +27,25 @@ package me.lucko.luckperms.bungee;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LuckPermsApi;
import me.lucko.luckperms.bungee.calculators.BungeeCalculatorFactory;
import me.lucko.luckperms.bungee.contexts.BackendServerCalculator;
import me.lucko.luckperms.bungee.contexts.BungeeContextManager;
import me.lucko.luckperms.bungee.contexts.RedisBungeeCalculator;
import me.lucko.luckperms.bungee.calculator.BungeeCalculatorFactory;
import me.lucko.luckperms.bungee.context.BackendServerCalculator;
import me.lucko.luckperms.bungee.context.BungeeContextManager;
import me.lucko.luckperms.bungee.context.RedisBungeeCalculator;
import me.lucko.luckperms.bungee.listeners.BungeeConnectionListener;
import me.lucko.luckperms.bungee.listeners.BungeePermissionCheckListener;
import me.lucko.luckperms.bungee.messaging.BungeeMessagingFactory;
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.calculator.CalculatorFactory;
import me.lucko.luckperms.common.command.CommandManager;
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
import me.lucko.luckperms.common.contexts.ContextManager;
import me.lucko.luckperms.common.context.ContextManager;
import me.lucko.luckperms.common.dependencies.Dependency;
import me.lucko.luckperms.common.event.AbstractEventBus;
import me.lucko.luckperms.common.managers.group.StandardGroupManager;
import me.lucko.luckperms.common.managers.track.StandardTrackManager;
import me.lucko.luckperms.common.managers.user.StandardUserManager;
import me.lucko.luckperms.common.messaging.MessagingFactory;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.model.manager.group.StandardGroupManager;
import me.lucko.luckperms.common.model.manager.track.StandardTrackManager;
import me.lucko.luckperms.common.model.manager.user.StandardUserManager;
import me.lucko.luckperms.common.plugin.AbstractLuckPermsPlugin;
import me.lucko.luckperms.common.plugin.util.AbstractConnectionListener;
import me.lucko.luckperms.common.sender.Sender;
@@ -94,7 +94,7 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin {
@Override
protected Set<Dependency> getGlobalDependencies() {
return EnumSet.of(Dependency.TEXT, Dependency.CAFFEINE, Dependency.OKIO, Dependency.OKHTTP, Dependency.EVENT);
return EnumSet.of(Dependency.TEXT, Dependency.TEXT_ADAPTER_BUNGEECORD, Dependency.CAFFEINE, Dependency.OKIO, Dependency.OKHTTP, Dependency.EVENT);
}
@Override
@@ -141,7 +141,7 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin {
this.contextManager.registerCalculator(new BackendServerCalculator(this));
if (this.bootstrap.getProxy().getPluginManager().getPlugin("RedisBungee") != null) {
this.contextManager.registerStaticCalculator(new RedisBungeeCalculator());
this.contextManager.registerCalculator(new RedisBungeeCalculator());
}
}
@@ -23,20 +23,20 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bungee.calculators;
package me.lucko.luckperms.bungee.calculator;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.bungee.LPBungeePlugin;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.calculators.PermissionCalculator;
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
import me.lucko.luckperms.common.cacheddata.CacheMetadata;
import me.lucko.luckperms.common.calculator.CalculatorFactory;
import me.lucko.luckperms.common.calculator.PermissionCalculator;
import me.lucko.luckperms.common.calculator.processor.MapProcessor;
import me.lucko.luckperms.common.calculator.processor.PermissionProcessor;
import me.lucko.luckperms.common.calculator.processor.RegexProcessor;
import me.lucko.luckperms.common.calculator.processor.WildcardProcessor;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.processors.MapProcessor;
import me.lucko.luckperms.common.processors.PermissionProcessor;
import me.lucko.luckperms.common.processors.RegexProcessor;
import me.lucko.luckperms.common.processors.WildcardProcessor;
public class BungeeCalculatorFactory implements CalculatorFactory {
private final LPBungeePlugin plugin;
@@ -46,7 +46,7 @@ public class BungeeCalculatorFactory implements CalculatorFactory {
}
@Override
public PermissionCalculator build(Contexts contexts, PermissionCalculatorMetadata metadata) {
public PermissionCalculator build(Contexts contexts, CacheMetadata metadata) {
ImmutableList.Builder<PermissionProcessor> processors = ImmutableList.builder();
processors.add(new MapProcessor());
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bungee.contexts;
package me.lucko.luckperms.bungee.context;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.context.ContextCalculator;
@@ -23,16 +23,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bungee.contexts;
package me.lucko.luckperms.bungee.context;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.bungee.LPBungeePlugin;
import me.lucko.luckperms.common.contexts.ContextManager;
import me.lucko.luckperms.common.contexts.ContextsSupplier;
import me.lucko.luckperms.common.context.ContextManager;
import me.lucko.luckperms.common.context.ContextsSupplier;
import me.lucko.luckperms.common.util.CaffeineFactory;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@@ -40,7 +40,7 @@ import java.util.concurrent.TimeUnit;
public class BungeeContextManager extends ContextManager<ProxiedPlayer> {
private final LoadingCache<ProxiedPlayer, Contexts> contextsCache = Caffeine.newBuilder()
private final LoadingCache<ProxiedPlayer, Contexts> contextsCache = CaffeineFactory.newBuilder()
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
.build(this::calculate);
@@ -90,10 +90,5 @@ public class BungeeContextManager extends ContextManager<ProxiedPlayer> {
public Contexts getContexts() {
return this.contextsCache.get(this.key);
}
@Override
public ImmutableContextSet getContextSet() {
return getContexts().getContexts().makeImmutable();
}
}
}
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.bungee.contexts;
package me.lucko.luckperms.bungee.context;
import com.imaginarycode.minecraft.redisbungee.RedisBungee;
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
@@ -82,8 +82,8 @@ public class BungeeConnectionListener extends AbstractConnectionListener impleme
- setting up cached data. */
try {
User user = loadUser(c.getUniqueId(), c.getName());
this.plugin.getEventFactory().handleUserLoginProcess(c.getUniqueId(), c.getName(), user);
recordConnection(c.getUniqueId());
this.plugin.getEventFactory().handlePlayerLoginProcess(c.getUniqueId(), c.getName(), user);
} catch (Exception ex) {
this.plugin.getLogger().severe("Exception occurred whilst loading data for " + c.getUniqueId() + " - " + c.getName());
ex.printStackTrace();
@@ -94,6 +94,7 @@ public class BungeeConnectionListener extends AbstractConnectionListener impleme
e.setCancelReason(TextComponent.fromLegacyText(Message.LOADING_DATABASE_ERROR.asString(this.plugin.getLocaleManager())));
e.setCancelled(true);
}
this.plugin.getEventFactory().handlePlayerLoginProcess(c.getUniqueId(), c.getName(), null);
}
// finally, complete our intent to modify state, so the proxy can continue handling the connection.
@@ -30,9 +30,9 @@ import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.bungee.LPBungeePlugin;
import me.lucko.luckperms.bungee.event.TristateCheckEvent;
import me.lucko.luckperms.common.calculator.result.TristateResult;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.model.User;
import me.lucko.luckperms.common.verbose.CheckOrigin;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PermissionCheckEvent;
@@ -67,7 +67,7 @@ public class BungeePermissionCheckListener implements Listener {
}
Contexts contexts = this.plugin.getContextManager().getApplicableContexts(player);
Tristate result = user.getCachedData().getPermissionData(contexts).getPermissionValue(e.getPermission(), CheckOrigin.PLATFORM_PERMISSION_CHECK);
Tristate result = user.getCachedData().getPermissionData(contexts).getPermissionValue(e.getPermission(), me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK).result();
if (result == Tristate.UNDEFINED && this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUNGEE_CONFIG_PERMISSIONS)) {
return; // just use the result provided by the proxy when the event was created
}
@@ -93,7 +93,7 @@ public class BungeePermissionCheckListener implements Listener {
}
Contexts contexts = this.plugin.getContextManager().getApplicableContexts(player);
Tristate result = user.getCachedData().getPermissionData(contexts).getPermissionValue(e.getPermission(), CheckOrigin.PLATFORM_LOOKUP_CHECK);
Tristate result = user.getCachedData().getPermissionData(contexts).getPermissionValue(e.getPermission(), me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK).result();
if (result == Tristate.UNDEFINED && this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUNGEE_CONFIG_PERMISSIONS)) {
return; // just use the result provided by the proxy when the event was created
}
@@ -114,7 +114,7 @@ public class BungeePermissionCheckListener implements Listener {
Tristate result = Tristate.fromBoolean(e.hasPermission());
String name = "internal/" + e.getSender().getName();
this.plugin.getVerboseHandler().offerCheckData(CheckOrigin.PLATFORM_PERMISSION_CHECK, name, ContextSet.empty(), permission, result);
this.plugin.getVerboseHandler().offerPermissionCheckEvent(me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_PERMISSION_CHECK, name, ContextSet.empty(), permission, TristateResult.of(result));
this.plugin.getPermissionRegistry().offer(permission);
}
@@ -131,7 +131,7 @@ public class BungeePermissionCheckListener implements Listener {
Tristate result = e.getResult();
String name = "internal/" + e.getSender().getName();
this.plugin.getVerboseHandler().offerCheckData(CheckOrigin.PLATFORM_LOOKUP_CHECK, name, ContextSet.empty(), permission, result);
this.plugin.getVerboseHandler().offerPermissionCheckEvent(me.lucko.luckperms.common.verbose.event.PermissionCheckEvent.Origin.PLATFORM_LOOKUP_CHECK, name, ContextSet.empty(), permission, TristateResult.of(result));
this.plugin.getPermissionRegistry().offer(permission);
}
}
@@ -32,13 +32,14 @@ import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
import me.lucko.luckperms.common.locale.LocaleManager;
import me.lucko.luckperms.common.locale.command.CommandSpec;
import me.lucko.luckperms.common.locale.message.Message;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.utils.Iterators;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.utils.ProgressLogger;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.Predicates;
import me.lucko.luckperms.common.util.ProgressLogger;
import net.alpenblock.bungeeperms.BungeePerms;
import net.alpenblock.bungeeperms.Group;
@@ -57,7 +58,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
ProgressLogger log = new ProgressLogger("BungeePerms");
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "BungeePerms");
log.addListener(plugin.getConsoleSender());
log.addListener(sender);
@@ -118,7 +119,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user);
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet());
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
});
log.log("Migrated " + userCount.get() + " users.");
@@ -31,6 +31,7 @@ import java.util.Optional;
import java.util.UUID;
public final class RedisBungeeUtil {
private RedisBungeeUtil() {}
/**
* Looks up a UUID from username via RedisBungee's uuid cache.
@@ -46,6 +47,4 @@ public final class RedisBungeeUtil {
return Optional.ofNullable(RedisBungee.getApi()).map(a -> a.getNameFromUuid(uuid, true));
}
private RedisBungeeUtil() {}
}
+6 -1
View File
@@ -4,6 +4,7 @@
# | | | | / ` |__/ |__) |__ |__) |\/| /__` | #
# | |___ \__/ \__, | \ | |___ | \ | | .__/ | #
# | | #
# | https://luckperms.github.io | #
# | | #
# | SOURCE CODE: https://github.com/lucko/LuckPerms | #
# | WIKI: https://github.com/lucko/LuckPerms/wiki | #
@@ -247,7 +248,7 @@ redis:
# If LuckPerms should ensure all players have permission data when they connect to the server.
#
# - When set to true, LuckPerms will cancel login attempts if it is unable to load permissions data
# for a user, of if the storage provider is unavailable.
# for a user, or if the storage provider is unavailable.
# - When set to false, LuckPerms will allow a player to connect regardless of whether their
# permissions data could be loaded.
# - This option does not exist on other platforms, and effectively defaults to true - however,
@@ -308,6 +309,8 @@ log-notify: true
# - It is explained and documented in more detail on the wiki under "Prefix & Suffix Stacking".
#
# - The options are divided into separate sections for prefixes and suffixes.
# - The 'duplicates' setting refers to how duplicate elements are handled. Can be 'retain-all',
# 'first-only' or 'last-only'.
# - The value of 'start-spacer' is included at the start of the resultant prefix/suffix.
# - The value of 'end-spacer' is included at the end of the resultant prefix/suffix.
# - The value of 'middle-spacer' is included between each element in the resultant prefix/suffix.
@@ -341,12 +344,14 @@ meta-formatting:
prefix:
format:
- "highest"
duplicates: first-only
start-spacer: ""
middle-spacer: " "
end-spacer: ""
suffix:
format:
- "highest"
duplicates: first-only
start-spacer: ""
middle-spacer: " "
end-spacer: ""
+8 -8
View File
@@ -2,7 +2,7 @@ dependencies {
compile project(':luckperms-api')
compile 'org.checkerframework:checker-qual:2.5.5'
compile('net.kyori:text:1.11-1.6.4') {
compile('net.kyori:text:1.11-1.6.5') {
exclude(module: 'checker-qual')
exclude(module: 'guava')
exclude(module: 'gson')
@@ -13,9 +13,9 @@ dependencies {
}
compile 'com.google.code.gson:gson:2.7'
compile 'com.google.guava:guava:19.0'
compile 'com.github.ben-manes.caffeine:caffeine:2.6.2'
compile 'com.squareup.okhttp3:okhttp:3.11.0'
compile 'com.squareup.okio:okio:1.15.0'
compile 'com.github.ben-manes.caffeine:caffeine:2.7.0'
compile 'com.squareup.okhttp3:okhttp:3.13.1'
compile 'com.squareup.okio:okio:1.17.2'
compile('me.lucko.configurate:configurate-core:3.5') {
exclude(module: 'guava')
}
@@ -29,8 +29,8 @@ dependencies {
compile('me.lucko.configurate:configurate-toml:3.5') {
exclude(module: 'toml4j')
}
compile 'com.zaxxer:HikariCP:3.2.0'
compile 'redis.clients:jedis:2.9.0'
compile 'org.mongodb:mongo-java-driver:3.8.1'
compile 'org.yaml:snakeyaml:1.22'
compile 'com.zaxxer:HikariCP:3.3.1'
compile 'redis.clients:jedis:2.10.2'
compile 'org.mongodb:mongo-java-driver:3.10.1'
compile 'org.yaml:snakeyaml:1.23'
}
@@ -31,6 +31,7 @@ import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.HolderType;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.User;
@@ -46,7 +47,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* An implementation of {@link LogEntry} and {@link LogEntry.Builder},
@@ -287,11 +287,11 @@ public class ExtendedLogEntry implements LogEntry {
}
public Builder acted(PermissionHolder acted) {
if (acted.getType().isUser()) {
if (acted.getType() == HolderType.USER) {
actedName(((User) acted).getName().orElse("null"));
acted(((User) acted).getUuid());
type(Type.USER);
} else if (acted.getType().isGroup()) {
} else if (acted.getType() == HolderType.GROUP) {
actedName(((Group) acted).getName());
type(Type.GROUP);
}
@@ -331,7 +331,7 @@ public class ExtendedLogEntry implements LogEntry {
}
}
action(parts.stream().collect(Collectors.joining(" ")));
action(String.join(" ", parts));
return this;
}
@@ -28,7 +28,7 @@ package me.lucko.luckperms.common.actionlog;
import com.google.common.collect.ImmutableSortedSet;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import java.util.Comparator;
import java.util.SortedSet;
@@ -35,6 +35,7 @@ import me.lucko.luckperms.api.LogEntry;
import java.util.UUID;
public final class LogEntryJsonSerializer {
private LogEntryJsonSerializer() {}
public static JsonObject serialize(LogEntry logEntry) {
JsonObject data = new JsonObject();
@@ -58,7 +59,7 @@ public final class LogEntryJsonSerializer {
builder.actor(UUID.fromString(data.get("actor").getAsString()));
builder.actorName(data.get("actorName").getAsString());
builder.type(LogEntry.Type.valueOf(data.get("type").getAsString()));
builder.type(LogEntry.Type.parse(data.get("type").getAsString()));
if (data.has("acted")) {
builder.actor(UUID.fromString(data.get("acted").getAsString()));
}
@@ -68,5 +69,4 @@ public final class LogEntryJsonSerializer {
return builder.build();
}
private LogEntryJsonSerializer() {}
}
@@ -27,19 +27,25 @@ package me.lucko.luckperms.common.api;
import com.google.common.base.Preconditions;
import me.lucko.luckperms.common.storage.DataConstraints;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.misc.DataConstraints;
import java.util.function.Predicate;
public final class ApiUtils {
private ApiUtils() {}
public static String checkUsername(String s) {
public static String checkUsername(String s, LuckPermsPlugin plugin) {
if (s == null) {
return null;
}
Preconditions.checkArgument(
DataConstraints.PLAYER_USERNAME_TEST.test(s),
"Invalid username entry '" + s + "'. Usernames must be less than 16 chars and only contain 'a-z A-Z 1-9 _'."
);
Predicate<String> test = plugin.getConfiguration().get(ConfigKeys.ALLOW_INVALID_USERNAMES) ?
DataConstraints.PLAYER_USERNAME_TEST_LENIENT :
DataConstraints.PLAYER_USERNAME_TEST;
Preconditions.checkArgument(test.test(s), "Invalid username entry: " + s);
return s;
}
@@ -48,13 +54,8 @@ public final class ApiUtils {
return null;
}
Preconditions.checkArgument(
DataConstraints.GROUP_NAME_TEST.test(s),
"Invalid name entry '" + s + "'. Names must be less than 37 chars and only contain 'a-z A-Z 1-9'."
);
Preconditions.checkArgument(DataConstraints.GROUP_NAME_TEST.test(s), "Invalid name entry: " + s);
return s.toLowerCase();
}
private ApiUtils() {}
}
@@ -40,22 +40,23 @@ 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 me.lucko.luckperms.common.api.delegates.manager.ApiContextManager;
import me.lucko.luckperms.common.api.delegates.manager.ApiGroupManager;
import me.lucko.luckperms.common.api.delegates.manager.ApiTrackManager;
import me.lucko.luckperms.common.api.delegates.manager.ApiUserManager;
import me.lucko.luckperms.common.api.delegates.misc.ApiActionLogger;
import me.lucko.luckperms.common.api.delegates.misc.ApiMessagingService;
import me.lucko.luckperms.common.api.delegates.misc.ApiMetaStackFactory;
import me.lucko.luckperms.common.api.delegates.misc.ApiNodeFactory;
import me.lucko.luckperms.common.api.delegates.misc.ApiPlatformInfo;
import me.lucko.luckperms.common.api.delegates.misc.NoopUuidCache;
import me.lucko.luckperms.common.api.implementation.ApiActionLogger;
import me.lucko.luckperms.common.api.implementation.ApiContextManager;
import me.lucko.luckperms.common.api.implementation.ApiGroupManager;
import me.lucko.luckperms.common.api.implementation.ApiMessagingService;
import me.lucko.luckperms.common.api.implementation.ApiMetaStackFactory;
import me.lucko.luckperms.common.api.implementation.ApiNodeFactory;
import me.lucko.luckperms.common.api.implementation.ApiPlatformInfo;
import me.lucko.luckperms.common.api.implementation.ApiTrackManager;
import me.lucko.luckperms.common.api.implementation.ApiUserManager;
import me.lucko.luckperms.common.api.implementation.NoopUuidCache;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.messaging.LuckPermsMessagingService;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@@ -154,6 +155,11 @@ public class LuckPermsApiProvider implements LuckPermsApi {
return this.contextManager;
}
@Override
public @NonNull Collection<String> getKnownPermissions() {
return this.plugin.getPermissionRegistry().rootAsList();
}
@Override
public @NonNull NodeFactory getNodeFactory() {
return ApiNodeFactory.INSTANCE;
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.manager;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
@@ -23,13 +23,12 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.misc;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.api.ActionLogger;
import me.lucko.luckperms.api.Log;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
import me.lucko.luckperms.common.api.delegates.model.ApiLog;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -23,14 +23,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.misc;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.api.LPConfiguration;
import me.lucko.luckperms.api.LookupSetting;
import me.lucko.luckperms.common.config.ConfigKey;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.config.LuckPermsConfiguration;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -52,22 +52,22 @@ public class ApiConfiguration implements LPConfiguration {
@Override
public boolean getIncludeGlobalPerms() {
return this.handle.get(ConfigKeys.LOOKUP_SETTINGS).contains(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER);
return this.handle.get(ConfigKeys.GLOBAL_CONTEXTS).hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER);
}
@Override
public boolean getIncludeGlobalWorldPerms() {
return this.handle.get(ConfigKeys.LOOKUP_SETTINGS).contains(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD);
return this.handle.get(ConfigKeys.GLOBAL_CONTEXTS).hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD);
}
@Override
public boolean getApplyGlobalGroups() {
return this.handle.get(ConfigKeys.LOOKUP_SETTINGS).contains(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER);
return this.handle.get(ConfigKeys.GLOBAL_CONTEXTS).hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER);
}
@Override
public boolean getApplyGlobalWorldGroups() {
return this.handle.get(ConfigKeys.LOOKUP_SETTINGS).contains(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD);
return this.handle.get(ConfigKeys.GLOBAL_CONTEXTS).hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD);
}
@Override
@@ -23,15 +23,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.manager;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.context.ContextCalculator;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.api.context.StaticContextCalculator;
import me.lucko.luckperms.common.api.delegates.model.ApiUser;
import me.lucko.luckperms.common.contexts.ContextManager;
import me.lucko.luckperms.common.context.ContextManager;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -110,9 +108,9 @@ public class ApiContextManager implements me.lucko.luckperms.api.context.Context
}
@Override
public void registerStaticCalculator(@NonNull StaticContextCalculator calculator) {
public void unregisterCalculator(@NonNull ContextCalculator<?> calculator) {
Objects.requireNonNull(calculator, "calculator");
this.handle.registerStaticCalculator(calculator);
this.handle.unregisterCalculator(calculator);
}
@Override
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.model;
package me.lucko.luckperms.common.api.implementation;
import com.google.common.base.Preconditions;
@@ -37,7 +37,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Objects;
import java.util.OptionalInt;
public final class ApiGroup extends ApiPermissionHolder implements me.lucko.luckperms.api.Group {
public class ApiGroup extends ApiPermissionHolder implements me.lucko.luckperms.api.Group {
public static Group cast(me.lucko.luckperms.api.Group group) {
Objects.requireNonNull(group, "group");
Preconditions.checkState(group instanceof ApiGroup, "Illegal instance " + group.getClass() + " cannot be handled by this implementation.");
@@ -23,20 +23,19 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.manager;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.api.HeldPermission;
import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.api.event.cause.DeletionCause;
import me.lucko.luckperms.common.api.ApiUtils;
import me.lucko.luckperms.common.api.delegates.model.ApiGroup;
import me.lucko.luckperms.common.bulkupdate.comparisons.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparisons.StandardComparison;
import me.lucko.luckperms.common.managers.group.GroupManager;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.manager.group.GroupManager;
import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -23,10 +23,11 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.model;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.common.actionlog.Log;
import me.lucko.luckperms.common.api.ApiUtils;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -34,8 +35,6 @@ import java.util.Objects;
import java.util.SortedSet;
import java.util.UUID;
import static me.lucko.luckperms.common.api.ApiUtils.checkName;
@SuppressWarnings("unchecked")
public class ApiLog implements me.lucko.luckperms.api.Log {
private final Log handle;
@@ -64,12 +63,12 @@ public class ApiLog implements me.lucko.luckperms.api.Log {
@Override
public @NonNull SortedSet<LogEntry> getGroupHistory(@NonNull String name) {
Objects.requireNonNull(name, "name");
return (SortedSet) this.handle.getGroupHistory(checkName(name));
return (SortedSet) this.handle.getGroupHistory(ApiUtils.checkName(name));
}
@Override
public @NonNull SortedSet<LogEntry> getTrackHistory(@NonNull String name) {
Objects.requireNonNull(name, "name");
return (SortedSet) this.handle.getTrackHistory(checkName(name));
return (SortedSet) this.handle.getTrackHistory(ApiUtils.checkName(name));
}
}
@@ -23,11 +23,10 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.misc;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.api.MessagingService;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.common.api.delegates.model.ApiUser;
import me.lucko.luckperms.common.messaging.InternalMessagingService;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -23,10 +23,11 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.misc;
package me.lucko.luckperms.common.api.implementation;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.metastacking.DuplicateRemovalFunction;
import me.lucko.luckperms.api.metastacking.MetaStackDefinition;
import me.lucko.luckperms.api.metastacking.MetaStackElement;
import me.lucko.luckperms.api.metastacking.MetaStackFactory;
@@ -63,7 +64,7 @@ public class ApiMetaStackFactory implements MetaStackFactory {
}
@Override
public @NonNull MetaStackDefinition createDefinition(@NonNull List<MetaStackElement> elements, @NonNull String startSpacer, @NonNull String middleSpacer, @NonNull String endSpacer) {
return new SimpleMetaStackDefinition(elements, startSpacer, middleSpacer, endSpacer);
public @NonNull MetaStackDefinition createDefinition(@NonNull List<MetaStackElement> elements, @NonNull DuplicateRemovalFunction duplicateRemovalFunction, @NonNull String startSpacer, @NonNull String middleSpacer, @NonNull String endSpacer) {
return new SimpleMetaStackDefinition(elements, duplicateRemovalFunction, startSpacer, middleSpacer, endSpacer);
}
}
@@ -23,12 +23,11 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.misc;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.api.ChatMetaType;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.api.delegates.model.ApiGroup;
import me.lucko.luckperms.common.node.factory.NodeFactory;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.model;
package me.lucko.luckperms.common.api.implementation;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -44,6 +44,7 @@ import me.lucko.luckperms.api.caching.CachedData;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.common.model.Group;
import me.lucko.luckperms.common.model.HolderType;
import me.lucko.luckperms.common.model.NodeMapType;
import me.lucko.luckperms.common.model.PermissionHolder;
import me.lucko.luckperms.common.model.User;
@@ -51,7 +52,7 @@ import me.lucko.luckperms.common.node.comparator.NodeWithContextComparator;
import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.node.utils.MetaType;
import me.lucko.luckperms.common.node.utils.NodeTools;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -217,7 +218,7 @@ public class ApiPermissionHolder implements me.lucko.luckperms.api.PermissionHol
Objects.requireNonNull(group, "group");
Group g = ApiGroup.cast(group);
if (this.handle.getType().isGroup() && g.getName().equals(this.handle.getObjectName())) {
if (this.handle.getType() == HolderType.GROUP && g.getName().equals(this.handle.getObjectName())) {
return true;
}
@@ -230,7 +231,7 @@ public class ApiPermissionHolder implements me.lucko.luckperms.api.PermissionHol
Objects.requireNonNull(contextSet, "contextSet");
Group g = ApiGroup.cast(group);
if (this.handle.getType().isGroup() && g.getName().equals(this.handle.getObjectName())) {
if (this.handle.getType() == HolderType.GROUP && g.getName().equals(this.handle.getObjectName())) {
return true;
}
@@ -279,7 +280,7 @@ public class ApiPermissionHolder implements me.lucko.luckperms.api.PermissionHol
public void clearMatching(@NonNull Predicate<Node> test) {
Objects.requireNonNull(test, "test");
this.handle.removeIf(test);
if (this.handle.getType().isUser()) {
if (this.handle.getType() == HolderType.USER) {
this.handle.getPlugin().getUserManager().giveDefaultIfNeeded((User) this.handle, false);
}
}
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.misc;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.api.platform.PlatformInfo;
import me.lucko.luckperms.api.platform.PlatformType;
@@ -49,7 +49,7 @@ public class ApiPlatformInfo implements PlatformInfo {
@Override
public double getApiVersion() {
return 4.2;
return 4.4;
}
@Override
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.model;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.HeldPermission;
@@ -33,8 +33,9 @@ import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.api.event.cause.DeletionCause;
import me.lucko.luckperms.common.bulkupdate.comparisons.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparisons.StandardComparison;
import me.lucko.luckperms.common.api.ApiUtils;
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
import me.lucko.luckperms.common.bulkupdate.comparison.StandardComparison;
import me.lucko.luckperms.common.node.factory.NodeFactory;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.Storage;
@@ -50,9 +51,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Function;
import static me.lucko.luckperms.common.api.ApiUtils.checkName;
import static me.lucko.luckperms.common.api.ApiUtils.checkUsername;
public class ApiStorage implements me.lucko.luckperms.api.Storage {
private static final Function<Throwable, Boolean> CONSUME_EXCEPTION = throwable -> {
throwable.printStackTrace();
@@ -114,7 +112,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
@Override
public @NonNull CompletableFuture<Boolean> loadUser(@NonNull UUID uuid, String username) {
Objects.requireNonNull(uuid, "uuid");
username = checkUsername(username);
username = ApiUtils.checkUsername(username, this.plugin);
if (this.plugin.getUserManager().getIfLoaded(uuid) == null) {
this.plugin.getUserManager().getHouseKeeper().registerApiUsage(uuid);
@@ -147,7 +145,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
@Override
public @NonNull CompletableFuture<Boolean> createAndLoadGroup(@NonNull String name) {
Objects.requireNonNull(name, "name");
return this.handle.createAndLoadGroup(checkName(name), CreationCause.API)
return this.handle.createAndLoadGroup(ApiUtils.checkName(name), CreationCause.API)
.thenApply(r -> true)
.exceptionally(consumeExceptionToFalse());
}
@@ -155,7 +153,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
@Override
public @NonNull CompletableFuture<Boolean> loadGroup(@NonNull String name) {
Objects.requireNonNull(name, "name");
return this.handle.loadGroup(checkName(name))
return this.handle.loadGroup(ApiUtils.checkName(name))
.thenApply(Optional::isPresent)
.exceptionally(consumeExceptionToFalse());
}
@@ -195,7 +193,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
@Override
public @NonNull CompletableFuture<Boolean> createAndLoadTrack(@NonNull String name) {
Objects.requireNonNull(name, "name");
return this.handle.createAndLoadTrack(checkName(name), CreationCause.API)
return this.handle.createAndLoadTrack(ApiUtils.checkName(name), CreationCause.API)
.thenApply(r -> true)
.exceptionally(consumeExceptionToFalse());
}
@@ -203,7 +201,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
@Override
public @NonNull CompletableFuture<Boolean> loadTrack(@NonNull String name) {
Objects.requireNonNull(name, "name");
return this.handle.loadTrack(checkName(name))
return this.handle.loadTrack(ApiUtils.checkName(name))
.thenApply(Optional::isPresent)
.exceptionally(consumeExceptionToFalse());
}
@@ -235,7 +233,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
public @NonNull CompletableFuture<Boolean> saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
Objects.requireNonNull(username, "username");
Objects.requireNonNull(uuid, "uuid");
return this.handle.savePlayerData(uuid, checkUsername(username))
return this.handle.savePlayerData(uuid, ApiUtils.checkUsername(username, this.plugin))
.thenApply(r -> true)
.exceptionally(consumeExceptionToFalse());
}
@@ -243,7 +241,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
@Override
public @NonNull CompletableFuture<UUID> getUUID(@NonNull String username) {
Objects.requireNonNull(username, "username");
return this.handle.getPlayerUuid(checkUsername(username));
return this.handle.getPlayerUuid(ApiUtils.checkUsername(username, this.plugin));
}
@Override
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.model;
package me.lucko.luckperms.common.api.implementation;
import com.google.common.base.Preconditions;
@@ -34,14 +34,14 @@ import me.lucko.luckperms.api.PromotionResult;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.common.util.Predicates;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.List;
import java.util.Objects;
public final class ApiTrack implements me.lucko.luckperms.api.Track {
public class ApiTrack implements me.lucko.luckperms.api.Track {
public static Track cast(me.lucko.luckperms.api.Track track) {
Objects.requireNonNull(track, "track");
Preconditions.checkState(track instanceof ApiTrack, "Illegal instance " + track.getClass() + " cannot be handled by this implementation.");
@@ -23,16 +23,15 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.manager;
package me.lucko.luckperms.common.api.implementation;
import me.lucko.luckperms.api.event.cause.CreationCause;
import me.lucko.luckperms.api.event.cause.DeletionCause;
import me.lucko.luckperms.common.api.ApiUtils;
import me.lucko.luckperms.common.api.delegates.model.ApiTrack;
import me.lucko.luckperms.common.managers.track.TrackManager;
import me.lucko.luckperms.common.model.Track;
import me.lucko.luckperms.common.model.manager.track.TrackManager;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
import me.lucko.luckperms.common.util.ImmutableCollectors;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.api.delegates.model;
package me.lucko.luckperms.common.api.implementation;
import com.google.common.base.Preconditions;
@@ -39,7 +39,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Objects;
import java.util.UUID;
public final class ApiUser extends ApiPermissionHolder implements me.lucko.luckperms.api.User {
public class ApiUser extends ApiPermissionHolder implements me.lucko.luckperms.api.User {
public static User cast(me.lucko.luckperms.api.User u) {
Preconditions.checkState(u instanceof ApiUser, "Illegal instance " + u.getClass() + " cannot be handled by this implementation.");
return ((ApiUser) u).getHandle();
Loaded 100 of 497 files, more files were not shown because too many files have changed in this diff. Show more