Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64838708ab | ||
|
|
91b7af52ac | ||
|
|
d3dded8791 | ||
|
|
022b385c0a | ||
|
|
7ee9b93365 | ||
|
|
c4c98aaabf | ||
|
|
10c0efaa5d | ||
|
|
d8a7d8de4a | ||
|
|
ab8b675bae | ||
|
|
194b602fd6 | ||
|
|
7da0c58b76 | ||
|
|
2dbbea4993 | ||
|
|
55d59bb1c4 | ||
|
|
a6facf7492 | ||
|
|
b8a1871cf1 | ||
|
|
f556c75d94 | ||
|
|
58bd7de66a | ||
|
|
4547b52748 | ||
|
|
b9acb84119 | ||
|
|
e3a783c546 | ||
|
|
2e136666be | ||
|
|
7d089cb5f0 | ||
|
|
3784d904fb | ||
|
|
fef6ebf793 | ||
|
|
316e177c1d | ||
|
|
4cdff14c7c | ||
|
|
97121bc719 | ||
|
|
1312aac349 | ||
|
|
8a5c9ddef2 | ||
|
|
55382519a1 | ||
|
|
cbb562b603 | ||
|
|
ba51f803ba | ||
|
|
d73543408e | ||
|
|
7d90dba08b | ||
|
|
f11ebe6166 | ||
|
|
1b917f0901 | ||
|
|
328353d053 | ||
|
|
4e87489dc1 | ||
|
|
8e5bcdd5ea | ||
|
|
882a29029e | ||
|
|
4704c5c975 | ||
|
|
957365ab91 | ||
|
|
f8d34d7f46 | ||
|
|
cb185e4827 | ||
|
|
f5c6b9e3d4 | ||
|
|
96f0f46b3e | ||
|
|
6a5b7ce3a1 | ||
|
|
f33c540efb | ||
|
|
7684ac5d3a | ||
|
|
c13b01da01 | ||
|
|
3453f05aca | ||
|
|
c8bb85a06b | ||
|
|
2aabc9902f | ||
|
|
6dba778e60 | ||
|
|
cbeaaca7af | ||
|
|
0e69c8902d | ||
|
|
f63d6cfced | ||
|
|
72f9de6cc7 | ||
|
|
509e89b9cf | ||
|
|
90cce19baf | ||
|
|
e4e93b1af1 | ||
|
|
8f30176edd | ||
|
|
4923d10b86 | ||
|
|
bd3a4e1ad7 | ||
|
|
0f99a6c5ca | ||
|
|
0150da94a8 | ||
|
|
b8da286f64 | ||
|
|
da797f154d | ||
|
|
926195efc4 | ||
|
|
8c1c5c820c | ||
|
|
f63f652edb | ||
|
|
174ef187e8 | ||
|
|
d1e76f401a | ||
|
|
d52983c5af | ||
|
|
4773934481 | ||
|
|
dbfc524180 | ||
|
|
60aa7c6104 | ||
|
|
907d716929 | ||
|
|
1689a8abe2 | ||
|
|
5db3820df4 | ||
|
|
f969e2e52b | ||
|
|
cde2306079 | ||
|
|
f6c440c172 | ||
|
|
1b98667365 | ||
|
|
bf69d5314e | ||
|
|
6d2ea659a4 | ||
|
|
0d89840179 | ||
|
|
f93e8fdccd | ||
|
|
68e4d36f40 | ||
|
|
cd5447de38 | ||
|
|
6c0bb61cb1 | ||
|
|
d9a45b1090 | ||
|
|
7549b3eb9e | ||
|
|
8f82ef7eb4 | ||
|
|
fbe84322b5 | ||
|
|
98fb9946e4 | ||
|
|
984bc5860f | ||
|
|
a42d27f056 | ||
|
|
aa4833ed74 | ||
|
|
6704ac4b46 | ||
|
|
4e4ec8e608 | ||
|
|
4f4a387f04 | ||
|
|
d0143f9e54 | ||
|
|
b2175e885f | ||
|
|
68dd96e563 |
No files matched your search
@@ -5,24 +5,23 @@ LuckPerms is an advanced permissions implementation aiming to be a fast, reliabl
|
||||
|
||||
LuckPerms also includes an extensive API for developers, and support for a variety of Minecraft server software & data storage options.
|
||||
|
||||
The main features of the project are detailed on this wiki page: [Why LuckPerms?](https://github.com/lucko/LuckPerms/wiki/Why-LuckPerms)
|
||||
|
||||
* [Spigot Plugin Release Page](https://www.spigotmc.org/resources/luckperms-an-advanced-permissions-system.28140/ "Spigot Plugin Page")
|
||||
* [Sponge Plugin Release Page](https://forums.spongepowered.org/t/luckperms-an-advanced-permissions-system/14274 "Sponge Plugin Page")
|
||||
Still not convinced? More information can be found on the wiki, under: [Why LuckPerms?](https://github.com/lucko/LuckPerms/wiki/Why-LuckPerms)
|
||||
|
||||
## Useful Links
|
||||
* **Downloads** - <https://ci.lucko.me/job/LuckPerms>
|
||||
* **Wiki** - <https://github.com/lucko/LuckPerms/wiki>
|
||||
|
||||
The latest **downloads** can be found on the [project's homepage](https://luckperms.github.io/).
|
||||
|
||||
More information about the project & how to use the plugin can be found in the [wiki](https://github.com/lucko/LuckPerms/wiki).
|
||||
|
||||
## Building
|
||||
LuckPerms uses Maven to handle dependencies.
|
||||
|
||||
#### Requirements
|
||||
* Java 8 JDK
|
||||
* Maven 3.3.x (the older versions will not work.)
|
||||
* Java 8 JDK or newer
|
||||
* Maven 3.3.x or newer (the older versions will not work.)
|
||||
* Git
|
||||
|
||||
#### Then run
|
||||
#### Compiling from source
|
||||
```sh
|
||||
git clone https://github.com/lucko/LuckPerms.git
|
||||
cd LuckPerms/
|
||||
@@ -42,7 +41,7 @@ The project is split up into 5 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** - Each use the common module to implement plugins on the respective server platforms.
|
||||
|
||||
## License
|
||||
LuckPerms is licensed under the permissive MIT license. Please see [`LICENSE.txt`](https://github.com/lucko/LuckPerms/blob/master/LICENSE.txt) for more info.
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>4.1-SNAPSHOT</version>
|
||||
<version>4.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -47,8 +47,6 @@ public interface ActionLogger {
|
||||
/**
|
||||
* Gets a {@link Log} instance from the plugin storage.
|
||||
*
|
||||
* <p>Returns the same result as {@link Storage#getLog()}.</p>
|
||||
*
|
||||
* @return a log instance
|
||||
* @see Storage#getLog()
|
||||
*/
|
||||
|
||||
@@ -25,16 +25,21 @@
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* Encapsulates the options and settings for a permission or meta lookup.
|
||||
* Encapsulates the {@link ContextSet contexts} and {@link LookupSetting settings} for
|
||||
* a permission or meta lookup.
|
||||
*
|
||||
* <p>This class is immutable.</p>
|
||||
*
|
||||
@@ -53,12 +58,24 @@ public class Contexts {
|
||||
*/
|
||||
public static final String WORLD_KEY = "world";
|
||||
|
||||
/**
|
||||
* The default {@link LookupSetting}s.
|
||||
*/
|
||||
private static final EnumSet<LookupSetting> DEFAULT_SETTINGS = EnumSet.of(
|
||||
LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER,
|
||||
LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD,
|
||||
LookupSetting.RESOLVE_INHERITANCE,
|
||||
LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER,
|
||||
LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD
|
||||
);
|
||||
|
||||
/**
|
||||
* A 'global' or default contexts instance.
|
||||
*
|
||||
* Simply passes an empty context set, with all accumulation settings set to true.
|
||||
* <p>Formed of an empty {@link ContextSet} and all inclusion and
|
||||
* inheritance {@link LookupSetting}s applied.</p>
|
||||
*/
|
||||
private static final Contexts GLOBAL = new Contexts(ContextSet.empty(), true, true, true, true, true, false);
|
||||
private static final Contexts GLOBAL = new Contexts(ImmutableContextSet.empty(), ImmutableSet.copyOf(DEFAULT_SETTINGS));
|
||||
|
||||
/**
|
||||
* Gets the {@link FullySatisfiedContexts} instance.
|
||||
@@ -71,7 +88,10 @@ public class Contexts {
|
||||
}
|
||||
|
||||
/**
|
||||
* A contexts instance with no defined context.
|
||||
* Returns a 'global' or default contexts instance.
|
||||
*
|
||||
* <p>Formed of an empty {@link ContextSet} and all inclusion and
|
||||
* inheritance {@link LookupSetting}s applied.</p>
|
||||
*
|
||||
* @return the global contexts
|
||||
* @since 3.3
|
||||
@@ -81,140 +101,208 @@ public class Contexts {
|
||||
return GLOBAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Contexts} instance.
|
||||
*
|
||||
* @param contextSet the context set
|
||||
* @param includeNodesSetWithoutServer the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER}
|
||||
* @param includeNodesSetWithoutWorld the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD}
|
||||
* @param resolveInheritance the value of {@link LookupSetting#RESOLVE_INHERITANCE}
|
||||
* @param applyParentsWithoutServer the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER}
|
||||
* @param applyParentsWithoutWorld the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD}
|
||||
* @param isOp the value of {@link LookupSetting#IS_OP}
|
||||
* @return a new instance
|
||||
*/
|
||||
@Nonnull
|
||||
public static Contexts of(@Nonnull ContextSet context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
|
||||
return new Contexts(context, includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups, op);
|
||||
public static Contexts of(@Nonnull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
|
||||
Objects.requireNonNull(contextSet, "contextSet");
|
||||
EnumSet<LookupSetting> settings = formSettings(
|
||||
includeNodesSetWithoutServer,
|
||||
includeNodesSetWithoutWorld,
|
||||
resolveInheritance,
|
||||
applyParentsWithoutServer,
|
||||
applyParentsWithoutWorld,
|
||||
isOp
|
||||
);
|
||||
if (contextSet.isEmpty() && DEFAULT_SETTINGS.equals(settings)) {
|
||||
return GLOBAL;
|
||||
}
|
||||
return new Contexts(contextSet.makeImmutable(), ImmutableSet.copyOf(settings));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Contexts} instance.
|
||||
*
|
||||
* @param contextSet the context set
|
||||
* @param settings the settings
|
||||
* @return a new instance
|
||||
*/
|
||||
public static Contexts of(@Nonnull ContextSet contextSet, @Nonnull Set<LookupSetting> settings) {
|
||||
Objects.requireNonNull(contextSet, "contextSet");
|
||||
Objects.requireNonNull(settings, "settings");
|
||||
|
||||
EnumSet<LookupSetting> settingsCopy = EnumSet.copyOf(settings);
|
||||
if (contextSet.isEmpty() && DEFAULT_SETTINGS.equals(settingsCopy)) {
|
||||
return GLOBAL;
|
||||
}
|
||||
|
||||
return new Contexts(contextSet.makeImmutable(), ImmutableSet.copyOf(settingsCopy));
|
||||
}
|
||||
|
||||
/**
|
||||
* The contexts that apply for this lookup
|
||||
*/
|
||||
private final ImmutableContextSet context;
|
||||
private final ImmutableContextSet contextSet;
|
||||
|
||||
/**
|
||||
* If the target subject is OP. This is used to parse defaults on Bukkit,
|
||||
* and is ignored on all other platforms.
|
||||
*
|
||||
* @since 2.12
|
||||
* The settings for this lookup
|
||||
*/
|
||||
private final boolean op;
|
||||
|
||||
/**
|
||||
* If global or non server specific nodes should be applied
|
||||
*/
|
||||
private final boolean includeGlobal;
|
||||
|
||||
/**
|
||||
* If global or non world specific nodes should be applied
|
||||
*/
|
||||
private final boolean includeGlobalWorld;
|
||||
|
||||
/**
|
||||
* If parent groups should be applied
|
||||
*/
|
||||
private final boolean applyGroups;
|
||||
|
||||
/**
|
||||
* If global or non server specific group memberships should be applied
|
||||
*/
|
||||
private final boolean applyGlobalGroups;
|
||||
|
||||
/**
|
||||
* If global or non world specific group memberships should be applied
|
||||
*/
|
||||
private final boolean applyGlobalWorldGroups;
|
||||
private final ImmutableSet<LookupSetting> settings;
|
||||
|
||||
// cache hashcode - this class is immutable, and is used as an index in the permission cache.
|
||||
private final int hashCode;
|
||||
|
||||
public Contexts(@Nonnull ContextSet context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
|
||||
this.context = Objects.requireNonNull(context, "context").makeImmutable();
|
||||
this.includeGlobal = includeGlobal;
|
||||
this.includeGlobalWorld = includeGlobalWorld;
|
||||
this.applyGroups = applyGroups;
|
||||
this.applyGlobalGroups = applyGlobalGroups;
|
||||
this.applyGlobalWorldGroups = applyGlobalWorldGroups;
|
||||
this.op = op;
|
||||
/**
|
||||
* Creates a new {@link Contexts} instance.
|
||||
*
|
||||
* @param contextSet the context set
|
||||
* @param includeNodesSetWithoutServer the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER}
|
||||
* @param includeNodesSetWithoutWorld the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD}
|
||||
* @param resolveInheritance the value of {@link LookupSetting#RESOLVE_INHERITANCE}
|
||||
* @param applyParentsWithoutServer the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER}
|
||||
* @param applyParentsWithoutWorld the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD}
|
||||
* @param isOp the value of {@link LookupSetting#IS_OP}
|
||||
* @deprecated in favour of {@link #of(ContextSet, boolean, boolean, boolean, boolean, boolean, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Contexts(@Nonnull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
|
||||
this.contextSet = Objects.requireNonNull(contextSet, "contextSet").makeImmutable();
|
||||
this.settings = ImmutableSet.copyOf(formSettings(
|
||||
includeNodesSetWithoutServer,
|
||||
includeNodesSetWithoutWorld,
|
||||
resolveInheritance,
|
||||
applyParentsWithoutServer,
|
||||
applyParentsWithoutWorld,
|
||||
isOp
|
||||
));
|
||||
this.hashCode = calculateHashCode();
|
||||
}
|
||||
|
||||
protected Contexts(@Nonnull ImmutableContextSet contextSet, @Nonnull ImmutableSet<LookupSetting> settings) {
|
||||
this.contextSet = contextSet;
|
||||
this.settings = settings;
|
||||
this.hashCode = calculateHashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the contexts that apply for this lookup
|
||||
* Gets the {@link ContextSet} which represent these {@link Contexts}.
|
||||
*
|
||||
* @return an immutable set of context key value pairs
|
||||
* @return an immutable context from this instance
|
||||
* @since 2.13
|
||||
*/
|
||||
@Nonnull
|
||||
public ContextSet getContexts() {
|
||||
return this.context;
|
||||
return this.contextSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the target subject is OP. This is used to parse defaults on Bukkit,
|
||||
* and is ignored on all other platforms.
|
||||
* Gets the set of {@link LookupSetting}s which represent these {@link Contexts}.
|
||||
*
|
||||
* @return true if op defaults should be included
|
||||
* @return the settings
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
public Set<LookupSetting> getSettings() {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the given {@link LookupSetting} is set.
|
||||
*
|
||||
* @param setting the setting
|
||||
* @return the value
|
||||
* @since 4.2
|
||||
*/
|
||||
public boolean hasSetting(@Nonnull LookupSetting setting) {
|
||||
return this.settings.contains(setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of {@link LookupSetting#IS_OP}.
|
||||
*
|
||||
* @return the value
|
||||
* @see LookupSetting#IS_OP
|
||||
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isOp() {
|
||||
return this.op;
|
||||
return hasSetting(LookupSetting.IS_OP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non server specific nodes should be applied
|
||||
* Gets the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER}.
|
||||
*
|
||||
* @return true if global or non server specific nodes should be applied
|
||||
* @return the value
|
||||
* @see LookupSetting#INCLUDE_NODES_SET_WITHOUT_SERVER
|
||||
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isIncludeGlobal() {
|
||||
return this.includeGlobal;
|
||||
return hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non world specific nodes should be applied
|
||||
* Gets the value of {@link LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD}.
|
||||
*
|
||||
* @return true if global or non world specific nodes should be applied
|
||||
* @return the value
|
||||
* @see LookupSetting#INCLUDE_NODES_SET_WITHOUT_WORLD
|
||||
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isIncludeGlobalWorld() {
|
||||
return this.includeGlobalWorld;
|
||||
return hasSetting(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if parent groups should be applied
|
||||
* Gets the value of {@link LookupSetting#RESOLVE_INHERITANCE}.
|
||||
*
|
||||
* @return true if parent groups should be applied
|
||||
* @return the value
|
||||
* @see LookupSetting#RESOLVE_INHERITANCE
|
||||
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isApplyGroups() {
|
||||
return this.applyGroups;
|
||||
return hasSetting(LookupSetting.RESOLVE_INHERITANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non server specific group memberships should be applied
|
||||
* Gets the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER}.
|
||||
*
|
||||
* @return true if global or non server specific group memberships should be applied
|
||||
* @return the value
|
||||
* @see LookupSetting#APPLY_PARENTS_SET_WITHOUT_SERVER
|
||||
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isApplyGlobalGroups() {
|
||||
return this.applyGlobalGroups;
|
||||
return hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non world specific group memberships should be applied
|
||||
* Gets the value of {@link LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD}.
|
||||
*
|
||||
* @return true if global or non world specific group memberships should be applied
|
||||
* @return the value
|
||||
* @see LookupSetting#APPLY_PARENTS_SET_WITHOUT_WORLD
|
||||
* @deprecated in favour of {@link #hasSetting(LookupSetting)}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isApplyGlobalWorldGroups() {
|
||||
return this.applyGlobalWorldGroups;
|
||||
return hasSetting(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Contexts(" +
|
||||
"context=" + this.context + ", " +
|
||||
"op=" + this.op + ", " +
|
||||
"includeGlobal=" + this.includeGlobal + ", " +
|
||||
"includeGlobalWorld=" + this.includeGlobalWorld + ", " +
|
||||
"applyGroups=" + this.applyGroups + ", " +
|
||||
"applyGlobalGroups=" + this.applyGlobalGroups + ", " +
|
||||
"applyGlobalWorldGroups=" + this.applyGlobalWorldGroups + ")";
|
||||
return "Contexts(contextSet=" + this.contextSet + ", settings=" + this.settings + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -223,26 +311,14 @@ public class Contexts {
|
||||
if (o == allowAll()) return false;
|
||||
if (!(o instanceof Contexts)) return false;
|
||||
final Contexts that = (Contexts) o;
|
||||
|
||||
return this.context.equals(that.context) &&
|
||||
this.op == that.op &&
|
||||
this.includeGlobal == that.includeGlobal &&
|
||||
this.includeGlobalWorld == that.includeGlobalWorld &&
|
||||
this.applyGroups == that.applyGroups &&
|
||||
this.applyGlobalGroups == that.applyGlobalGroups &&
|
||||
this.applyGlobalWorldGroups == that.applyGlobalWorldGroups;
|
||||
return this.contextSet.equals(that.contextSet) && this.settings.equals(that.settings);
|
||||
}
|
||||
|
||||
private int calculateHashCode() {
|
||||
final int PRIME = 59;
|
||||
int result = 1;
|
||||
result = result * PRIME + this.context.hashCode();
|
||||
result = result * PRIME + (this.op ? 79 : 97);
|
||||
result = result * PRIME + (this.includeGlobal ? 79 : 97);
|
||||
result = result * PRIME + (this.includeGlobalWorld ? 79 : 97);
|
||||
result = result * PRIME + (this.applyGroups ? 79 : 97);
|
||||
result = result * PRIME + (this.applyGlobalGroups ? 79 : 97);
|
||||
result = result * PRIME + (this.applyGlobalWorldGroups ? 79 : 97);
|
||||
result = result * PRIME + this.contextSet.hashCode();
|
||||
result = result * PRIME + this.settings.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -250,4 +326,28 @@ public class Contexts {
|
||||
public int hashCode() {
|
||||
return this.hashCode;
|
||||
}
|
||||
|
||||
private static EnumSet<LookupSetting> formSettings(boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
|
||||
EnumSet<LookupSetting> settings = EnumSet.noneOf(LookupSetting.class);
|
||||
if (includeNodesSetWithoutServer) {
|
||||
settings.add(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER);
|
||||
}
|
||||
if (includeNodesSetWithoutWorld) {
|
||||
settings.add(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD);
|
||||
}
|
||||
if (resolveInheritance) {
|
||||
settings.add(LookupSetting.RESOLVE_INHERITANCE);
|
||||
}
|
||||
if (applyParentsWithoutServer) {
|
||||
settings.add(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER);
|
||||
}
|
||||
if (applyParentsWithoutWorld) {
|
||||
settings.add(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD);
|
||||
}
|
||||
if (isOp) {
|
||||
settings.add(LookupSetting.IS_OP);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,9 +26,11 @@
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
/**
|
||||
* Represents the result of a mutation call.
|
||||
* Represents the result of a data mutation call on a LuckPerms object.
|
||||
*
|
||||
* <p>Usually as the result to a call on a {@link PermissionHolder} or {@link Track}.</p>
|
||||
*/
|
||||
public enum DataMutateResult {
|
||||
public enum DataMutateResult implements MutateResult {
|
||||
|
||||
/**
|
||||
* Indicates the mutation was a success
|
||||
@@ -50,39 +52,14 @@ public enum DataMutateResult {
|
||||
*/
|
||||
FAIL(false);
|
||||
|
||||
private final boolean value;
|
||||
private final boolean success;
|
||||
|
||||
DataMutateResult(boolean value) {
|
||||
this.value = value;
|
||||
DataMutateResult(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a boolean representation of the result.
|
||||
*
|
||||
* @return a boolean representation
|
||||
*/
|
||||
public boolean asBoolean() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the result indicates a success
|
||||
*
|
||||
* @return if the result indicates a success
|
||||
* @since 3.4
|
||||
*/
|
||||
@Override
|
||||
public boolean wasSuccess() {
|
||||
return this.value;
|
||||
return this.success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the result indicates a failure
|
||||
*
|
||||
* @return if the result indicates a failure
|
||||
* @since 3.4
|
||||
*/
|
||||
public boolean wasFailure() {
|
||||
return !this.value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Encapsulates the result of {@link User}s demotion along a {@link Track}.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface DemotionResult extends MutateResult {
|
||||
|
||||
/**
|
||||
* Gets the status of the result.
|
||||
*
|
||||
* @return the status
|
||||
*/
|
||||
@Nonnull
|
||||
Status getStatus();
|
||||
|
||||
@Override
|
||||
default boolean wasSuccess() {
|
||||
return getStatus().wasSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the group the user was demoted from, if applicable.
|
||||
*
|
||||
* <p>Will only be present for results with a {@link #getStatus() status} of
|
||||
* {@link Status#SUCCESS} or {@link Status#REMOVED_FROM_FIRST_GROUP}.</p>
|
||||
*
|
||||
* <p>The value will also be set for results with the {@link Status#MALFORMED_TRACK} status,
|
||||
* with this value marking the group which no longer exists.</p>
|
||||
*
|
||||
* @return the group the user was demoted from.
|
||||
*/
|
||||
@Nonnull
|
||||
Optional<String> getGroupFrom();
|
||||
|
||||
/**
|
||||
* Gets the name of the group the user was demoted from, if applicable.
|
||||
*
|
||||
* <p>Will only be present for results with a {@link #getStatus() status} of
|
||||
* {@link Status#SUCCESS}.</p>
|
||||
*
|
||||
* @return the group the user was demoted to.
|
||||
*/
|
||||
@Nonnull
|
||||
Optional<String> getGroupTo();
|
||||
|
||||
/**
|
||||
* The result status
|
||||
*/
|
||||
enum Status implements MutateResult {
|
||||
|
||||
/**
|
||||
* Indicates that the user was demoted normally.
|
||||
*/
|
||||
SUCCESS(true),
|
||||
|
||||
/**
|
||||
* Indicates that the user was removed from the first group in the track.
|
||||
*
|
||||
* <p>This usually occurs when the user is currently on the first group, and was demoted
|
||||
* "over the start" of the track.</p>
|
||||
*/
|
||||
REMOVED_FROM_FIRST_GROUP(true),
|
||||
|
||||
/**
|
||||
* Indicates that the previous group in the track no longer exists.
|
||||
*/
|
||||
MALFORMED_TRACK(false),
|
||||
|
||||
/**
|
||||
* Indicates that the user isn't a member of any of the groups on this track.
|
||||
*/
|
||||
NOT_ON_TRACK(false),
|
||||
|
||||
/**
|
||||
* Indicates that the implementation was unable to determine the users current position on
|
||||
* this track.
|
||||
*
|
||||
* <p>This usually occurs when the user is on more than one group on the track.</p>
|
||||
*/
|
||||
AMBIGUOUS_CALL(false),
|
||||
|
||||
/**
|
||||
* An undefined failure occurred.
|
||||
*/
|
||||
UNDEFINED_FAILURE(false);
|
||||
|
||||
private final boolean success;
|
||||
|
||||
Status(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wasSuccess() {
|
||||
return this.success;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,9 +25,11 @@
|
||||
|
||||
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.ContextSet;
|
||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@@ -58,7 +60,7 @@ public final class FullySatisfiedContexts extends Contexts {
|
||||
}
|
||||
|
||||
private FullySatisfiedContexts() {
|
||||
super(ContextSet.empty(), true, true, true, true, true, false);
|
||||
super(ImmutableContextSet.empty(), ImmutableSet.copyOf(Contexts.global().getSettings()));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The various lookup setting flags for {@link Contexts}.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public enum LookupSetting {
|
||||
|
||||
/**
|
||||
* If the target subject is OP
|
||||
*/
|
||||
IS_OP,
|
||||
|
||||
/**
|
||||
* If global or non-server-specific nodes should be applied
|
||||
*/
|
||||
INCLUDE_NODES_SET_WITHOUT_SERVER,
|
||||
|
||||
/**
|
||||
* If global or non-world-specific nodes should be applied
|
||||
*/
|
||||
INCLUDE_NODES_SET_WITHOUT_WORLD,
|
||||
|
||||
/**
|
||||
* If parent groups should be resolved
|
||||
*/
|
||||
RESOLVE_INHERITANCE,
|
||||
|
||||
/**
|
||||
* If global or non-server-specific group memberships should be applied
|
||||
*/
|
||||
APPLY_PARENTS_SET_WITHOUT_SERVER,
|
||||
|
||||
/**
|
||||
* If global or non-world-specific group memberships should be applied
|
||||
*/
|
||||
APPLY_PARENTS_SET_WITHOUT_WORLD
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Represents the result to a "mutation" on an object.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface MutateResult {
|
||||
|
||||
/**
|
||||
* Instance of {@link MutateResult} which always reports success.
|
||||
*/
|
||||
MutateResult GENERIC_SUCCESS = () -> true;
|
||||
|
||||
/**
|
||||
* Instance of {@link MutateResult} which always reports failure.
|
||||
*/
|
||||
MutateResult GENERIC_FAILURE = () -> false;
|
||||
|
||||
/**
|
||||
* Gets if the operation which produced this result completed successfully.
|
||||
*
|
||||
* @return if the result indicates a success
|
||||
*/
|
||||
boolean wasSuccess();
|
||||
|
||||
/**
|
||||
* Gets if the operation which produced this result failed.
|
||||
*
|
||||
* @return if the result indicates a failure
|
||||
*/
|
||||
default boolean wasFailure() {
|
||||
return !wasSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a boolean representation of the result.
|
||||
*
|
||||
* <p>A value of <code>true</code> marks that the operation {@link #wasSuccess() was a success}
|
||||
* and a value of <code>false</code> marks that the operation
|
||||
* {@link #wasFailure() was a failure}.</p>
|
||||
*
|
||||
* @return a boolean representation
|
||||
*/
|
||||
default boolean asBoolean() {
|
||||
return wasSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,13 +25,25 @@
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.nodetype.NodeType;
|
||||
import me.lucko.luckperms.api.nodetype.NodeTypeKey;
|
||||
import me.lucko.luckperms.api.nodetype.types.DisplayNameType;
|
||||
import me.lucko.luckperms.api.nodetype.types.InheritanceType;
|
||||
import me.lucko.luckperms.api.nodetype.types.MetaType;
|
||||
import me.lucko.luckperms.api.nodetype.types.PrefixType;
|
||||
import me.lucko.luckperms.api.nodetype.types.SuffixType;
|
||||
import me.lucko.luckperms.api.nodetype.types.WeightType;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -60,7 +72,7 @@ import javax.annotation.concurrent.Immutable;
|
||||
* <p></p>
|
||||
* <ul>
|
||||
* <li>{@link #getPermission() permission} - the actual permission string</li>
|
||||
* <li>{@link #getValuePrimitive() value} - the value of the node (false for negated)</li>
|
||||
* <li>{@link #getValue() value} - the value of the node (false for negated)</li>
|
||||
* <li>{@link #isOverride() override} - if the node is marked as having special priority over other nodes</li>
|
||||
* <li>{@link #getServer() server} - the specific server where this node should apply</li>
|
||||
* <li>{@link #getWorld() world} - the specific world where this node should apply</li>
|
||||
@@ -68,14 +80,23 @@ import javax.annotation.concurrent.Immutable;
|
||||
* <li>{@link #getExpiry() expiry} - the time when this node should expire</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Nodes can also fall into the following sub categories.</p>
|
||||
* <p>The 'permission' property of a {@link Node} is also used in some cases to represent state
|
||||
* beyond a granted permission. This state is encapsulated by extra {@link NodeType} data which
|
||||
* can be obtained from this instance using {@link #getTypeData(NodeTypeKey)}.</p>
|
||||
*
|
||||
* <p>Type data is mapped by {@link NodeTypeKey}s, which are usually stored as static members of the
|
||||
* corresponding {@link NodeType} class under the <code>KEY</code> field.</p>
|
||||
*
|
||||
* <p>The current types are:</p>
|
||||
* <p></p>
|
||||
* <ul>
|
||||
* <li>normal - just a regular permission</li>
|
||||
* <li>{@link #isGroupNode() group node} - a "group node" marks that the holder should inherit data from another group</li>
|
||||
* <li>{@link #isPrefix() prefix} - represents an assigned prefix</li>
|
||||
* <li>{@link #isSuffix() suffix} - represents an assigned suffix</li>
|
||||
* <li>{@link #isMeta() meta} - represents an assigned meta option</li>
|
||||
* <li>{@link InheritanceType} - an "inheritance node" marks that the holder should inherit data from another group</li>
|
||||
* <li>{@link PrefixType} - represents an assigned prefix</li>
|
||||
* <li>{@link SuffixType} - represents an assigned suffix</li>
|
||||
* <li>{@link MetaType} - represents an assigned meta option</li>
|
||||
* <li>{@link WeightType} - marks the weight of the object holding this node</li>
|
||||
* <li>{@link DisplayNameType} - marks the display name of the object holding this node</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>The core node state must be immutable in all implementations.</p>
|
||||
@@ -87,7 +108,10 @@ import javax.annotation.concurrent.Immutable;
|
||||
public interface Node {
|
||||
|
||||
/**
|
||||
* Gets the permission string
|
||||
* Gets the permission string this node encapsulates.
|
||||
*
|
||||
* <p>The exact value of this string may vary for nodes which aren't regular
|
||||
* permission settings.</p>
|
||||
*
|
||||
* @return the actual permission node
|
||||
*/
|
||||
@@ -95,56 +119,47 @@ public interface Node {
|
||||
String getPermission();
|
||||
|
||||
/**
|
||||
* Gets the value.
|
||||
* Gets the value of the node.
|
||||
*
|
||||
* <p>A negated node would return a value of <code>false</code>.</p>
|
||||
* <p>A negated setting would result in a value of <code>false</code>.</p>
|
||||
*
|
||||
* @return the permission's value
|
||||
* @return the nodes value
|
||||
*/
|
||||
@Nonnull
|
||||
default Boolean getValue() {
|
||||
return getValuePrimitive();
|
||||
}
|
||||
boolean getValue();
|
||||
|
||||
/**
|
||||
* Gets the value.
|
||||
*
|
||||
* <p>A negated node would return a value of <code>false</code>.</p>
|
||||
*
|
||||
* @return the permission's value
|
||||
*/
|
||||
boolean getValuePrimitive();
|
||||
|
||||
/**
|
||||
* Gets the value of this node as a {@link Tristate}
|
||||
* Gets the value of this node as a {@link Tristate}.
|
||||
*
|
||||
* @return the value of this node as a Tristate
|
||||
*/
|
||||
@Nonnull
|
||||
default Tristate getTristate() {
|
||||
return Tristate.fromBoolean(getValuePrimitive());
|
||||
return Tristate.fromBoolean(getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the node is negated
|
||||
* Gets if the node is negated.
|
||||
*
|
||||
* <p>This is the inverse of the {@link #getValue() value}.</p>
|
||||
*
|
||||
* @return true if the node is negated
|
||||
*/
|
||||
default boolean isNegated() {
|
||||
return !getValuePrimitive();
|
||||
return !getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if this node is set to override explicitly.
|
||||
*
|
||||
* <p>This value does not persist across saves, and is therefore only useful for transient nodes</p>
|
||||
* <p>This value does not persist across saves, and is therefore only
|
||||
* useful for transient nodes.</p>
|
||||
*
|
||||
* @return true if this node is set to override explicitly
|
||||
*/
|
||||
boolean isOverride();
|
||||
|
||||
/**
|
||||
* Gets the server this node applies on, if the node is server specific
|
||||
* Gets the server this node applies on, if the node is server specific.
|
||||
*
|
||||
* @return an {@link Optional} containing the server, if one is defined
|
||||
*/
|
||||
@@ -152,7 +167,7 @@ public interface Node {
|
||||
Optional<String> getServer();
|
||||
|
||||
/**
|
||||
* Gets the world this node applies on, if the node is world specific
|
||||
* Gets the world this node applies on, if the node is world specific.
|
||||
*
|
||||
* @return an {@link Optional} containing the world, if one is defined
|
||||
*/
|
||||
@@ -160,21 +175,21 @@ public interface Node {
|
||||
Optional<String> getWorld();
|
||||
|
||||
/**
|
||||
* Gets if this node is server specific
|
||||
* Gets if this node is server specific.
|
||||
*
|
||||
* @return true if this node is server specific
|
||||
*/
|
||||
boolean isServerSpecific();
|
||||
|
||||
/**
|
||||
* Gets if this node is server specific
|
||||
* Gets if this node is server specific.
|
||||
*
|
||||
* @return true if this node is server specific
|
||||
*/
|
||||
boolean isWorldSpecific();
|
||||
|
||||
/**
|
||||
* Gets if this node applies globally, and therefore has no specific context
|
||||
* Gets if this node applies globally, and therefore has no specific context.
|
||||
*
|
||||
* @return true if this node applies globally, and has no specific context
|
||||
* @since 3.1
|
||||
@@ -182,7 +197,7 @@ public interface Node {
|
||||
boolean appliesGlobally();
|
||||
|
||||
/**
|
||||
* Gets if this node has any specific context in order for it to apply
|
||||
* Gets if this node has any specific context in order for it to apply.
|
||||
*
|
||||
* @return true if this node has specific context
|
||||
* @since 3.1
|
||||
@@ -192,14 +207,17 @@ public interface Node {
|
||||
/**
|
||||
* Gets if this node should apply in the given context
|
||||
*
|
||||
* @param context the context key value pairs
|
||||
* @param contextSet the context set
|
||||
* @return true if the node should apply
|
||||
* @since 2.13
|
||||
*/
|
||||
boolean shouldApplyWithContext(@Nonnull ContextSet context);
|
||||
boolean shouldApplyWithContext(@Nonnull ContextSet contextSet);
|
||||
|
||||
/**
|
||||
* Resolves any shorthand parts of this node and returns the full list
|
||||
* Resolves any shorthand parts of this node and returns the full list of
|
||||
* resolved nodes.
|
||||
*
|
||||
* <p>The list will not contain the exact permission itself.</p>
|
||||
*
|
||||
* @return a list of full nodes
|
||||
*/
|
||||
@@ -207,14 +225,14 @@ public interface Node {
|
||||
List<String> resolveShorthand();
|
||||
|
||||
/**
|
||||
* Gets if this node will expire in the future
|
||||
* Gets if this node is assigned temporarily.
|
||||
*
|
||||
* @return true if this node will expire in the future
|
||||
*/
|
||||
boolean isTemporary();
|
||||
|
||||
/**
|
||||
* Gets if this node will not expire
|
||||
* Gets if this node is permanent (will not expire).
|
||||
*
|
||||
* @return true if this node will not expire
|
||||
*/
|
||||
@@ -223,7 +241,7 @@ public interface Node {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a unix timestamp in seconds when this node will expire
|
||||
* Gets the unix timestamp (in seconds) when this node will expire.
|
||||
*
|
||||
* @return the time in Unix time when this node will expire
|
||||
* @throws IllegalStateException if the node is not temporary
|
||||
@@ -231,7 +249,7 @@ public interface Node {
|
||||
long getExpiryUnixTime() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Gets the date when this node will expire
|
||||
* Gets the date when this node will expire.
|
||||
*
|
||||
* @return the {@link Date} when this node will expire
|
||||
* @throws IllegalStateException if the node is not temporary
|
||||
@@ -240,7 +258,9 @@ public interface Node {
|
||||
Date getExpiry() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Gets the number of seconds until this permission will expire
|
||||
* Gets the number of seconds until this permission will expire.
|
||||
*
|
||||
* <p>Will return a negative value if the node has already expired.</p>
|
||||
*
|
||||
* @return the number of seconds until this permission will expire
|
||||
* @throws IllegalStateException if the node is not temporary
|
||||
@@ -250,14 +270,14 @@ public interface Node {
|
||||
/**
|
||||
* Gets if the node has expired.
|
||||
*
|
||||
* <p>This also returns false if the node is not temporary.</p>
|
||||
* <p>This returns false if the node is not temporary.</p>
|
||||
*
|
||||
* @return true if this node has expired
|
||||
*/
|
||||
boolean hasExpired();
|
||||
|
||||
/**
|
||||
* Gets the extra contexts required for this node to apply
|
||||
* Gets the extra contexts required for this node to apply.
|
||||
*
|
||||
* @return the extra contexts required for this node to apply
|
||||
* @since 2.13
|
||||
@@ -266,39 +286,32 @@ public interface Node {
|
||||
ContextSet getContexts();
|
||||
|
||||
/**
|
||||
* The same as {@link #getContexts()}, but also includes values for "server" and "world" keys if present.
|
||||
* The same as {@link #getContexts()}, but also includes context pairs for
|
||||
* "server" and "world" keys if present.
|
||||
*
|
||||
* @return the full contexts required for this node to apply
|
||||
* @since 3.1
|
||||
* @see Contexts#SERVER_KEY
|
||||
* @see Contexts#WORLD_KEY
|
||||
*/
|
||||
@Nonnull
|
||||
ContextSet getFullContexts();
|
||||
|
||||
/**
|
||||
* Gets if this is a group node
|
||||
* Gets if this node is a wildcard permission.
|
||||
*
|
||||
* @return true if this is a group node
|
||||
*/
|
||||
boolean isGroupNode();
|
||||
|
||||
/**
|
||||
* Gets the name of the group, if this is a group node.
|
||||
*
|
||||
* @return the name of the group
|
||||
* @throws IllegalStateException if this is not a group node. See {@link #isGroupNode()}
|
||||
*/
|
||||
@Nonnull
|
||||
String getGroupName() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Gets if this node is a wildcard node
|
||||
*
|
||||
* @return true if this node is a wildcard node
|
||||
* @return true if this node is a wildcard permission
|
||||
*/
|
||||
boolean isWildcard();
|
||||
|
||||
/**
|
||||
* Gets the level of this wildcard, higher is more specific
|
||||
* Gets the level of this wildcard.
|
||||
*
|
||||
* <p>The node <code>luckperms.*</code> has a wildcard level of 1.</p>
|
||||
* <p>The node <code>luckperms.user.permission.*</code> has a wildcard level of 3.</p>
|
||||
*
|
||||
* <p>Nodes with a higher wildcard level are more specific and have priority over
|
||||
* less specific nodes (nodes with a lower wildcard level).</p>
|
||||
*
|
||||
* @return the wildcard level
|
||||
* @throws IllegalStateException if this is not a wildcard
|
||||
@@ -306,55 +319,126 @@ public interface Node {
|
||||
int getWildcardLevel() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Gets if this node is a meta node
|
||||
* Gets if this node has any extra {@link NodeType} data attached to it.
|
||||
*
|
||||
* @return true if this node is a meta node
|
||||
* @return if this node has any type data
|
||||
* @since 4.2
|
||||
*/
|
||||
boolean isMeta();
|
||||
boolean hasTypeData();
|
||||
|
||||
/**
|
||||
* Gets the meta value from this node
|
||||
* Gets the type data corresponding to the given <code>key</code>, if present.
|
||||
*
|
||||
* @return the meta value
|
||||
* @throws IllegalStateException if this node is not a meta node
|
||||
* @param key the key
|
||||
* @param <T> the {@link NodeType} type
|
||||
* @return the data, if present
|
||||
* @since 4.2
|
||||
*/
|
||||
<T extends NodeType> Optional<T> getTypeData(NodeTypeKey<T> key);
|
||||
|
||||
/**
|
||||
* Gets the type data corresponding to the given <code>key</code>, throwing an exception
|
||||
* if no data is present.
|
||||
*
|
||||
* @param key the key
|
||||
* @param <T> the {@link NodeType} type
|
||||
* @return the data
|
||||
* @throws IllegalStateException if data isn't present
|
||||
* @since 4.2
|
||||
*/
|
||||
default <T extends NodeType> T typeData(NodeTypeKey<T> key) throws IllegalStateException {
|
||||
return getTypeData(key)
|
||||
.orElseThrow(() ->
|
||||
new IllegalStateException("Node '" + getPermission() + "' does not have the '" + key.getTypeName() + "' type.")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if this node has {@link InheritanceType} type data.
|
||||
*
|
||||
* @return true if this is a inheritance (group) node.
|
||||
*/
|
||||
default boolean isGroupNode() {
|
||||
return getTypeData(InheritanceType.KEY).isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the inherited group if this node has {@link InheritanceType} type data,
|
||||
* throwing an exception if the data is not present.
|
||||
*
|
||||
* @return the name of the group
|
||||
* @throws IllegalStateException if this node doesn't have {@link InheritanceType} data
|
||||
*/
|
||||
@Nonnull
|
||||
Map.Entry<String, String> getMeta() throws IllegalStateException;
|
||||
default String getGroupName() throws IllegalStateException {
|
||||
return typeData(InheritanceType.KEY).getGroupName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if this node is a prefix node
|
||||
* Gets if this node has {@link MetaType} type data.
|
||||
*
|
||||
* @return true if this is a meta node.
|
||||
*/
|
||||
default boolean isMeta() {
|
||||
return getTypeData(MetaType.KEY).isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the meta entry if this node has {@link MetaType} type data,
|
||||
* throwing an exception if the data is not present.
|
||||
*
|
||||
* @return the meta entry
|
||||
* @throws IllegalStateException if this node doesn't have {@link MetaType} data
|
||||
*/
|
||||
@Nonnull
|
||||
default Map.Entry<String, String> getMeta() throws IllegalStateException {
|
||||
return typeData(MetaType.KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if this node has {@link PrefixType} type data.
|
||||
*
|
||||
* @return true if this node is a prefix node
|
||||
*/
|
||||
boolean isPrefix();
|
||||
default boolean isPrefix() {
|
||||
return getTypeData(PrefixType.KEY).isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prefix value from this node
|
||||
* Gets the prefix entry if this node has {@link PrefixType} type data,
|
||||
* throwing an exception if the data is not present.
|
||||
*
|
||||
* @return the prefix value
|
||||
* @throws IllegalStateException if this node is a not a prefix node
|
||||
* @return the meta entry
|
||||
* @throws IllegalStateException if this node doesn't have {@link PrefixType} data
|
||||
*/
|
||||
@Nonnull
|
||||
Map.Entry<Integer, String> getPrefix() throws IllegalStateException;
|
||||
default Map.Entry<Integer, String> getPrefix() throws IllegalStateException {
|
||||
return typeData(PrefixType.KEY).getAsEntry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if this node is a suffix node
|
||||
* Gets if this node has {@link SuffixType} type data.
|
||||
*
|
||||
* @return true if this node is a suffix node
|
||||
*/
|
||||
boolean isSuffix();
|
||||
default boolean isSuffix() {
|
||||
return getTypeData(SuffixType.KEY).isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the suffix value from this node
|
||||
* Gets the suffix entry if this node has {@link SuffixType} type data,
|
||||
* throwing an exception if the data is not present.
|
||||
*
|
||||
* @return the suffix value
|
||||
* @throws IllegalStateException if this node is a not a suffix node
|
||||
* @return the meta entry
|
||||
* @throws IllegalStateException if this node doesn't have {@link SuffixType} data
|
||||
*/
|
||||
@Nonnull
|
||||
Map.Entry<Integer, String> getSuffix() throws IllegalStateException;
|
||||
default Map.Entry<Integer, String> getSuffix() throws IllegalStateException {
|
||||
return typeData(SuffixType.KEY).getAsEntry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this Node is equal to another node
|
||||
* Gets if this Node is equal to another node.
|
||||
*
|
||||
* @param obj the other node
|
||||
* @return true if this node is equal to the other provided
|
||||
@@ -364,7 +448,7 @@ public interface Node {
|
||||
boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* Returns if this Node is equal to another node as defined by the given
|
||||
* Gets if this Node is equal to another node as defined by the given
|
||||
* {@link StandardNodeEquality} predicate.
|
||||
*
|
||||
* @param other the other node
|
||||
@@ -375,7 +459,7 @@ public interface Node {
|
||||
boolean standardEquals(Node other, StandardNodeEquality equalityPredicate);
|
||||
|
||||
/**
|
||||
* Returns if this Node is equal to another node as defined by the given
|
||||
* Gets if this Node is equal to another node as defined by the given
|
||||
* {@link NodeEqualityPredicate}.
|
||||
*
|
||||
* @param other the other node
|
||||
@@ -444,6 +528,19 @@ public interface Node {
|
||||
*/
|
||||
interface Builder {
|
||||
|
||||
/**
|
||||
* Copies the attributes from the given node and applies them to this
|
||||
* builder.
|
||||
*
|
||||
* <p>Note that this copies all attributes <strong>except</strong> the
|
||||
* permission itself.</p>
|
||||
*
|
||||
* @param node the node to copy from
|
||||
* @return the builder
|
||||
* @since 4.2
|
||||
*/
|
||||
Builder copyFrom(@Nonnull Node node);
|
||||
|
||||
/**
|
||||
* Sets the value of negated for the node.
|
||||
*
|
||||
@@ -459,7 +556,7 @@ public interface Node {
|
||||
*
|
||||
* @param value the value
|
||||
* @return the builder
|
||||
* @see Node#getValuePrimitive()
|
||||
* @see Node#getValue()
|
||||
*/
|
||||
@Nonnull
|
||||
Builder setValue(boolean value);
|
||||
@@ -478,14 +575,45 @@ public interface Node {
|
||||
Builder setOverride(boolean override);
|
||||
|
||||
/**
|
||||
* Sets the nodes expiry as a unix timestamp in seconds.
|
||||
* Sets the time when the node should expire.
|
||||
*
|
||||
* @param expireAt the expiry time
|
||||
* <p>The parameter passed to this method must be the unix timestamp
|
||||
* (in seconds) when the node should expire.</p>
|
||||
*
|
||||
* @param expiryUnixTimestamp the expiry timestamp (unix seconds)
|
||||
* @return the builder
|
||||
* @see Node#getExpiryUnixTime()
|
||||
*/
|
||||
@Nonnull
|
||||
Builder setExpiry(long expireAt);
|
||||
Builder setExpiry(long expiryUnixTimestamp);
|
||||
|
||||
/**
|
||||
* Sets the time when the node should expire.
|
||||
*
|
||||
* <p>The expiry timestamp is calculated relative to the current
|
||||
* system time.</p>
|
||||
*
|
||||
* @param duration how long the node should be added for
|
||||
* @param unit the unit <code>duration</code> is measured in
|
||||
* @return the builder
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
default Builder setExpiry(long duration, TimeUnit unit) {
|
||||
Preconditions.checkArgument(duration > 0, "duration must be positive");
|
||||
long seconds = Objects.requireNonNull(unit, "unit").toSeconds(duration);
|
||||
long timeNow = System.currentTimeMillis() / 1000L;
|
||||
return setExpiry(timeNow + seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks that the node being built should never expire.
|
||||
*
|
||||
* @return the builder
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
Builder clearExpiry();
|
||||
|
||||
/**
|
||||
* Sets the world value for the node.
|
||||
@@ -555,13 +683,25 @@ public interface Node {
|
||||
/**
|
||||
* Appends extra contexts onto the node.
|
||||
*
|
||||
* @param set a contextset
|
||||
* @param contextSet a context set
|
||||
* @return the builder
|
||||
* @see ContextSet
|
||||
* @see Node#getContexts()
|
||||
*/
|
||||
@Nonnull
|
||||
Builder withExtraContext(@Nonnull ContextSet set);
|
||||
Builder withExtraContext(@Nonnull ContextSet contextSet);
|
||||
|
||||
/**
|
||||
* Sets the extra contexts for the node.
|
||||
*
|
||||
* @param contextSet a context set
|
||||
* @return the builder
|
||||
* @see ContextSet
|
||||
* @see Node#getContexts()
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
Builder setExtraContext(@Nonnull ContextSet contextSet);
|
||||
|
||||
/**
|
||||
* Creates a {@link Node} instance from the builder.
|
||||
|
||||
@@ -84,6 +84,9 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Refreshes and applies any changes to the cached holder data.
|
||||
*
|
||||
* <p>Calling this method is unnecessary in most cases. Cache updates are handled
|
||||
* behind the scenes by the implementation.</p>
|
||||
*
|
||||
* @return the task future
|
||||
* @since 4.0
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Encapsulates the result of an operation to save uuid data about a player.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface PlayerSaveResult {
|
||||
|
||||
/**
|
||||
* Gets the status returned by the operation
|
||||
*
|
||||
* @return the status
|
||||
*/
|
||||
@Nonnull
|
||||
Set<Status> getStatus();
|
||||
|
||||
/**
|
||||
* Gets if the result includes a certain status code.
|
||||
*
|
||||
* @param status the status to check for
|
||||
* @return if the result includes the status
|
||||
*/
|
||||
boolean includes(@Nonnull Status status);
|
||||
|
||||
/**
|
||||
* Gets the old username involved in the result
|
||||
*
|
||||
* @return the old username
|
||||
* @see Status#USERNAME_UPDATED
|
||||
*/
|
||||
@Nullable
|
||||
String getOldUsername();
|
||||
|
||||
/**
|
||||
* Gets the other uuids involved in the result
|
||||
*
|
||||
* @return the other uuids
|
||||
* @see Status#OTHER_UUIDS_PRESENT_FOR_USERNAME
|
||||
*/
|
||||
@Nullable
|
||||
Set<UUID> getOtherUuids();
|
||||
|
||||
/**
|
||||
* The various states the result can take
|
||||
*/
|
||||
enum Status {
|
||||
|
||||
/**
|
||||
* There was no existing data saved for either the uuid or username
|
||||
*/
|
||||
CLEAN_INSERT,
|
||||
|
||||
/**
|
||||
* There was existing data for the player, no change was needed.
|
||||
*/
|
||||
NO_CHANGE,
|
||||
|
||||
/**
|
||||
* There was already a record for the UUID saved, but it was for a different username.
|
||||
*
|
||||
* <p>This is normal, players are able to change their usernames.</p>
|
||||
*/
|
||||
USERNAME_UPDATED,
|
||||
|
||||
/**
|
||||
* There was already a record for the username saved, but it was under a different uuid.
|
||||
*
|
||||
* <p>This is a bit of a cause for concern. It's possible that "player1" has changed
|
||||
* their username to "player2", and "player3" has changed their username to "player1".
|
||||
* If the original "player1" doesn't join after changing their name, this conflict could
|
||||
* occur.</p>
|
||||
*
|
||||
* <p>However, what's more likely is that the server is not setup to authenticate
|
||||
* correctly. Usually this is a problem with BungeeCord "ip-forwarding", but could be
|
||||
* that the user of the plugin is running a network off a shared database with one
|
||||
* server in online mode and another in offline mode.</p>
|
||||
*/
|
||||
OTHER_UUIDS_PRESENT_FOR_USERNAME,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Encapsulates the result of {@link User}s promotion along a {@link Track}.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface PromotionResult extends MutateResult {
|
||||
|
||||
/**
|
||||
* Gets the status of the result.
|
||||
*
|
||||
* @return the status
|
||||
*/
|
||||
@Nonnull
|
||||
Status getStatus();
|
||||
|
||||
@Override
|
||||
default boolean wasSuccess() {
|
||||
return getStatus().wasSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the group the user was promoted from, if applicable.
|
||||
*
|
||||
* <p>Will only be present for results with a {@link #getStatus() status} of
|
||||
* {@link Status#SUCCESS}.</p>
|
||||
*
|
||||
* @return the group the user was promoted from.
|
||||
*/
|
||||
@Nonnull
|
||||
Optional<String> getGroupFrom();
|
||||
|
||||
/**
|
||||
* Gets the name of the group the user was promoted from, if applicable.
|
||||
*
|
||||
* <p>Will only be present for results with a {@link #getStatus() status} of
|
||||
* {@link Status#SUCCESS} or {@link Status#ADDED_TO_FIRST_GROUP}.</p>
|
||||
*
|
||||
* <p>The value will also be set for results with the {@link Status#MALFORMED_TRACK} status,
|
||||
* with this value marking the group which no longer exists.</p>
|
||||
*
|
||||
* @return the group the user was promoted to.
|
||||
*/
|
||||
@Nonnull
|
||||
Optional<String> getGroupTo();
|
||||
|
||||
/**
|
||||
* The result status
|
||||
*/
|
||||
enum Status implements MutateResult {
|
||||
|
||||
/**
|
||||
* Indicates that the user was promoted normally.
|
||||
*/
|
||||
SUCCESS(true),
|
||||
|
||||
/**
|
||||
* Indicates that the user was added to the first group in the track.
|
||||
*
|
||||
* <p>This usually occurs when the user isn't already on any of the groups in the track.</p>
|
||||
*/
|
||||
ADDED_TO_FIRST_GROUP(true),
|
||||
|
||||
/**
|
||||
* Indicates that the next group in the track no longer exists.
|
||||
*/
|
||||
MALFORMED_TRACK(false),
|
||||
|
||||
/**
|
||||
* Indicates that the user is already a member of the group at the end of the track,
|
||||
* and as such cannot be promoted any further.
|
||||
*/
|
||||
END_OF_TRACK(false),
|
||||
|
||||
/**
|
||||
* Indicates that the implementation was unable to determine the users current position on
|
||||
* this track.
|
||||
*
|
||||
* <p>This usually occurs when the user is on more than one group on the track.</p>
|
||||
*/
|
||||
AMBIGUOUS_CALL(false),
|
||||
|
||||
/**
|
||||
* An undefined failure occurred.
|
||||
*/
|
||||
UNDEFINED_FAILURE(false);
|
||||
|
||||
private final boolean success;
|
||||
|
||||
Status(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wasSuccess() {
|
||||
return this.success;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public enum StandardNodeEquality implements NodeEqualityPredicate {
|
||||
|
||||
/**
|
||||
* All attributes must match, except for
|
||||
* {@link Node#getValuePrimitive() value}, which is ignored.
|
||||
* {@link Node#getValue() value}, which is ignored.
|
||||
*/
|
||||
IGNORE_VALUE,
|
||||
|
||||
@@ -59,14 +59,14 @@ public enum StandardNodeEquality implements NodeEqualityPredicate {
|
||||
|
||||
/**
|
||||
* All attributes must match, except for
|
||||
* {@link Node#getValuePrimitive() value} and the
|
||||
* {@link Node#getValue() value} and the
|
||||
* {@link Node#getExpiry() expiry time}, which are ignored.
|
||||
*/
|
||||
IGNORE_EXPIRY_TIME_AND_VALUE,
|
||||
|
||||
/**
|
||||
* All attributes must match, except for
|
||||
* {@link Node#getValuePrimitive() value} and the if the node is
|
||||
* {@link Node#getValue() value} and the if the node is
|
||||
* {@link Node#isTemporary() temporary}, which are ignored.
|
||||
*/
|
||||
IGNORE_VALUE_OR_IF_TEMPORARY;
|
||||
|
||||
@@ -34,7 +34,6 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -42,16 +41,6 @@ import javax.annotation.Nullable;
|
||||
/**
|
||||
* A means of loading and saving permission data to/from the backend.
|
||||
*
|
||||
* <p>All blocking methods return {@link CompletableFuture}s, which will be
|
||||
* populated with the result once the data has been loaded/saved asynchronously.
|
||||
* Care should be taken when using such methods to ensure that the main server
|
||||
* thread is not blocked.</p>
|
||||
*
|
||||
* <p>Methods such as {@link CompletableFuture#get()} and equivalent should
|
||||
* <strong>not</strong> be called on the main server thread. If you need to use
|
||||
* the result of these operations on the main server thread, register a
|
||||
* callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.</p>
|
||||
*
|
||||
* @since 2.14
|
||||
*/
|
||||
public interface Storage {
|
||||
@@ -64,80 +53,6 @@ public interface Storage {
|
||||
@Nonnull
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Loads and returns the entire log from storage
|
||||
*
|
||||
* @return a log instance, could be null if loading failed
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<Log> getLog();
|
||||
|
||||
/**
|
||||
* Gets a set all "unique" user UUIDs.
|
||||
*
|
||||
* <p>"Unique" meaning the user isn't just a member of the "default" group.</p>
|
||||
*
|
||||
* @return a set of uuids, or null if the operation failed.
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<Set<UUID>> getUniqueUsers();
|
||||
|
||||
/**
|
||||
* Searches for a list of users with a given permission.
|
||||
*
|
||||
* @param permission the permission to search for
|
||||
* @return a list of held permissions, or null if the operation failed
|
||||
* @throws NullPointerException if the permission is null
|
||||
* @since 2.17
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(@Nonnull String permission);
|
||||
|
||||
/**
|
||||
* Searches for a list of groups with a given permission.
|
||||
*
|
||||
* @param permission the permission to search for
|
||||
* @return a list of held permissions, or null if the operation failed
|
||||
* @throws NullPointerException if the permission is null
|
||||
* @since 2.17
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(@Nonnull String permission);
|
||||
|
||||
/**
|
||||
* Saves UUID caching data to the global cache
|
||||
*
|
||||
* @param username the users username
|
||||
* @param uuid the users mojang unique id
|
||||
* @return true if the operation completed successfully.
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @throws IllegalArgumentException if the username is invalid
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<Boolean> saveUUIDData(@Nonnull String username, @Nonnull UUID uuid);
|
||||
|
||||
/**
|
||||
* Gets a UUID from a username
|
||||
*
|
||||
* @param username the corresponding username
|
||||
* @return a uuid object, could be null
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @throws IllegalArgumentException if the username is invalid
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<UUID> getUUID(@Nonnull String username);
|
||||
|
||||
/**
|
||||
* Gets a username from a UUID
|
||||
*
|
||||
* @param uuid the corresponding uuid
|
||||
* @return a name string, could be null
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @since 2.17
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<String> getName(@Nonnull UUID uuid);
|
||||
|
||||
/**
|
||||
* Gets whether the storage instance is allowing logins on the platform.
|
||||
*
|
||||
@@ -147,34 +62,6 @@ public interface Storage {
|
||||
@Deprecated
|
||||
boolean isAcceptingLogins();
|
||||
|
||||
/**
|
||||
* Returns an executor which will run all passed runnables on the
|
||||
* main server thread.
|
||||
*
|
||||
* <p>This method is deprecated as plugins should create and use their own
|
||||
* executor instances.</p>
|
||||
*
|
||||
* @return an executor instance
|
||||
* @deprecated as plugins should create their own executors
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
Executor getSyncExecutor();
|
||||
|
||||
/**
|
||||
* Returns an executor which will run all passed runnables asynchronously
|
||||
* using the platforms scheduler and thread pools.
|
||||
*
|
||||
* <p>This method is deprecated as plugins should create and use their own
|
||||
* executor instances.</p>
|
||||
*
|
||||
* @return an executor instance
|
||||
* @deprecated as plugins should create their own executors
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
Executor getAsyncExecutor();
|
||||
|
||||
/**
|
||||
* Saves an action to storage
|
||||
*
|
||||
@@ -187,6 +74,16 @@ public interface Storage {
|
||||
@Deprecated
|
||||
CompletableFuture<Boolean> logAction(@Nonnull LogEntry entry);
|
||||
|
||||
/**
|
||||
* Loads and returns the entire log from storage
|
||||
*
|
||||
* @return a log instance, could be null if loading failed
|
||||
* @deprecated in favour of {@link ActionLogger#getLog()}
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
CompletableFuture<Log> getLog();
|
||||
|
||||
/**
|
||||
* Loads a user's data from the main storage into the plugins local storage.
|
||||
*
|
||||
@@ -229,6 +126,31 @@ public interface Storage {
|
||||
@Deprecated
|
||||
CompletableFuture<Boolean> saveUser(@Nonnull User user);
|
||||
|
||||
/**
|
||||
* Gets a set all "unique" user UUIDs.
|
||||
*
|
||||
* <p>"Unique" meaning the user isn't just a member of the "default" group.</p>
|
||||
*
|
||||
* @return a set of uuids, or null if the operation failed.
|
||||
* @deprecated in favour of {@link UserManager#getUniqueUsers()}
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
CompletableFuture<Set<UUID>> getUniqueUsers();
|
||||
|
||||
/**
|
||||
* Searches for a list of users with a given permission.
|
||||
*
|
||||
* @param permission the permission to search for
|
||||
* @return a list of held permissions, or null if the operation failed
|
||||
* @throws NullPointerException if the permission is null
|
||||
* @since 2.17
|
||||
* @deprecated in favour of {@link UserManager#getWithPermission(String)}
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(@Nonnull String permission);
|
||||
|
||||
/**
|
||||
* Creates and loads a group into the plugins local storage
|
||||
*
|
||||
@@ -293,6 +215,19 @@ public interface Storage {
|
||||
@Deprecated
|
||||
CompletableFuture<Boolean> deleteGroup(@Nonnull Group group);
|
||||
|
||||
/**
|
||||
* Searches for a list of groups with a given permission.
|
||||
*
|
||||
* @param permission the permission to search for
|
||||
* @return a list of held permissions, or null if the operation failed
|
||||
* @throws NullPointerException if the permission is null
|
||||
* @since 2.17
|
||||
* @deprecated in favour of {@link GroupManager#getWithPermission(String)}
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(@Nonnull String permission);
|
||||
|
||||
/**
|
||||
* Creates and loads a track into the plugins local storage
|
||||
*
|
||||
@@ -355,4 +290,70 @@ public interface Storage {
|
||||
@Deprecated
|
||||
CompletableFuture<Boolean> deleteTrack(@Nonnull Track track);
|
||||
|
||||
/**
|
||||
* Saves UUID caching data to the global cache
|
||||
*
|
||||
* @param username the users username
|
||||
* @param uuid the users mojang unique id
|
||||
* @return true if the operation completed successfully.
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @throws IllegalArgumentException if the username is invalid
|
||||
* @deprecated in favour of {@link UserManager#savePlayerData(UUID, String)}
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<Boolean> saveUUIDData(@Nonnull String username, @Nonnull UUID uuid);
|
||||
|
||||
/**
|
||||
* Gets a UUID from a username
|
||||
*
|
||||
* @param username the corresponding username
|
||||
* @return a uuid object, could be null
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @throws IllegalArgumentException if the username is invalid
|
||||
* @deprecated in favour of {@link UserManager#lookupUuid(String)}
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<UUID> getUUID(@Nonnull String username);
|
||||
|
||||
/**
|
||||
* Gets a username from a UUID
|
||||
*
|
||||
* @param uuid the corresponding uuid
|
||||
* @return a name string, could be null
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @since 2.17
|
||||
* @deprecated in favour of {@link UserManager#lookupUsername(UUID)}
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
CompletableFuture<String> getName(@Nonnull UUID uuid);
|
||||
|
||||
/**
|
||||
* Returns an executor which will run all passed runnables on the
|
||||
* main server thread.
|
||||
*
|
||||
* <p>This method is deprecated as plugins should create and use their own
|
||||
* executor instances.</p>
|
||||
*
|
||||
* @return an executor instance
|
||||
* @deprecated as plugins should create their own executors
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
Executor getSyncExecutor();
|
||||
|
||||
/**
|
||||
* Returns an executor which will run all passed runnables asynchronously
|
||||
* using the platforms scheduler and thread pools.
|
||||
*
|
||||
* <p>This method is deprecated as plugins should create and use their own
|
||||
* executor instances.</p>
|
||||
*
|
||||
* @return an executor instance
|
||||
* @deprecated as plugins should create their own executors
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
Executor getAsyncExecutor();
|
||||
|
||||
}
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -88,6 +90,28 @@ public interface Track {
|
||||
@Nullable
|
||||
String getPrevious(@Nonnull Group current);
|
||||
|
||||
/**
|
||||
* Promotes the given user along this track.
|
||||
*
|
||||
* @param user the user to promote
|
||||
* @param contextSet the contexts to promote the user in
|
||||
* @return the result of the action
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
PromotionResult promote(@Nonnull User user, @Nonnull ContextSet contextSet);
|
||||
|
||||
/**
|
||||
* Demotes the given user along this track.
|
||||
*
|
||||
* @param user the user to demote
|
||||
* @param contextSet the contexts to demote the user in
|
||||
* @return the result of the action
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
DemotionResult demote(@Nonnull User user, @Nonnull ContextSet contextSet);
|
||||
|
||||
/**
|
||||
* Appends a group to the end of this track
|
||||
*
|
||||
@@ -96,6 +120,7 @@ public interface Track {
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
@Nonnull
|
||||
DataMutateResult appendGroup(@Nonnull Group group);
|
||||
|
||||
/**
|
||||
@@ -108,6 +133,7 @@ public interface Track {
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
@Nonnull
|
||||
DataMutateResult insertGroup(@Nonnull Group group, int position) throws IndexOutOfBoundsException;
|
||||
|
||||
/**
|
||||
@@ -118,6 +144,7 @@ public interface Track {
|
||||
* @throws NullPointerException if the group is null
|
||||
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
|
||||
*/
|
||||
@Nonnull
|
||||
DataMutateResult removeGroup(@Nonnull Group group);
|
||||
|
||||
/**
|
||||
@@ -127,6 +154,7 @@ public interface Track {
|
||||
* @return the result of the operation
|
||||
* @throws NullPointerException if the group is null
|
||||
*/
|
||||
@Nonnull
|
||||
DataMutateResult removeGroup(@Nonnull String group);
|
||||
|
||||
/**
|
||||
|
||||
@@ -74,6 +74,7 @@ public interface User extends PermissionHolder {
|
||||
* @throws IllegalStateException if the user is not a member of that group
|
||||
* @throws NullPointerException if the group is null
|
||||
*/
|
||||
@Nonnull
|
||||
DataMutateResult setPrimaryGroup(@Nonnull String group);
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,12 +36,14 @@ import javax.annotation.Nonnull;
|
||||
/**
|
||||
* Holds cached permission and meta lookup data for a {@link PermissionHolder}.
|
||||
*
|
||||
* <p>All calls will account for inheritance, as well as any default data provided by
|
||||
* the platform. This calls are heavily cached and are therefore fast.</p>
|
||||
* <p>All calls will account for inheritance, as well as any default data
|
||||
* provided by the platform. This calls are heavily cached and are therefore
|
||||
* fast.</p>
|
||||
*
|
||||
* <p>For meta, both methods accepting {@link Contexts} and {@link MetaContexts} are provided. The only difference is that
|
||||
* the latter allows you to define how the meta stack should be structured internally. Where {@link Contexts} are passed, the
|
||||
* values from the configuration are used.</p>
|
||||
* <p>For meta, both methods accepting {@link Contexts} and {@link MetaContexts}
|
||||
* are provided. The only difference is that the latter allows you to define
|
||||
* how the meta stack should be structured internally. Where {@link Contexts}
|
||||
* are passed, the values from the configuration are used.</p>
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
@@ -399,6 +401,20 @@ public interface CachedData {
|
||||
*/
|
||||
void invalidateMeta(@Nonnull Contexts contexts);
|
||||
|
||||
/**
|
||||
* Invalidates all cached {@link PermissionData} instances.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
void invalidatePermissions();
|
||||
|
||||
/**
|
||||
* Invalidates all cached {@link MetaData} instances.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
void invalidateMeta();
|
||||
|
||||
/**
|
||||
* Invalidates all of the underlying Permission calculators.
|
||||
*
|
||||
|
||||
@@ -25,12 +25,11 @@
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -38,18 +37,9 @@ import javax.annotation.Nonnull;
|
||||
|
||||
abstract class AbstractContextSet implements ContextSet {
|
||||
|
||||
protected abstract Multimap<String, String> backing();
|
||||
protected abstract SetMultimap<String, String> backing();
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public Map<String, String> toMap() {
|
||||
ImmutableMap.Builder<String, String> m = ImmutableMap.builder();
|
||||
for (Map.Entry<String, String> e : backing().entries()) {
|
||||
m.put(e.getKey(), e.getValue());
|
||||
}
|
||||
return m.build();
|
||||
}
|
||||
protected abstract void copyTo(SetMultimap<String, String> other);
|
||||
|
||||
@Override
|
||||
public boolean containsKey(@Nonnull String key) {
|
||||
@@ -68,27 +58,6 @@ abstract class AbstractContextSet implements ContextSet {
|
||||
return backing().containsEntry(sanitizeKey(key), sanitizeValue(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIgnoreCase(@Nonnull String key, @Nonnull String value) {
|
||||
String v = sanitizeValue(value);
|
||||
|
||||
Collection<String> values = backing().asMap().get(sanitizeKey(key));
|
||||
if (values == null || values.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (values.contains(v)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (String val : values) {
|
||||
if (val.equalsIgnoreCase(v)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return backing().isEmpty();
|
||||
@@ -126,8 +95,7 @@ abstract class AbstractContextSet implements ContextSet {
|
||||
if (stringIsEmpty(key)) {
|
||||
throw new IllegalArgumentException("key is (effectively) empty");
|
||||
}
|
||||
|
||||
return key.toLowerCase().intern();
|
||||
return key.toLowerCase();
|
||||
}
|
||||
|
||||
static String sanitizeValue(String value) {
|
||||
@@ -135,8 +103,7 @@ abstract class AbstractContextSet implements ContextSet {
|
||||
if (stringIsEmpty(value)) {
|
||||
throw new IllegalArgumentException("value is (effectively) empty");
|
||||
}
|
||||
|
||||
return value.intern();
|
||||
return value.toLowerCase();
|
||||
}
|
||||
|
||||
private static boolean stringIsEmpty(String s) {
|
||||
|
||||
@@ -28,7 +28,7 @@ package me.lucko.luckperms.api.context;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Calculates whether contexts are applicable to {@link T}
|
||||
* Calculates whether contexts are applicable to a {@link T subject}.
|
||||
*
|
||||
* @param <T> the subject type. Is ALWAYS the player class of the platform.
|
||||
* @since 2.13
|
||||
|
||||
@@ -27,6 +27,7 @@ package me.lucko.luckperms.api.context;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@@ -47,9 +48,8 @@ import javax.annotation.Nonnull;
|
||||
* <p>Contexts can be combined with each other to form so called
|
||||
* "context sets" - simply a collection of context pairs.</p>
|
||||
*
|
||||
* <p>Context keys are case-insensitive, and will be converted to
|
||||
* {@link String#toLowerCase() lowercase} by all implementations.
|
||||
* Values however are case-sensitive.</p>
|
||||
* <p>Context keys and values are case-insensitive, and will be converted to
|
||||
* {@link String#toLowerCase() lowercase} by all implementations.</p>
|
||||
*
|
||||
* <p>Context keys and values may not be null or empty. A key/value will be
|
||||
* deemed empty if it's length is zero, or if it consists of only space
|
||||
@@ -61,7 +61,7 @@ import javax.annotation.Nonnull;
|
||||
*
|
||||
* @since 2.13
|
||||
*/
|
||||
public interface ContextSet {
|
||||
public interface ContextSet extends Iterable<Map.Entry<String, String>> {
|
||||
|
||||
/**
|
||||
* Creates an {@link ImmutableContextSet} from a context pair.
|
||||
@@ -231,6 +231,20 @@ public interface ContextSet {
|
||||
@Nonnull
|
||||
Multimap<String, String> toMultimap();
|
||||
|
||||
/**
|
||||
* Returns an {@link Iterator} over each of the context pairs in this set.
|
||||
*
|
||||
* <p>The returned iterator represents the state of the set at the time of creation. It is not
|
||||
* updated as the set changes.</p>
|
||||
*
|
||||
* <p>The iterator does not support {@link Iterator#remove()} calls.</p>
|
||||
*
|
||||
* @return an iterator
|
||||
*/
|
||||
@Nonnull
|
||||
@Override
|
||||
Iterator<Map.Entry<String, String>> iterator();
|
||||
|
||||
/**
|
||||
* Returns if the {@link ContextSet} contains at least one value for the
|
||||
* given key.
|
||||
@@ -272,33 +286,16 @@ public interface ContextSet {
|
||||
/**
|
||||
* Returns if the {@link ContextSet} contains a given context pairing.
|
||||
*
|
||||
* <p>This lookup is case-sensitive on the value.</p>
|
||||
*
|
||||
* @param key the key to look for
|
||||
* @param value the value to look for (case sensitive)
|
||||
* @param value the value to look for
|
||||
* @return true if the set contains the context pair
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
boolean has(@Nonnull String key, @Nonnull String value);
|
||||
|
||||
/**
|
||||
* Returns if the {@link ContextSet} contains a given context pairing,
|
||||
* ignoring the case of values.
|
||||
*
|
||||
* <p>This lookup is case-insensitive on the value.</p>
|
||||
*
|
||||
* @param key the key to look for
|
||||
* @param value the value to look for
|
||||
* @return true if the set contains the context pair
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
boolean hasIgnoreCase(@Nonnull String key, @Nonnull String value);
|
||||
|
||||
/**
|
||||
* Returns if the {@link ContextSet} contains a given context pairing.
|
||||
*
|
||||
* <p>This lookup is case-sensitive on the value.</p>
|
||||
*
|
||||
* @param entry the entry to look for
|
||||
* @return true if the set contains the context pair
|
||||
* @throws NullPointerException if the key or value is null
|
||||
@@ -308,21 +305,6 @@ public interface ContextSet {
|
||||
return has(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the {@link ContextSet} contains a given context pairing,
|
||||
* ignoring the case of values.
|
||||
*
|
||||
* <p>This lookup is case-insensitive on the value.</p>
|
||||
*
|
||||
* @param entry the entry to look for
|
||||
* @return true if the set contains the context pair
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
default boolean hasIgnoreCase(@Nonnull Map.Entry<String, String> entry) {
|
||||
Objects.requireNonNull(entry, "entry");
|
||||
return hasIgnoreCase(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this {@link ContextSet} is fully "satisfied" by another set.
|
||||
*
|
||||
@@ -331,31 +313,11 @@ public interface ContextSet {
|
||||
*
|
||||
* <p>Mathematically, this method returns true if this set is a <b>subset</b> of the other.</p>
|
||||
*
|
||||
* <p>This check is case-sensitive. For a case-insensitive check,
|
||||
* use {@link #isSatisfiedBy(ContextSet, boolean)}.</p>
|
||||
*
|
||||
* @param other the other set to check
|
||||
* @return true if all entries in this set are also in the other set
|
||||
* @since 3.1
|
||||
*/
|
||||
default boolean isSatisfiedBy(@Nonnull ContextSet other) {
|
||||
return isSatisfiedBy(other, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this {@link ContextSet} is fully "satisfied" by another set.
|
||||
*
|
||||
* <p>For a context set to "satisfy" another, it must itself contain all of
|
||||
* the context pairings in the other set.</p>
|
||||
*
|
||||
* <p>Mathematically, this method returns true if this set is a <b>subset</b> of the other.</p>
|
||||
*
|
||||
* @param other the other set to check
|
||||
* @param caseSensitive if the check should be case sensitive
|
||||
* @return true if all entries in this set are also in the other set
|
||||
* @since 3.4
|
||||
*/
|
||||
default boolean isSatisfiedBy(@Nonnull ContextSet other, boolean caseSensitive) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
@@ -373,14 +335,8 @@ public interface ContextSet {
|
||||
} else {
|
||||
// neither are empty, we need to compare the individual entries
|
||||
for (Map.Entry<String, String> context : toSet()) {
|
||||
if (caseSensitive) {
|
||||
if (!other.has(context)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!other.hasIgnoreCase(context)) {
|
||||
return false;
|
||||
}
|
||||
if (!other.has(context)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -25,12 +25,16 @@
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
@@ -164,10 +168,15 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Multimap<String, String> backing() {
|
||||
protected SetMultimap<String, String> backing() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void copyTo(SetMultimap<String, String> other) {
|
||||
other.putAll(this.map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable() {
|
||||
return true;
|
||||
@@ -192,12 +201,34 @@ public final class ImmutableContextSet extends AbstractContextSet implements Con
|
||||
return this.map.entries();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public Map<String, String> toMap() {
|
||||
ImmutableMap.Builder<String, String> m = ImmutableMap.builder();
|
||||
for (Map.Entry<String, String> e : this.map.entries()) {
|
||||
m.put(e.getKey(), e.getValue());
|
||||
}
|
||||
return m.build();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Multimap<String, String> toMultimap() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Iterator<Map.Entry<String, String>> iterator() {
|
||||
return this.map.entries().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<Map.Entry<String, String>> spliterator() {
|
||||
return this.map.entries().spliterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.hashCode;
|
||||
|
||||
@@ -26,16 +26,18 @@
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@@ -144,9 +146,17 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
|
||||
@Nonnull
|
||||
public static MutableContextSet fromSet(@Nonnull ContextSet contextSet) {
|
||||
Objects.requireNonNull(contextSet, "contextSet");
|
||||
MutableContextSet set = create();
|
||||
set.addAll(contextSet);
|
||||
return set;
|
||||
|
||||
if (contextSet instanceof ImmutableContextSet) {
|
||||
SetMultimap<String, String> map = ((ImmutableContextSet) contextSet).backing();
|
||||
return new MutableContextSet(map);
|
||||
} else if (contextSet instanceof MutableContextSet) {
|
||||
return contextSet.mutableCopy();
|
||||
} else {
|
||||
MutableContextSet set = create();
|
||||
set.addAll(contextSet);
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,15 +175,22 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
|
||||
this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create());
|
||||
}
|
||||
|
||||
private MutableContextSet(MutableContextSet other) {
|
||||
this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create(other.map));
|
||||
private MutableContextSet(SetMultimap<String, String> other) {
|
||||
this.map = Multimaps.synchronizedSetMultimap(HashMultimap.create(other));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Multimap<String, String> backing() {
|
||||
protected SetMultimap<String, String> backing() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void copyTo(SetMultimap<String, String> other) {
|
||||
synchronized (this.map) {
|
||||
other.putAll(this.map);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable() {
|
||||
return false;
|
||||
@@ -186,25 +203,58 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
|
||||
if (this.map.isEmpty()) {
|
||||
return ImmutableContextSet.empty();
|
||||
}
|
||||
return new ImmutableContextSet(ImmutableSetMultimap.copyOf(this.map));
|
||||
synchronized (this.map) {
|
||||
return new ImmutableContextSet(ImmutableSetMultimap.copyOf(this.map));
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MutableContextSet mutableCopy() {
|
||||
return new MutableContextSet(this);
|
||||
synchronized (this.map) {
|
||||
return new MutableContextSet(this.map);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Set<Map.Entry<String, String>> toSet() {
|
||||
return ImmutableSet.copyOf(this.map.entries());
|
||||
synchronized (this.map) {
|
||||
// map.entries() returns immutable Map.Entry instances, so we can just call copyOf
|
||||
return ImmutableSet.copyOf(this.map.entries());
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public Map<String, String> toMap() {
|
||||
ImmutableMap.Builder<String, String> m = ImmutableMap.builder();
|
||||
synchronized (this.map) {
|
||||
for (Map.Entry<String, String> e : this.map.entries()) {
|
||||
m.put(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
return m.build();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Multimap<String, String> toMultimap() {
|
||||
return ImmutableSetMultimap.copyOf(this.map);
|
||||
synchronized (this.map) {
|
||||
return ImmutableSetMultimap.copyOf(this.map);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Iterator<Map.Entry<String, String>> iterator() {
|
||||
return toSet().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<Map.Entry<String, String>> spliterator() {
|
||||
return toSet().spliterator();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +322,9 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
|
||||
Objects.requireNonNull(contextSet, "contextSet");
|
||||
if (contextSet instanceof AbstractContextSet) {
|
||||
AbstractContextSet other = ((AbstractContextSet) contextSet);
|
||||
this.map.putAll(other.backing());
|
||||
synchronized (this.map) {
|
||||
other.copyTo(this.map);
|
||||
}
|
||||
} else {
|
||||
addAll(contextSet.toMultimap());
|
||||
}
|
||||
@@ -282,28 +334,13 @@ public final class MutableContextSet extends AbstractContextSet implements Conte
|
||||
* Removes a context from this set.
|
||||
*
|
||||
* @param key the key to remove
|
||||
* @param value the value to remove (case sensitive)
|
||||
* @param value the value to remove
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void remove(@Nonnull String key, @Nonnull String value) {
|
||||
this.map.remove(sanitizeKey(key), sanitizeValue(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a context from this set. (case-insensitive)
|
||||
*
|
||||
* @param key the key to remove
|
||||
* @param value the value to remove
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void removeIgnoreCase(@Nonnull String key, @Nonnull String value) {
|
||||
String v = sanitizeValue(value);
|
||||
Collection<String> strings = this.map.asMap().get(sanitizeKey(key));
|
||||
if (strings != null) {
|
||||
strings.removeIf(e -> e.equalsIgnoreCase(v));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all contexts from this set with the given key.
|
||||
*
|
||||
|
||||
@@ -31,16 +31,20 @@ import java.util.function.Consumer;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* The internal LuckPerms event bus.
|
||||
* The LuckPerms event bus.
|
||||
*
|
||||
* <p>LuckPerms events are posted to any listeners registered with the bus.</p>
|
||||
* <p>Used to subscribe (or "listen") to LuckPerms events.</p>
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface EventBus {
|
||||
|
||||
/**
|
||||
* Subscribes to an event.
|
||||
* Registers a new subscription to the given event.
|
||||
*
|
||||
* <p>The returned {@link EventHandler} instance encapsulates the subscription state. It has
|
||||
* methods which can be used to terminate the subscription, or view stats about the nature of
|
||||
* the subscription.</p>
|
||||
*
|
||||
* @param eventClass the event class
|
||||
* @param handler the event handler
|
||||
@@ -48,7 +52,28 @@ public interface EventBus {
|
||||
* @return an event handler instance representing this subscription
|
||||
*/
|
||||
@Nonnull
|
||||
<T extends LuckPermsEvent> EventHandler<T> subscribe(@Nonnull Class<T> eventClass, @Nonnull Consumer<T> handler);
|
||||
<T extends LuckPermsEvent> EventHandler<T> subscribe(@Nonnull Class<T> eventClass, @Nonnull Consumer<? super T> handler);
|
||||
|
||||
/**
|
||||
* Registers a new subscription to the given event.
|
||||
*
|
||||
* <p>The returned {@link EventHandler} instance encapsulates the subscription state. It has
|
||||
* methods which can be used to terminate the subscription, or view stats about the nature of
|
||||
* the subscription.</p>
|
||||
*
|
||||
* <p>Unlike {@link #subscribe(Class, Consumer)}, this method accepts an additional parameter
|
||||
* for {@code plugin}. This object must be a "plugin" instance on the platform, and is used to
|
||||
* automatically {@link EventHandler#unregister() unregister} the subscription when the
|
||||
* corresponding plugin is disabled.</p>
|
||||
*
|
||||
* @param <T> the event class
|
||||
* @param plugin a plugin instance to bind the subscription to.
|
||||
* @param eventClass the event class
|
||||
* @param handler the event handler
|
||||
* @return an event handler instance representing this subscription
|
||||
*/
|
||||
@Nonnull
|
||||
<T extends LuckPermsEvent> EventHandler<T> subscribe(Object plugin, @Nonnull Class<T> eventClass, @Nonnull Consumer<? super T> handler);
|
||||
|
||||
/**
|
||||
* Gets a set of all registered handlers for a given event.
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.function.Consumer;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Represents a handler for a LuckPerms event
|
||||
* Represents a subscription to a {@link LuckPermsEvent}.
|
||||
*
|
||||
* @param <T> the event class
|
||||
*/
|
||||
@@ -64,7 +64,7 @@ public interface EventHandler<T extends LuckPermsEvent> extends AutoCloseable {
|
||||
* @return the event consumer
|
||||
*/
|
||||
@Nonnull
|
||||
Consumer<T> getConsumer();
|
||||
Consumer<? super T> getConsumer();
|
||||
|
||||
/**
|
||||
* Gets the number of times this handler has been called
|
||||
|
||||
@@ -26,11 +26,15 @@
|
||||
package me.lucko.luckperms.api.manager;
|
||||
|
||||
import me.lucko.luckperms.api.Group;
|
||||
import me.lucko.luckperms.api.HeldPermission;
|
||||
import me.lucko.luckperms.api.Storage;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -38,6 +42,16 @@ import javax.annotation.Nullable;
|
||||
/**
|
||||
* Represents the object responsible for managing {@link Group} instances.
|
||||
*
|
||||
* <p>All blocking methods return {@link CompletableFuture}s, which will be
|
||||
* populated with the result once the data has been loaded/saved asynchronously.
|
||||
* Care should be taken when using such methods to ensure that the main server
|
||||
* thread is not blocked.</p>
|
||||
*
|
||||
* <p>Methods such as {@link CompletableFuture#get()} and equivalent should
|
||||
* <strong>not</strong> be called on the main server thread. If you need to use
|
||||
* the result of these operations on the main server thread, register a
|
||||
* callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.</p>
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface GroupManager {
|
||||
@@ -138,6 +152,17 @@ public interface GroupManager {
|
||||
@Nonnull
|
||||
CompletableFuture<Void> loadAllGroups();
|
||||
|
||||
/**
|
||||
* Searches for a list of groups with a given permission.
|
||||
*
|
||||
* @param permission the permission to search for
|
||||
* @return a list of held permissions, or null if the operation failed
|
||||
* @throws NullPointerException if the permission is null
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<List<HeldPermission<String>>> getWithPermission(@Nonnull String permission);
|
||||
|
||||
/**
|
||||
* Gets a loaded group.
|
||||
*
|
||||
|
||||
@@ -31,6 +31,8 @@ import me.lucko.luckperms.api.Track;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -38,6 +40,16 @@ import javax.annotation.Nullable;
|
||||
/**
|
||||
* Represents the object responsible for managing {@link Track} instances.
|
||||
*
|
||||
* <p>All blocking methods return {@link CompletableFuture}s, which will be
|
||||
* populated with the result once the data has been loaded/saved asynchronously.
|
||||
* Care should be taken when using such methods to ensure that the main server
|
||||
* thread is not blocked.</p>
|
||||
*
|
||||
* <p>Methods such as {@link CompletableFuture#get()} and equivalent should
|
||||
* <strong>not</strong> be called on the main server thread. If you need to use
|
||||
* the result of these operations on the main server thread, register a
|
||||
* callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.</p>
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface TrackManager {
|
||||
|
||||
@@ -25,13 +25,18 @@
|
||||
|
||||
package me.lucko.luckperms.api.manager;
|
||||
|
||||
import me.lucko.luckperms.api.HeldPermission;
|
||||
import me.lucko.luckperms.api.PlayerSaveResult;
|
||||
import me.lucko.luckperms.api.Storage;
|
||||
import me.lucko.luckperms.api.User;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -42,6 +47,16 @@ import javax.annotation.Nullable;
|
||||
* <p>Note that User instances are automatically loaded for online players.
|
||||
* It's likely that offline players will not have an instance pre-loaded.</p>
|
||||
*
|
||||
* <p>All blocking methods return {@link CompletableFuture}s, which will be
|
||||
* populated with the result once the data has been loaded/saved asynchronously.
|
||||
* Care should be taken when using such methods to ensure that the main server
|
||||
* thread is not blocked.</p>
|
||||
*
|
||||
* <p>Methods such as {@link CompletableFuture#get()} and equivalent should
|
||||
* <strong>not</strong> be called on the main server thread. If you need to use
|
||||
* the result of these operations on the main server thread, register a
|
||||
* callback using {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)}.</p>
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface UserManager {
|
||||
@@ -85,6 +100,32 @@ public interface UserManager {
|
||||
return loadUser(uuid, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the LuckPerms cache to find a uuid for the given username.
|
||||
*
|
||||
* <p>This lookup is case insensitive.</p>
|
||||
*
|
||||
* @param username the username
|
||||
* @return a uuid, could be null
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @throws IllegalArgumentException if the username is invalid
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<UUID> lookupUuid(@Nonnull String username);
|
||||
|
||||
/**
|
||||
* Uses the LuckPerms cache to find a username for the given uuid.
|
||||
*
|
||||
* @param uuid the uuid
|
||||
* @return a username, could be null
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @throws IllegalArgumentException if the username is invalid
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<String> lookupUsername(@Nonnull UUID uuid);
|
||||
|
||||
/**
|
||||
* Saves a user's data back to the plugin's storage provider.
|
||||
*
|
||||
@@ -105,6 +146,41 @@ public interface UserManager {
|
||||
@Nonnull
|
||||
CompletableFuture<Void> saveUser(@Nonnull User user);
|
||||
|
||||
/**
|
||||
* Saves data about a player to the uuid caching system.
|
||||
*
|
||||
* @param uuid the users mojang unique id
|
||||
* @param username the users username
|
||||
* @return the result of the operation.
|
||||
* @throws NullPointerException if either parameters are null
|
||||
* @throws IllegalArgumentException if the username is invalid
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<PlayerSaveResult> savePlayerData(@Nonnull UUID uuid, @Nonnull String username);
|
||||
|
||||
/**
|
||||
* Gets a set all "unique" user UUIDs.
|
||||
*
|
||||
* <p>"Unique" meaning the user isn't just a member of the "default" group.</p>
|
||||
*
|
||||
* @return a set of uuids
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<Set<UUID>> getUniqueUsers();
|
||||
|
||||
/**
|
||||
* Searches for a list of users with a given permission.
|
||||
*
|
||||
* @param permission the permission to search for
|
||||
* @return a list of held permissions
|
||||
* @throws NullPointerException if the permission is null
|
||||
* @since 4.2
|
||||
*/
|
||||
@Nonnull
|
||||
CompletableFuture<List<HeldPermission<UUID>>> getWithPermission(@Nonnull String permission);
|
||||
|
||||
/**
|
||||
* Gets a loaded user.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.nodetype;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
|
||||
/**
|
||||
* Superinterface for extended {@link Node} types.
|
||||
*
|
||||
* <p>The 'permission' property of a {@link Node} is also used in some cases to represent state
|
||||
* beyond a granted permission. This state is encapsulated by extra {@link NodeType} data which
|
||||
* can be obtained from this instance using {@link Node#getTypeData(NodeTypeKey)}.</p>
|
||||
*
|
||||
* <p>Type data is mapped by {@link NodeTypeKey}s, which are usually stored as static members of the
|
||||
* corresponding {@link NodeType} class under the <code>KEY</code> field.</p>
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface NodeType {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.nodetype;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Marks an instance used as a key for a {@link NodeType}.
|
||||
*
|
||||
* <p>A single instance of this interface is created and stored statically for
|
||||
* each sub-interface of {@link NodeType}.</p>
|
||||
*
|
||||
* @param <N> the type of the {@link NodeType} being indexed by this key
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface NodeTypeKey<N extends NodeType> {
|
||||
|
||||
/**
|
||||
* Gets the {@link Class#getSimpleName() class name} of the represented type.
|
||||
*
|
||||
* @return the name of the represented type
|
||||
*/
|
||||
@Nonnull
|
||||
default String getTypeName() {
|
||||
ParameterizedType thisType = (ParameterizedType) getClass().getGenericSuperclass();
|
||||
Type nodeType = thisType.getActualTypeArguments()[0];
|
||||
return ((Class) nodeType).getSimpleName();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.nodetype.types;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.nodetype.NodeType;
|
||||
import me.lucko.luckperms.api.nodetype.NodeTypeKey;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A sub-type of {@link Node} used to mark the display name of the node's holder.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface DisplayNameType extends NodeType {
|
||||
|
||||
/**
|
||||
* The key for this type.
|
||||
*/
|
||||
NodeTypeKey<DisplayNameType> KEY = new NodeTypeKey<DisplayNameType>(){};
|
||||
|
||||
/**
|
||||
* Gets the display name.
|
||||
*
|
||||
* @return the display name
|
||||
*/
|
||||
@Nonnull
|
||||
String getDisplayName();
|
||||
|
||||
}
|
||||
+17
-16
@@ -23,34 +23,35 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.references;
|
||||
package me.lucko.luckperms.api.nodetype.types;
|
||||
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.nodetype.NodeType;
|
||||
import me.lucko.luckperms.api.nodetype.NodeTypeKey;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A reference to a specific {@link PermissionHolder}.
|
||||
* A sub-type of {@link Node} used to mark that the holder of the node should inherit
|
||||
* from another group.
|
||||
*
|
||||
* @param <S> the holder type
|
||||
* @param <I> the holder identifier type
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface HolderReference<S, I> extends Identifiable<I> {
|
||||
public interface InheritanceType extends NodeType {
|
||||
|
||||
/**
|
||||
* Gets the holder type
|
||||
*
|
||||
* @return the holder type
|
||||
* The key for this type.
|
||||
*/
|
||||
HolderType getType();
|
||||
NodeTypeKey<InheritanceType> KEY = new NodeTypeKey<InheritanceType>(){};
|
||||
|
||||
/**
|
||||
* Applies an action to this reference, if it is present and exists.
|
||||
* Gets the name of the group to be inherited.
|
||||
*
|
||||
* @param plugin the plugin
|
||||
* @param consumer the action
|
||||
* <p>This is no guarantee that this group exists.</p>
|
||||
*
|
||||
* @return the name of the group
|
||||
*/
|
||||
void apply(LuckPermsPlugin plugin, Consumer<S> consumer);
|
||||
@Nonnull
|
||||
String getGroupName();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.nodetype.types;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.nodetype.NodeType;
|
||||
import me.lucko.luckperms.api.nodetype.NodeTypeKey;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A sub-type of {@link Node} used to store meta assignments.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface MetaType extends NodeType, Map.Entry<String, String> {
|
||||
|
||||
/**
|
||||
* The key for this type.
|
||||
*/
|
||||
NodeTypeKey<MetaType> KEY = new NodeTypeKey<MetaType>(){};
|
||||
|
||||
/**
|
||||
* Gets the meta key.
|
||||
*
|
||||
* @return the meta key
|
||||
*/
|
||||
@Nonnull
|
||||
String getKey();
|
||||
|
||||
/**
|
||||
* Gets the meta value.
|
||||
*
|
||||
* @return the meta value
|
||||
*/
|
||||
@Nonnull
|
||||
String getValue();
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
default String setValue(String value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.nodetype.types;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.nodetype.NodeType;
|
||||
import me.lucko.luckperms.api.nodetype.NodeTypeKey;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A sub-type of {@link Node} used to store prefix assignments.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface PrefixType extends NodeType {
|
||||
|
||||
/**
|
||||
* The key for this type.
|
||||
*/
|
||||
NodeTypeKey<PrefixType> KEY = new NodeTypeKey<PrefixType>(){};
|
||||
|
||||
/**
|
||||
* Gets the priority of the prefix assignment.
|
||||
*
|
||||
* @return the priority
|
||||
*/
|
||||
int getPriority();
|
||||
|
||||
/**
|
||||
* Gets the actual prefix string.
|
||||
*
|
||||
* @return the prefix
|
||||
*/
|
||||
@Nonnull
|
||||
String getPrefix();
|
||||
|
||||
/**
|
||||
* Gets a representation of this instance as a {@link Map.Entry}.
|
||||
*
|
||||
* @return a map entry representation of the priority and prefix string
|
||||
*/
|
||||
@Nonnull
|
||||
Map.Entry<Integer, String> getAsEntry();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.nodetype.types;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.nodetype.NodeType;
|
||||
import me.lucko.luckperms.api.nodetype.NodeTypeKey;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A sub-type of {@link Node} used to store suffix assignments.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface SuffixType extends NodeType {
|
||||
|
||||
/**
|
||||
* The key for this type.
|
||||
*/
|
||||
NodeTypeKey<SuffixType> KEY = new NodeTypeKey<SuffixType>(){};
|
||||
|
||||
/**
|
||||
* Gets the priority of the suffix assignment.
|
||||
*
|
||||
* @return the priority
|
||||
*/
|
||||
int getPriority();
|
||||
|
||||
/**
|
||||
* Gets the actual suffix string.
|
||||
*
|
||||
* @return the suffix
|
||||
*/
|
||||
@Nonnull
|
||||
String getSuffix();
|
||||
|
||||
/**
|
||||
* Gets a representation of this instance as a {@link Map.Entry}.
|
||||
*
|
||||
* @return a map entry representation of the priority and suffix string
|
||||
*/
|
||||
@Nonnull
|
||||
Map.Entry<Integer, String> getAsEntry();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.nodetype.types;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.nodetype.NodeType;
|
||||
import me.lucko.luckperms.api.nodetype.NodeTypeKey;
|
||||
|
||||
/**
|
||||
* A sub-type of {@link Node} used to mark the weight of the node's holder.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface WeightType extends NodeType {
|
||||
|
||||
/**
|
||||
* The key for this type.
|
||||
*/
|
||||
NodeTypeKey<WeightType> KEY = new NodeTypeKey<WeightType>(){};
|
||||
|
||||
/**
|
||||
* Gets the weight value.
|
||||
*
|
||||
* @return the weight
|
||||
*/
|
||||
int getWeight();
|
||||
|
||||
}
|
||||
+3
-7
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>4.1-SNAPSHOT</version>
|
||||
<version>4.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -100,10 +100,6 @@
|
||||
<pattern>ninja.leaping.configurate</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.configurate</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.typesafe.config</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.hocon</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
@@ -133,14 +129,14 @@
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>2.6.1</version>
|
||||
<version>2.6.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- HikariCP -->
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>2.7.6</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ package me.lucko.luckperms.bukkit;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.command.CommandManager;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
@@ -45,7 +45,7 @@ public class BukkitCommandExecutor extends CommandManager implements CommandExec
|
||||
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
BukkitCommandExecutor(LPBukkitPlugin plugin) {
|
||||
public BukkitCommandExecutor(LPBukkitPlugin plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@@ -55,11 +55,6 @@ public class BukkitConfigAdapter extends AbstractConfigurationAdapter implements
|
||||
this.configuration = YamlConfiguration.loadConfiguration(this.file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(String path) {
|
||||
return this.configuration.contains(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String path, String def) {
|
||||
return this.configuration.getString(path, def);
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||
import me.lucko.luckperms.common.event.AbstractEventBus;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class BukkitEventBus extends AbstractEventBus<Plugin> implements Listener {
|
||||
public BukkitEventBus(LPBukkitPlugin plugin, LuckPermsApiProvider apiProvider) {
|
||||
super(plugin, apiProvider);
|
||||
|
||||
// register listener
|
||||
LPBukkitBootstrap bootstrap = plugin.getBootstrap();
|
||||
bootstrap.getServer().getPluginManager().registerEvents(this, bootstrap);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Plugin checkPlugin(Object plugin) throws IllegalArgumentException {
|
||||
if (plugin instanceof Plugin) {
|
||||
return (Plugin) plugin;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Object " + plugin + " (" + plugin.getClass().getName() + ") is not a plugin.");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPluginDisable(PluginDisableEvent e) {
|
||||
Plugin plugin = e.getPlugin();
|
||||
unregisterHandlers(plugin);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,7 +29,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||
import me.lucko.luckperms.common.utils.SafeIteration;
|
||||
import me.lucko.luckperms.common.utils.Iterators;
|
||||
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
@@ -45,7 +45,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
||||
private final LPBukkitPlugin plugin;
|
||||
private final LPBukkitBootstrap bootstrap;
|
||||
|
||||
private final ExecutorService asyncFallback;
|
||||
private final Executor asyncBukkit;
|
||||
@@ -56,8 +56,8 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
||||
|
||||
private final Set<SchedulerTask> tasks = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public BukkitSchedulerAdapter(LPBukkitPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
public BukkitSchedulerAdapter(LPBukkitBootstrap bootstrap) {
|
||||
this.bootstrap = bootstrap;
|
||||
|
||||
this.sync = new SyncExecutor();
|
||||
this.asyncFallback = new FallbackAsyncExecutor();
|
||||
@@ -66,7 +66,7 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
||||
}
|
||||
|
||||
private BukkitScheduler scheduler() {
|
||||
return this.plugin.getServer().getScheduler();
|
||||
return this.bootstrap.getServer().getScheduler();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,31 +81,31 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
||||
|
||||
@Override
|
||||
public SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks) {
|
||||
SchedulerTask task = new BukkitSchedulerTask(scheduler().runTaskTimerAsynchronously(this.plugin, runnable, intervalTicks, intervalTicks));
|
||||
SchedulerTask task = new BukkitSchedulerTask(scheduler().runTaskTimerAsynchronously(this.bootstrap, runnable, intervalTicks, intervalTicks));
|
||||
this.tasks.add(task);
|
||||
return task;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchedulerTask syncRepeating(Runnable runnable, long intervalTicks) {
|
||||
SchedulerTask task = new BukkitSchedulerTask(scheduler().runTaskTimer(this.plugin, runnable, intervalTicks, intervalTicks));
|
||||
SchedulerTask task = new BukkitSchedulerTask(scheduler().runTaskTimer(this.bootstrap, runnable, intervalTicks, intervalTicks));
|
||||
this.tasks.add(task);
|
||||
return task;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchedulerTask asyncLater(Runnable runnable, long delayTicks) {
|
||||
return new BukkitSchedulerTask(scheduler().runTaskLaterAsynchronously(this.plugin, runnable, delayTicks));
|
||||
return new BukkitSchedulerTask(scheduler().runTaskLaterAsynchronously(this.bootstrap, runnable, delayTicks));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchedulerTask syncLater(Runnable runnable, long delayTicks) {
|
||||
return new BukkitSchedulerTask(scheduler().runTaskLater(this.plugin, runnable, delayTicks));
|
||||
return new BukkitSchedulerTask(scheduler().runTaskLater(this.bootstrap, runnable, delayTicks));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
SafeIteration.iterate(this.tasks, SchedulerTask::cancel);
|
||||
Iterators.iterate(this.tasks, SchedulerTask::cancel);
|
||||
|
||||
// wait for executor
|
||||
this.asyncFallback.shutdown();
|
||||
@@ -116,15 +116,6 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ExecutorService asyncFallback() {
|
||||
return this.asyncFallback;
|
||||
}
|
||||
|
||||
public Executor asyncBukkit() {
|
||||
return this.asyncBukkit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Executor sync() {
|
||||
return this.sync;
|
||||
@@ -135,6 +126,11 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
||||
return this.async;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Executor platformAsync() {
|
||||
return this.asyncBukkit;
|
||||
}
|
||||
|
||||
public void setUseFallback(boolean useFallback) {
|
||||
this.useFallback = useFallback;
|
||||
}
|
||||
@@ -142,14 +138,14 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
||||
private final class SyncExecutor implements Executor {
|
||||
@Override
|
||||
public void execute(@Nonnull Runnable runnable) {
|
||||
BukkitSchedulerAdapter.this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(BukkitSchedulerAdapter.this.plugin, runnable);
|
||||
BukkitSchedulerAdapter.this.bootstrap.getServer().getScheduler().scheduleSyncDelayedTask(BukkitSchedulerAdapter.this.bootstrap, runnable);
|
||||
}
|
||||
}
|
||||
|
||||
private final class AsyncExecutor implements Executor {
|
||||
@Override
|
||||
public void execute(@Nonnull Runnable runnable) {
|
||||
if (BukkitSchedulerAdapter.this.useFallback || !BukkitSchedulerAdapter.this.plugin.isEnabled()) {
|
||||
if (BukkitSchedulerAdapter.this.useFallback || !BukkitSchedulerAdapter.this.bootstrap.isEnabled()) {
|
||||
BukkitSchedulerAdapter.this.asyncFallback.execute(runnable);
|
||||
} else {
|
||||
BukkitSchedulerAdapter.this.asyncBukkit.execute(runnable);
|
||||
@@ -160,7 +156,7 @@ public class BukkitSchedulerAdapter implements SchedulerAdapter {
|
||||
private final class BukkitAsyncExecutor implements Executor {
|
||||
@Override
|
||||
public void execute(@Nonnull Runnable runnable) {
|
||||
BukkitSchedulerAdapter.this.plugin.getServer().getScheduler().runTaskAsynchronously(BukkitSchedulerAdapter.this.plugin, runnable);
|
||||
BukkitSchedulerAdapter.this.bootstrap.getServer().getScheduler().runTaskAsynchronously(BukkitSchedulerAdapter.this.bootstrap, runnable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.bukkit.compat.BukkitJsonMessageHandler;
|
||||
import me.lucko.luckperms.bukkit.compat.ReflectionUtil;
|
||||
import me.lucko.luckperms.bukkit.compat.SpigotJsonMessageHandler;
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.sender.SenderFactory;
|
||||
import me.lucko.luckperms.common.command.CommandManager;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.SenderFactory;
|
||||
import me.lucko.luckperms.common.utils.TextUtils;
|
||||
|
||||
import net.kyori.text.Component;
|
||||
@@ -79,7 +79,7 @@ public class BukkitSenderFactory extends SenderFactory<CommandSender> {
|
||||
}
|
||||
|
||||
// otherwise, send the message sync
|
||||
getPlugin().getScheduler().doSync(new SyncMessengerAgent(sender, s));
|
||||
getPlugin().getBootstrap().getScheduler().doSync(new SyncMessengerAgent(sender, s));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import me.lucko.luckperms.api.platform.PlatformType;
|
||||
import me.lucko.luckperms.bukkit.compat.NullSafeConsoleCommandSender;
|
||||
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
||||
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
|
||||
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Bootstrap plugin for LuckPerms running on Bukkit.
|
||||
*/
|
||||
public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap {
|
||||
|
||||
/**
|
||||
* A scheduler adapter for the platform
|
||||
*/
|
||||
private final BukkitSchedulerAdapter schedulerAdapter;
|
||||
|
||||
/**
|
||||
* The plugin classloader
|
||||
*/
|
||||
private final PluginClassLoader classLoader;
|
||||
|
||||
/**
|
||||
* A null-safe console instance which delegates to the server logger
|
||||
* if {@link Server#getConsoleSender()} returns null.
|
||||
*/
|
||||
private final ConsoleCommandSender console;
|
||||
|
||||
/**
|
||||
* The plugin instance
|
||||
*/
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
/**
|
||||
* The time when the plugin was enabled
|
||||
*/
|
||||
private long startTime;
|
||||
|
||||
// load/enable latches
|
||||
private final CountDownLatch loadLatch = new CountDownLatch(1);
|
||||
private final CountDownLatch enableLatch = new CountDownLatch(1);
|
||||
|
||||
// if the plugin has been loaded on an incompatible version
|
||||
private boolean incompatibleVersion = false;
|
||||
|
||||
public LPBukkitBootstrap() {
|
||||
this.schedulerAdapter = new BukkitSchedulerAdapter(this);
|
||||
this.classLoader = new ReflectionClassLoader(this);
|
||||
this.console = new NullSafeConsoleCommandSender(getServer());
|
||||
this.plugin = new LPBukkitPlugin(this);
|
||||
}
|
||||
|
||||
// provide adapters
|
||||
|
||||
@Override
|
||||
public BukkitSchedulerAdapter getScheduler() {
|
||||
return this.schedulerAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginClassLoader getPluginClassLoader() {
|
||||
return this.classLoader;
|
||||
}
|
||||
|
||||
public ConsoleCommandSender getConsole() {
|
||||
return this.console;
|
||||
}
|
||||
|
||||
// lifecycle
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
if (checkIncompatibleVersion()) {
|
||||
this.incompatibleVersion = true;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.plugin.load();
|
||||
} finally {
|
||||
this.loadLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
if (this.incompatibleVersion) {
|
||||
getLogger().severe("----------------------------------------------------------------------");
|
||||
getLogger().severe("Your server version is not compatible with this build of LuckPerms. :(");
|
||||
getLogger().severe("");
|
||||
getLogger().severe("If your server is running 1.8, please update to 1.8.8 or higher.");
|
||||
getLogger().severe("If your server is running 1.7.10, please download the Bukkit-Legacy version of LuckPerms from here:");
|
||||
getLogger().severe("==> https://ci.lucko.me/job/LuckPermsLegacy/");
|
||||
getLogger().severe("----------------------------------------------------------------------");
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
this.startTime = System.currentTimeMillis();
|
||||
try {
|
||||
this.plugin.enable();
|
||||
} finally {
|
||||
this.enableLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (this.incompatibleVersion) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.plugin.disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CountDownLatch getEnableLatch() {
|
||||
return this.enableLatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CountDownLatch getLoadLatch() {
|
||||
return this.loadLatch;
|
||||
}
|
||||
|
||||
// provide information about the plugin
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartupTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
// provide information about the platform
|
||||
|
||||
@Override
|
||||
public PlatformType getType() {
|
||||
return PlatformType.BUKKIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerBrand() {
|
||||
return getServer().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersion() {
|
||||
return getServer().getVersion() + " - " + getServer().getBukkitVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerName() {
|
||||
return getServer().getServerName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getDataDirectory() {
|
||||
return getDataFolder().toPath().toAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceStream(String path) {
|
||||
return getResource(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Player> getPlayer(UUID uuid) {
|
||||
return Optional.ofNullable(getServer().getPlayer(uuid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> lookupUuid(String username) {
|
||||
//noinspection deprecation
|
||||
return Optional.ofNullable(getServer().getOfflinePlayer(username)).map(OfflinePlayer::getUniqueId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> lookupUsername(UUID uuid) {
|
||||
return Optional.ofNullable(getServer().getOfflinePlayer(uuid)).map(OfflinePlayer::getName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getServer().getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getPlayerList() {
|
||||
return getServer().getOnlinePlayers().stream().map(Player::getName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<UUID> getOnlinePlayers() {
|
||||
return getServer().getOnlinePlayers().stream().map(Player::getUniqueId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerOnline(UUID uuid) {
|
||||
Player player = getServer().getPlayer(uuid);
|
||||
return player != null && player.isOnline();
|
||||
}
|
||||
|
||||
private static boolean checkIncompatibleVersion() {
|
||||
try {
|
||||
Class.forName("com.google.gson.JsonElement");
|
||||
return false;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ package me.lucko.luckperms.bukkit;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.LuckPermsApi;
|
||||
import me.lucko.luckperms.api.platform.PlatformType;
|
||||
import me.lucko.luckperms.api.event.user.UserDataRecalculateEvent;
|
||||
import me.lucko.luckperms.bukkit.calculators.BukkitCalculatorFactory;
|
||||
import me.lucko.luckperms.bukkit.contexts.BukkitContextManager;
|
||||
import me.lucko.luckperms.bukkit.contexts.WorldCalculator;
|
||||
@@ -44,212 +44,132 @@ 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.actionlog.LogDispatcher;
|
||||
import me.lucko.luckperms.common.api.ApiRegistrationUtil;
|
||||
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||
import me.lucko.luckperms.common.buffers.BufferedRequest;
|
||||
import me.lucko.luckperms.common.buffers.UpdateTaskBuffer;
|
||||
import me.lucko.luckperms.common.caching.handlers.CachedStateManager;
|
||||
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||
import me.lucko.luckperms.common.commands.CommandPermission;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.config.AbstractConfiguration;
|
||||
import me.lucko.luckperms.common.api.delegates.model.ApiUser;
|
||||
import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.config.LuckPermsConfiguration;
|
||||
import me.lucko.luckperms.common.config.adapter.ConfigurationAdapter;
|
||||
import me.lucko.luckperms.common.contexts.ContextManager;
|
||||
import me.lucko.luckperms.common.contexts.LuckPermsCalculator;
|
||||
import me.lucko.luckperms.common.dependencies.DependencyManager;
|
||||
import me.lucko.luckperms.common.dependencies.DependencyRegistry;
|
||||
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
||||
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
|
||||
import me.lucko.luckperms.common.event.EventFactory;
|
||||
import me.lucko.luckperms.common.inheritance.InheritanceHandler;
|
||||
import me.lucko.luckperms.common.locale.LocaleManager;
|
||||
import me.lucko.luckperms.common.locale.NoopLocaleManager;
|
||||
import me.lucko.luckperms.common.locale.SimpleLocaleManager;
|
||||
import me.lucko.luckperms.common.logging.Logger;
|
||||
import me.lucko.luckperms.common.logging.SenderLogger;
|
||||
import me.lucko.luckperms.common.dependencies.Dependency;
|
||||
import me.lucko.luckperms.common.event.AbstractEventBus;
|
||||
import me.lucko.luckperms.common.listener.ConnectionListener;
|
||||
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.InternalMessagingService;
|
||||
import me.lucko.luckperms.common.messaging.MessagingFactory;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.Storage;
|
||||
import me.lucko.luckperms.common.storage.StorageFactory;
|
||||
import me.lucko.luckperms.common.storage.StorageType;
|
||||
import me.lucko.luckperms.common.storage.dao.file.FileWatcher;
|
||||
import me.lucko.luckperms.common.plugin.AbstractLuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
|
||||
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
|
||||
import me.lucko.luckperms.common.tasks.UpdateTask;
|
||||
import me.lucko.luckperms.common.treeview.PermissionVault;
|
||||
import me.lucko.luckperms.common.verbose.VerboseHandler;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* LuckPerms implementation for the Bukkit API.
|
||||
*/
|
||||
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
|
||||
private final LPBukkitBootstrap bootstrap;
|
||||
|
||||
private long startTime;
|
||||
private BukkitSchedulerAdapter scheduler;
|
||||
private BukkitSenderFactory senderFactory;
|
||||
private BukkitConnectionListener connectionListener;
|
||||
private BukkitCommandExecutor commandManager;
|
||||
private VaultHookManager vaultHookManager = null;
|
||||
private LuckPermsConfiguration configuration;
|
||||
private StandardUserManager userManager;
|
||||
private StandardGroupManager groupManager;
|
||||
private StandardTrackManager trackManager;
|
||||
private Storage storage;
|
||||
private FileWatcher fileWatcher = null;
|
||||
private InternalMessagingService messagingService = null;
|
||||
private LuckPermsApiProvider apiProvider;
|
||||
private EventFactory eventFactory;
|
||||
private Logger log;
|
||||
private ContextManager<Player> contextManager;
|
||||
private LPSubscriptionMap subscriptionMap;
|
||||
private LPPermissionMap permissionMap;
|
||||
private LPDefaultsMap defaultPermissionMap;
|
||||
private LocaleManager localeManager;
|
||||
private PluginClassLoader pluginClassLoader;
|
||||
private DependencyManager dependencyManager;
|
||||
private InheritanceHandler inheritanceHandler;
|
||||
private CachedStateManager cachedStateManager;
|
||||
private ContextManager<Player> contextManager;
|
||||
private CalculatorFactory calculatorFactory;
|
||||
private BufferedRequest<Void> updateTaskBuffer;
|
||||
private CountDownLatch enableLatch = new CountDownLatch(1);
|
||||
private VerboseHandler verboseHandler;
|
||||
private BukkitSenderFactory senderFactory;
|
||||
private PermissionVault permissionVault;
|
||||
private LogDispatcher logDispatcher;
|
||||
private Set<UUID> uniqueConnections = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private boolean invalidVersion = false;
|
||||
private VaultHookManager vaultHookManager = null;
|
||||
|
||||
public LPBukkitPlugin(LPBukkitBootstrap bootstrap) {
|
||||
this.bootstrap = bootstrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
if (checkInvalidVersion()) {
|
||||
this.invalidVersion = true;
|
||||
return;
|
||||
}
|
||||
public LPBukkitBootstrap getBootstrap() {
|
||||
return this.bootstrap;
|
||||
}
|
||||
|
||||
// setup minimal functionality in order to load initial dependencies
|
||||
this.scheduler = new BukkitSchedulerAdapter(this);
|
||||
this.localeManager = new NoopLocaleManager();
|
||||
@Override
|
||||
protected void setupSenderFactory() {
|
||||
this.senderFactory = new BukkitSenderFactory(this);
|
||||
this.log = new SenderLogger(this, getConsoleSender());
|
||||
|
||||
this.pluginClassLoader = new ReflectionClassLoader(this);
|
||||
this.dependencyManager = new DependencyManager(this);
|
||||
this.dependencyManager.loadDependencies(DependencyRegistry.GLOBAL_DEPENDENCIES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
if (this.invalidVersion) {
|
||||
getLogger().severe("----------------------------------------------------------------------");
|
||||
getLogger().severe("Your server version is not compatible with this build of LuckPerms. :(");
|
||||
getLogger().severe("");
|
||||
getLogger().severe("If your server is running 1.8, please update to 1.8.8 or higher.");
|
||||
getLogger().severe("If your server is running 1.7.10, please download the Bukkit-Legacy version of LuckPerms from here:");
|
||||
getLogger().severe("==> https://ci.lucko.me/job/LuckPermsLegacy/");
|
||||
getLogger().severe("----------------------------------------------------------------------");
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
enable();
|
||||
} finally {
|
||||
// count down the latch when onEnable has been called
|
||||
// we don't care about the result here
|
||||
this.enableLatch.countDown();
|
||||
}
|
||||
protected Set<Dependency> getGlobalDependencies() {
|
||||
return EnumSet.of(Dependency.CAFFEINE, Dependency.OKIO, Dependency.OKHTTP);
|
||||
}
|
||||
|
||||
private void enable() {
|
||||
this.startTime = System.currentTimeMillis();
|
||||
sendStartupBanner(getConsoleSender());
|
||||
this.verboseHandler = new VerboseHandler(this.scheduler.asyncBukkit());
|
||||
this.permissionVault = new PermissionVault(this.scheduler.asyncBukkit());
|
||||
this.logDispatcher = new LogDispatcher(this);
|
||||
@Override
|
||||
protected ConfigurationAdapter provideConfigurationAdapter() {
|
||||
return new BukkitConfigAdapter(this, resolveConfig());
|
||||
}
|
||||
|
||||
getLog().info("Loading configuration...");
|
||||
this.configuration = new AbstractConfiguration(this, new BukkitConfigAdapter(this, resolveConfig("config.yml")));
|
||||
this.configuration.loadAll();
|
||||
@Override
|
||||
protected void registerPlatformListeners() {
|
||||
this.connectionListener = new BukkitConnectionListener(this);
|
||||
this.bootstrap.getServer().getPluginManager().registerEvents(this.connectionListener, this.bootstrap);
|
||||
this.bootstrap.getServer().getPluginManager().registerEvents(new BukkitPlatformListener(this), this.bootstrap);
|
||||
}
|
||||
|
||||
StorageFactory storageFactory = new StorageFactory(this);
|
||||
Set<StorageType> storageTypes = storageFactory.getRequiredTypes(StorageType.H2);
|
||||
this.dependencyManager.loadStorageDependencies(storageTypes);
|
||||
@Override
|
||||
protected MessagingFactory<?> provideMessagingFactory() {
|
||||
return new BukkitMessagingFactory(this);
|
||||
}
|
||||
|
||||
// register events
|
||||
BukkitConnectionListener connectionListener = new BukkitConnectionListener(this);
|
||||
getServer().getPluginManager().registerEvents(connectionListener, this);
|
||||
getServer().getPluginManager().registerEvents(new BukkitPlatformListener(this), this);
|
||||
|
||||
if (getConfiguration().get(ConfigKeys.WATCH_FILES)) {
|
||||
this.fileWatcher = new FileWatcher(this);
|
||||
getScheduler().asyncRepeating(this.fileWatcher, 30L);
|
||||
}
|
||||
|
||||
// initialise datastore
|
||||
this.storage = storageFactory.getInstance(StorageType.H2);
|
||||
|
||||
// initialise messaging
|
||||
this.messagingService = new BukkitMessagingFactory(this).getInstance();
|
||||
|
||||
// setup the update task buffer
|
||||
this.updateTaskBuffer = new UpdateTaskBuffer(this);
|
||||
|
||||
// load locale
|
||||
this.localeManager = new SimpleLocaleManager();
|
||||
this.localeManager.tryLoad(this, new File(getDataFolder(), "lang.yml"));
|
||||
|
||||
// register commands
|
||||
@Override
|
||||
protected void registerCommands() {
|
||||
this.commandManager = new BukkitCommandExecutor(this);
|
||||
PluginCommand main = getServer().getPluginCommand("luckperms");
|
||||
PluginCommand main = this.bootstrap.getServer().getPluginCommand("luckperms");
|
||||
main.setExecutor(this.commandManager);
|
||||
main.setTabCompleter(this.commandManager);
|
||||
main.setDescription("Manage permissions");
|
||||
main.setAliases(Arrays.asList("lp", "perm", "perms", "permission", "permissions"));
|
||||
}
|
||||
|
||||
// load internal managers
|
||||
getLog().info("Loading internal permission managers...");
|
||||
this.inheritanceHandler = new InheritanceHandler(this);
|
||||
@Override
|
||||
protected void setupManagers() {
|
||||
this.userManager = new StandardUserManager(this);
|
||||
this.groupManager = new StandardGroupManager(this);
|
||||
this.trackManager = new StandardTrackManager(this);
|
||||
this.calculatorFactory = new BukkitCalculatorFactory(this);
|
||||
this.cachedStateManager = new CachedStateManager();
|
||||
}
|
||||
|
||||
// setup context manager
|
||||
@Override
|
||||
protected PlatformCalculatorFactory provideCalculatorFactory() {
|
||||
return new BukkitCalculatorFactory(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupContextManager() {
|
||||
this.contextManager = new BukkitContextManager(this);
|
||||
this.contextManager.registerCalculator(new WorldCalculator(this));
|
||||
this.contextManager.registerStaticCalculator(new LuckPermsCalculator(getConfiguration()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupPlatformHooks() {
|
||||
// inject our own custom permission maps
|
||||
Runnable[] injectors = new Runnable[]{
|
||||
new InjectorSubscriptionMap(this),
|
||||
new InjectorPermissionMap(this),
|
||||
new InjectorDefaultsMap(this)
|
||||
new InjectorDefaultsMap(this),
|
||||
new PermissibleMonitoringInjector(this)
|
||||
};
|
||||
|
||||
for (Runnable injector : injectors) {
|
||||
@@ -257,49 +177,52 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
|
||||
// schedule another injection after all plugins have loaded
|
||||
// the entire pluginmanager instance is replaced by some plugins :(
|
||||
this.scheduler.asyncLater(injector, 1L);
|
||||
this.bootstrap.getScheduler().asyncLater(injector, 1L);
|
||||
}
|
||||
|
||||
// inject verbose handlers into internal bukkit objects
|
||||
new PermissibleMonitoringInjector(this).run();
|
||||
|
||||
// Provide vault support
|
||||
tryVaultHook(false);
|
||||
}
|
||||
|
||||
// register with the LP API
|
||||
this.apiProvider = new LuckPermsApiProvider(this);
|
||||
@Override
|
||||
protected AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider) {
|
||||
return new BukkitEventBus(this, apiProvider);
|
||||
}
|
||||
|
||||
// setup event factory
|
||||
this.eventFactory = new EventFactory(this, this.apiProvider);
|
||||
|
||||
ApiRegistrationUtil.registerProvider(this.apiProvider);
|
||||
getServer().getServicesManager().register(LuckPermsApi.class, this.apiProvider, this, ServicePriority.Normal);
|
||||
|
||||
|
||||
// schedule update tasks
|
||||
int mins = getConfiguration().get(ConfigKeys.SYNC_TIME);
|
||||
if (mins > 0) {
|
||||
long ticks = mins * 60 * 20;
|
||||
this.scheduler.asyncRepeating(() -> this.updateTaskBuffer.request(), ticks);
|
||||
public void tryVaultHook(boolean force) {
|
||||
if (this.vaultHookManager != null) {
|
||||
return; // already hooked
|
||||
}
|
||||
this.scheduler.asyncLater(() -> this.updateTaskBuffer.request(), 40L);
|
||||
|
||||
// run an update instantly.
|
||||
getLog().info("Performing initial data load...");
|
||||
try {
|
||||
new UpdateTask(this, true).run();
|
||||
if (force || this.bootstrap.getServer().getPluginManager().isPluginEnabled("Vault")) {
|
||||
this.vaultHookManager = new VaultHookManager();
|
||||
this.vaultHookManager.hook(this);
|
||||
getLogger().info("Registered Vault permission & chat hook.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.vaultHookManager = null;
|
||||
getLogger().severe("Error occurred whilst hooking into Vault.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerApiOnPlatform(LuckPermsApi api) {
|
||||
this.bootstrap.getServer().getServicesManager().register(LuckPermsApi.class, api, this.bootstrap, ServicePriority.Normal);
|
||||
}
|
||||
|
||||
// register tasks
|
||||
this.scheduler.asyncRepeating(new ExpireTemporaryTask(this), 60L);
|
||||
this.scheduler.asyncRepeating(new CacheHousekeepingTask(this), 2400L);
|
||||
@Override
|
||||
protected void registerHousekeepingTasks() {
|
||||
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 60L);
|
||||
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2400L);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performFinalSetup() {
|
||||
// register permissions
|
||||
try {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
PluginManager pm = this.bootstrap.getServer().getPluginManager();
|
||||
PermissionDefault permDefault = getConfiguration().get(ConfigKeys.COMMANDS_ALLOW_OP) ? PermissionDefault.OP : PermissionDefault.FALSE;
|
||||
|
||||
for (CommandPermission p : CommandPermission.values()) {
|
||||
@@ -309,20 +232,34 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
// this throws an exception if the plugin is /reloaded, grr
|
||||
}
|
||||
|
||||
// remove all operators on startup if they're disabled
|
||||
if (!getConfiguration().get(ConfigKeys.OPS_ENABLED)) {
|
||||
this.scheduler.doSync(() -> getServer().getOperators().forEach(o -> o.setOp(false)));
|
||||
this.bootstrap.getScheduler().platformAsync().execute(() -> {
|
||||
for (OfflinePlayer player : this.bootstrap.getServer().getOperators()) {
|
||||
player.setOp(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// register autoop listener
|
||||
if (getConfiguration().get(ConfigKeys.AUTO_OP)) {
|
||||
getApiProvider().getEventBus().subscribe(UserDataRecalculateEvent.class, event -> {
|
||||
User user = ApiUser.cast(event.getUser());
|
||||
Optional<Player> player = getBootstrap().getPlayer(user.getUuid());
|
||||
player.ifPresent(this::refreshAutoOp);
|
||||
});
|
||||
}
|
||||
|
||||
// replace the temporary executor when the Bukkit one starts
|
||||
getServer().getScheduler().runTaskAsynchronously(this, () -> this.scheduler.setUseFallback(false));
|
||||
this.bootstrap.getServer().getScheduler().runTaskAsynchronously(this.bootstrap, () -> this.bootstrap.getScheduler().setUseFallback(false));
|
||||
|
||||
// Load any online users (in the case of a reload)
|
||||
for (Player player : getServer().getOnlinePlayers()) {
|
||||
this.scheduler.doAsync(() -> {
|
||||
for (Player player : this.bootstrap.getServer().getOnlinePlayers()) {
|
||||
this.bootstrap.getScheduler().doAsync(() -> {
|
||||
try {
|
||||
User user = connectionListener.loadUser(player.getUniqueId(), player.getName());
|
||||
User user = this.connectionListener.loadUser(player.getUniqueId(), player.getName());
|
||||
if (user != null) {
|
||||
this.scheduler.doSync(() -> {
|
||||
this.bootstrap.getScheduler().doSync(() -> {
|
||||
try {
|
||||
LPPermissible lpPermissible = new LPPermissible(player, user, this);
|
||||
PermissibleInjector.inject(player, lpPermissible);
|
||||
@@ -336,24 +273,18 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getLog().info("Successfully enabled. (took " + (System.currentTimeMillis() - this.startTime) + "ms)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (this.invalidVersion) {
|
||||
return;
|
||||
}
|
||||
|
||||
protected void performEarlyDisableTasks() {
|
||||
// Switch back to the fallback executor, the bukkit one won't allow new tasks
|
||||
this.scheduler.setUseFallback(true);
|
||||
|
||||
this.permissionVault.shutdown();
|
||||
this.verboseHandler.shutdown();
|
||||
this.bootstrap.getScheduler().setUseFallback(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removePlatformHooks() {
|
||||
// uninject from players
|
||||
for (Player player : getServer().getOnlinePlayers()) {
|
||||
for (Player player : this.bootstrap.getServer().getOnlinePlayers()) {
|
||||
try {
|
||||
PermissibleInjector.unInject(player, false);
|
||||
} catch (Exception e) {
|
||||
@@ -366,7 +297,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
|
||||
final User user = getUserManager().getIfLoaded(player.getUniqueId());
|
||||
if (user != null) {
|
||||
user.getCachedData().invalidateCaches();
|
||||
user.getCachedData().invalidate();
|
||||
getUserManager().unload(user);
|
||||
}
|
||||
}
|
||||
@@ -376,75 +307,86 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
InjectorPermissionMap.uninject();
|
||||
InjectorDefaultsMap.uninject();
|
||||
|
||||
getLog().info("Closing storage...");
|
||||
this.storage.shutdown();
|
||||
|
||||
if (this.fileWatcher != null) {
|
||||
this.fileWatcher.close();
|
||||
}
|
||||
|
||||
if (this.messagingService != null) {
|
||||
getLog().info("Closing messaging service...");
|
||||
this.messagingService.close();
|
||||
}
|
||||
|
||||
ApiRegistrationUtil.unregisterProvider();
|
||||
getServer().getServicesManager().unregisterAll(this);
|
||||
|
||||
// unhook vault
|
||||
if (this.vaultHookManager != null) {
|
||||
this.vaultHookManager.unhook(this);
|
||||
}
|
||||
|
||||
getLog().info("Shutting down internal scheduler...");
|
||||
this.scheduler.shutdown();
|
||||
|
||||
// Bukkit will do this again when #onDisable completes, but we do it early to prevent NPEs elsewhere.
|
||||
getServer().getScheduler().cancelTasks(this);
|
||||
HandlerList.unregisterAll(this);
|
||||
getLog().info("Goodbye!");
|
||||
}
|
||||
|
||||
public void tryVaultHook(boolean force) {
|
||||
if (this.vaultHookManager != null) {
|
||||
return; // already hooked
|
||||
}
|
||||
|
||||
try {
|
||||
if (force || getServer().getPluginManager().isPluginEnabled("Vault")) {
|
||||
this.vaultHookManager = new VaultHookManager();
|
||||
this.vaultHookManager.hook(this);
|
||||
getLog().info("Registered Vault permission & chat hook.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.vaultHookManager = null;
|
||||
getLog().severe("Error occurred whilst hooking into Vault.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshAutoOp(User user, Player player) {
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void refreshAutoOp(Player player) {
|
||||
if (getConfiguration().get(ConfigKeys.AUTO_OP)) {
|
||||
Map<String, Boolean> backing = user.getCachedData().getPermissionData(this.contextManager.getApplicableContexts(player)).getImmutableBacking();
|
||||
boolean op = Optional.ofNullable(backing.get("luckperms.autoop")).orElse(false);
|
||||
player.setOp(op);
|
||||
User user = getUserManager().getIfLoaded(player.getUniqueId());
|
||||
if (user == null) {
|
||||
player.setOp(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Boolean> permData = user.getCachedData().getPermissionData(this.contextManager.getApplicableContexts(player)).getImmutableBacking();
|
||||
player.setOp(permData.getOrDefault("luckperms.autoop", false));
|
||||
}
|
||||
}
|
||||
|
||||
private File resolveConfig(String file) {
|
||||
File configFile = new File(getDataFolder(), file);
|
||||
|
||||
private File resolveConfig() {
|
||||
File configFile = new File(this.bootstrap.getDataFolder(), "config.yml");
|
||||
if (!configFile.exists()) {
|
||||
getDataFolder().mkdirs();
|
||||
saveResource("config.yml", false);
|
||||
this.bootstrap.getDataFolder().mkdirs();
|
||||
this.bootstrap.saveResource("config.yml", false);
|
||||
}
|
||||
|
||||
return configFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Contexts> getContextForUser(User user) {
|
||||
return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getApplicableContexts(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Sender> getOnlineSenders() {
|
||||
return Stream.concat(
|
||||
Stream.of(getConsoleSender()),
|
||||
this.bootstrap.getServer().getOnlinePlayers().stream().map(p -> getSenderFactory().wrap(p))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return getSenderFactory().wrap(this.bootstrap.getConsole());
|
||||
}
|
||||
|
||||
public BukkitSenderFactory getSenderFactory() {
|
||||
return this.senderFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionListener getConnectionListener() {
|
||||
return this.connectionListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitCommandExecutor getCommandManager() {
|
||||
return this.commandManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardUserManager getUserManager() {
|
||||
return this.userManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardGroupManager getGroupManager() {
|
||||
return this.groupManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardTrackManager getTrackManager() {
|
||||
return this.trackManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextManager<Player> getContextManager() {
|
||||
return this.contextManager;
|
||||
}
|
||||
|
||||
public LPSubscriptionMap getSubscriptionMap() {
|
||||
return this.subscriptionMap;
|
||||
}
|
||||
@@ -469,250 +411,4 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
this.defaultPermissionMap = defaultPermissionMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<InternalMessagingService> getMessagingService() {
|
||||
return Optional.ofNullable(this.messagingService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessagingService(InternalMessagingService messagingService) {
|
||||
if (this.messagingService == null) {
|
||||
this.messagingService = messagingService;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<FileWatcher> getFileWatcher() {
|
||||
return Optional.ofNullable(this.fileWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformType getServerType() {
|
||||
return PlatformType.BUKKIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerBrand() {
|
||||
return getServer().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersion() {
|
||||
return getServer().getVersion() + " - " + getServer().getBukkitVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerName() {
|
||||
return getServer().getServerName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataDirectory() {
|
||||
return super.getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceStream(String path) {
|
||||
return getResource(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer(User user) {
|
||||
return getServer().getPlayer(user.getUuid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> lookupUuid(String username) {
|
||||
try {
|
||||
//noinspection deprecation
|
||||
return Optional.ofNullable(getServer().getOfflinePlayer(username)).flatMap(p -> Optional.ofNullable(p.getUniqueId()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Contexts> getContextForUser(User user) {
|
||||
Player player = getPlayer(user);
|
||||
if (player == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(this.contextManager.getApplicableContexts(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getServer().getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getPlayerList() {
|
||||
return getServer().getOnlinePlayers().stream().map(Player::getName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<UUID> getOnlinePlayers() {
|
||||
return getServer().getOnlinePlayers().stream().map(Player::getUniqueId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerOnline(UUID external) {
|
||||
Player player = getServer().getPlayer(external);
|
||||
return player != null && player.isOnline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Sender> getOnlineSenders() {
|
||||
return Stream.concat(
|
||||
Stream.of(getConsoleSender()),
|
||||
getServer().getOnlinePlayers().stream().map(p -> getSenderFactory().wrap(p))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return getSenderFactory().wrap(getServer().getConsoleSender());
|
||||
}
|
||||
|
||||
private static boolean checkInvalidVersion() {
|
||||
try {
|
||||
Class.forName("com.google.gson.JsonElement");
|
||||
return false;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitSchedulerAdapter getScheduler() {
|
||||
return this.scheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitCommandExecutor getCommandManager() {
|
||||
return this.commandManager;
|
||||
}
|
||||
|
||||
public VaultHookManager getVaultHookManager() {
|
||||
return this.vaultHookManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LuckPermsConfiguration getConfiguration() {
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardUserManager getUserManager() {
|
||||
return this.userManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardGroupManager getGroupManager() {
|
||||
return this.groupManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardTrackManager getTrackManager() {
|
||||
return this.trackManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Storage getStorage() {
|
||||
return this.storage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LuckPermsApiProvider getApiProvider() {
|
||||
return this.apiProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventFactory getEventFactory() {
|
||||
return this.eventFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLog() {
|
||||
return this.log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleManager getLocaleManager() {
|
||||
return this.localeManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginClassLoader getPluginClassLoader() {
|
||||
return this.pluginClassLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DependencyManager getDependencyManager() {
|
||||
return this.dependencyManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedStateManager getCachedStateManager() {
|
||||
return this.cachedStateManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextManager<Player> getContextManager() {
|
||||
return this.contextManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InheritanceHandler getInheritanceHandler() {
|
||||
return this.inheritanceHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculatorFactory getCalculatorFactory() {
|
||||
return this.calculatorFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedRequest<Void> getUpdateTaskBuffer() {
|
||||
return this.updateTaskBuffer;
|
||||
}
|
||||
|
||||
public CountDownLatch getEnableLatch() {
|
||||
return this.enableLatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerboseHandler getVerboseHandler() {
|
||||
return this.verboseHandler;
|
||||
}
|
||||
|
||||
public BukkitSenderFactory getSenderFactory() {
|
||||
return this.senderFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionVault getPermissionVault() {
|
||||
return this.permissionVault;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogDispatcher getLogDispatcher() {
|
||||
return this.logDispatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueConnections() {
|
||||
return this.uniqueConnections;
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -28,6 +28,7 @@ package me.lucko.luckperms.bukkit.calculators;
|
||||
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;
|
||||
@@ -35,11 +36,11 @@ import me.lucko.luckperms.common.calculators.AbstractCalculatorFactory;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculator;
|
||||
import me.lucko.luckperms.common.calculators.PermissionCalculatorMetadata;
|
||||
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;
|
||||
import me.lucko.luckperms.common.references.HolderType;
|
||||
|
||||
public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
|
||||
private final LPBukkitPlugin plugin;
|
||||
@@ -67,7 +68,7 @@ public class BukkitCalculatorFactory extends AbstractCalculatorFactory {
|
||||
}
|
||||
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.APPLY_BUKKIT_DEFAULT_PERMISSIONS) && metadata.getHolderType() == HolderType.USER) {
|
||||
processors.add(new DefaultsProcessor(this.plugin, contexts.isOp()));
|
||||
processors.add(new DefaultsProcessor(this.plugin, contexts.hasSetting(LookupSetting.IS_OP)));
|
||||
}
|
||||
|
||||
return registerCalculator(new PermissionCalculator(this.plugin, metadata, processors.build()));
|
||||
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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.ChatColor;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.conversations.Conversation;
|
||||
import org.bukkit.conversations.ConversationAbandonedEvent;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The {@link Server#getConsoleSender()} method returns null during onEnable
|
||||
* in older CraftBukkit builds. This prevents LuckPerms from loading correctly.
|
||||
*/
|
||||
public class NullSafeConsoleCommandSender implements ConsoleCommandSender {
|
||||
private final Server server;
|
||||
|
||||
public NullSafeConsoleCommandSender(Server server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
private Optional<ConsoleCommandSender> get() {
|
||||
return Optional.ofNullable(this.server.getConsoleSender());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Server getServer() {
|
||||
return this.server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "CONSOLE";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
Optional<ConsoleCommandSender> console = get();
|
||||
if (console.isPresent()) {
|
||||
console.get().sendMessage(message);
|
||||
} else {
|
||||
this.server.getLogger().info(ChatColor.stripColor(message));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String[] messages) {
|
||||
for (String msg : messages) {
|
||||
sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(String s) {
|
||||
return get().map(c -> c.isPermissionSet(s)).orElse(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(Permission permission) {
|
||||
return get().map(c -> c.isPermissionSet(permission)).orElse(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String s) {
|
||||
return get().map(c -> c.hasPermission(s)).orElse(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Permission permission) {
|
||||
return get().map(c -> c.hasPermission(permission)).orElse(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// just throw UnsupportedOperationException - we never use any of these methods
|
||||
@Override public Spigot spigot() { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean isConversing() { throw new UnsupportedOperationException(); }
|
||||
@Override public void acceptConversationInput(String s) { throw new UnsupportedOperationException(); }
|
||||
@Override public boolean beginConversation(Conversation conversation) { throw new UnsupportedOperationException(); }
|
||||
@Override public void abandonConversation(Conversation conversation) { throw new UnsupportedOperationException(); }
|
||||
@Override public void abandonConversation(Conversation conversation, ConversationAbandonedEvent conversationAbandonedEvent) { throw new UnsupportedOperationException(); }
|
||||
@Override public void sendRawMessage(String s) { throw new UnsupportedOperationException(); }
|
||||
@Override public PermissionAttachment addAttachment(Plugin plugin, String s, boolean b) { throw new UnsupportedOperationException(); }
|
||||
@Override public PermissionAttachment addAttachment(Plugin plugin) { throw new UnsupportedOperationException(); }
|
||||
@Override public PermissionAttachment addAttachment(Plugin plugin, String s, boolean b, int i) { throw new UnsupportedOperationException(); }
|
||||
@Override public PermissionAttachment addAttachment(Plugin plugin, int i) { throw new UnsupportedOperationException(); }
|
||||
@Override public void removeAttachment(PermissionAttachment permissionAttachment) { throw new UnsupportedOperationException(); }
|
||||
@Override public void recalculatePermissions() { throw new UnsupportedOperationException(); }
|
||||
@Override public Set<PermissionAttachmentInfo> getEffectivePermissions() { throw new UnsupportedOperationException(); }
|
||||
@Override public void setOp(boolean b) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
@@ -28,10 +28,10 @@ package me.lucko.luckperms.bukkit.compat;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public final class ReflectionUtil {
|
||||
private static final String SERVER_VERSION = _getServerVersion();
|
||||
private static final String SERVER_VERSION = getServerVersion();
|
||||
private static final boolean CHAT_COMPATIBLE = !SERVER_VERSION.startsWith(".v1_7_");
|
||||
|
||||
private static String _getServerVersion() {
|
||||
private static String getServerVersion() {
|
||||
Class<?> server = Bukkit.getServer().getClass();
|
||||
if (!server.getSimpleName().equals("CraftServer")) {
|
||||
return ".";
|
||||
@@ -45,16 +45,12 @@ public final class ReflectionUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static String getServerVersion() {
|
||||
return SERVER_VERSION;
|
||||
}
|
||||
|
||||
public static boolean isChatCompatible() {
|
||||
return CHAT_COMPATIBLE;
|
||||
}
|
||||
|
||||
public static String nms(String className) {
|
||||
return "net.minecraft.server" + getServerVersion() + className;
|
||||
return "net.minecraft.server" + SERVER_VERSION + className;
|
||||
}
|
||||
|
||||
public static Class<?> nmsClass(String className) throws ClassNotFoundException {
|
||||
@@ -62,7 +58,7 @@ public final class ReflectionUtil {
|
||||
}
|
||||
|
||||
public static String obc(String className) {
|
||||
return "org.bukkit.craftbukkit" + getServerVersion() + className;
|
||||
return "org.bukkit.craftbukkit" + SERVER_VERSION + className;
|
||||
}
|
||||
|
||||
public static Class<?> obcClass(String className) throws ClassNotFoundException {
|
||||
|
||||
@@ -40,7 +40,7 @@ public class BukkitContextManager extends AbstractContextManager<Player> {
|
||||
|
||||
@Override
|
||||
public Contexts formContexts(Player subject, ImmutableContextSet contextSet) {
|
||||
return new Contexts(
|
||||
return Contexts.of(
|
||||
contextSet,
|
||||
this.plugin.getConfiguration().get(ConfigKeys.INCLUDING_GLOBAL_PERMS),
|
||||
this.plugin.getConfiguration().get(ConfigKeys.INCLUDING_GLOBAL_WORLD_PERMS),
|
||||
|
||||
+13
-24
@@ -29,9 +29,9 @@ 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.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.listener.AbstractConnectionListener;
|
||||
import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.utils.AbstractLoginListener;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -47,7 +47,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BukkitConnectionListener extends AbstractLoginListener implements Listener {
|
||||
public class BukkitConnectionListener extends AbstractConnectionListener implements Listener {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
private final Set<UUID> deniedAsyncLogin = Collections.synchronizedSet(new HashSet<>());
|
||||
@@ -66,16 +66,16 @@ public class BukkitConnectionListener extends AbstractLoginListener implements L
|
||||
/* wait for the plugin to enable. because these events are fired async, they can be called before
|
||||
the plugin has enabled. */
|
||||
try {
|
||||
this.plugin.getEnableLatch().await(60, TimeUnit.SECONDS);
|
||||
this.plugin.getBootstrap().getEnableLatch().await(60, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
|
||||
this.plugin.getLog().info("Processing pre-login for " + e.getUniqueId() + " - " + e.getName());
|
||||
this.plugin.getLogger().info("Processing pre-login for " + e.getUniqueId() + " - " + e.getName());
|
||||
}
|
||||
|
||||
this.plugin.getUniqueConnections().add(e.getUniqueId());
|
||||
recordConnection(e.getUniqueId());
|
||||
|
||||
/* Actually process the login for the connection.
|
||||
We do this here to delay the login until the data is ready.
|
||||
@@ -90,7 +90,7 @@ public class BukkitConnectionListener extends AbstractLoginListener implements L
|
||||
User user = loadUser(e.getUniqueId(), e.getName());
|
||||
this.plugin.getEventFactory().handleUserLoginProcess(e.getUniqueId(), e.getName(), user);
|
||||
} catch (Exception ex) {
|
||||
this.plugin.getLog().severe("Exception occurred whilst loading data for " + e.getUniqueId() + " - " + e.getName());
|
||||
this.plugin.getLogger().severe("Exception occurred whilst loading data for " + e.getUniqueId() + " - " + e.getName());
|
||||
ex.printStackTrace();
|
||||
|
||||
// deny the connection
|
||||
@@ -110,7 +110,7 @@ public class BukkitConnectionListener extends AbstractLoginListener implements L
|
||||
|
||||
// This is a problem, as they were denied at low priority, but are now being allowed.
|
||||
if (e.getLoginResult() == AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
||||
this.plugin.getLog().severe("Player connection was re-allowed for " + e.getUniqueId());
|
||||
this.plugin.getLogger().severe("Player connection was re-allowed for " + e.getUniqueId());
|
||||
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, "");
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ public class BukkitConnectionListener extends AbstractLoginListener implements L
|
||||
final Player player = e.getPlayer();
|
||||
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
|
||||
this.plugin.getLog().info("Processing login for " + player.getUniqueId() + " - " + player.getName());
|
||||
this.plugin.getLogger().info("Processing login for " + player.getUniqueId() + " - " + player.getName());
|
||||
}
|
||||
|
||||
final User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
||||
@@ -133,7 +133,7 @@ public class BukkitConnectionListener extends AbstractLoginListener implements L
|
||||
if (user == null) {
|
||||
this.deniedLogin.add(e.getPlayer().getUniqueId());
|
||||
|
||||
this.plugin.getLog().warn("User " + player.getUniqueId() + " - " + player.getName() + " doesn't have data pre-loaded. - denying login.");
|
||||
this.plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getName() + " doesn't have data pre-loaded. - denying login.");
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.asString(this.plugin.getLocaleManager()));
|
||||
return;
|
||||
}
|
||||
@@ -151,7 +151,7 @@ public class BukkitConnectionListener extends AbstractLoginListener implements L
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
||||
this.plugin.refreshAutoOp(user, player);
|
||||
this.plugin.refreshAutoOp(player);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
@@ -160,24 +160,13 @@ public class BukkitConnectionListener extends AbstractLoginListener implements L
|
||||
If the connection was cancelled here, we need to do something to clean up the data that was loaded. */
|
||||
|
||||
// Check to see if this connection was denied at LOW. Even if it was denied at LOW, their data will still be present.
|
||||
boolean denied = false;
|
||||
if (this.deniedLogin.remove(e.getPlayer().getUniqueId())) {
|
||||
denied = true;
|
||||
|
||||
// This is a problem, as they were denied at low priority, but are now being allowed.
|
||||
if (e.getResult() == PlayerLoginEvent.Result.ALLOWED) {
|
||||
this.plugin.getLog().severe("Player connection was re-allowed for " + e.getPlayer().getUniqueId());
|
||||
this.plugin.getLogger().severe("Player connection was re-allowed for " + e.getPlayer().getUniqueId());
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, "");
|
||||
}
|
||||
}
|
||||
|
||||
// Login event was cancelled by another plugin since we first loaded their data
|
||||
if (denied || e.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// everything is going well. login was processed ok, this is just to refresh auto-op status.
|
||||
this.plugin.refreshAutoOp(this.plugin.getUserManager().getIfLoaded(e.getPlayer().getUniqueId()), e.getPlayer());
|
||||
}
|
||||
|
||||
// Wait until the last priority to unload, so plugins can still perform permission checks on this event
|
||||
@@ -202,7 +191,7 @@ public class BukkitConnectionListener extends AbstractLoginListener implements L
|
||||
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
||||
|
||||
// force a clear of transient nodes
|
||||
this.plugin.getScheduler().doAsync(() -> {
|
||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
||||
if (user != null) {
|
||||
user.clearTransientNodes();
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ package me.lucko.luckperms.bukkit.listeners;
|
||||
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.locale.message.Message;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Cancellable;
|
||||
@@ -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(this.plugin.getUserManager().getIfLoaded(e.getPlayer().getUniqueId()), e.getPlayer());
|
||||
this.plugin.refreshAutoOp(e.getPlayer());
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -49,8 +49,8 @@ public class BukkitMessagingFactory extends MessagingFactory<LPBukkitPlugin> {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (messagingType.equals("lilypad")) {
|
||||
if (getPlugin().getServer().getPluginManager().getPlugin("LilyPad-Connect") == null) {
|
||||
getPlugin().getLog().warn("LilyPad-Connect plugin not present.");
|
||||
if (getPlugin().getBootstrap().getServer().getPluginManager().getPlugin("LilyPad-Connect") == null) {
|
||||
getPlugin().getLogger().warn("LilyPad-Connect plugin not present.");
|
||||
} else {
|
||||
try {
|
||||
return new LuckPermsMessagingService(getPlugin(), new LilyPadMessengerProvider());
|
||||
|
||||
@@ -58,14 +58,14 @@ public class BungeeMessenger implements Messenger, PluginMessageListener {
|
||||
}
|
||||
|
||||
public void init() {
|
||||
this.plugin.getServer().getMessenger().registerOutgoingPluginChannel(this.plugin, CHANNEL);
|
||||
this.plugin.getServer().getMessenger().registerIncomingPluginChannel(this.plugin, CHANNEL, this);
|
||||
this.plugin.getBootstrap().getServer().getMessenger().registerOutgoingPluginChannel(this.plugin.getBootstrap(), CHANNEL);
|
||||
this.plugin.getBootstrap().getServer().getMessenger().registerIncomingPluginChannel(this.plugin.getBootstrap(), CHANNEL, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.plugin.getServer().getMessenger().unregisterIncomingPluginChannel(this.plugin, CHANNEL);
|
||||
this.plugin.getServer().getMessenger().unregisterOutgoingPluginChannel(this.plugin, CHANNEL);
|
||||
this.plugin.getBootstrap().getServer().getMessenger().unregisterIncomingPluginChannel(this.plugin.getBootstrap(), CHANNEL);
|
||||
this.plugin.getBootstrap().getServer().getMessenger().unregisterOutgoingPluginChannel(this.plugin.getBootstrap(), CHANNEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,7 +73,7 @@ public class BungeeMessenger implements Messenger, PluginMessageListener {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Collection<? extends Player> players = BungeeMessenger.this.plugin.getServer().getOnlinePlayers();
|
||||
Collection<? extends Player> players = BungeeMessenger.this.plugin.getBootstrap().getServer().getOnlinePlayers();
|
||||
Player p = Iterables.getFirst(players, null);
|
||||
if (p == null) {
|
||||
return;
|
||||
@@ -84,10 +84,10 @@ public class BungeeMessenger implements Messenger, PluginMessageListener {
|
||||
|
||||
byte[] data = out.toByteArray();
|
||||
|
||||
p.sendPluginMessage(BungeeMessenger.this.plugin, CHANNEL, data);
|
||||
p.sendPluginMessage(BungeeMessenger.this.plugin.getBootstrap(), CHANNEL, data);
|
||||
cancel();
|
||||
}
|
||||
}.runTaskTimer(this.plugin, 1L, 100L);
|
||||
}.runTaskTimer(this.plugin.getBootstrap(), 1L, 100L);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -58,7 +58,7 @@ public class LilyPadMessenger implements Messenger {
|
||||
}
|
||||
|
||||
public void init() {
|
||||
this.connect = this.plugin.getServer().getServicesManager().getRegistration(Connect.class).getProvider();
|
||||
this.connect = this.plugin.getBootstrap().getServer().getServicesManager().getRegistration(Connect.class).getProvider();
|
||||
this.connect.registerEvents(this);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class LilyPadMessenger implements Messenger {
|
||||
|
||||
@EventListener
|
||||
public void onMessage(MessageEvent event) {
|
||||
this.plugin.getScheduler().doAsync(() -> {
|
||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
try {
|
||||
String channel = event.getChannel();
|
||||
|
||||
|
||||
+4
-4
@@ -32,24 +32,24 @@ import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class BukkitMigrationUtils {
|
||||
public final class BukkitUuids {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static UUID lookupUuid(ProgressLogger log, String s) {
|
||||
UUID uuid = Uuids.parseNullable(s);
|
||||
if (uuid == null) {
|
||||
try {
|
||||
//noinspection deprecation
|
||||
uuid = Bukkit.getOfflinePlayer(s).getUniqueId();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (uuid == null) {
|
||||
log.logErr("Unable to get a UUID for user identifier: " + s);
|
||||
log.logError("Unable to get a UUID for user identifier: " + s);
|
||||
}
|
||||
return uuid;
|
||||
}
|
||||
|
||||
private BukkitMigrationUtils() {}
|
||||
private BukkitUuids() {}
|
||||
|
||||
}
|
||||
+17
-16
@@ -33,20 +33,21 @@ import de.bananaco.bpermissions.api.WorldManager;
|
||||
|
||||
import me.lucko.luckperms.api.ChatMetaType;
|
||||
import me.lucko.luckperms.api.event.cause.CreationCause;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.abstraction.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.locale.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.SubCommand;
|
||||
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.logging.ProgressLogger;
|
||||
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.NodeFactory;
|
||||
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.SafeIteration;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
@@ -58,7 +59,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static me.lucko.luckperms.common.commands.CommandPermission.MIGRATION;
|
||||
import static me.lucko.luckperms.common.command.access.CommandPermission.MIGRATION;
|
||||
|
||||
public class MigrationBPermissions extends SubCommand<Object> {
|
||||
private static final Field UCONFIG_FIELD;
|
||||
@@ -72,7 +73,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
|
||||
}
|
||||
|
||||
public MigrationBPermissions(LocaleManager locale) {
|
||||
super(CommandSpec.MIGRATION_COMMAND.spec(locale), "bpermissions", MIGRATION, Predicates.alwaysFalse());
|
||||
super(CommandSpec.MIGRATION_COMMAND.localize(locale), "bpermissions", MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,7 +86,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
|
||||
|
||||
WorldManager worldManager = WorldManager.getInstance();
|
||||
if (worldManager == null) {
|
||||
log.logErr("Plugin not loaded.");
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -111,7 +112,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
|
||||
|
||||
Set<String> users = configSection.getKeys(false);
|
||||
if (users == null) {
|
||||
log.logErr("Couldn't get a list of users.");
|
||||
log.logError("Couldn't get a list of users.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
AtomicInteger userLoadCount = new AtomicInteger(0);
|
||||
@@ -124,14 +125,14 @@ public class MigrationBPermissions extends SubCommand<Object> {
|
||||
|
||||
// Migrate one world at a time.
|
||||
log.log("Starting world migration.");
|
||||
SafeIteration.iterate(worldManager.getAllWorlds(), world -> {
|
||||
Iterators.iterate(worldManager.getAllWorlds(), world -> {
|
||||
log.log("Migrating world: " + world.getName());
|
||||
|
||||
// Migrate all groups
|
||||
log.log("Starting group migration in world " + world.getName() + ".");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
|
||||
SafeIteration.iterate(world.getAll(CalculableType.GROUP), group -> {
|
||||
Iterators.iterate(world.getAll(CalculableType.GROUP), group -> {
|
||||
String groupName = MigrationUtils.standardizeName(group.getName());
|
||||
if (group.getName().equalsIgnoreCase(world.getDefaultGroup())) {
|
||||
groupName = NodeFactory.DEFAULT_GROUP_NAME;
|
||||
@@ -153,9 +154,9 @@ public class MigrationBPermissions extends SubCommand<Object> {
|
||||
// Migrate all users
|
||||
log.log("Starting user migration in world " + world.getName() + ".");
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
SafeIteration.iterate(world.getAll(CalculableType.USER), user -> {
|
||||
Iterators.iterate(world.getAll(CalculableType.USER), user -> {
|
||||
// There is no mention of UUIDs in the API. I assume that name = uuid. idk?
|
||||
UUID uuid = BukkitMigrationUtils.lookupUuid(log, user.getName());
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, user.getName());
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
@@ -212,7 +213,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (meta.getKey().equalsIgnoreCase(NodeFactory.PREFIX_KEY) || meta.getKey().equalsIgnoreCase(NodeFactory.SUFFIX_KEY)) {
|
||||
if (meta.getKey().equalsIgnoreCase(NodeTypes.PREFIX_KEY) || meta.getKey().equalsIgnoreCase(NodeTypes.SUFFIX_KEY)) {
|
||||
ChatMetaType type = ChatMetaType.valueOf(meta.getKey().toUpperCase());
|
||||
holder.setPermission(NodeFactory.buildChatMetaNode(type, c.getPriority(), meta.getValue()).setWorld(world.getName()).build());
|
||||
continue;
|
||||
|
||||
+38
-28
@@ -28,20 +28,23 @@ package me.lucko.luckperms.bukkit.migration;
|
||||
import me.lucko.luckperms.api.ChatMetaType;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.event.cause.CreationCause;
|
||||
import me.lucko.luckperms.common.commands.CommandPermission;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.abstraction.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.locale.CommandSpec;
|
||||
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.logging.ProgressLogger;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
import me.lucko.luckperms.common.model.UserIdentifier;
|
||||
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.SafeIteration;
|
||||
import me.lucko.luckperms.common.utils.Uuids;
|
||||
|
||||
import org.anjocaido.groupmanager.GlobalGroups;
|
||||
import org.anjocaido.groupmanager.GroupManager;
|
||||
@@ -62,7 +65,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class MigrationGroupManager extends SubCommand<Object> {
|
||||
public MigrationGroupManager(LocaleManager locale) {
|
||||
super(CommandSpec.MIGRATION_GROUPMANAGER.spec(locale), "groupmanager", CommandPermission.MIGRATION, Predicates.is(0));
|
||||
super(CommandSpec.MIGRATION_GROUPMANAGER.localize(locale), "groupmanager", CommandPermission.MIGRATION, Predicates.is(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,14 +77,14 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
log.log("Starting.");
|
||||
|
||||
if (!args.get(0).equalsIgnoreCase("true") && !args.get(0).equalsIgnoreCase("false")) {
|
||||
log.logErr("Was expecting true/false, but got " + args.get(0) + " instead.");
|
||||
log.logError("Was expecting true/false, but got " + args.get(0) + " instead.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
final boolean migrateAsGlobal = Boolean.parseBoolean(args.get(0));
|
||||
final Function<String, String> worldMappingFunc = s -> migrateAsGlobal ? null : s;
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("GroupManager")) {
|
||||
log.logErr("Plugin not loaded.");
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -93,7 +96,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
GlobalGroups gg = GroupManager.getGlobalGroups();
|
||||
|
||||
AtomicInteger globalGroupCount = new AtomicInteger(0);
|
||||
SafeIteration.iterate(gg.getGroupList(), g -> {
|
||||
Iterators.iterate(gg.getGroupList(), g -> {
|
||||
String groupName = MigrationUtils.standardizeName(g.getName());
|
||||
Group group = plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
|
||||
|
||||
@@ -112,7 +115,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
log.log("Migrated " + globalGroupCount.get() + " global groups");
|
||||
|
||||
// Collect data
|
||||
Map<UUID, Set<Node>> users = new HashMap<>();
|
||||
Map<UserIdentifier, Set<Node>> users = new HashMap<>();
|
||||
Map<UUID, String> primaryGroups = new HashMap<>();
|
||||
Map<String, Set<Node>> groups = new HashMap<>();
|
||||
|
||||
@@ -120,13 +123,13 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
|
||||
// Collect data for all users and groups.
|
||||
log.log("Collecting user and group data.");
|
||||
SafeIteration.iterate(worlds, String::toLowerCase, world -> {
|
||||
Iterators.iterate(worlds, String::toLowerCase, world -> {
|
||||
log.log("Querying world " + world);
|
||||
|
||||
WorldDataHolder wdh = wh.getWorldData(world);
|
||||
|
||||
AtomicInteger groupWorldCount = new AtomicInteger(0);
|
||||
SafeIteration.iterate(wdh.getGroupList(), group -> {
|
||||
Iterators.iterate(wdh.getGroupList(), group -> {
|
||||
String groupName = MigrationUtils.standardizeName(group.getName());
|
||||
|
||||
groups.putIfAbsent(groupName, new HashSet<>());
|
||||
@@ -147,7 +150,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
if (key.isEmpty() || value.isEmpty()) continue;
|
||||
if (key.equals("build")) continue;
|
||||
|
||||
if (key.equals(NodeFactory.PREFIX_KEY) || key.equals(NodeFactory.SUFFIX_KEY)) {
|
||||
if (key.equals(NodeTypes.PREFIX_KEY) || key.equals(NodeTypes.SUFFIX_KEY)) {
|
||||
ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase());
|
||||
groups.get(groupName).add(NodeFactory.buildChatMetaNode(type, 50, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
} else {
|
||||
@@ -160,22 +163,29 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
log.log("Migrated " + groupWorldCount.get() + " groups in world " + world);
|
||||
|
||||
AtomicInteger userWorldCount = new AtomicInteger(0);
|
||||
SafeIteration.iterate(wdh.getUserList(), user -> {
|
||||
UUID uuid = BukkitMigrationUtils.lookupUuid(log, user.getUUID());
|
||||
Iterators.iterate(wdh.getUserList(), user -> {
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, user.getUUID());
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
users.putIfAbsent(uuid, new HashSet<>());
|
||||
String lastName = user.getLastName();
|
||||
if (Uuids.parse(lastName).isPresent()) {
|
||||
lastName = null;
|
||||
}
|
||||
|
||||
UserIdentifier id = UserIdentifier.of(uuid, lastName);
|
||||
|
||||
users.putIfAbsent(id, new HashSet<>());
|
||||
|
||||
for (String node : user.getPermissionList()) {
|
||||
if (node.isEmpty()) continue;
|
||||
users.get(uuid).add(MigrationUtils.parseNode(node, true).setWorld(worldMappingFunc.apply(world)).build());
|
||||
users.get(id).add(MigrationUtils.parseNode(node, true).setWorld(worldMappingFunc.apply(world)).build());
|
||||
}
|
||||
|
||||
// Collect sub groups
|
||||
String finalWorld = worldMappingFunc.apply(world);
|
||||
users.get(uuid).addAll(user.subGroupListStringCopy().stream()
|
||||
users.get(id).addAll(user.subGroupListStringCopy().stream()
|
||||
.filter(n -> !n.isEmpty())
|
||||
.map(n -> NodeFactory.groupNode(MigrationUtils.standardizeName(n)))
|
||||
.map(n -> NodeFactory.make(n, true, null, finalWorld))
|
||||
@@ -192,11 +202,11 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
if (key.isEmpty() || value.isEmpty()) continue;
|
||||
if (key.equals("build")) continue;
|
||||
|
||||
if (key.equals(NodeFactory.PREFIX_KEY) || key.equals(NodeFactory.SUFFIX_KEY)) {
|
||||
if (key.equals(NodeTypes.PREFIX_KEY) || key.equals(NodeTypes.SUFFIX_KEY)) {
|
||||
ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase());
|
||||
users.get(uuid).add(NodeFactory.buildChatMetaNode(type, 100, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
users.get(id).add(NodeFactory.buildChatMetaNode(type, 100, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
} else {
|
||||
users.get(uuid).add(NodeFactory.buildMetaNode(key, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
users.get(id).add(NodeFactory.buildMetaNode(key, value).setWorld(worldMappingFunc.apply(world)).build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +220,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
|
||||
log.log("Starting group migration.");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
SafeIteration.iterate(groups.entrySet(), e -> {
|
||||
Iterators.iterate(groups.entrySet(), e -> {
|
||||
Group group = plugin.getStorage().createAndLoadGroup(e.getKey(), CreationCause.INTERNAL).join();
|
||||
|
||||
for (Node node : e.getValue()) {
|
||||
@@ -224,14 +234,14 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
|
||||
log.log("Starting user migration.");
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
SafeIteration.iterate(users.entrySet(), e -> {
|
||||
User user = plugin.getStorage().loadUser(e.getKey(), null).join();
|
||||
Iterators.iterate(users.entrySet(), e -> {
|
||||
User user = plugin.getStorage().loadUser(e.getKey().getUuid(), e.getKey().getUsername().orElse(null)).join();
|
||||
|
||||
for (Node node : e.getValue()) {
|
||||
user.setPermission(node);
|
||||
}
|
||||
|
||||
String primaryGroup = primaryGroups.get(e.getKey());
|
||||
String primaryGroup = primaryGroups.get(e.getKey().getUuid());
|
||||
if (primaryGroup != null && !primaryGroup.isEmpty()) {
|
||||
user.setPermission(NodeFactory.buildGroupNode(primaryGroup).build());
|
||||
user.getPrimaryGroup().setStoredValue(primaryGroup);
|
||||
|
||||
+13
-13
@@ -28,21 +28,21 @@ package me.lucko.luckperms.bukkit.migration;
|
||||
import com.platymuus.bukkit.permissions.PermissionsPlugin;
|
||||
|
||||
import me.lucko.luckperms.api.event.cause.CreationCause;
|
||||
import me.lucko.luckperms.common.commands.CommandPermission;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.abstraction.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.locale.CommandSpec;
|
||||
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.logging.ProgressLogger;
|
||||
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.NodeFactory;
|
||||
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.SafeIteration;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@@ -54,7 +54,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class MigrationPermissionsBukkit extends SubCommand<Object> {
|
||||
public MigrationPermissionsBukkit(LocaleManager locale) {
|
||||
super(CommandSpec.MIGRATION_COMMAND.spec(locale), "permissionsbukkit", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
super(CommandSpec.MIGRATION_COMMAND.localize(locale), "permissionsbukkit", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,7 +66,7 @@ public class MigrationPermissionsBukkit extends SubCommand<Object> {
|
||||
log.log("Starting.");
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("PermissionsBukkit")) {
|
||||
log.logErr("Plugin not loaded.");
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class MigrationPermissionsBukkit extends SubCommand<Object> {
|
||||
|
||||
ConfigurationSection groupsSection = config.getConfigurationSection("groups");
|
||||
|
||||
SafeIteration.iterate(groupsSection.getKeys(false), key -> {
|
||||
Iterators.iterate(groupsSection.getKeys(false), key -> {
|
||||
final String groupName = MigrationUtils.standardizeName(key);
|
||||
Group lpGroup = plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
|
||||
|
||||
@@ -99,8 +99,8 @@ public class MigrationPermissionsBukkit extends SubCommand<Object> {
|
||||
|
||||
ConfigurationSection usersSection = config.getConfigurationSection("users");
|
||||
|
||||
SafeIteration.iterate(usersSection.getKeys(false), key -> {
|
||||
UUID uuid = BukkitMigrationUtils.lookupUuid(log, key);
|
||||
Iterators.iterate(usersSection.getKeys(false), key -> {
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, key);
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
+17
-16
@@ -28,22 +28,23 @@ package me.lucko.luckperms.bukkit.migration;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import me.lucko.luckperms.api.event.cause.CreationCause;
|
||||
import me.lucko.luckperms.common.commands.CommandPermission;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.abstraction.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.locale.CommandSpec;
|
||||
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.logging.ProgressLogger;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
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.SafeIteration;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@@ -86,7 +87,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
}
|
||||
|
||||
public MigrationPermissionsEx(LocaleManager locale) {
|
||||
super(CommandSpec.MIGRATION_COMMAND.spec(locale), "permissionsex", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
super(CommandSpec.MIGRATION_COMMAND.localize(locale), "permissionsex", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@@ -99,7 +100,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
log.log("Starting.");
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("PermissionsEx")) {
|
||||
log.logErr("Plugin not loaded.");
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -117,7 +118,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
log.log("Starting group migration.");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
Set<String> ladders = new HashSet<>();
|
||||
SafeIteration.iterate(manager.getGroupList(), group -> {
|
||||
Iterators.iterate(manager.getGroupList(), group -> {
|
||||
int groupWeight = maxWeight - group.getRank();
|
||||
|
||||
final String groupName = MigrationUtils.standardizeName(group.getName());
|
||||
@@ -161,8 +162,8 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
// Increment the max weight from the group migrations. All user meta should override.
|
||||
int userWeight = maxWeight + 5;
|
||||
|
||||
SafeIteration.iterate(manager.getUsers(), user -> {
|
||||
UUID u = BukkitMigrationUtils.lookupUuid(log, user.getIdentifier());
|
||||
Iterators.iterate(manager.getUsers(), user -> {
|
||||
UUID u = BukkitUuids.lookupUuid(log, user.getIdentifier());
|
||||
if (u == null) {
|
||||
return;
|
||||
}
|
||||
@@ -288,9 +289,9 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
}
|
||||
|
||||
String key = opt.getKey().toLowerCase();
|
||||
boolean ignore = key.equals(NodeFactory.PREFIX_KEY) ||
|
||||
key.equals(NodeFactory.SUFFIX_KEY) ||
|
||||
key.equals(NodeFactory.WEIGHT_KEY) ||
|
||||
boolean ignore = key.equals(NodeTypes.PREFIX_KEY) ||
|
||||
key.equals(NodeTypes.SUFFIX_KEY) ||
|
||||
key.equals(NodeTypes.WEIGHT_KEY) ||
|
||||
key.equals("rank") ||
|
||||
key.equals("rank-ladder") ||
|
||||
key.equals("name") ||
|
||||
|
||||
+13
-13
@@ -35,21 +35,21 @@ import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.event.cause.CreationCause;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.abstraction.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.locale.CommandSpec;
|
||||
import me.lucko.luckperms.common.locale.LocaleManager;
|
||||
import me.lucko.luckperms.common.locale.command.CommandSpec;
|
||||
import me.lucko.luckperms.common.logging.ProgressLogger;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
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.SafeIteration;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@@ -68,12 +68,12 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static me.lucko.luckperms.common.commands.CommandPermission.MIGRATION;
|
||||
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.spec(locale), "powerfulperms", MIGRATION, Predicates.not(5));
|
||||
super(CommandSpec.MIGRATION_POWERFULPERMS.localize(locale), "powerfulperms", MIGRATION, Predicates.not(5));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,7 +85,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
log.log("Starting.");
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("PowerfulPerms")) {
|
||||
log.logErr("Plugin not loaded.");
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
}
|
||||
|
||||
if (uuids.isEmpty()) {
|
||||
log.logErr("Unable to find any UUIDs to migrate.");
|
||||
log.logError("Unable to find any UUIDs to migrate.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
// Groups first.
|
||||
log.log("Starting group migration.");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
SafeIteration.iterate(groups, g -> {
|
||||
Iterators.iterate(groups, g -> {
|
||||
maxWeight.set(Math.max(maxWeight.get(), g.getRank()));
|
||||
|
||||
String groupName = MigrationUtils.standardizeName(g.getName());
|
||||
@@ -219,7 +219,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
maxWeight.addAndGet(5);
|
||||
|
||||
// Migrate all users and their groups
|
||||
SafeIteration.iterate(uuids, uuid -> {
|
||||
Iterators.iterate(uuids, uuid -> {
|
||||
|
||||
// Create a LuckPerms user for the UUID
|
||||
User user = plugin.getStorage().loadUser(uuid, null).join();
|
||||
|
||||
+25
-19
@@ -28,22 +28,23 @@ package me.lucko.luckperms.bukkit.migration;
|
||||
import me.lucko.luckperms.api.ChatMetaType;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.event.cause.CreationCause;
|
||||
import me.lucko.luckperms.common.commands.CommandPermission;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.abstraction.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.locale.CommandSpec;
|
||||
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.logging.ProgressLogger;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
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.SafeIteration;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
|
||||
@@ -64,7 +65,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class MigrationZPermissions extends SubCommand<Object> {
|
||||
public MigrationZPermissions(LocaleManager locale) {
|
||||
super(CommandSpec.MIGRATION_COMMAND.spec(locale), "zpermissions", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
super(CommandSpec.MIGRATION_COMMAND.localize(locale), "zpermissions", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,12 +77,12 @@ public class MigrationZPermissions extends SubCommand<Object> {
|
||||
log.log("Starting.");
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("zPermissions")) {
|
||||
log.logErr("Plugin not loaded.");
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
if (!Bukkit.getServicesManager().isProvidedFor(ZPermissionsService.class)) {
|
||||
log.logErr("Plugin not loaded.");
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -104,7 +105,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
|
||||
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
AtomicInteger maxWeight = new AtomicInteger(0);
|
||||
SafeIteration.iterate(internalService.getEntities(true), entity -> {
|
||||
Iterators.iterate(internalService.getEntities(true), entity -> {
|
||||
String groupName = MigrationUtils.standardizeName(entity.getDisplayName());
|
||||
Group group = plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
|
||||
|
||||
@@ -116,7 +117,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
|
||||
// store user data for later
|
||||
Set<Membership> members = entity.getMemberships();
|
||||
for (Membership membership : members) {
|
||||
UUID uuid = BukkitMigrationUtils.lookupUuid(log, membership.getMember());
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, membership.getMember());
|
||||
if (uuid == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -138,7 +139,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
|
||||
// Migrate all tracks
|
||||
log.log("Starting track migration.");
|
||||
AtomicInteger trackCount = new AtomicInteger(0);
|
||||
SafeIteration.iterate(service.getAllTracks(), t -> {
|
||||
Iterators.iterate(service.getAllTracks(), t -> {
|
||||
String trackName = MigrationUtils.standardizeName(t);
|
||||
Track track = plugin.getStorage().createAndLoadTrack(trackName, CreationCause.INTERNAL).join();
|
||||
track.setGroups(service.getTrackGroups(t));
|
||||
@@ -156,7 +157,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
|
||||
Set<UUID> usersToMigrate = new HashSet<>(userParents.keySet());
|
||||
usersToMigrate.addAll(service.getAllPlayersUUID());
|
||||
|
||||
SafeIteration.iterate(usersToMigrate, u -> {
|
||||
Iterators.iterate(usersToMigrate, u -> {
|
||||
PermissionEntity entity = internalService.getEntity(null, u, false);
|
||||
|
||||
String username = null;
|
||||
@@ -211,13 +212,18 @@ public class MigrationZPermissions extends SubCommand<Object> {
|
||||
|
||||
for (EntityMetadata metadata : entity.getMetadata()) {
|
||||
String key = metadata.getName().toLowerCase();
|
||||
if (key.isEmpty() || metadata.getStringValue().isEmpty()) continue;
|
||||
Object value = metadata.getValue();
|
||||
|
||||
if (key.equals(NodeFactory.PREFIX_KEY) || key.equals(NodeFactory.SUFFIX_KEY)) {
|
||||
if (key.isEmpty() || value == null) continue;
|
||||
|
||||
String valueString = value.toString();
|
||||
if (valueString.isEmpty()) continue;
|
||||
|
||||
if (key.equals(NodeTypes.PREFIX_KEY) || key.equals(NodeTypes.SUFFIX_KEY)) {
|
||||
ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase());
|
||||
holder.setPermission(NodeFactory.buildChatMetaNode(type, weight, metadata.getStringValue()).build());
|
||||
holder.setPermission(NodeFactory.buildChatMetaNode(type, weight, valueString).build());
|
||||
} else {
|
||||
holder.setPermission(NodeFactory.buildMetaNode(key, metadata.getStringValue()).build());
|
||||
holder.setPermission(NodeFactory.buildMetaNode(key, valueString).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ public class LPPermissible extends PermissibleBase {
|
||||
}
|
||||
|
||||
LPPermissionAttachment ret = addAttachment(plugin);
|
||||
if (getPlugin().getServer().getScheduler().scheduleSyncDelayedTask(plugin, ret::remove, ticks) == -1) {
|
||||
if (getPlugin().getBootstrap().getServer().getScheduler().scheduleSyncDelayedTask(plugin, ret::remove, ticks) == -1) {
|
||||
ret.remove();
|
||||
throw new RuntimeException("Could not add PermissionAttachment to " + this.player + " for plugin " + plugin.getDescription().getFullName() + ": Scheduler returned -1");
|
||||
}
|
||||
|
||||
+6
-12
@@ -31,8 +31,8 @@ import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.bukkit.model.dummy.DummyPlugin;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.ImmutableTransientNode;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
import me.lucko.luckperms.common.node.factory.NodeFactory;
|
||||
import me.lucko.luckperms.common.node.model.ImmutableTransientNode;
|
||||
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionRemovedExecutor;
|
||||
@@ -178,9 +178,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
|
||||
// set the transient node
|
||||
User user = this.permissible.getUser();
|
||||
if (user.setTransientPermission(transientNode).asBoolean()) {
|
||||
user.reloadCachedData();
|
||||
}
|
||||
user.setTransientPermission(transientNode);
|
||||
}
|
||||
|
||||
private void unsetPermissionInternal(String name) {
|
||||
@@ -190,17 +188,13 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
|
||||
// remove transient permissions from the holder which were added by this attachment & equal the permission
|
||||
User user = this.permissible.getUser();
|
||||
if (user.removeIfTransient(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this && n.getPermission().equals(name))) {
|
||||
user.reloadCachedData();
|
||||
}
|
||||
user.removeIfTransient(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this && n.getPermission().equals(name));
|
||||
}
|
||||
|
||||
private void clearInternal() {
|
||||
// remove all transient permissions added by this attachment
|
||||
User user = this.permissible.getUser();
|
||||
if (user.removeIfTransient(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this)) {
|
||||
user.reloadCachedData();
|
||||
}
|
||||
user.removeIfTransient(n -> n instanceof ImmutableTransientNode && ((ImmutableTransientNode) n).getOwner() == this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -276,7 +270,7 @@ public class LPPermissionAttachment extends PermissionAttachment {
|
||||
|
||||
@Override
|
||||
public Plugin getPlugin() {
|
||||
return this.owner != null ? this.owner : this.permissible.getPlugin();
|
||||
return this.owner != null ? this.owner : this.permissible.getPlugin().getBootstrap();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ public class MonitoredPermissibleBase extends PermissibleBase {
|
||||
|
||||
private void logCheck(CheckOrigin origin, String permission, boolean result) {
|
||||
this.plugin.getVerboseHandler().offerCheckData(origin, this.name, ContextSet.empty(), permission, Tristate.fromBoolean(result));
|
||||
this.plugin.getPermissionVault().offer(permission);
|
||||
this.plugin.getPermissionRegistry().offer(permission);
|
||||
}
|
||||
|
||||
PermissibleBase getDelegate() {
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ public class PermissibleMonitoringInjector implements Runnable {
|
||||
}
|
||||
|
||||
private void injectConsole() throws Exception {
|
||||
ConsoleCommandSender consoleSender = this.plugin.getServer().getConsoleSender();
|
||||
ConsoleCommandSender consoleSender = this.plugin.getBootstrap().getServer().getConsoleSender();
|
||||
|
||||
// get the ServerCommandSender class
|
||||
Class<?> serverCommandSenderClass = ReflectionUtil.obcClass("command.ServerCommandSender");
|
||||
|
||||
+4
-4
@@ -69,18 +69,18 @@ public class InjectorDefaultsMap implements Runnable {
|
||||
this.plugin.setDefaultPermissionMap(ret);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.plugin.getLog().severe("Exception occurred whilst injecting LuckPerms Default Permission map.");
|
||||
this.plugin.getLogger().severe("Exception occurred whilst injecting LuckPerms Default Permission map.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private LPDefaultsMap inject() throws Exception {
|
||||
Objects.requireNonNull(DEFAULT_PERMISSIONS_FIELD, "DEFAULT_PERMISSIONS_FIELD");
|
||||
PluginManager pluginManager = this.plugin.getServer().getPluginManager();
|
||||
PluginManager pluginManager = this.plugin.getBootstrap().getServer().getPluginManager();
|
||||
|
||||
if (!(pluginManager instanceof SimplePluginManager)) {
|
||||
this.plugin.getLog().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
|
||||
this.plugin.getLog().severe("Unable to inject LuckPerms Default Permission map.");
|
||||
this.plugin.getLogger().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
|
||||
this.plugin.getLogger().severe("Unable to inject LuckPerms Default Permission map.");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -68,18 +68,18 @@ public class InjectorPermissionMap implements Runnable {
|
||||
this.plugin.setPermissionMap(ret);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.plugin.getLog().severe("Exception occurred whilst injecting LuckPerms Permission map.");
|
||||
this.plugin.getLogger().severe("Exception occurred whilst injecting LuckPerms Permission map.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private LPPermissionMap inject() throws Exception {
|
||||
Objects.requireNonNull(PERMISSIONS_FIELD, "PERMISSIONS_FIELD");
|
||||
PluginManager pluginManager = this.plugin.getServer().getPluginManager();
|
||||
PluginManager pluginManager = this.plugin.getBootstrap().getServer().getPluginManager();
|
||||
|
||||
if (!(pluginManager instanceof SimplePluginManager)) {
|
||||
this.plugin.getLog().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
|
||||
this.plugin.getLog().severe("Unable to inject LuckPerms Permission map.");
|
||||
this.plugin.getLogger().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
|
||||
this.plugin.getLogger().severe("Unable to inject LuckPerms Permission map.");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -67,18 +67,18 @@ public class InjectorSubscriptionMap implements Runnable {
|
||||
this.plugin.setSubscriptionMap(ret);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.plugin.getLog().severe("Exception occurred whilst injecting LuckPerms Permission Subscription map.");
|
||||
this.plugin.getLogger().severe("Exception occurred whilst injecting LuckPerms Permission Subscription map.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private LPSubscriptionMap inject() throws Exception {
|
||||
Objects.requireNonNull(PERM_SUBS_FIELD, "PERM_SUBS_FIELD");
|
||||
PluginManager pluginManager = this.plugin.getServer().getPluginManager();
|
||||
PluginManager pluginManager = this.plugin.getBootstrap().getServer().getPluginManager();
|
||||
|
||||
if (!(pluginManager instanceof SimplePluginManager)) {
|
||||
this.plugin.getLog().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
|
||||
this.plugin.getLog().severe("Unable to inject LuckPerms Permission Subscription map.");
|
||||
this.plugin.getLogger().severe("PluginManager instance is not a 'SimplePluginManager', instead: " + pluginManager.getClass());
|
||||
this.plugin.getLogger().severe("Unable to inject LuckPerms Permission Subscription map.");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ 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.PermissionVault;
|
||||
import me.lucko.luckperms.common.treeview.PermissionRegistry;
|
||||
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
@@ -40,17 +40,19 @@ import org.bukkit.plugin.PluginManager;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* 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 PermissionVault}.
|
||||
* {@link PermissionRegistry}.
|
||||
*
|
||||
* It also allows us to pre-determine child permission relationships.
|
||||
*
|
||||
@@ -94,7 +96,10 @@ public final class LPPermissionMap extends ForwardingMap<String, Permission> {
|
||||
|
||||
@Override
|
||||
public Permission put(@Nonnull String key, @Nonnull Permission value) {
|
||||
this.plugin.getPermissionVault().offer(key);
|
||||
Objects.requireNonNull(key, "key");
|
||||
Objects.requireNonNull(value, "value");
|
||||
|
||||
this.plugin.getPermissionRegistry().offer(key);
|
||||
Permission ret = super.put(key, value);
|
||||
update();
|
||||
return ret;
|
||||
@@ -102,19 +107,55 @@ public final class LPPermissionMap extends ForwardingMap<String, Permission> {
|
||||
|
||||
@Override
|
||||
public void putAll(@Nonnull Map<? extends String, ? extends Permission> m) {
|
||||
this.plugin.getPermissionVault().offerAll(m.keySet());
|
||||
this.plugin.getPermissionRegistry().offerAll(m.keySet());
|
||||
super.putAll(m);
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Permission putIfAbsent(String key, Permission value) {
|
||||
this.plugin.getPermissionVault().offer(key);
|
||||
Objects.requireNonNull(key, "key");
|
||||
Objects.requireNonNull(value, "value");
|
||||
|
||||
this.plugin.getPermissionRegistry().offer(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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object key, Object value) {
|
||||
return key != null && value != null && super.remove(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(@Nullable Object key) {
|
||||
return key != null && super.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(@Nullable Object value) {
|
||||
return value != null && super.containsValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Permission get(@Nullable Object key) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
private final class ChildPermissionResolver implements CacheLoader<String, Map<String, Boolean>> {
|
||||
private final boolean value;
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ public final class LPSubscriptionMap extends HashMap<String, Map<Permissible, Bo
|
||||
@Override
|
||||
public Set<Permissible> keySet() {
|
||||
// gather players (LPPermissibles)
|
||||
Set<Permissible> players = LPSubscriptionMap.this.plugin.getServer().getOnlinePlayers().stream()
|
||||
Set<Permissible> players = LPSubscriptionMap.this.plugin.getBootstrap().getServer().getOnlinePlayers().stream()
|
||||
.filter(player -> player.isPermissionSet(this.permission))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -73,18 +74,18 @@ public abstract class AbstractVaultChat extends Chat {
|
||||
}
|
||||
|
||||
// methods subclasses are expected to implement
|
||||
public abstract String getPlayerPrefix(String world, UUID uuid);
|
||||
public abstract String getPlayerSuffix(String world, UUID uuid);
|
||||
public abstract void setPlayerPrefix(String world, UUID uuid, String prefix);
|
||||
public abstract void setPlayerSuffix(String world, UUID uuid, String suffix);
|
||||
public abstract String getPlayerInfo(String world, UUID uuid, String key);
|
||||
public abstract void setPlayerInfo(String world, UUID uuid, String key, Object value);
|
||||
public abstract String getGroupsPrefix(String world, String name); // note "groups" not "group"
|
||||
public abstract String getGroupsSuffix(String world, String name); // note "groups" not "group"
|
||||
public abstract void setGroupsPrefix(String world, String name, String prefix); // note "groups" not "group"
|
||||
public abstract void setGroupsSuffix(String world, String name, String suffix); // note "groups" not "group"
|
||||
public abstract String getGroupInfo(String world, String name, String key);
|
||||
public abstract void setGroupInfo(String world, String name, String key, Object value);
|
||||
public abstract String getUserChatPrefix(String world, UUID uuid);
|
||||
public abstract String getUserChatSuffix(String world, UUID uuid);
|
||||
public abstract void setUserChatPrefix(String world, UUID uuid, String prefix);
|
||||
public abstract void setUserChatSuffix(String world, UUID uuid, String suffix);
|
||||
public abstract String getUserMeta(String world, UUID uuid, String key);
|
||||
public abstract void setUserMeta(String world, UUID uuid, String key, Object value);
|
||||
public abstract String getGroupChatPrefix(String world, String name);
|
||||
public abstract String getGroupChatSuffix(String world, String name);
|
||||
public abstract void setGroupChatPrefix(String world, String name, String prefix);
|
||||
public abstract void setGroupChatSuffix(String world, String name, String suffix);
|
||||
public abstract String getGroupMeta(String world, String name, String key);
|
||||
public abstract void setGroupMeta(String world, String name, String key, Object value);
|
||||
|
||||
// utility methods for parsing metadata values from strings
|
||||
|
||||
@@ -165,362 +166,482 @@ public abstract class AbstractVaultChat extends Chat {
|
||||
|
||||
@Override
|
||||
public String getPlayerPrefix(String world, String player) {
|
||||
return getPlayerPrefix(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return getUserChatPrefix(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerPrefix(String world, OfflinePlayer player) {
|
||||
return getPlayerPrefix(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return getUserChatPrefix(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerPrefix(World world, String player) {
|
||||
return getPlayerPrefix(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return getUserChatPrefix(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerPrefix(Player player) {
|
||||
return getPlayerPrefix(world(player), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return getUserChatPrefix(world(player), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerPrefix(String world, String player, String prefix) {
|
||||
setPlayerPrefix(world(world), player(player), prefix);
|
||||
Objects.requireNonNull(player, "player");
|
||||
setUserChatPrefix(world(world), player(player), prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerPrefix(String world, OfflinePlayer player, String prefix) {
|
||||
setPlayerPrefix(world(world), player(player), prefix);
|
||||
Objects.requireNonNull(player, "player");
|
||||
setUserChatPrefix(world(world), player(player), prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerPrefix(World world, String player, String prefix) {
|
||||
setPlayerPrefix(world(world), player(player), prefix);
|
||||
Objects.requireNonNull(player, "player");
|
||||
setUserChatPrefix(world(world), player(player), prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerPrefix(Player player, String prefix) {
|
||||
setPlayerPrefix(world(player), player(player), prefix);
|
||||
Objects.requireNonNull(player, "player");
|
||||
setUserChatPrefix(world(player), player(player), prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerSuffix(String world, String player) {
|
||||
return getPlayerSuffix(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return getUserChatSuffix(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerSuffix(String world, OfflinePlayer player) {
|
||||
return getPlayerSuffix(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return getUserChatSuffix(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerSuffix(World world, String player) {
|
||||
return getPlayerSuffix(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return getUserChatSuffix(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerSuffix(Player player) {
|
||||
return getPlayerSuffix(world(player), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return getUserChatSuffix(world(player), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerSuffix(String world, String player, String suffix) {
|
||||
setPlayerSuffix(world(world), player(player), suffix);
|
||||
Objects.requireNonNull(player, "player");
|
||||
setUserChatSuffix(world(world), player(player), suffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerSuffix(String world, OfflinePlayer player, String suffix) {
|
||||
setPlayerSuffix(world(world), player(player), suffix);
|
||||
Objects.requireNonNull(player, "player");
|
||||
setUserChatSuffix(world(world), player(player), suffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerSuffix(World world, String player, String suffix) {
|
||||
setPlayerSuffix(world(world), player(player), suffix);
|
||||
Objects.requireNonNull(player, "player");
|
||||
setUserChatSuffix(world(world), player(player), suffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerSuffix(Player player, String suffix) {
|
||||
setPlayerSuffix(world(player), player(player), suffix);
|
||||
Objects.requireNonNull(player, "player");
|
||||
setUserChatSuffix(world(player), player(player), suffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupPrefix(String world, String group) {
|
||||
return getGroupsPrefix(world(world), group);
|
||||
Objects.requireNonNull(group, "group");
|
||||
return getGroupChatPrefix(world(world), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupPrefix(World world, String group) {
|
||||
return getGroupsPrefix(world(world), group);
|
||||
Objects.requireNonNull(group, "group");
|
||||
return getGroupChatPrefix(world(world), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupPrefix(String world, String group, String prefix) {
|
||||
setGroupsPrefix(world(world), group, prefix);
|
||||
Objects.requireNonNull(group, "group");
|
||||
setGroupChatPrefix(world(world), group, prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupPrefix(World world, String group, String prefix) {
|
||||
setGroupsPrefix(world(world), group, prefix);
|
||||
Objects.requireNonNull(group, "group");
|
||||
setGroupChatPrefix(world(world), group, prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupSuffix(String world, String group) {
|
||||
return getGroupsSuffix(world(world), group);
|
||||
Objects.requireNonNull(group, "group");
|
||||
return getGroupChatSuffix(world(world), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupSuffix(World world, String group) {
|
||||
return getGroupsSuffix(world(world), group);
|
||||
Objects.requireNonNull(group, "group");
|
||||
return getGroupChatSuffix(world(world), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupSuffix(String world, String group, String suffix) {
|
||||
setGroupsSuffix(world(world), group, suffix);
|
||||
Objects.requireNonNull(group, "group");
|
||||
setGroupChatSuffix(world(world), group, suffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupSuffix(World world, String group, String suffix) {
|
||||
setGroupsSuffix(world(world), group, suffix);
|
||||
Objects.requireNonNull(group, "group");
|
||||
setGroupChatSuffix(world(world), group, suffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerInfoInteger(String world, OfflinePlayer player, String node, int defaultValue) {
|
||||
return intConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return intConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerInfoInteger(String world, String player, String node, int defaultValue) {
|
||||
return intConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return intConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerInfoInteger(World world, String player, String node, int defaultValue) {
|
||||
return intConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return intConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerInfoInteger(Player player, String node, int defaultValue) {
|
||||
return intConvert(getPlayerInfo(world(player), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return intConvert(getUserMeta(world(player), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoInteger(String world, OfflinePlayer player, String node, int value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoInteger(String world, String player, String node, int value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoInteger(World world, String player, String node, int value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoInteger(Player player, String node, int value) {
|
||||
setPlayerInfo(world(player), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(player), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGroupInfoInteger(String world, String group, String node, int defaultValue) {
|
||||
return intConvert(getGroupInfo(world(world), group, node), defaultValue);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return intConvert(getGroupMeta(world(world), group, node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGroupInfoInteger(World world, String group, String node, int defaultValue) {
|
||||
return intConvert(getGroupInfo(world(world), group, node), defaultValue);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return intConvert(getGroupMeta(world(world), group, node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupInfoInteger(String world, String group, String node, int value) {
|
||||
setGroupInfo(world(world), group, node, value);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setGroupMeta(world(world), group, node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupInfoInteger(World world, String group, String node, int value) {
|
||||
setGroupInfo(world(world), group, node, value);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setGroupMeta(world(world), group, node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPlayerInfoDouble(String world, OfflinePlayer player, String node, double defaultValue) {
|
||||
return doubleConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return doubleConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPlayerInfoDouble(String world, String player, String node, double defaultValue) {
|
||||
return doubleConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return doubleConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPlayerInfoDouble(World world, String player, String node, double defaultValue) {
|
||||
return doubleConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return doubleConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPlayerInfoDouble(Player player, String node, double defaultValue) {
|
||||
return doubleConvert(getPlayerInfo(world(player), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return doubleConvert(getUserMeta(world(player), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoDouble(String world, OfflinePlayer player, String node, double value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoDouble(String world, String player, String node, double value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoDouble(World world, String player, String node, double value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoDouble(Player player, String node, double value) {
|
||||
setPlayerInfo(world(player), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(player), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getGroupInfoDouble(String world, String group, String node, double defaultValue) {
|
||||
return doubleConvert(getGroupInfo(world(world), group, node), defaultValue);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return doubleConvert(getGroupMeta(world(world), group, node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getGroupInfoDouble(World world, String group, String node, double defaultValue) {
|
||||
return doubleConvert(getGroupInfo(world(world), group, node), defaultValue);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return doubleConvert(getGroupMeta(world(world), group, node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupInfoDouble(String world, String group, String node, double value) {
|
||||
setGroupInfo(world(world), group, node, value);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setGroupMeta(world(world), group, node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupInfoDouble(World world, String group, String node, double value) {
|
||||
setGroupInfo(world(world), group, node, value);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setGroupMeta(world(world), group, node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPlayerInfoBoolean(String world, OfflinePlayer player, String node, boolean defaultValue) {
|
||||
return booleanConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return booleanConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPlayerInfoBoolean(String world, String player, String node, boolean defaultValue) {
|
||||
return booleanConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return booleanConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPlayerInfoBoolean(World world, String player, String node, boolean defaultValue) {
|
||||
return booleanConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return booleanConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPlayerInfoBoolean(Player player, String node, boolean defaultValue) {
|
||||
return booleanConvert(getPlayerInfo(world(player), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return booleanConvert(getUserMeta(world(player), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoBoolean(String world, OfflinePlayer player, String node, boolean value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoBoolean(String world, String player, String node, boolean value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoBoolean(World world, String player, String node, boolean value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoBoolean(Player player, String node, boolean value) {
|
||||
setPlayerInfo(world(player), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(player), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getGroupInfoBoolean(String world, String group, String node, boolean defaultValue) {
|
||||
return booleanConvert(getGroupInfo(world(world), group, node), defaultValue);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return booleanConvert(getGroupMeta(world(world), group, node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getGroupInfoBoolean(World world, String group, String node, boolean defaultValue) {
|
||||
return booleanConvert(getGroupInfo(world(world), group, node), defaultValue);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return booleanConvert(getGroupMeta(world(world), group, node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupInfoBoolean(String world, String group, String node, boolean value) {
|
||||
setGroupInfo(world(world), group, node, value);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setGroupMeta(world(world), group, node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupInfoBoolean(World world, String group, String node, boolean value) {
|
||||
setGroupInfo(world(world), group, node, value);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setGroupMeta(world(world), group, node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerInfoString(String world, OfflinePlayer player, String node, String defaultValue) {
|
||||
return strConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return strConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerInfoString(String world, String player, String node, String defaultValue) {
|
||||
return strConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return strConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerInfoString(World world, String player, String node, String defaultValue) {
|
||||
return strConvert(getPlayerInfo(world(world), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return strConvert(getUserMeta(world(world), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerInfoString(Player player, String node, String defaultValue) {
|
||||
return strConvert(getPlayerInfo(world(player), player(player), node), defaultValue);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return strConvert(getUserMeta(world(player), player(player), node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoString(String world, OfflinePlayer player, String node, String value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoString(String world, String player, String node, String value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoString(World world, String player, String node, String value) {
|
||||
setPlayerInfo(world(world), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(world), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfoString(Player player, String node, String value) {
|
||||
setPlayerInfo(world(player), player(player), node, value);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setUserMeta(world(player), player(player), node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupInfoString(String world, String group, String node, String defaultValue) {
|
||||
return strConvert(getGroupInfo(world(world), group, node), defaultValue);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return strConvert(getGroupMeta(world(world), group, node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupInfoString(World world, String group, String node, String defaultValue) {
|
||||
return strConvert(getGroupInfo(world(world), group, node), defaultValue);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
return strConvert(getGroupMeta(world(world), group, node), defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupInfoString(String world, String group, String node, String value) {
|
||||
setGroupInfo(world(world), group, node, value);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setGroupMeta(world(world), group, node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupInfoString(World world, String group, String node, String value) {
|
||||
setGroupInfo(world(world), group, node, value);
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(node, "node");
|
||||
setGroupMeta(world(world), group, node, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+117
-43
@@ -33,6 +33,7 @@ import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -81,14 +82,14 @@ public abstract class AbstractVaultPermission extends Permission {
|
||||
}
|
||||
|
||||
// methods subclasses are expected to implement
|
||||
public abstract boolean hasPermission(String world, UUID uuid, String permission);
|
||||
public abstract boolean playerAddPermission(String world, UUID uuid, String permission);
|
||||
public abstract boolean playerRemovePermission(String world, UUID uuid, String permission);
|
||||
public abstract boolean playerInGroup(String world, UUID uuid, String group);
|
||||
public abstract boolean playerAddGroup(String world, UUID uuid, String group);
|
||||
public abstract boolean playerRemoveGroup(String world, UUID uuid, String group);
|
||||
public abstract String[] playerGetGroups(String world, UUID uuid);
|
||||
public abstract String playerPrimaryGroup(String world, UUID uuid);
|
||||
public abstract boolean userHasPermission(String world, UUID uuid, String permission);
|
||||
public abstract boolean userAddPermission(String world, UUID uuid, String permission);
|
||||
public abstract boolean userRemovePermission(String world, UUID uuid, String permission);
|
||||
public abstract boolean userInGroup(String world, UUID uuid, String group);
|
||||
public abstract boolean userAddGroup(String world, UUID uuid, String group);
|
||||
public abstract boolean userRemoveGroup(String world, UUID uuid, String group);
|
||||
public abstract String[] userGetGroups(String world, UUID uuid);
|
||||
public abstract String userGetPrimaryGroup(String world, UUID uuid);
|
||||
public abstract boolean groupHasPermission(String world, String name, String permission);
|
||||
public abstract boolean groupAddPermission(String world, String name, String permission);
|
||||
public abstract boolean groupRemovePermission(String world, String name, String permission);
|
||||
@@ -129,207 +130,280 @@ public abstract class AbstractVaultPermission extends Permission {
|
||||
|
||||
@Override
|
||||
public boolean has(String world, String player, String permission) {
|
||||
return hasPermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userHasPermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(World world, String player, String permission) {
|
||||
return hasPermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userHasPermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(Player player, String permission) {
|
||||
return hasPermission(world(player), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userHasPermission(world(player), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHas(String world, String player, String permission) {
|
||||
return hasPermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userHasPermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHas(World world, String player, String permission) {
|
||||
return hasPermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userHasPermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHas(String world, OfflinePlayer player, String permission) {
|
||||
return hasPermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userHasPermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHas(Player player, String permission) {
|
||||
return hasPermission(world(player), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userHasPermission(world(player), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAdd(String world, String player, String permission) {
|
||||
return playerAddPermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userAddPermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAdd(World world, String player, String permission) {
|
||||
return playerAddPermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userAddPermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAdd(String world, OfflinePlayer player, String permission) {
|
||||
return playerAddPermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userAddPermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAdd(Player player, String permission) {
|
||||
return playerAddPermission(world(player), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userAddPermission(world(player), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemove(String world, String player, String permission) {
|
||||
return playerRemovePermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userRemovePermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemove(String world, OfflinePlayer player, String permission) {
|
||||
return playerRemovePermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userRemovePermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemove(World world, String player, String permission) {
|
||||
return playerRemovePermission(world(world), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userRemovePermission(world(world), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemove(Player player, String permission) {
|
||||
return playerRemovePermission(world(player), player(player), permission);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return userRemovePermission(world(player), player(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupHas(String world, String group, String permission) {
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return groupHasPermission(world(world), group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupHas(World world, String group, String permission) {
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return groupHasPermission(world(world), group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupAdd(String world, String group, String permission) {
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return groupAddPermission(world(world), group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupAdd(World world, String group, String permission) {
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return groupAddPermission(world(world), group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupRemove(String world, String group, String permission) {
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return groupRemovePermission(world(world), group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupRemove(World world, String group, String permission) {
|
||||
Objects.requireNonNull(group, "group");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return groupRemovePermission(world(world), group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerInGroup(String world, String player, String group) {
|
||||
return playerInGroup(world(world), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userInGroup(world(world), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerInGroup(World world, String player, String group) {
|
||||
return playerInGroup(world(world), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userInGroup(world(world), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerInGroup(String world, OfflinePlayer player, String group) {
|
||||
return playerInGroup(world(world), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userInGroup(world(world), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerInGroup(Player player, String group) {
|
||||
return playerInGroup(world(player), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userInGroup(world(player), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAddGroup(String world, String player, String group) {
|
||||
return playerAddGroup(world(world), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userAddGroup(world(world), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAddGroup(World world, String player, String group) {
|
||||
return playerAddGroup(world(world), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userAddGroup(world(world), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAddGroup(String world, OfflinePlayer player, String group) {
|
||||
return playerAddGroup(world(world), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userAddGroup(world(world), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAddGroup(Player player, String group) {
|
||||
return playerAddGroup(world(player), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userAddGroup(world(player), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemoveGroup(String world, String player, String group) {
|
||||
return playerRemoveGroup(world(world), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userRemoveGroup(world(world), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemoveGroup(World world, String player, String group) {
|
||||
return playerRemoveGroup(world(world), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userRemoveGroup(world(world), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemoveGroup(String world, OfflinePlayer player, String group) {
|
||||
return playerRemoveGroup(world(world), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
Objects.requireNonNull(group, "group");
|
||||
return userRemoveGroup(world(world), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemoveGroup(Player player, String group) {
|
||||
return playerRemoveGroup(world(player), player(player), group);
|
||||
Objects.requireNonNull(player, "player");
|
||||
return userRemoveGroup(world(player), player(player), group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPlayerGroups(String world, String player) {
|
||||
return playerGetGroups(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return userGetGroups(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPlayerGroups(World world, String player) {
|
||||
return playerGetGroups(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return userGetGroups(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPlayerGroups(String world, OfflinePlayer player) {
|
||||
return playerGetGroups(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return userGetGroups(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPlayerGroups(Player player) {
|
||||
return playerGetGroups(world(player), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return userGetGroups(world(player), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimaryGroup(String world, String player) {
|
||||
return playerPrimaryGroup(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return userGetPrimaryGroup(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimaryGroup(World world, String player) {
|
||||
return playerPrimaryGroup(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return userGetPrimaryGroup(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimaryGroup(String world, OfflinePlayer player) {
|
||||
return playerPrimaryGroup(world(world), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return userGetPrimaryGroup(world(world), player(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimaryGroup(Player player) {
|
||||
return playerPrimaryGroup(world(player), player(player));
|
||||
Objects.requireNonNull(player, "player");
|
||||
return userGetPrimaryGroup(world(player), player(player));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,12 +34,13 @@ 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.commands.CommandManager;
|
||||
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.NodeFactory;
|
||||
import me.lucko.luckperms.common.node.factory.NodeFactory;
|
||||
import me.lucko.luckperms.common.node.model.NodeTypes;
|
||||
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
|
||||
@@ -84,8 +85,10 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerPrefix(String world, UUID uuid) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public String getUserChatPrefix(String world, UUID uuid) {
|
||||
if (uuid == null) {
|
||||
return null;
|
||||
}
|
||||
User user = getUser(uuid);
|
||||
if (user == null) {
|
||||
return null;
|
||||
@@ -94,14 +97,16 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
MetaCache metaData = user.getCachedData().getMetaData(contexts);
|
||||
String ret = metaData.getPrefix();
|
||||
if (log()) {
|
||||
logMsg("#getPlayerPrefix: %s - %s - %s", user.getFriendlyName(), contexts.getContexts().toMultimap(), ret);
|
||||
logMsg("#getUserChatPrefix: %s - %s - %s", user.getFriendlyName(), contexts.getContexts().toMultimap(), ret);
|
||||
}
|
||||
return Strings.nullToEmpty(ret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerSuffix(String world, UUID uuid) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public String getUserChatSuffix(String world, UUID uuid) {
|
||||
if (uuid == null) {
|
||||
return null;
|
||||
}
|
||||
User user = getUser(uuid);
|
||||
if (user == null) {
|
||||
return null;
|
||||
@@ -110,14 +115,16 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
MetaCache metaData = user.getCachedData().getMetaData(contexts);
|
||||
String ret = metaData.getSuffix();
|
||||
if (log()) {
|
||||
logMsg("#getPlayerSuffix: %s - %s - %s", user.getFriendlyName(), contexts.getContexts().toMultimap(), ret);
|
||||
logMsg("#getUserChatSuffix: %s - %s - %s", user.getFriendlyName(), contexts.getContexts().toMultimap(), ret);
|
||||
}
|
||||
return Strings.nullToEmpty(ret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerPrefix(String world, UUID uuid, String prefix) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public void setUserChatPrefix(String world, UUID uuid, String prefix) {
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
User user = getUser(uuid);
|
||||
if (user == null) {
|
||||
return;
|
||||
@@ -126,8 +133,10 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerSuffix(String world, UUID uuid, String suffix) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public void setUserChatSuffix(String world, UUID uuid, String suffix) {
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
User user = getUser(uuid);
|
||||
if (user == null) {
|
||||
return;
|
||||
@@ -136,8 +145,10 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerInfo(String world, UUID uuid, String key) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public String getUserMeta(String world, UUID uuid, String key) {
|
||||
if (uuid == null) {
|
||||
return null;
|
||||
}
|
||||
Objects.requireNonNull(key, "key");
|
||||
User user = getUser(uuid);
|
||||
if (user == null) {
|
||||
@@ -147,14 +158,16 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
MetaCache metaData = user.getCachedData().getMetaData(contexts);
|
||||
String ret = metaData.getMeta().get(key);
|
||||
if (log()) {
|
||||
logMsg("#getPlayerInfo: %s - %s - %s - %s", user.getFriendlyName(), contexts.getContexts().toMultimap(), key, ret);
|
||||
logMsg("#getUserMeta: %s - %s - %s - %s", user.getFriendlyName(), contexts.getContexts().toMultimap(), key, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerInfo(String world, UUID uuid, String key, Object value) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public void setUserMeta(String world, UUID uuid, String key, Object value) {
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
Objects.requireNonNull(key, "key");
|
||||
User user = getUser(uuid);
|
||||
if (user == null) {
|
||||
@@ -164,7 +177,7 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupsPrefix(String world, String name) {
|
||||
public String getGroupChatPrefix(String world, String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
Group group = getGroup(name);
|
||||
if (group == null) {
|
||||
@@ -180,7 +193,7 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupsSuffix(String world, String name) {
|
||||
public String getGroupChatSuffix(String world, String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
Group group = getGroup(name);
|
||||
if (group == null) {
|
||||
@@ -196,7 +209,7 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupsPrefix(String world, String name, String prefix) {
|
||||
public void setGroupChatPrefix(String world, String name, String prefix) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
Group group = getGroup(name);
|
||||
if (group == null) {
|
||||
@@ -206,7 +219,7 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupsSuffix(String world, String name, String suffix) {
|
||||
public void setGroupChatSuffix(String world, String name, String suffix) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
Group group = getGroup(name);
|
||||
if (group == null) {
|
||||
@@ -216,7 +229,7 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupInfo(String world, String name, String key) {
|
||||
public String getGroupMeta(String world, String name, String key) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
Objects.requireNonNull(key, "key");
|
||||
Group group = getGroup(name);
|
||||
@@ -227,13 +240,13 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
MetaCache metaData = group.getCachedData().getMetaData(contexts);
|
||||
String ret = metaData.getMeta().get(key);
|
||||
if (log()) {
|
||||
logMsg("#getGroupInfo: %s - %s - %s - %s", group.getName(), contexts.getContexts().toMultimap(), key, ret);
|
||||
logMsg("#getGroupMeta: %s - %s - %s - %s", group.getName(), contexts.getContexts().toMultimap(), key, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupInfo(String world, String name, String key, Object value) {
|
||||
public void setGroupMeta(String world, String name, String key, Object value) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
Objects.requireNonNull(key, "key");
|
||||
Group group = getGroup(name);
|
||||
@@ -258,7 +271,7 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
return this.plugin.getConfiguration().get(ConfigKeys.VAULT_DEBUG);
|
||||
}
|
||||
private void logMsg(String format, Object... args) {
|
||||
this.plugin.getLog().info("[VAULT-CHAT] " + String.format(format, args)
|
||||
this.plugin.getLogger().info("[VAULT-CHAT] " + String.format(format, args)
|
||||
.replace(CommandManager.SECTION_CHAR, '$')
|
||||
.replace(CommandManager.AMPERSAND_CHAR, '$')
|
||||
);
|
||||
@@ -306,7 +319,7 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
}
|
||||
|
||||
Node.Builder metaNode;
|
||||
if (key.equalsIgnoreCase(NodeFactory.PREFIX_KEY) || key.equalsIgnoreCase(NodeFactory.SUFFIX_KEY)) {
|
||||
if (key.equalsIgnoreCase(NodeTypes.PREFIX_KEY) || key.equalsIgnoreCase(NodeTypes.SUFFIX_KEY)) {
|
||||
metaNode = NodeFactory.buildChatMetaNode(ChatMetaType.valueOf(key.toUpperCase()), 100, value.toString());
|
||||
} else {
|
||||
metaNode = NodeFactory.buildMetaNode(key, value.toString());
|
||||
@@ -326,6 +339,6 @@ public class VaultChatHook extends AbstractVaultChat {
|
||||
context.add(Contexts.WORLD_KEY, world.toLowerCase());
|
||||
}
|
||||
context.add(Contexts.SERVER_KEY, this.permissionHook.getVaultServer());
|
||||
return new Contexts(context.build(), this.permissionHook.isIncludeGlobal(), true, true, true, true, false);
|
||||
return Contexts.of(context.build(), this.permissionHook.isIncludeGlobal(), true, true, true, true, false);
|
||||
}
|
||||
}
|
||||
@@ -56,9 +56,9 @@ public class VaultHookManager {
|
||||
this.chatHook = new VaultChatHook(plugin, this.permissionHook);
|
||||
}
|
||||
|
||||
final ServicesManager sm = plugin.getServer().getServicesManager();
|
||||
sm.register(Permission.class, this.permissionHook, plugin, ServicePriority.High);
|
||||
sm.register(Chat.class, this.chatHook, plugin, ServicePriority.High);
|
||||
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);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -71,7 +71,7 @@ public class VaultHookManager {
|
||||
* @param plugin the plugin
|
||||
*/
|
||||
public void unhook(LPBukkitPlugin plugin) {
|
||||
final ServicesManager sm = plugin.getServer().getServicesManager();
|
||||
final ServicesManager sm = plugin.getBootstrap().getServer().getServicesManager();
|
||||
|
||||
if (this.permissionHook != null) {
|
||||
sm.unregister(Permission.class, this.permissionHook);
|
||||
|
||||
@@ -34,12 +34,12 @@ 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.commands.CommandManager;
|
||||
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.NodeFactory;
|
||||
import me.lucko.luckperms.common.node.factory.NodeFactory;
|
||||
import me.lucko.luckperms.common.verbose.CheckOrigin;
|
||||
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
@@ -48,6 +48,7 @@ import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -116,8 +117,10 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String world, UUID uuid, String permission) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public boolean userHasPermission(String world, UUID uuid, String permission) {
|
||||
if (uuid == null) {
|
||||
return false;
|
||||
}
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
|
||||
User user = getUser(uuid);
|
||||
@@ -130,14 +133,16 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
|
||||
Tristate result = permissionData.getPermissionValue(permission, CheckOrigin.INTERNAL);
|
||||
if (log()) {
|
||||
logMsg("#hasPermission: %s - %s - %s - %s", user.getFriendlyName(), contexts.getContexts().toMultimap(), permission, result);
|
||||
logMsg("#userHasPermission: %s - %s - %s - %s", user.getFriendlyName(), contexts.getContexts().toMultimap(), permission, result);
|
||||
}
|
||||
return result.asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAddPermission(String world, UUID uuid, String permission) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public boolean userAddPermission(String world, UUID uuid, String permission) {
|
||||
if (uuid == null) {
|
||||
return false;
|
||||
}
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
|
||||
User user = getUser(uuid);
|
||||
@@ -150,8 +155,10 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemovePermission(String world, UUID uuid, String permission) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public boolean userRemovePermission(String world, UUID uuid, String permission) {
|
||||
if (uuid == null) {
|
||||
return false;
|
||||
}
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
|
||||
User user = getUser(uuid);
|
||||
@@ -164,29 +171,37 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerInGroup(String world, UUID uuid, String group) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public boolean userInGroup(String world, UUID uuid, String group) {
|
||||
if (uuid == null) {
|
||||
return false;
|
||||
}
|
||||
Objects.requireNonNull(group, "group");
|
||||
return hasPermission(world, uuid, NodeFactory.groupNode(rewriteGroupName(group)));
|
||||
return userHasPermission(world, uuid, NodeFactory.groupNode(rewriteGroupName(group)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAddGroup(String world, UUID uuid, String group) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public boolean userAddGroup(String world, UUID uuid, String group) {
|
||||
if (uuid == null) {
|
||||
return false;
|
||||
}
|
||||
Objects.requireNonNull(group, "group");
|
||||
return checkGroupExists(group) && playerAddPermission(world, uuid, NodeFactory.groupNode(rewriteGroupName(group)));
|
||||
return checkGroupExists(group) && userAddPermission(world, uuid, NodeFactory.groupNode(rewriteGroupName(group)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemoveGroup(String world, UUID uuid, String group) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public boolean userRemoveGroup(String world, UUID uuid, String group) {
|
||||
if (uuid == null) {
|
||||
return false;
|
||||
}
|
||||
Objects.requireNonNull(group, "group");
|
||||
return checkGroupExists(group) && playerRemovePermission(world, uuid, NodeFactory.groupNode(rewriteGroupName(group)));
|
||||
return checkGroupExists(group) && userRemovePermission(world, uuid, NodeFactory.groupNode(rewriteGroupName(group)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] playerGetGroups(String world, UUID uuid) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public String[] userGetGroups(String world, UUID uuid) {
|
||||
if (uuid == null) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
User user = getUser(uuid);
|
||||
if (user == null) {
|
||||
@@ -195,7 +210,7 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
|
||||
ContextSet contexts = contextForLookup(user, world).getContexts();
|
||||
|
||||
String[] ret = user.getEnduringNodes().values().stream()
|
||||
String[] ret = user.enduringData().immutable().values().stream()
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(n -> n.shouldApplyWithContext(contexts))
|
||||
.map(n -> {
|
||||
@@ -208,15 +223,17 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
.toArray(String[]::new);
|
||||
|
||||
if (log()) {
|
||||
logMsg("#playerGetGroups: %s - %s - %s", user.getFriendlyName(), contexts, Arrays.toString(ret));
|
||||
logMsg("#userGetGroups: %s - %s - %s", user.getFriendlyName(), contexts, Arrays.toString(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String playerPrimaryGroup(String world, UUID uuid) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
public String userGetPrimaryGroup(String world, UUID uuid) {
|
||||
if (uuid == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
User user = getUser(uuid);
|
||||
if (user == null) {
|
||||
@@ -230,7 +247,7 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
}
|
||||
|
||||
if (log()) {
|
||||
logMsg("#playerPrimaryGroup: %s - %s - %s", user.getFriendlyName(), world, value);
|
||||
logMsg("#userGetPrimaryGroup: %s - %s - %s", user.getFriendlyName(), world, value);
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -311,7 +328,7 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
return this.plugin.getConfiguration().get(ConfigKeys.VAULT_DEBUG);
|
||||
}
|
||||
private void logMsg(String format, Object... args) {
|
||||
this.plugin.getLog().info("[VAULT-PERMS] " + String.format(format, args)
|
||||
this.plugin.getLogger().info("[VAULT-PERMS] " + String.format(format, args)
|
||||
.replace(CommandManager.SECTION_CHAR, '$')
|
||||
.replace(CommandManager.AMPERSAND_CHAR, '$')
|
||||
);
|
||||
@@ -321,7 +338,7 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
Contexts contextForLookup(User user, String world) {
|
||||
MutableContextSet context;
|
||||
|
||||
Player player = user == null ? null : this.plugin.getPlayer(user);
|
||||
Player player = Optional.ofNullable(user).flatMap(u -> this.plugin.getBootstrap().getPlayer(u.getUuid())).orElse(null);
|
||||
if (player != null) {
|
||||
context = this.plugin.getContextManager().getApplicableContext(player).mutableCopy();
|
||||
} else {
|
||||
@@ -348,7 +365,7 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
}
|
||||
}
|
||||
|
||||
return new Contexts(context, isIncludeGlobal(), true, true, true, true, false);
|
||||
return Contexts.of(context, isIncludeGlobal(), true, true, true, true, false);
|
||||
}
|
||||
|
||||
// utility methods for modifying the state of PermissionHolders
|
||||
@@ -386,11 +403,11 @@ public class VaultPermissionHook extends AbstractVaultPermission {
|
||||
void holderSave(PermissionHolder holder) {
|
||||
if (holder.getType().isUser()) {
|
||||
User u = (User) holder;
|
||||
this.plugin.getStorage().saveUser(u).thenRunAsync(() -> u.getRefreshBuffer().request(), this.plugin.getScheduler().async());
|
||||
this.plugin.getStorage().saveUser(u);
|
||||
}
|
||||
if (holder.getType().isGroup()) {
|
||||
Group g = (Group) holder;
|
||||
this.plugin.getStorage().saveGroup(g).thenRunAsync(() -> this.plugin.getUpdateTaskBuffer().request(), this.plugin.getScheduler().async());
|
||||
this.plugin.getStorage().saveGroup(g).thenRunAsync(() -> this.plugin.getUpdateTaskBuffer().request(), this.plugin.getBootstrap().getScheduler().async());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,161 +18,312 @@
|
||||
####################################################################################################
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | General | #
|
||||
# | | #
|
||||
# | ESSENTIAL SETTINGS | #
|
||||
# | | #
|
||||
# | Important settings that control how LuckPerms functions. | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# The name of the server, used for server specific permissions. Set to 'global' to disable.
|
||||
# The name of the server, used for server specific permissions.
|
||||
#
|
||||
# - When set to "global" this setting is effectively ignored.
|
||||
# - In all other cases, the value here is added to all players in a "server" context.
|
||||
# - See: https://github.com/lucko/LuckPerms/wiki/Context
|
||||
server: global
|
||||
|
||||
# If users on this server should have their global permissions applied.
|
||||
# If set to false, only server specific permissions will apply for users on this server
|
||||
include-global: true
|
||||
|
||||
# If users on this server should have their global world permissions applied.
|
||||
# If set to false, only world specific permissions will apply for users on this server
|
||||
include-global-world: true
|
||||
|
||||
# If users on this server should have global (non-server specific) groups applied
|
||||
apply-global-groups: true
|
||||
|
||||
# If users on this server should have global (non-world specific) groups applied
|
||||
apply-global-world-groups: true
|
||||
|
||||
# If the servers own UUID cache/lookup facility should be used when there is no record for a player
|
||||
# in the LuckPerms cache.
|
||||
# already in LuckPerms.
|
||||
#
|
||||
# - When this is set to 'false', commands using a player's username will not work unless the player
|
||||
# has joined since LuckPerms was first installed.
|
||||
# - To get around this, you can use a player's uuid directly in the command, or enable this option.
|
||||
# - When this is set to 'true', the server facility is used. This may use a number of methods,
|
||||
# including checking the servers local cache, or making a request to the Mojang API.
|
||||
use-server-uuid-cache: false
|
||||
|
||||
# If LuckPerms should use the "server-name" property from the "server.properties"
|
||||
# file as the "server" option within LuckPerms.
|
||||
use-server-properties-name: false
|
||||
|
||||
# If set to true, LuckPerms will allow usernames with non alphanumeric characters.
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | | #
|
||||
# | STORAGE SETTINGS | #
|
||||
# | | #
|
||||
# | Controls which storage method LuckPerms will use to store data. | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# How the plugin should store data
|
||||
#
|
||||
# Note that due to the design of the storage implementation, usernames must still be
|
||||
# 16 characters or less.
|
||||
allow-invalid-usernames: false
|
||||
|
||||
# If LuckPerms should produce extra logging output when it handles logins.
|
||||
# Useful if you're having issues with UUID forwarding or data not being loaded.
|
||||
debug-logins: false
|
||||
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
log-notify: true
|
||||
|
||||
# Mirrors world names. Whenever LuckPerms checks what world a user is in, if the world name is in
|
||||
# this list, the value assigned will be sent forward for permission calculation instead.
|
||||
world-rewrite:
|
||||
# world_nether: world
|
||||
# world_the_end: world
|
||||
|
||||
# Controls how temporary permissions/parents/meta should be accumulated
|
||||
# - The various options are explained in more detail on the wiki:
|
||||
# https://github.com/lucko/LuckPerms/wiki/Choosing-a-Storage-type
|
||||
#
|
||||
# The default behaviour is "deny"
|
||||
# If "accumulate": durations will be added to the existing expiry time
|
||||
# If "replace": durations will be replaced if the new duration is later than the current expiration
|
||||
# If "deny": the command will just fail if you try to add another node with the same expiry
|
||||
# - Possible options:
|
||||
#
|
||||
# | Remote databases - require connection information to be configured below
|
||||
# |=> MySQL
|
||||
# |=> MariaDB (preferred over MySQL)
|
||||
# |=> PostgreSQL
|
||||
# |=> MongoDB
|
||||
#
|
||||
# | Flatfile/local database - don't require any extra configuration
|
||||
# |=> H2 (preferred over SQLite)
|
||||
# |=> SQLite
|
||||
#
|
||||
# | Readable & editable text files - don't require any extra configuration
|
||||
# |=> YAML (.yml files)
|
||||
# |=> JSON (.json files)
|
||||
# |=> HOCON (.conf files)
|
||||
# |=> TOML (.toml files)
|
||||
# |
|
||||
# | By default, user, group and track data is separated into different files. Data can be combined
|
||||
# | and all stored in the same file by switching to a combined storage variant.
|
||||
# | Just add '-combined' to the end of the storage-method, e.g. 'yaml-combined'
|
||||
#
|
||||
# - A H2 database is the default option.
|
||||
# - If you want to edit data manually in "traditional" storage files, we suggest using YAML.
|
||||
storage-method: h2
|
||||
|
||||
# The following block defines the settings for remote database storage methods.
|
||||
#
|
||||
# - You don't need to touch any of the settings here if you're using a local storage method!
|
||||
# - The connection detail options are shared between all remote storage types.
|
||||
data:
|
||||
|
||||
# Define the address and port for the database.
|
||||
# - The standard DB engine port is used by default
|
||||
# (MySQL: 3306, PostgreSQL: 5432, MongoDB: 27017)
|
||||
# - Specify as "host:port" if differs
|
||||
address: localhost
|
||||
|
||||
# The name of the database to store LuckPerms data in.
|
||||
# - This must be created already. Don't worry about this setting if you're using MongoDB.
|
||||
database: minecraft
|
||||
|
||||
# Credentials for the database.
|
||||
username: root
|
||||
password: ''
|
||||
|
||||
# These settings apply to the MySQL connection pool.
|
||||
# - The default values will be suitable for the majority of users.
|
||||
# - Do not change these settings unless you know what you're doing!
|
||||
pool-settings:
|
||||
|
||||
# Sets the maximum size of the MySQL connection pool.
|
||||
# - Basically this value will determine the maximum number of actual
|
||||
# connections to the database backend.
|
||||
# - More information about determining the size of connection pools can be found here:
|
||||
# https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
|
||||
maximum-pool-size: 10
|
||||
|
||||
# Sets the minimum number of idle connections that the pool will try to maintain.
|
||||
# - For maximum performance and responsiveness to spike demands, it is recommended to not set
|
||||
# this value and instead allow the pool to act as a fixed size connection pool.
|
||||
# (set this value to the same as 'maximum-pool-size')
|
||||
minimum-idle: 10
|
||||
|
||||
# This setting controls the maximum lifetime of a connection in the pool in milliseconds.
|
||||
# - The value should be at least 30 seconds less than any database or infrastructure imposed
|
||||
# connection time limit.
|
||||
maximum-lifetime: 1800000 # 30 minutes
|
||||
|
||||
# This setting controls the maximum number of milliseconds that the plugin will wait for a
|
||||
# connection from the pool, before timing out.
|
||||
connection-timeout: 5000 # 5 seconds
|
||||
|
||||
# This setting allows you to define extra properties for connections.
|
||||
properties:
|
||||
useUnicode: true
|
||||
characterEncoding: utf8
|
||||
|
||||
# The prefix for all LuckPerms SQL tables.
|
||||
# - Change this is you want to use different tables for different servers.
|
||||
table_prefix: 'luckperms_'
|
||||
|
||||
# The prefix to use for all LuckPerms collections. Change this if you want to use different
|
||||
# collections for different servers. The default is no prefix.
|
||||
mongodb_collection_prefix: ''
|
||||
|
||||
# MongoDB ClientConnectionURI for use with replica sets and custom connection options
|
||||
# - See https://docs.mongodb.com/manual/reference/connection-string/
|
||||
mongodb_connection_URI: ''
|
||||
|
||||
# Define settings for a "split" storage setup.
|
||||
#
|
||||
# - This allows you to define a storage method for each type of data.
|
||||
# - The connection options above still have to be correct for each type here.
|
||||
split-storage:
|
||||
# Don't touch this if you don't want to use split storage!
|
||||
enabled: false
|
||||
methods:
|
||||
# These options don't need to be modified if split storage isn't enabled.
|
||||
user: h2
|
||||
group: h2
|
||||
track: h2
|
||||
uuid: h2
|
||||
log: h2
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | | #
|
||||
# | UPDATE PROPAGATION & MESSAGING SERVICE | #
|
||||
# | | #
|
||||
# | Controls the ways in which LuckPerms will sync data & notify other servers of changes. | #
|
||||
# | These options are documented on greater detail on the wiki under "Instant Updates". | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# This option controls how frequently LuckPerms will perform a sync task.
|
||||
#
|
||||
# - A sync task will refresh all data from the storage, and ensure that the most up-to-date data is
|
||||
# being used by the plugin.
|
||||
# - This is disabled by default, as most users will not need it. However, if you're using a remote
|
||||
# storage type without a messaging service setup, you may wish to set this to something like 3.
|
||||
# - Set to -1 to disable the task completely.
|
||||
sync-minutes: -1
|
||||
|
||||
# If the file watcher should be enabled.
|
||||
#
|
||||
# - When using a file-based storage type, LuckPerms can monitor the data files for changes, and
|
||||
# automatically update when changes are detected.
|
||||
# - If you don't want this feature to be active, set this option to false.
|
||||
watch-files: true
|
||||
|
||||
# Define which messaging service should be used by the plugin.
|
||||
#
|
||||
# - If enabled and configured, LuckPerms will use the messaging service to inform other connected
|
||||
# servers of changes.
|
||||
# - Use the command "/lp networksync" to manually push changes.
|
||||
# - Data is NOT stored using this service. It is only used as a messaging platform.
|
||||
#
|
||||
# - If you decide to enable this feature, you should set "sync-minutes" to -1, as there is no need
|
||||
# for LuckPerms to poll the database for changes.
|
||||
#
|
||||
# - Possible options:
|
||||
# => sql Uses the SQL database to form a queue system for communication. Will only work when
|
||||
# 'storage-method' is set to MySQL or MariaDB. This is chosen by default if the
|
||||
# option is set to 'none' and SQL storage is in use. Set to 'notsql' to disable this.
|
||||
# => bungee Uses the plugin messaging channels to communicate with the proxy.
|
||||
# LuckPerms must be installed on your proxy & all connected servers backend servers.
|
||||
# Won't work if you have more than one BungeeCord proxy.
|
||||
# => lilypad Uses LilyPad pub-sub to push changes. You need to have the LilyPad-Connect plugin
|
||||
# installed.
|
||||
# => redis Uses Redis pub-sub to push changes. Your server connection info must be configured
|
||||
# below.
|
||||
# => none Disables the service.
|
||||
messaging-service: none
|
||||
|
||||
# If LuckPerms should automatically push updates after a change has been made with a command.
|
||||
auto-push-updates: true
|
||||
|
||||
# If LuckPerms should push logging entries to connected servers via the messaging service.
|
||||
push-log-entries: true
|
||||
|
||||
# If LuckPerms should broadcast received logging entries to players on this platform.
|
||||
#
|
||||
# - If you have LuckPerms installed on your backend servers as well as a BungeeCord proxy, you
|
||||
# should set this option to false on either your backends or your proxies, to avoid players being
|
||||
# messaged twice about log entries.
|
||||
broadcast-received-log-entries: true
|
||||
|
||||
# Settings for Redis.
|
||||
# Port 6379 is used by default; set address to "host:port" if differs
|
||||
redis:
|
||||
enabled: false
|
||||
address: localhost
|
||||
password: ''
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | | #
|
||||
# | CUSTOMIZATION SETTINGS | #
|
||||
# | | #
|
||||
# | Settings that allow admins to customize the way LuckPerms operates. | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# Controls how temporary permissions/parents/meta should be accumulated.
|
||||
#
|
||||
# - The default behaviour is "deny".
|
||||
# - This behaviour can also be specified when the command is executed. See the command usage
|
||||
# documentation for more info.
|
||||
#
|
||||
# - Possible options:
|
||||
# => accumulate durations will be added to the existing expiry time
|
||||
# => replace durations will be replaced if the new duration is later than the current
|
||||
# expiration
|
||||
# => deny the command will just fail if you try to add another node with the same expiry
|
||||
temporary-add-behaviour: deny
|
||||
|
||||
# How should LuckPerms determine a users "primary" group.
|
||||
# Controls how LuckPerms will determine a users "primary" group.
|
||||
#
|
||||
# Available Options:
|
||||
# -> stored use the value stored against the users record in the file/database
|
||||
# -> parents-by-weight just use the users most highly weighted parent
|
||||
# -> all-parents-by-weight same as above, but calculates based upon all parents inherited from both
|
||||
# directly and indirectly
|
||||
# - The meaning and influence of "primary groups" are explained in detail on the wiki.
|
||||
# - The preferred approach is to let LuckPerms automatically determine a users primary group
|
||||
# based on the relative weight of their parent groups.
|
||||
#
|
||||
# - Possible options:
|
||||
# => stored use the value stored against the users record in the file/database
|
||||
# => parents-by-weight just use the users most highly weighted parent
|
||||
# => all-parents-by-weight same as above, but calculates based upon all parents inherited from
|
||||
# both directly and indirectly
|
||||
primary-group-calculation: parents-by-weight
|
||||
|
||||
# If set to false, the plugin will allow a Users primary group to be removed with the
|
||||
# 'parent remove' command, and will set their primary group back to default.
|
||||
prevent-primary-group-removal: false
|
||||
|
||||
# If the plugin should check for "extra" permissions with users run LP commands.
|
||||
#
|
||||
# These extra permissions allow finer control over what users can do with each command, and
|
||||
# who they have access to edit.
|
||||
#
|
||||
# The permissions are *not* static, unlike the 'base' permisssions, and will depend upon the
|
||||
# arguments given within the command.
|
||||
# - These extra permissions allow finer control over what users can do with each command, and who
|
||||
# they have access to edit.
|
||||
# - The nature of the checks are documented on the wiki under "Argument based command permissions".
|
||||
# - Argument based permissions are *not* static, unlike the 'base' permissions, and will depend upon
|
||||
# the arguments given within the command.
|
||||
argument-based-command-permissions: false
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Permission Calculation | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
# If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered
|
||||
# permissions matching the wildcard.
|
||||
apply-wildcards: true
|
||||
|
||||
# If the plugin should parse regex permissions.
|
||||
# If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the
|
||||
# node, and resolve & apply all registered permissions matching the regex.
|
||||
apply-regex: true
|
||||
|
||||
# If the plugin should complete and apply shorthand permissions.
|
||||
# If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||
apply-shorthand: true
|
||||
|
||||
# If the plugin should apply Bukkit child permissions.
|
||||
# Plugin authors can define custom permissions structures for their plugin, which will be resolved
|
||||
# and used by LuckPerms if this setting is enabled.
|
||||
apply-bukkit-child-permissions: true
|
||||
|
||||
# If the plugin should apply Bukkit default permissions.
|
||||
# Plugin authors can define permissions which should be given to all users by default, or setup
|
||||
# permissions which should/shouldn't be given to opped players.
|
||||
# If this option is set to false, LuckPerms will ignore these defaults.
|
||||
apply-bukkit-default-permissions: true
|
||||
|
||||
# If the plugin should apply attachment permissions.
|
||||
# Other plugins on the server are able to add their own "permission attachments" to players. This
|
||||
# allows them to grant players additional permissions which last until the end of the session, or
|
||||
# until they're removed. If this option is set to false, LuckPerms will not include these attachment
|
||||
# permissions when considering if a player should have access to a certain permission.
|
||||
apply-bukkit-attachment-permissions: true
|
||||
|
||||
# The algorithm LuckPerms should use when traversing the "inheritance tree".
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
#
|
||||
# The valid options are:
|
||||
# - breadth-first
|
||||
# - depth-first-pre-order
|
||||
# - depth-first-post-order
|
||||
# - Notifications are only sent to those with the appropriate permission to receive them
|
||||
# - They can also be temporarily enabled/disabled on a per-user basis using
|
||||
# '/lp log notify <on|off>'
|
||||
log-notify: true
|
||||
|
||||
# Defines the options for prefix and suffix stacking.
|
||||
#
|
||||
# See here for information about the differences between each algorithm.
|
||||
# - https://en.wikipedia.org/wiki/Breadth-first_search
|
||||
# - https://en.wikipedia.org/wiki/Depth-first_search
|
||||
inheritance-traversal-algorithm: depth-first-pre-order
|
||||
|
||||
# Define special group weights for this server.
|
||||
# Default is just 0.
|
||||
group-weight:
|
||||
# admin: 10
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Meta Formatting & Stacking | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# Allows you to setup prefix/suffix stacking options.
|
||||
# - The feature allows you to display multiple prefixes or suffixes alongside a players username in
|
||||
# chat.
|
||||
# - It is explained and documented in more detail on the wiki under "Prefix & Suffix Stacking".
|
||||
#
|
||||
# Available formats:
|
||||
# - highest
|
||||
# - lowest
|
||||
# - highest_own
|
||||
# - lowest_own
|
||||
# - highest_inherited
|
||||
# - lowest_inherited
|
||||
# - highest_on_track_<track>
|
||||
# - lowest_on_track_<track>
|
||||
# - highest_not_on_track_<track>
|
||||
# - lowest_not_on_track_<track>
|
||||
# - The options are divided into separate sections for prefixes and suffixes.
|
||||
# - 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.
|
||||
#
|
||||
# Each element is added in the order listed.
|
||||
# - Possible format options:
|
||||
# => highest Selects the value with the highest weight, from all values
|
||||
# held by or inherited by the player.
|
||||
#
|
||||
# => lowest Same as above, except takes the one with the lowest weight.
|
||||
#
|
||||
# => highest_own Selects the value with the highest weight, but will not
|
||||
# accept any inherited values.
|
||||
#
|
||||
# => lowest_own Same as above, except takes the value with the lowest weight.
|
||||
#
|
||||
# => highest_inherited Selects the value with the highest weight, but will only
|
||||
# accept inherited values.
|
||||
#
|
||||
# => lowest_inherited Same as above, except takes the value with the lowest weight.
|
||||
#
|
||||
# => highest_on_track_<track> Selects the value with the highest weight, but only if the
|
||||
# value was inherited from a group on the given track.
|
||||
#
|
||||
# => lowest_on_track_<track> Same as above, except takes the value with the lowest weight.
|
||||
#
|
||||
# => highest_not_on_track_<track> Selects the value with the highest weight, but only if the
|
||||
# value was inherited from a group not on the given track.
|
||||
#
|
||||
# => lowest_not_on_track_<track> Same as above, except takes the value with the lowest weight.
|
||||
meta-formatting:
|
||||
prefix:
|
||||
format:
|
||||
@@ -191,46 +342,153 @@ meta-formatting:
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | OP (Server Operator) Settings | #
|
||||
# | | #
|
||||
# | PERMISSION CALCULATION AND INHERITANCE | #
|
||||
# | | #
|
||||
# | Modify the way permission checks, meta lookups and inheritance resolutions are handled. | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# If the vanilla OP system is enabled. If set to false, all users will be de-opped, and the op/deop
|
||||
# commands will be disabled.
|
||||
# The algorithm LuckPerms should use when traversing the "inheritance tree".
|
||||
#
|
||||
# - Possible options:
|
||||
# => breadth-first See: https://en.wikipedia.org/wiki/Breadth-first_search
|
||||
# => depth-first-pre-order See: https://en.wikipedia.org/wiki/Depth-first_search
|
||||
# => depth-first-post-order See: https://en.wikipedia.org/wiki/Depth-first_search
|
||||
inheritance-traversal-algorithm: depth-first-pre-order
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Permission resolution settings | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# If users on this server should have their global permissions applied.
|
||||
# When set to false, only server specific permissions will apply for users on this server
|
||||
include-global: true
|
||||
|
||||
# If users on this server should have their global world permissions applied.
|
||||
# When set to false, only world specific permissions will apply for users on this server
|
||||
include-global-world: true
|
||||
|
||||
# If users on this server should have global (non-server specific) groups applied
|
||||
apply-global-groups: true
|
||||
|
||||
# If users on this server should have global (non-world specific) groups applied
|
||||
apply-global-world-groups: true
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Inheritance settings | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
#
|
||||
# - If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered
|
||||
# permissions matching the wildcard.
|
||||
apply-wildcards: true
|
||||
|
||||
# If the plugin should parse regex permissions.
|
||||
#
|
||||
# - If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the
|
||||
# node, and resolve & apply all registered permissions matching the regex.
|
||||
apply-regex: true
|
||||
|
||||
# If the plugin should complete and apply shorthand permissions.
|
||||
#
|
||||
# - If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||
apply-shorthand: true
|
||||
|
||||
# If the plugin should apply Bukkit child permissions.
|
||||
#
|
||||
# - Plugin authors can define custom permissions structures for their plugin, which will be resolved
|
||||
# and used by LuckPerms if this setting is enabled.
|
||||
apply-bukkit-child-permissions: true
|
||||
|
||||
# If the plugin should apply Bukkit default permissions.
|
||||
#
|
||||
# - Plugin authors can define permissions which should be given to all users by default, or setup
|
||||
# permissions which should/shouldn't be given to opped players.
|
||||
# - If this option is set to false, LuckPerms will ignore these defaults.
|
||||
apply-bukkit-default-permissions: true
|
||||
|
||||
# If the plugin should apply attachment permissions.
|
||||
#
|
||||
# - Other plugins on the server are able to add their own "permission attachments" to players.
|
||||
# - This allows them to grant players additional permissions which last until the end of the
|
||||
# session, or until they're removed.
|
||||
# - If this option is set to false, LuckPerms will not include these attachment permissions when
|
||||
# considering if a player should have access to a certain permission.
|
||||
apply-bukkit-attachment-permissions: true
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Extra settings | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# Allows you to set "aliases" for the worlds sent forward for context calculation.
|
||||
#
|
||||
# - These aliases are provided in addition to the real world name. Applied recursively.
|
||||
# - Remove the comment characters for the default aliases to apply.
|
||||
world-rewrite:
|
||||
# world_nether: world
|
||||
# world_the_end: world
|
||||
|
||||
# Define special group weights for this server.
|
||||
#
|
||||
# - Group weights can also be applied directly to group data, using the setweight command.
|
||||
# - This section allows weights to be set on a per-server basis.
|
||||
group-weight:
|
||||
# admin: 10
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | | #
|
||||
# | FINE TUNING OPTIONS | #
|
||||
# | | #
|
||||
# | A number of more niche settings for tweaking and changing behaviour. The section also | #
|
||||
# | contains toggles for some more specialised features. It is only necessary to make changes to | #
|
||||
# | these options if you want to fine-tune LuckPerms behaviour. | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Server Operator (OP) settings | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# Controls whether server operators should exist at all.
|
||||
#
|
||||
# - When set to 'false', all players will be de-opped, and the /op and /deop commands will be
|
||||
# disabled.
|
||||
enable-ops: true
|
||||
|
||||
# If set to true, any user with the permission "luckperms.autoop" will automatically be granted
|
||||
# server operator status. This permission can be inherited, or set on specific servers/worlds,
|
||||
# temporarily, etc.
|
||||
# Enables or disables a special permission based system in LuckPerms for controlling OP status.
|
||||
#
|
||||
# Additionally, setting this to true will force the "enable-ops" option above to false. All users
|
||||
# will be de-opped unless they have the permission node, and the op/deop commands will be disabled.
|
||||
#
|
||||
# It is important to note that this setting is only checked when a player first joins the server,
|
||||
# and when they switch worlds. Therefore, simply removing this permission from a user will not
|
||||
# automatically de-op them. A player needs to relog to have the change take effect.
|
||||
#
|
||||
# It is recommended that you use this option instead of assigning a single '*' permission.
|
||||
# - If set to true, any user with the permission "luckperms.autoop" will automatically be granted
|
||||
# server operator status. This permission can be inherited, or set on specific servers/worlds,
|
||||
# temporarily, etc.
|
||||
# - Additionally, setting this to true will force the "enable-ops" option above to false. All users
|
||||
# will be de-opped unless they have the permission node, and the op/deop commands will be
|
||||
# disabled.
|
||||
# - It is recommended that you use this option instead of assigning a single '*' permission.
|
||||
auto-op: false
|
||||
|
||||
# If opped players should be allowed to use LuckPerms commands. Set to false to only allow users who
|
||||
# have the permissions access to the commands
|
||||
# Defines if "opped" players should be able to use all LuckPerms commands by default.
|
||||
#
|
||||
# - Set to false to only allow users who have the permissions access to the commands
|
||||
commands-allow-op: true
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Vault | #
|
||||
# | Vault integration settings | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# 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.
|
||||
#
|
||||
# - When this option is set to false, the server value defined above under "server" is used.
|
||||
use-vault-server: false
|
||||
|
||||
# The name of the server used within Vault operations. If you don't want Vault operations to be
|
||||
# server specific, set this to "global".
|
||||
# The name of the server used within Vault operations.
|
||||
#
|
||||
# Will only take effect if use-vault-server is set to true above.
|
||||
# - If you don't want Vault operations to be server specific, set this to "global".
|
||||
# - Will only take effect if use-vault-server is set to true above.
|
||||
vault-server: global
|
||||
|
||||
# If global permissions should be considered when retrieving meta or player groups
|
||||
@@ -242,150 +500,37 @@ vault-ignore-world: false
|
||||
# If LuckPerms should print debugging info to console when a plugin uses a Vault function
|
||||
vault-debug: false
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Storage | #
|
||||
# | Miscellaneous (and rarely used) settings | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# If LuckPerms should produce extra logging output when it handles logins.
|
||||
#
|
||||
# See: https://github.com/lucko/LuckPerms/wiki/Choosing-a-Storage-type
|
||||
# Currently supported: mysql, mariadb, postgresql, sqlite, h2, json, yaml, hocon, mongodb
|
||||
# - Useful if you're having issues with UUID forwarding or data not being loaded.
|
||||
debug-logins: false
|
||||
|
||||
# If LuckPerms should use the "server-name" property from the "server.properties" file as the
|
||||
# "server" option within LuckPerms.
|
||||
use-server-properties-name: false
|
||||
|
||||
# If LuckPerms should allow usernames with non alphanumeric characters.
|
||||
#
|
||||
# Fill out connection info below if you're using MySQL, MariaDB, PostgreSQL or MongoDB
|
||||
# If your MySQL server supports it, the "mariadb" option is preferred over "mysql".
|
||||
storage-method: h2
|
||||
# - Note that due to the design of the storage implementation, usernames must still be 16 characters
|
||||
# or less.
|
||||
allow-invalid-usernames: false
|
||||
|
||||
# When using a file-based storage type, LuckPerms can monitor the data files for changes, and then
|
||||
# schedule automatic updates when changes are detected.
|
||||
# If LuckPerms should allow a users primary group to be removed with the 'parent remove' command.
|
||||
#
|
||||
# If you don't want this to happen, set this option to false.
|
||||
watch-files: true
|
||||
|
||||
# This block enables support for split datastores.
|
||||
split-storage:
|
||||
enabled: false
|
||||
methods:
|
||||
user: h2
|
||||
group: h2
|
||||
track: h2
|
||||
uuid: h2
|
||||
log: h2
|
||||
|
||||
data:
|
||||
# Uses standard DB engine port by default
|
||||
# MySQL: 3306, PostgreSQL: 5432, MongoDB: 27017
|
||||
# Specify as "host:port" if differs
|
||||
address: localhost
|
||||
|
||||
database: minecraft
|
||||
username: root
|
||||
password: ''
|
||||
|
||||
# These settings apply to the MySQL connection pool.
|
||||
# The default values will be suitable for the majority of users.
|
||||
# Do not change these settings unless you know what you're doing!
|
||||
pool-settings:
|
||||
|
||||
# Sets the maximum size of the MySQL connection pool.
|
||||
# Basically this value will determine the maximum number of actual
|
||||
# connections to the database backend.
|
||||
#
|
||||
# More information about determining the size of connection pools can be found here:
|
||||
# https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
|
||||
maximum-pool-size: 10
|
||||
|
||||
# Sets the minimum number of idle connections that the pool will try to maintain.
|
||||
#
|
||||
# For maximum performance and responsiveness to spike demands, it is recommended to not set
|
||||
# this value and instead allow the pool to act as a fixed size connection pool.
|
||||
# (set this value to the same as 'maximum-pool-size')
|
||||
minimum-idle: 10
|
||||
|
||||
# This setting controls the maximum lifetime of a connection in the pool in milliseconds.
|
||||
# The value should be at least 30 seconds less than any database or infrastructure imposed
|
||||
# connection time limit.
|
||||
maximum-lifetime: 1800000 # 30 minutes
|
||||
|
||||
# This setting controls the maximum number of milliseconds that the plugin will wait for a
|
||||
# connection from the pool, before timing out.
|
||||
connection-timeout: 5000 # 5 seconds
|
||||
|
||||
# This setting allows you to define extra properties for connections.
|
||||
properties:
|
||||
useUnicode: true
|
||||
characterEncoding: utf8
|
||||
|
||||
# The prefix for all LuckPerms tables. Change this is you want to use different tables for
|
||||
# different servers.
|
||||
#
|
||||
# This should *not* be set to "lp_" if you have previously ran LuckPerms v2.16.81 or earlier with
|
||||
# this database.
|
||||
table_prefix: 'luckperms_'
|
||||
|
||||
# The prefix to use for all LuckPerms collections. Change this if you want to use different
|
||||
# collections for different servers. The default is no prefix.
|
||||
mongodb_collection_prefix: ''
|
||||
|
||||
# MongoDB ClientConnectionURI for use with replicasets and custom connection options
|
||||
# See https://docs.mongodb.com/manual/reference/connection-string/
|
||||
mongodb_connection_URI: ''
|
||||
|
||||
# This option controls how frequently LuckPerms will perform a sync task.
|
||||
# A sync task will refresh all data from the storage, and ensure that the most up-to-date data is
|
||||
# being used by the plugin.
|
||||
#
|
||||
# This is disabled by default, as most users will not need it. However, if you're using a remote
|
||||
# storage type without a messaging service setup, you may wish to set this value to something like
|
||||
# 3.
|
||||
#
|
||||
# Set to -1 to disable the task completely.
|
||||
sync-minutes: -1
|
||||
|
||||
# Settings for the messaging service
|
||||
#
|
||||
# If enabled and configured, LuckPerms will use the messaging system to inform other
|
||||
# connected servers of changes. Use the command "/luckperms networksync" to push changes.
|
||||
# Data is NOT stored using this service. It is only used as a messaging platform.
|
||||
#
|
||||
# If you decide to enable this feature, you should set "sync-minutes" to -1, as there is no need for
|
||||
# LuckPerms to poll the database for changes.
|
||||
#
|
||||
# Available options:
|
||||
# -> bungee uses the plugin messaging channels. Must be enabled on all connected servers to work.
|
||||
# -> lilypad uses lilypad pub sub to push changes. You need to have the LilyPad-Connect plugin
|
||||
# installed.
|
||||
# -> redis uses redis pub sub to push changes. Your redis server must be configured below.
|
||||
# -> none nothing
|
||||
messaging-service: none
|
||||
|
||||
# If LuckPerms should automatically push updates after a change has been made with a command.
|
||||
auto-push-updates: true
|
||||
|
||||
# If LuckPerms should push logging entries to connected servers via the messaging service.
|
||||
push-log-entries: true
|
||||
|
||||
# If LuckPerms should broadcast received logging entries to players on this platform.
|
||||
#
|
||||
# If you have LuckPerms installed on your backend servers as well as a BungeeCord proxy, you should
|
||||
# set this option to false on either your backends or your proxies, to avoid players being messaged
|
||||
# twice about log entries.
|
||||
broadcast-received-log-entries: true
|
||||
|
||||
# Settings for Redis.
|
||||
# Port 6379 is used by default; set address to "host:port" if differs
|
||||
redis:
|
||||
enabled: false
|
||||
address: localhost
|
||||
password: ''
|
||||
# - When this happens, the plugin will set their primary group back to default.
|
||||
prevent-primary-group-removal: false
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Default Assignments | #
|
||||
# | | #
|
||||
# | DEFAULT ASSIGNMENTS | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# This section allows you to define defaults to give users whenever they connect to the server.
|
||||
|
||||
@@ -4,7 +4,7 @@ description: A permissions plugin
|
||||
author: Luck
|
||||
website: https://github.com/lucko/LuckPerms
|
||||
|
||||
main: me.lucko.luckperms.bukkit.LPBukkitPlugin
|
||||
main: me.lucko.luckperms.bukkit.LPBukkitBootstrap
|
||||
load: STARTUP
|
||||
|
||||
# This means that all plugins that (soft-)depend on Vault, depend on LuckPerms too.
|
||||
|
||||
+1
-5
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>4.1-SNAPSHOT</version>
|
||||
<version>4.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -100,10 +100,6 @@
|
||||
<pattern>ninja.leaping.configurate</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.configurate</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.typesafe.config</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.hocon</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
@@ -28,8 +28,8 @@ package me.lucko.luckperms.bungee;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.command.CommandManager;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
@@ -45,7 +45,7 @@ public class BungeeCommandExecutor extends Command implements TabExecutor {
|
||||
private final LPBungeePlugin plugin;
|
||||
private final CommandManager manager;
|
||||
|
||||
BungeeCommandExecutor(LPBungeePlugin plugin, CommandManager manager) {
|
||||
public BungeeCommandExecutor(LPBungeePlugin plugin, CommandManager manager) {
|
||||
super("luckpermsbungee", null, "lpb", "bperm", "bperms", "bpermission", "bpermissions");
|
||||
this.plugin = plugin;
|
||||
this.manager = manager;
|
||||
|
||||
@@ -61,11 +61,6 @@ public class BungeeConfigAdapter extends AbstractConfigurationAdapter implements
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(String path) {
|
||||
return this.configuration.contains(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String path, String def) {
|
||||
return this.configuration.getString(path, def);
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.bungee;
|
||||
|
||||
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||
import me.lucko.luckperms.common.event.AbstractEventBus;
|
||||
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
public class BungeeEventBus extends AbstractEventBus<Plugin> implements Listener {
|
||||
private final LPBungeeBootstrap bootstrap;
|
||||
|
||||
public BungeeEventBus(LPBungeePlugin plugin, LuckPermsApiProvider apiProvider) {
|
||||
super(plugin, apiProvider);
|
||||
this.bootstrap = plugin.getBootstrap();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Plugin checkPlugin(Object plugin) throws IllegalArgumentException {
|
||||
if (plugin instanceof Plugin) {
|
||||
Plugin bungeePlugin = (Plugin) plugin;
|
||||
|
||||
// add a custom log handler to effectively listen for the plugin being disabled.
|
||||
// BungeeCord doesn't really support enabling/disabling plugins at runtime, and as
|
||||
// such doesn't have a PluginDisableEvent. However, some plugins do exist to reload
|
||||
// plugins at runtime. We rely on these plugins following the BungeeCord behaviour,
|
||||
// and #close ing the plugins logger, so we can unregister the listeners. :)
|
||||
Handler[] handlers = bungeePlugin.getLogger().getHandlers();
|
||||
for (Handler handler : handlers) {
|
||||
if (handler instanceof UnloadHookLoggerHandler) {
|
||||
return bungeePlugin;
|
||||
}
|
||||
}
|
||||
|
||||
bungeePlugin.getLogger().addHandler(new UnloadHookLoggerHandler(bungeePlugin));
|
||||
return bungeePlugin;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Object " + plugin + " (" + plugin.getClass().getName() + ") is not a plugin.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
for (Plugin plugin : this.bootstrap.getProxy().getPluginManager().getPlugins()) {
|
||||
for (Handler handler : plugin.getLogger().getHandlers()) {
|
||||
if (handler instanceof UnloadHookLoggerHandler) {
|
||||
plugin.getLogger().removeHandler(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.close();
|
||||
}
|
||||
|
||||
private final class UnloadHookLoggerHandler extends Handler {
|
||||
private final Plugin plugin;
|
||||
|
||||
private UnloadHookLoggerHandler(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
unregisterHandlers(this.plugin);
|
||||
}
|
||||
|
||||
@Override public void publish(LogRecord record) {}
|
||||
@Override public void flush() {}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ package me.lucko.luckperms.bungee;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.plugin.SchedulerTask;
|
||||
import me.lucko.luckperms.common.utils.SafeIteration;
|
||||
import me.lucko.luckperms.common.utils.Iterators;
|
||||
|
||||
import net.md_5.bungee.api.scheduler.ScheduledTask;
|
||||
import net.md_5.bungee.api.scheduler.TaskScheduler;
|
||||
@@ -50,18 +50,18 @@ public class BungeeSchedulerAdapter implements SchedulerAdapter {
|
||||
return ticks * MILLISECONDS_PER_TICK;
|
||||
}
|
||||
|
||||
private final LPBungeePlugin plugin;
|
||||
private final LPBungeeBootstrap bootstrap;
|
||||
|
||||
private final Executor asyncExecutor;
|
||||
private final Set<SchedulerTask> tasks = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public BungeeSchedulerAdapter(LPBungeePlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.asyncExecutor = r -> plugin.getProxy().getScheduler().runAsync(plugin, r);
|
||||
public BungeeSchedulerAdapter(LPBungeeBootstrap bootstrap) {
|
||||
this.bootstrap = bootstrap;
|
||||
this.asyncExecutor = r -> bootstrap.getProxy().getScheduler().runAsync(bootstrap, r);
|
||||
}
|
||||
|
||||
private TaskScheduler scheduler() {
|
||||
return this.plugin.getProxy().getScheduler();
|
||||
return this.bootstrap.getProxy().getScheduler();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,7 +87,7 @@ public class BungeeSchedulerAdapter implements SchedulerAdapter {
|
||||
@Override
|
||||
public SchedulerTask asyncRepeating(Runnable runnable, long intervalTicks) {
|
||||
long millis = ticksToMillis(intervalTicks);
|
||||
SchedulerTask task = new BungeeSchedulerTask(scheduler().schedule(this.plugin, runnable, millis, millis, TimeUnit.MILLISECONDS));
|
||||
SchedulerTask task = new BungeeSchedulerTask(scheduler().schedule(this.bootstrap, runnable, millis, millis, TimeUnit.MILLISECONDS));
|
||||
this.tasks.add(task);
|
||||
return task;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ public class BungeeSchedulerAdapter implements SchedulerAdapter {
|
||||
|
||||
@Override
|
||||
public SchedulerTask asyncLater(Runnable runnable, long delayTicks) {
|
||||
return new BungeeSchedulerTask(scheduler().schedule(this.plugin, runnable, ticksToMillis(delayTicks), TimeUnit.MILLISECONDS));
|
||||
return new BungeeSchedulerTask(scheduler().schedule(this.bootstrap, runnable, ticksToMillis(delayTicks), TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,7 +109,7 @@ public class BungeeSchedulerAdapter implements SchedulerAdapter {
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
SafeIteration.iterate(this.tasks, SchedulerTask::cancel);
|
||||
Iterators.iterate(this.tasks, SchedulerTask::cancel);
|
||||
}
|
||||
|
||||
private static final class BungeeSchedulerTask implements SchedulerTask {
|
||||
|
||||
@@ -27,15 +27,16 @@ package me.lucko.luckperms.bungee;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.bungee.event.TristateCheckEvent;
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.sender.SenderFactory;
|
||||
import me.lucko.luckperms.common.command.CommandManager;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.SenderFactory;
|
||||
import me.lucko.luckperms.common.utils.TextUtils;
|
||||
|
||||
import net.kyori.text.Component;
|
||||
import net.kyori.text.serializer.ComponentSerializers;
|
||||
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;
|
||||
|
||||
@@ -67,7 +68,7 @@ public class BungeeSenderFactory extends SenderFactory<CommandSender> {
|
||||
|
||||
@Override
|
||||
protected void sendMessage(CommandSender sender, Component message) {
|
||||
sender.sendMessage(net.md_5.bungee.chat.ComponentSerializer.parse(ComponentSerializers.JSON.serialize(message)));
|
||||
sender.sendMessage(ComponentSerializer.parse(ComponentSerializers.JSON.serialize(message)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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.bungee;
|
||||
|
||||
import me.lucko.luckperms.api.platform.PlatformType;
|
||||
import me.lucko.luckperms.bungee.util.RedisBungeeUtil;
|
||||
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
||||
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
|
||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
|
||||
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Bootstrap plugin for LuckPerms running on BungeeCord.
|
||||
*/
|
||||
public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
|
||||
|
||||
/**
|
||||
* A scheduler adapter for the platform
|
||||
*/
|
||||
private final SchedulerAdapter schedulerAdapter;
|
||||
|
||||
/**
|
||||
* The plugin classloader
|
||||
*/
|
||||
private final PluginClassLoader classLoader;
|
||||
|
||||
/**
|
||||
* The plugin instance
|
||||
*/
|
||||
private final LPBungeePlugin plugin;
|
||||
|
||||
/**
|
||||
* The time when the plugin was enabled
|
||||
*/
|
||||
private long startTime;
|
||||
|
||||
// load/enable latches
|
||||
private final CountDownLatch loadLatch = new CountDownLatch(1);
|
||||
private final CountDownLatch enableLatch = new CountDownLatch(1);
|
||||
|
||||
public LPBungeeBootstrap() {
|
||||
this.schedulerAdapter = new BungeeSchedulerAdapter(this);
|
||||
this.classLoader = new ReflectionClassLoader(this);
|
||||
this.plugin = new LPBungeePlugin(this);
|
||||
}
|
||||
|
||||
// provide adapters
|
||||
|
||||
@Override
|
||||
public SchedulerAdapter getScheduler() {
|
||||
return this.schedulerAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginClassLoader getPluginClassLoader() {
|
||||
return this.classLoader;
|
||||
}
|
||||
|
||||
// lifecycle
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
try {
|
||||
this.plugin.load();
|
||||
} finally {
|
||||
this.loadLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
this.startTime = System.currentTimeMillis();
|
||||
try {
|
||||
this.plugin.enable();
|
||||
} finally {
|
||||
this.enableLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
this.plugin.disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CountDownLatch getEnableLatch() {
|
||||
return this.enableLatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CountDownLatch getLoadLatch() {
|
||||
return this.loadLatch;
|
||||
}
|
||||
|
||||
// provide information about the plugin
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartupTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
// provide information about the platform
|
||||
|
||||
@Override
|
||||
public PlatformType getType() {
|
||||
return PlatformType.BUNGEE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerBrand() {
|
||||
return getProxy().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersion() {
|
||||
return getProxy().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getDataDirectory() {
|
||||
return getDataFolder().toPath().toAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceStream(String path) {
|
||||
return getResourceAsStream(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ProxiedPlayer> getPlayer(UUID uuid) {
|
||||
return Optional.ofNullable(getProxy().getPlayer(uuid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> lookupUuid(String username) {
|
||||
if (getProxy().getPluginManager().getPlugin("RedisBungee") != null) {
|
||||
try {
|
||||
return RedisBungeeUtil.lookupUuid(username);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> lookupUsername(UUID uuid) {
|
||||
if (getProxy().getPluginManager().getPlugin("RedisBungee") != null) {
|
||||
try {
|
||||
return RedisBungeeUtil.lookupUsername(uuid);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getProxy().getOnlineCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getPlayerList() {
|
||||
return getProxy().getPlayers().stream().map(ProxiedPlayer::getName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<UUID> getOnlinePlayers() {
|
||||
return getProxy().getPlayers().stream().map(ProxiedPlayer::getUniqueId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerOnline(UUID uuid) {
|
||||
ProxiedPlayer player = getProxy().getPlayer(uuid);
|
||||
return player != null && player.isConnected();
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.platform.PlatformType;
|
||||
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;
|
||||
@@ -34,235 +34,148 @@ import me.lucko.luckperms.bungee.contexts.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.bungee.util.RedisBungeeUtil;
|
||||
import me.lucko.luckperms.common.actionlog.LogDispatcher;
|
||||
import me.lucko.luckperms.common.api.ApiRegistrationUtil;
|
||||
import me.lucko.luckperms.common.api.LuckPermsApiProvider;
|
||||
import me.lucko.luckperms.common.buffers.BufferedRequest;
|
||||
import me.lucko.luckperms.common.buffers.UpdateTaskBuffer;
|
||||
import me.lucko.luckperms.common.caching.handlers.CachedStateManager;
|
||||
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.config.AbstractConfiguration;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.config.LuckPermsConfiguration;
|
||||
import me.lucko.luckperms.common.calculators.PlatformCalculatorFactory;
|
||||
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.contexts.LuckPermsCalculator;
|
||||
import me.lucko.luckperms.common.dependencies.DependencyManager;
|
||||
import me.lucko.luckperms.common.dependencies.DependencyRegistry;
|
||||
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
|
||||
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
|
||||
import me.lucko.luckperms.common.event.EventFactory;
|
||||
import me.lucko.luckperms.common.inheritance.InheritanceHandler;
|
||||
import me.lucko.luckperms.common.locale.LocaleManager;
|
||||
import me.lucko.luckperms.common.locale.NoopLocaleManager;
|
||||
import me.lucko.luckperms.common.locale.SimpleLocaleManager;
|
||||
import me.lucko.luckperms.common.logging.Logger;
|
||||
import me.lucko.luckperms.common.logging.SenderLogger;
|
||||
import me.lucko.luckperms.common.dependencies.Dependency;
|
||||
import me.lucko.luckperms.common.event.AbstractEventBus;
|
||||
import me.lucko.luckperms.common.listener.ConnectionListener;
|
||||
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.InternalMessagingService;
|
||||
import me.lucko.luckperms.common.messaging.MessagingFactory;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.plugin.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.storage.Storage;
|
||||
import me.lucko.luckperms.common.storage.StorageFactory;
|
||||
import me.lucko.luckperms.common.storage.StorageType;
|
||||
import me.lucko.luckperms.common.storage.dao.file.FileWatcher;
|
||||
import me.lucko.luckperms.common.plugin.AbstractLuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
|
||||
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
|
||||
import me.lucko.luckperms.common.tasks.UpdateTask;
|
||||
import me.lucko.luckperms.common.treeview.PermissionVault;
|
||||
import me.lucko.luckperms.common.verbose.VerboseHandler;
|
||||
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* LuckPerms implementation for the BungeeCord API.
|
||||
*/
|
||||
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
public class LPBungeePlugin extends AbstractLuckPermsPlugin {
|
||||
private final LPBungeeBootstrap bootstrap;
|
||||
|
||||
private long startTime;
|
||||
private SchedulerAdapter scheduler;
|
||||
private BungeeSenderFactory senderFactory;
|
||||
private BungeeConnectionListener connectionListener;
|
||||
private CommandManager commandManager;
|
||||
private LuckPermsConfiguration configuration;
|
||||
private StandardUserManager userManager;
|
||||
private StandardGroupManager groupManager;
|
||||
private StandardTrackManager trackManager;
|
||||
private Storage storage;
|
||||
private FileWatcher fileWatcher = null;
|
||||
private InternalMessagingService messagingService = null;
|
||||
private LuckPermsApiProvider apiProvider;
|
||||
private EventFactory eventFactory;
|
||||
private Logger log;
|
||||
private LocaleManager localeManager;
|
||||
private PluginClassLoader pluginClassLoader;
|
||||
private DependencyManager dependencyManager;
|
||||
private InheritanceHandler inheritanceHandler;
|
||||
private CachedStateManager cachedStateManager;
|
||||
private ContextManager<ProxiedPlayer> contextManager;
|
||||
private CalculatorFactory calculatorFactory;
|
||||
private BufferedRequest<Void> updateTaskBuffer;
|
||||
private VerboseHandler verboseHandler;
|
||||
private BungeeSenderFactory senderFactory;
|
||||
private PermissionVault permissionVault;
|
||||
private LogDispatcher logDispatcher;
|
||||
private Set<UUID> uniqueConnections = ConcurrentHashMap.newKeySet();
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// setup minimal functionality in order to load initial dependencies
|
||||
this.scheduler = new BungeeSchedulerAdapter(this);
|
||||
this.localeManager = new NoopLocaleManager();
|
||||
this.senderFactory = new BungeeSenderFactory(this);
|
||||
this.log = new SenderLogger(this, getConsoleSender());
|
||||
|
||||
this.pluginClassLoader = new ReflectionClassLoader(this);
|
||||
this.dependencyManager = new DependencyManager(this);
|
||||
this.dependencyManager.loadDependencies(DependencyRegistry.GLOBAL_DEPENDENCIES);
|
||||
public LPBungeePlugin(LPBungeeBootstrap bootstrap) {
|
||||
this.bootstrap = bootstrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
this.startTime = System.currentTimeMillis();
|
||||
sendStartupBanner(getConsoleSender());
|
||||
this.verboseHandler = new VerboseHandler(this.scheduler.async());
|
||||
this.permissionVault = new PermissionVault(this.scheduler.async());
|
||||
this.logDispatcher = new LogDispatcher(this);
|
||||
public LPBungeeBootstrap getBootstrap() {
|
||||
return this.bootstrap;
|
||||
}
|
||||
|
||||
getLog().info("Loading configuration...");
|
||||
this.configuration = new AbstractConfiguration(this, new BungeeConfigAdapter(this, resolveConfig("config.yml")));
|
||||
this.configuration.loadAll();
|
||||
@Override
|
||||
protected void setupSenderFactory() {
|
||||
this.senderFactory = new BungeeSenderFactory(this);
|
||||
}
|
||||
|
||||
StorageFactory storageFactory = new StorageFactory(this);
|
||||
Set<StorageType> storageTypes = storageFactory.getRequiredTypes(StorageType.H2);
|
||||
this.dependencyManager.loadStorageDependencies(storageTypes);
|
||||
@Override
|
||||
protected Set<Dependency> getGlobalDependencies() {
|
||||
return EnumSet.of(Dependency.CAFFEINE, Dependency.OKIO, Dependency.OKHTTP);
|
||||
}
|
||||
|
||||
// register events
|
||||
getProxy().getPluginManager().registerListener(this, new BungeeConnectionListener(this));
|
||||
getProxy().getPluginManager().registerListener(this, new BungeePermissionCheckListener(this));
|
||||
@Override
|
||||
protected ConfigurationAdapter provideConfigurationAdapter() {
|
||||
return new BungeeConfigAdapter(this, resolveConfig());
|
||||
}
|
||||
|
||||
if (getConfiguration().get(ConfigKeys.WATCH_FILES)) {
|
||||
this.fileWatcher = new FileWatcher(this);
|
||||
getScheduler().asyncRepeating(this.fileWatcher, 30L);
|
||||
}
|
||||
@Override
|
||||
protected void registerPlatformListeners() {
|
||||
this.connectionListener = new BungeeConnectionListener(this);
|
||||
this.bootstrap.getProxy().getPluginManager().registerListener(this.bootstrap, this.connectionListener);
|
||||
this.bootstrap.getProxy().getPluginManager().registerListener(this.bootstrap, new BungeePermissionCheckListener(this));
|
||||
}
|
||||
|
||||
// initialise datastore
|
||||
this.storage = storageFactory.getInstance(StorageType.H2);
|
||||
@Override
|
||||
protected MessagingFactory<?> provideMessagingFactory() {
|
||||
return new BungeeMessagingFactory(this);
|
||||
}
|
||||
|
||||
// initialise messaging
|
||||
this.messagingService = new BungeeMessagingFactory(this).getInstance();
|
||||
|
||||
// setup the update task buffer
|
||||
this.updateTaskBuffer = new UpdateTaskBuffer(this);
|
||||
|
||||
// load locale
|
||||
this.localeManager = new SimpleLocaleManager();
|
||||
this.localeManager.tryLoad(this, new File(getDataFolder(), "lang.yml"));
|
||||
|
||||
// register commands
|
||||
@Override
|
||||
protected void registerCommands() {
|
||||
this.commandManager = new CommandManager(this);
|
||||
getProxy().getPluginManager().registerCommand(this, new BungeeCommandExecutor(this, this.commandManager));
|
||||
this.bootstrap.getProxy().getPluginManager().registerCommand(this.bootstrap, new BungeeCommandExecutor(this, this.commandManager));
|
||||
|
||||
// disable the default Bungee /perms command so it gets handled by the Bukkit plugin
|
||||
getProxy().getDisabledCommands().add("perms");
|
||||
this.bootstrap.getProxy().getDisabledCommands().add("perms");
|
||||
}
|
||||
|
||||
// load internal managers
|
||||
getLog().info("Loading internal permission managers...");
|
||||
this.inheritanceHandler = new InheritanceHandler(this);
|
||||
@Override
|
||||
protected void setupManagers() {
|
||||
this.userManager = new StandardUserManager(this);
|
||||
this.groupManager = new StandardGroupManager(this);
|
||||
this.trackManager = new StandardTrackManager(this);
|
||||
this.calculatorFactory = new BungeeCalculatorFactory(this);
|
||||
this.cachedStateManager = new CachedStateManager();
|
||||
|
||||
// setup context manager
|
||||
this.contextManager = new BungeeContextManager(this);
|
||||
this.contextManager.registerCalculator(new BackendServerCalculator(this));
|
||||
this.contextManager.registerStaticCalculator(new LuckPermsCalculator(getConfiguration()));
|
||||
|
||||
if (getProxy().getPluginManager().getPlugin("RedisBungee") != null) {
|
||||
this.contextManager.registerStaticCalculator(new RedisBungeeCalculator());
|
||||
}
|
||||
|
||||
// register with the LP API
|
||||
this.apiProvider = new LuckPermsApiProvider(this);
|
||||
|
||||
// setup event factory
|
||||
this.eventFactory = new EventFactory(this, this.apiProvider);
|
||||
|
||||
ApiRegistrationUtil.registerProvider(this.apiProvider);
|
||||
|
||||
// schedule update tasks
|
||||
int mins = getConfiguration().get(ConfigKeys.SYNC_TIME);
|
||||
if (mins > 0) {
|
||||
long ticks = mins * 60 * 20;
|
||||
this.scheduler.asyncRepeating(() -> this.updateTaskBuffer.request(), ticks);
|
||||
}
|
||||
this.scheduler.asyncLater(() -> this.updateTaskBuffer.request(), 40L);
|
||||
|
||||
// run an update instantly.
|
||||
getLog().info("Performing initial data load...");
|
||||
try {
|
||||
new UpdateTask(this, true).run();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
// register tasks
|
||||
this.scheduler.asyncRepeating(new ExpireTemporaryTask(this), 60L);
|
||||
this.scheduler.asyncRepeating(new CacheHousekeepingTask(this), 2400L);
|
||||
|
||||
getLog().info("Successfully enabled. (took " + (System.currentTimeMillis() - this.startTime) + "ms)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
this.permissionVault.shutdown();
|
||||
this.verboseHandler.shutdown();
|
||||
|
||||
getLog().info("Closing storage...");
|
||||
this.storage.shutdown();
|
||||
|
||||
if (this.fileWatcher != null) {
|
||||
this.fileWatcher.close();
|
||||
}
|
||||
|
||||
if (this.messagingService != null) {
|
||||
getLog().info("Closing messaging service...");
|
||||
this.messagingService.close();
|
||||
}
|
||||
|
||||
ApiRegistrationUtil.unregisterProvider();
|
||||
|
||||
getLog().info("Shutting down internal scheduler...");
|
||||
this.scheduler.shutdown();
|
||||
|
||||
getProxy().getScheduler().cancel(this);
|
||||
getProxy().getPluginManager().unregisterListeners(this);
|
||||
getLog().info("Goodbye!");
|
||||
protected PlatformCalculatorFactory provideCalculatorFactory() {
|
||||
return new BungeeCalculatorFactory(this);
|
||||
}
|
||||
|
||||
private File resolveConfig(String file) {
|
||||
File configFile = new File(getDataFolder(), file);
|
||||
@Override
|
||||
protected void setupContextManager() {
|
||||
this.contextManager = new BungeeContextManager(this);
|
||||
this.contextManager.registerCalculator(new BackendServerCalculator(this));
|
||||
|
||||
if (this.bootstrap.getProxy().getPluginManager().getPlugin("RedisBungee") != null) {
|
||||
this.contextManager.registerStaticCalculator(new RedisBungeeCalculator());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupPlatformHooks() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractEventBus provideEventBus(LuckPermsApiProvider apiProvider) {
|
||||
return new BungeeEventBus(this, apiProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerApiOnPlatform(LuckPermsApi api) {
|
||||
// BungeeCord doesn't have a services manager
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerHousekeepingTasks() {
|
||||
this.bootstrap.getScheduler().asyncRepeating(new ExpireTemporaryTask(this), 60L);
|
||||
this.bootstrap.getScheduler().asyncRepeating(new CacheHousekeepingTask(this), 2400L);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performFinalSetup() {
|
||||
|
||||
}
|
||||
|
||||
private File resolveConfig() {
|
||||
File configFile = new File(this.bootstrap.getDataFolder(), "config.yml");
|
||||
|
||||
if (!configFile.exists()) {
|
||||
getDataFolder().mkdirs();
|
||||
try (InputStream is = getResourceAsStream(file)) {
|
||||
this.bootstrap.getDataFolder().mkdirs();
|
||||
try (InputStream is = this.bootstrap.getResourceAsStream("config.yml")) {
|
||||
Files.copy(is, configFile.toPath());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -272,122 +185,31 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
return configFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<InternalMessagingService> getMessagingService() {
|
||||
return Optional.ofNullable(this.messagingService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessagingService(InternalMessagingService messagingService) {
|
||||
if (this.messagingService == null) {
|
||||
this.messagingService = messagingService;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<FileWatcher> getFileWatcher() {
|
||||
return Optional.ofNullable(this.fileWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformType getServerType() {
|
||||
return PlatformType.BUNGEE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerBrand() {
|
||||
return getProxy().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersion() {
|
||||
return getProxy().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataDirectory() {
|
||||
return super.getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceStream(String path) {
|
||||
return getResourceAsStream(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProxiedPlayer getPlayer(User user) {
|
||||
return getProxy().getPlayer(user.getUuid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> lookupUuid(String username) {
|
||||
if (getProxy().getPluginManager().getPlugin("RedisBungee") != null) {
|
||||
try {
|
||||
return RedisBungeeUtil.lookupUuid(username);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Contexts> getContextForUser(User user) {
|
||||
ProxiedPlayer player = getPlayer(user);
|
||||
if (player == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(this.contextManager.getApplicableContexts(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getProxy().getOnlineCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getPlayerList() {
|
||||
return getProxy().getPlayers().stream().map(ProxiedPlayer::getName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<UUID> getOnlinePlayers() {
|
||||
return getProxy().getPlayers().stream().map(ProxiedPlayer::getUniqueId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerOnline(UUID external) {
|
||||
ProxiedPlayer player = getProxy().getPlayer(external);
|
||||
return player != null && player.isConnected();
|
||||
return this.bootstrap.getPlayer(user.getUuid()).map(player -> this.contextManager.getApplicableContexts(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Sender> getOnlineSenders() {
|
||||
return Stream.concat(
|
||||
Stream.of(getConsoleSender()),
|
||||
getProxy().getPlayers().stream().map(p -> getSenderFactory().wrap(p))
|
||||
this.bootstrap.getProxy().getPlayers().stream().map(p -> this.senderFactory.wrap(p))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return getSenderFactory().wrap(getProxy().getConsole());
|
||||
return this.senderFactory.wrap(this.bootstrap.getProxy().getConsole());
|
||||
}
|
||||
|
||||
public BungeeSenderFactory getSenderFactory() {
|
||||
return this.senderFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchedulerAdapter getScheduler() {
|
||||
return this.scheduler;
|
||||
public ConnectionListener getConnectionListener() {
|
||||
return this.connectionListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -395,11 +217,6 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
return this.commandManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LuckPermsConfiguration getConfiguration() {
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardUserManager getUserManager() {
|
||||
return this.userManager;
|
||||
@@ -415,87 +232,9 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
return this.trackManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Storage getStorage() {
|
||||
return this.storage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LuckPermsApiProvider getApiProvider() {
|
||||
return this.apiProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventFactory getEventFactory() {
|
||||
return this.eventFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLog() {
|
||||
return this.log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleManager getLocaleManager() {
|
||||
return this.localeManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginClassLoader getPluginClassLoader() {
|
||||
return this.pluginClassLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DependencyManager getDependencyManager() {
|
||||
return this.dependencyManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedStateManager getCachedStateManager() {
|
||||
return this.cachedStateManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextManager<ProxiedPlayer> getContextManager() {
|
||||
return this.contextManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InheritanceHandler getInheritanceHandler() {
|
||||
return this.inheritanceHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculatorFactory getCalculatorFactory() {
|
||||
return this.calculatorFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedRequest<Void> getUpdateTaskBuffer() {
|
||||
return this.updateTaskBuffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerboseHandler getVerboseHandler() {
|
||||
return this.verboseHandler;
|
||||
}
|
||||
|
||||
public BungeeSenderFactory getSenderFactory() {
|
||||
return this.senderFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionVault getPermissionVault() {
|
||||
return this.permissionVault;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogDispatcher getLogDispatcher() {
|
||||
return this.logDispatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueConnections() {
|
||||
return this.uniqueConnections;
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public class BungeeContextManager extends AbstractContextManager<ProxiedPlayer>
|
||||
|
||||
@Override
|
||||
public Contexts formContexts(ProxiedPlayer subject, ImmutableContextSet contextSet) {
|
||||
return new Contexts(
|
||||
return Contexts.of(
|
||||
contextSet,
|
||||
this.plugin.getConfiguration().get(ConfigKeys.INCLUDING_GLOBAL_PERMS),
|
||||
this.plugin.getConfiguration().get(ConfigKeys.INCLUDING_GLOBAL_WORLD_PERMS),
|
||||
|
||||
@@ -29,26 +29,46 @@ import me.lucko.luckperms.api.Tristate;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Copy of the internal BungeeCord PermissionCheckEvent, returning a tristate instead of a boolean.
|
||||
*/
|
||||
public class TristateCheckEvent extends Event {
|
||||
|
||||
public static Tristate call(CommandSender sender, String permission) {
|
||||
return ProxyServer.getInstance().getPluginManager().callEvent(new TristateCheckEvent(sender, permission)).getResult();
|
||||
|
||||
// calculate a default value based on the internal behaviour of
|
||||
// ConsoleCommandSender and UserConnection in order to replicate the
|
||||
// behaviour of CommandSender#hasPermission
|
||||
Tristate def = Tristate.UNDEFINED;
|
||||
if (!(sender instanceof ProxiedPlayer)) {
|
||||
// if not a ProxiedPlayer, assume it's console.
|
||||
def = Tristate.TRUE;
|
||||
} else if (sender.getPermissions().contains(permission)) {
|
||||
def = Tristate.TRUE;
|
||||
}
|
||||
|
||||
return call(sender, permission, def);
|
||||
}
|
||||
|
||||
public static Tristate call(CommandSender sender, String permission, Tristate def) {
|
||||
Objects.requireNonNull(sender, "sender");
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
Objects.requireNonNull(def, "def");
|
||||
|
||||
TristateCheckEvent event = new TristateCheckEvent(sender, permission, def);
|
||||
return ProxyServer.getInstance().getPluginManager().callEvent(event).getResult();
|
||||
}
|
||||
|
||||
private final CommandSender sender;
|
||||
private final String permission;
|
||||
|
||||
private Tristate result;
|
||||
|
||||
public TristateCheckEvent(CommandSender sender, String permission) {
|
||||
this(sender, permission, sender.getPermissions().contains(permission) ? Tristate.TRUE : Tristate.UNDEFINED);
|
||||
}
|
||||
|
||||
public TristateCheckEvent(CommandSender sender, String permission, Tristate result) {
|
||||
private TristateCheckEvent(CommandSender sender, String permission, Tristate result) {
|
||||
this.sender = sender;
|
||||
this.permission = permission;
|
||||
this.result = result;
|
||||
|
||||
+13
-13
@@ -27,9 +27,9 @@ package me.lucko.luckperms.bungee.listeners;
|
||||
|
||||
import me.lucko.luckperms.bungee.LPBungeePlugin;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.listener.AbstractConnectionListener;
|
||||
import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.utils.AbstractLoginListener;
|
||||
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
@@ -43,7 +43,7 @@ import net.md_5.bungee.event.EventPriority;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BungeeConnectionListener extends AbstractLoginListener implements Listener {
|
||||
public class BungeeConnectionListener extends AbstractConnectionListener implements Listener {
|
||||
private final LPBungeePlugin plugin;
|
||||
|
||||
public BungeeConnectionListener(LPBungeePlugin plugin) {
|
||||
@@ -62,16 +62,16 @@ public class BungeeConnectionListener extends AbstractLoginListener implements L
|
||||
|
||||
/* registers the plugins intent to modify this events state going forward.
|
||||
this will prevent the event from completing until we're finished handling. */
|
||||
e.registerIntent(this.plugin);
|
||||
e.registerIntent(this.plugin.getBootstrap());
|
||||
|
||||
final PendingConnection c = e.getConnection();
|
||||
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
|
||||
this.plugin.getLog().info("Processing pre-login for " + c.getUniqueId() + " - " + c.getName());
|
||||
this.plugin.getLogger().info("Processing pre-login for " + c.getUniqueId() + " - " + c.getName());
|
||||
}
|
||||
|
||||
this.plugin.getScheduler().doAsync(() -> {
|
||||
this.plugin.getUniqueConnections().add(c.getUniqueId());
|
||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
recordConnection(c.getUniqueId());
|
||||
|
||||
/* Actually process the login for the connection.
|
||||
We do this here to delay the login until the data is ready.
|
||||
@@ -86,7 +86,7 @@ public class BungeeConnectionListener extends AbstractLoginListener implements L
|
||||
User user = loadUser(c.getUniqueId(), c.getName());
|
||||
this.plugin.getEventFactory().handleUserLoginProcess(c.getUniqueId(), c.getName(), user);
|
||||
} catch (Exception ex) {
|
||||
this.plugin.getLog().severe("Exception occurred whilst loading data for " + c.getUniqueId() + " - " + c.getName());
|
||||
this.plugin.getLogger().severe("Exception occurred whilst loading data for " + c.getUniqueId() + " - " + c.getName());
|
||||
ex.printStackTrace();
|
||||
|
||||
// there was some error loading
|
||||
@@ -98,7 +98,7 @@ public class BungeeConnectionListener extends AbstractLoginListener implements L
|
||||
}
|
||||
|
||||
// finally, complete our intent to modify state, so the proxy can continue handling the connection.
|
||||
e.completeIntent(this.plugin);
|
||||
e.completeIntent(this.plugin.getBootstrap());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -108,17 +108,17 @@ public class BungeeConnectionListener extends AbstractLoginListener implements L
|
||||
final User user = this.plugin.getUserManager().getIfLoaded(e.getPlayer().getUniqueId());
|
||||
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
|
||||
this.plugin.getLog().info("Processing post-login for " + player.getUniqueId() + " - " + player.getName());
|
||||
this.plugin.getLogger().info("Processing post-login for " + player.getUniqueId() + " - " + player.getName());
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.CANCEL_FAILED_LOGINS)) {
|
||||
// disconnect the user
|
||||
this.plugin.getLog().warn("User " + player.getUniqueId() + " - " + player.getName() + " doesn't have data pre-loaded - cancelling login.");
|
||||
this.plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getName() + " doesn't have data pre-loaded - cancelling login.");
|
||||
e.getPlayer().disconnect(TextComponent.fromLegacyText(Message.LOADING_ERROR.asString(this.plugin.getLocaleManager())));
|
||||
} else {
|
||||
// just send a message
|
||||
this.plugin.getProxy().getScheduler().schedule(this.plugin, () -> {
|
||||
this.plugin.getBootstrap().getProxy().getScheduler().schedule(this.plugin.getBootstrap(), () -> {
|
||||
if (!player.isConnected()) {
|
||||
return;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ public class BungeeConnectionListener extends AbstractLoginListener implements L
|
||||
this.plugin.getUserManager().getHouseKeeper().registerUsage(player.getUniqueId());
|
||||
|
||||
// force a clear of transient nodes
|
||||
this.plugin.getScheduler().doAsync(() -> {
|
||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
User user = this.plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
||||
if (user != null) {
|
||||
user.clearTransientNodes();
|
||||
|
||||
+18
-1
@@ -115,6 +115,23 @@ public class BungeePermissionCheckListener implements Listener {
|
||||
String name = "internal/" + e.getSender().getName();
|
||||
|
||||
this.plugin.getVerboseHandler().offerCheckData(CheckOrigin.PLATFORM_PERMISSION_CHECK, name, ContextSet.empty(), permission, result);
|
||||
this.plugin.getPermissionVault().offer(permission);
|
||||
this.plugin.getPermissionRegistry().offer(permission);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onOtherTristateCheck(TristateCheckEvent e) {
|
||||
if (e.getSender() instanceof ProxiedPlayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
Objects.requireNonNull(e.getPermission(), "permission");
|
||||
Objects.requireNonNull(e.getSender(), "sender");
|
||||
|
||||
String permission = e.getPermission();
|
||||
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.getPermissionRegistry().offer(permission);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -49,8 +49,8 @@ public class BungeeMessagingFactory extends MessagingFactory<LPBungeePlugin> {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (messagingType.equals("redisbungee")) {
|
||||
if (getPlugin().getProxy().getPluginManager().getPlugin("RedisBungee") == null) {
|
||||
getPlugin().getLog().warn("RedisBungee plugin not present.");
|
||||
if (getPlugin().getBootstrap().getProxy().getPluginManager().getPlugin("RedisBungee") == null) {
|
||||
getPlugin().getLogger().warn("RedisBungee plugin not present.");
|
||||
} else {
|
||||
try {
|
||||
return new LuckPermsMessagingService(getPlugin(), new RedisBungeeMessengerProvider());
|
||||
|
||||
@@ -57,13 +57,13 @@ public class BungeeMessenger implements Messenger, Listener {
|
||||
}
|
||||
|
||||
public void init() {
|
||||
this.plugin.getProxy().getPluginManager().registerListener(this.plugin, this);
|
||||
this.plugin.getProxy().registerChannel(CHANNEL);
|
||||
this.plugin.getBootstrap().getProxy().getPluginManager().registerListener(this.plugin.getBootstrap(), this);
|
||||
this.plugin.getBootstrap().getProxy().registerChannel(CHANNEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.plugin.getProxy().unregisterChannel(CHANNEL);
|
||||
this.plugin.getBootstrap().getProxy().unregisterChannel(CHANNEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,7 +73,7 @@ public class BungeeMessenger implements Messenger, Listener {
|
||||
|
||||
byte[] data = out.toByteArray();
|
||||
|
||||
for (ServerInfo server : this.plugin.getProxy().getServers().values()) {
|
||||
for (ServerInfo server : this.plugin.getBootstrap().getProxy().getServers().values()) {
|
||||
server.sendData(CHANNEL, data, true);
|
||||
}
|
||||
}
|
||||
@@ -97,8 +97,8 @@ public class BungeeMessenger implements Messenger, Listener {
|
||||
|
||||
if (this.consumer.consumeIncomingMessageAsString(msg)) {
|
||||
// Forward to other servers
|
||||
this.plugin.getScheduler().doAsync(() -> {
|
||||
for (ServerInfo server : this.plugin.getProxy().getServers().values()) {
|
||||
this.plugin.getBootstrap().getScheduler().doAsync(() -> {
|
||||
for (ServerInfo server : this.plugin.getBootstrap().getProxy().getServers().values()) {
|
||||
server.sendData(CHANNEL, data, true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -58,7 +58,7 @@ public class RedisBungeeMessenger implements Messenger, Listener {
|
||||
this.redisBungee = RedisBungee.getApi();
|
||||
this.redisBungee.registerPubSubChannels(CHANNEL);
|
||||
|
||||
this.plugin.getProxy().getPluginManager().registerListener(this.plugin, this);
|
||||
this.plugin.getBootstrap().getProxy().getPluginManager().registerListener(this.plugin.getBootstrap(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,7 +66,7 @@ public class RedisBungeeMessenger implements Messenger, Listener {
|
||||
this.redisBungee.unregisterPubSubChannels(CHANNEL);
|
||||
this.redisBungee = null;
|
||||
|
||||
this.plugin.getProxy().getPluginManager().unregisterListener(this);
|
||||
this.plugin.getBootstrap().getProxy().getPluginManager().unregisterListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+13
-13
@@ -26,19 +26,19 @@
|
||||
package me.lucko.luckperms.bungee.migration;
|
||||
|
||||
import me.lucko.luckperms.api.event.cause.CreationCause;
|
||||
import me.lucko.luckperms.common.commands.CommandPermission;
|
||||
import me.lucko.luckperms.common.commands.CommandResult;
|
||||
import me.lucko.luckperms.common.commands.abstraction.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.locale.CommandSpec;
|
||||
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.logging.ProgressLogger;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.node.NodeFactory;
|
||||
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.SafeIteration;
|
||||
|
||||
import net.alpenblock.bungeeperms.BungeePerms;
|
||||
import net.alpenblock.bungeeperms.Group;
|
||||
@@ -52,7 +52,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class MigrationBungeePerms extends SubCommand<Object> {
|
||||
public MigrationBungeePerms(LocaleManager locale) {
|
||||
super(CommandSpec.MIGRATION_COMMAND.spec(locale), "bungeeperms", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
super(CommandSpec.MIGRATION_COMMAND.localize(locale), "bungeeperms", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,7 +66,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
|
||||
// Get BungeePerms instance
|
||||
BungeePerms bp = BungeePerms.getInstance();
|
||||
if (bp == null) {
|
||||
log.logErr("Plugin not loaded.");
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
|
||||
// Migrate all groups.
|
||||
log.log("Starting group migration.");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
SafeIteration.iterate(groups, g -> {
|
||||
Iterators.iterate(groups, g -> {
|
||||
int groupWeight = maxWeight - g.getRank();
|
||||
|
||||
// Make a LuckPerms group for the one being migrated
|
||||
@@ -104,9 +104,9 @@ public class MigrationBungeePerms extends SubCommand<Object> {
|
||||
// Increment the max weight from the group migrations. All user meta should override.
|
||||
int userWeight = maxWeight + 5;
|
||||
|
||||
SafeIteration.iterate(bp.getPermissionsManager().getBackEnd().loadUsers(), u -> {
|
||||
Iterators.iterate(bp.getPermissionsManager().getBackEnd().loadUsers(), u -> {
|
||||
if (u.getUUID() == null) {
|
||||
log.logErr("Could not parse UUID for user: " + u.getName());
|
||||
log.logError("Could not parse UUID for user: " + u.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,11 @@ public final class RedisBungeeUtil {
|
||||
* @return a uuid, if present
|
||||
*/
|
||||
public static Optional<UUID> lookupUuid(String username) {
|
||||
return Optional.ofNullable(RedisBungee.getApi()).flatMap(a -> Optional.ofNullable(a.getUuidFromName(username, true)));
|
||||
return Optional.ofNullable(RedisBungee.getApi()).map(a -> a.getUuidFromName(username, true));
|
||||
}
|
||||
|
||||
public static Optional<String> lookupUsername(UUID uuid) {
|
||||
return Optional.ofNullable(RedisBungee.getApi()).map(a -> a.getNameFromUuid(uuid, true));
|
||||
}
|
||||
|
||||
private RedisBungeeUtil() {}
|
||||
|
||||
@@ -18,158 +18,320 @@
|
||||
####################################################################################################
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | General | #
|
||||
# | | #
|
||||
# | ESSENTIAL SETTINGS | #
|
||||
# | | #
|
||||
# | Important settings that control how LuckPerms functions. | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# The name of the server, used for server specific permissions. Set to 'global' to disable.
|
||||
# The name of the server, used for server specific permissions.
|
||||
#
|
||||
# - When set to "global" this setting is effectively ignored.
|
||||
# - In all other cases, the value here is added to all players in a "server" context.
|
||||
# - See: https://github.com/lucko/LuckPerms/wiki/Context
|
||||
server: bungee
|
||||
|
||||
# If users on this server should have their global permissions applied.
|
||||
# If set to false, only server specific permissions will apply for users on this server
|
||||
include-global: true
|
||||
|
||||
# If users on this server should have their global world permissions applied.
|
||||
# If set to false, only world specific permissions will apply for users on this server
|
||||
include-global-world: true
|
||||
|
||||
# If users on this server should have global (non-server specific) groups applied
|
||||
apply-global-groups: true
|
||||
|
||||
# If users on this server should have global (non-world specific) groups applied
|
||||
apply-global-world-groups: true
|
||||
|
||||
# If the servers own UUID cache/lookup facility should be used when there is no record for a player
|
||||
# in the LuckPerms cache.
|
||||
# already in LuckPerms.
|
||||
#
|
||||
# Since BungeeCord doesn't maintain it's own UUID cache, when this option is true, LuckPerms will
|
||||
# try to find a uuid for a username using RedisBungee, if installed.
|
||||
# - Since BungeeCord doesn't maintain it's own UUID cache, when this option is true, LuckPerms will
|
||||
# try to find a uuid for a username using RedisBungee, if installed.
|
||||
use-server-uuid-cache: false
|
||||
|
||||
# If set to true, LuckPerms will allow usernames with non alphanumeric characters.
|
||||
#
|
||||
# Note that due to the design of the storage implementation, usernames must still be
|
||||
# 16 characters or less.
|
||||
allow-invalid-usernames: false
|
||||
|
||||
# If LuckPerms should produce extra logging output when it handles logins.
|
||||
# Useful if you're having issues with UUID forwarding or data not being loaded.
|
||||
debug-logins: false
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | | #
|
||||
# | STORAGE SETTINGS | #
|
||||
# | | #
|
||||
# | Controls which storage method LuckPerms will use to store data. | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# How the plugin should store data
|
||||
#
|
||||
# - The various options are explained in more detail on the wiki:
|
||||
# https://github.com/lucko/LuckPerms/wiki/Choosing-a-Storage-type
|
||||
#
|
||||
# - Possible options:
|
||||
#
|
||||
# | Remote databases - require connection information to be configured below
|
||||
# |=> MySQL
|
||||
# |=> MariaDB (preferred over MySQL)
|
||||
# |=> PostgreSQL
|
||||
# |=> MongoDB
|
||||
#
|
||||
# | Flatfile/local database - don't require any extra configuration
|
||||
# |=> H2 (preferred over SQLite)
|
||||
# |=> SQLite
|
||||
#
|
||||
# | Readable & editable text files - don't require any extra configuration
|
||||
# |=> YAML (.yml files)
|
||||
# |=> JSON (.json files)
|
||||
# |=> HOCON (.conf files)
|
||||
# |=> TOML (.toml files)
|
||||
# |
|
||||
# | By default, user, group and track data is separated into different files. Data can be combined
|
||||
# | and all stored in the same file by switching to a combined storage variant.
|
||||
# | Just add '-combined' to the end of the storage-method, e.g. 'yaml-combined'
|
||||
#
|
||||
# - A H2 database is the default option.
|
||||
# - If you want to edit data manually in "traditional" storage files, we suggest using YAML.
|
||||
storage-method: h2
|
||||
|
||||
# The following block defines the settings for remote database storage methods.
|
||||
#
|
||||
# - You don't need to touch any of the settings here if you're using a local storage method!
|
||||
# - The connection detail options are shared between all remote storage types.
|
||||
data:
|
||||
|
||||
# Define the address and port for the database.
|
||||
# - The standard DB engine port is used by default
|
||||
# (MySQL: 3306, PostgreSQL: 5432, MongoDB: 27017)
|
||||
# - Specify as "host:port" if differs
|
||||
address: localhost
|
||||
|
||||
# The name of the database to store LuckPerms data in.
|
||||
# - This must be created already. Don't worry about this setting if you're using MongoDB.
|
||||
database: minecraft
|
||||
|
||||
# Credentials for the database.
|
||||
username: root
|
||||
password: ''
|
||||
|
||||
# These settings apply to the MySQL connection pool.
|
||||
# - The default values will be suitable for the majority of users.
|
||||
# - Do not change these settings unless you know what you're doing!
|
||||
pool-settings:
|
||||
|
||||
# Sets the maximum size of the MySQL connection pool.
|
||||
# - Basically this value will determine the maximum number of actual
|
||||
# connections to the database backend.
|
||||
# - More information about determining the size of connection pools can be found here:
|
||||
# https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
|
||||
maximum-pool-size: 10
|
||||
|
||||
# Sets the minimum number of idle connections that the pool will try to maintain.
|
||||
# - For maximum performance and responsiveness to spike demands, it is recommended to not set
|
||||
# this value and instead allow the pool to act as a fixed size connection pool.
|
||||
# (set this value to the same as 'maximum-pool-size')
|
||||
minimum-idle: 10
|
||||
|
||||
# This setting controls the maximum lifetime of a connection in the pool in milliseconds.
|
||||
# - The value should be at least 30 seconds less than any database or infrastructure imposed
|
||||
# connection time limit.
|
||||
maximum-lifetime: 1800000 # 30 minutes
|
||||
|
||||
# This setting controls the maximum number of milliseconds that the plugin will wait for a
|
||||
# connection from the pool, before timing out.
|
||||
connection-timeout: 5000 # 5 seconds
|
||||
|
||||
# This setting allows you to define extra properties for connections.
|
||||
properties:
|
||||
useUnicode: true
|
||||
characterEncoding: utf8
|
||||
|
||||
# The prefix for all LuckPerms SQL tables.
|
||||
# - Change this is you want to use different tables for different servers.
|
||||
table_prefix: 'luckperms_'
|
||||
|
||||
# The prefix to use for all LuckPerms collections. Change this if you want to use different
|
||||
# collections for different servers. The default is no prefix.
|
||||
mongodb_collection_prefix: ''
|
||||
|
||||
# MongoDB ClientConnectionURI for use with replica sets and custom connection options
|
||||
# - See https://docs.mongodb.com/manual/reference/connection-string/
|
||||
mongodb_connection_URI: ''
|
||||
|
||||
# Define settings for a "split" storage setup.
|
||||
#
|
||||
# - This allows you to define a storage method for each type of data.
|
||||
# - The connection options above still have to be correct for each type here.
|
||||
split-storage:
|
||||
# Don't touch this if you don't want to use split storage!
|
||||
enabled: false
|
||||
methods:
|
||||
# These options don't need to be modified if split storage isn't enabled.
|
||||
user: h2
|
||||
group: h2
|
||||
track: h2
|
||||
uuid: h2
|
||||
log: h2
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | | #
|
||||
# | UPDATE PROPAGATION & MESSAGING SERVICE | #
|
||||
# | | #
|
||||
# | Controls the ways in which LuckPerms will sync data & notify other servers of changes. | #
|
||||
# | These options are documented on greater detail on the wiki under "Instant Updates". | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# This option controls how frequently LuckPerms will perform a sync task.
|
||||
#
|
||||
# - A sync task will refresh all data from the storage, and ensure that the most up-to-date data is
|
||||
# being used by the plugin.
|
||||
# - This is disabled by default, as most users will not need it. However, if you're using a remote
|
||||
# storage type without a messaging service setup, you may wish to set this to something like 3.
|
||||
# - Set to -1 to disable the task completely.
|
||||
sync-minutes: -1
|
||||
|
||||
# If the file watcher should be enabled.
|
||||
#
|
||||
# - When using a file-based storage type, LuckPerms can monitor the data files for changes, and
|
||||
# automatically update when changes are detected.
|
||||
# - If you don't want this feature to be active, set this option to false.
|
||||
watch-files: true
|
||||
|
||||
# Define which messaging service should be used by the plugin.
|
||||
#
|
||||
# - If enabled and configured, LuckPerms will use the messaging service to inform other connected
|
||||
# servers of changes.
|
||||
# - Use the command "/lp networksync" to manually push changes.
|
||||
# - Data is NOT stored using this service. It is only used as a messaging platform.
|
||||
#
|
||||
# - If you decide to enable this feature, you should set "sync-minutes" to -1, as there is no need
|
||||
# for LuckPerms to poll the database for changes.
|
||||
#
|
||||
# - Possible options:
|
||||
# => sql Uses the SQL database to form a queue system for communication. Will only work
|
||||
# when 'storage-method' is set to MySQL or MariaDB. This is chosen by default if
|
||||
# the option is set to 'none' and SQL storage is in use. Set to 'notsql' to
|
||||
# disable this.
|
||||
# => bungee Uses the plugin messaging channels to communicate with the proxy.
|
||||
# LuckPerms must be installed on your proxy & all connected servers backend
|
||||
# servers. Won't work if you have more than one BungeeCord proxy.
|
||||
# => redis Uses Redis pub-sub to push changes. Your server connection info must be
|
||||
# configured below.
|
||||
# => redisbungee Uses Redis pub-sub to push changes, using the RedisBungee API. You need to have
|
||||
# the RedisBungee plugin installed.
|
||||
# => none Disables the service.
|
||||
messaging-service: none
|
||||
|
||||
# If LuckPerms should automatically push updates after a change has been made with a command.
|
||||
auto-push-updates: true
|
||||
|
||||
# If LuckPerms should push logging entries to connected servers via the messaging service.
|
||||
push-log-entries: true
|
||||
|
||||
# If LuckPerms should broadcast received logging entries to players on this platform.
|
||||
#
|
||||
# - If you have LuckPerms installed on your backend servers as well as a BungeeCord proxy, you
|
||||
# should set this option to false on either your backends or your proxies, to avoid players being
|
||||
# messaged twice about log entries.
|
||||
broadcast-received-log-entries: false
|
||||
|
||||
# Settings for Redis.
|
||||
# Port 6379 is used by default; set address to "host:port" if differs
|
||||
redis:
|
||||
enabled: false
|
||||
address: localhost
|
||||
password: ''
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | | #
|
||||
# | CUSTOMIZATION SETTINGS | #
|
||||
# | | #
|
||||
# | Settings that allow admins to customize the way LuckPerms operates. | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# 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.
|
||||
#
|
||||
# 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,
|
||||
# the option is provided on BungeeCord, as it is less likely to be so dependant on permissions.
|
||||
# - 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.
|
||||
# - 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,
|
||||
# the option is provided on BungeeCord, as it is less likely to be so dependant on permissions.
|
||||
cancel-failed-logins: false
|
||||
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
log-notify: true
|
||||
|
||||
# Mirrors world names. Whenever LuckPerms checks what world a user is in, if the world name is in
|
||||
# this list, the value assigned will be sent forward for permission calculation instead.
|
||||
world-rewrite:
|
||||
# world_nether: world
|
||||
# world_the_end: world
|
||||
|
||||
# Controls how temporary permissions/parents/meta should be accumulated
|
||||
# Controls how temporary permissions/parents/meta should be accumulated.
|
||||
#
|
||||
# The default behaviour is "deny"
|
||||
# If "accumulate": durations will be added to the existing expiry time
|
||||
# If "replace": durations will be replaced if the new duration is later than the current expiration
|
||||
# If "deny": the command will just fail if you try to add another node with the same expiry
|
||||
# - The default behaviour is "deny".
|
||||
# - This behaviour can also be specified when the command is executed. See the command usage
|
||||
# documentation for more info.
|
||||
#
|
||||
# - Possible options:
|
||||
# => accumulate durations will be added to the existing expiry time
|
||||
# => replace durations will be replaced if the new duration is later than the current
|
||||
# expiration
|
||||
# => deny the command will just fail if you try to add another node with the same expiry
|
||||
temporary-add-behaviour: deny
|
||||
|
||||
# How should LuckPerms determine a users "primary" group.
|
||||
# Controls how LuckPerms will determine a users "primary" group.
|
||||
#
|
||||
# Available Options:
|
||||
# -> stored use the value stored against the users record in the file/database
|
||||
# -> parents-by-weight just use the users most highly weighted parent
|
||||
# -> all-parents-by-weight same as above, but calculates based upon all parents inherited from both
|
||||
# directly and indirectly
|
||||
# - The meaning and influence of "primary groups" are explained in detail on the wiki.
|
||||
# - The preferred approach is to let LuckPerms automatically determine a users primary group
|
||||
# based on the relative weight of their parent groups.
|
||||
#
|
||||
# - Possible options:
|
||||
# => stored use the value stored against the users record in the file/database
|
||||
# => parents-by-weight just use the users most highly weighted parent
|
||||
# => all-parents-by-weight same as above, but calculates based upon all parents inherited from
|
||||
# both directly and indirectly
|
||||
primary-group-calculation: parents-by-weight
|
||||
|
||||
# If set to false, the plugin will allow a Users primary group to be removed with the
|
||||
# 'parent remove' command, and will set their primary group back to default.
|
||||
prevent-primary-group-removal: false
|
||||
|
||||
# If the plugin should check for "extra" permissions with users run LP commands.
|
||||
#
|
||||
# These extra permissions allow finer control over what users can do with each command, and
|
||||
# who they have access to edit.
|
||||
#
|
||||
# The permissions are *not* static, unlike the 'base' permisssions, and will depend upon the
|
||||
# arguments given within the command.
|
||||
# - These extra permissions allow finer control over what users can do with each command, and who
|
||||
# they have access to edit.
|
||||
# - The nature of the checks are documented on the wiki under "Argument based command permissions".
|
||||
# - Argument based permissions are *not* static, unlike the 'base' permissions, and will depend upon
|
||||
# the arguments given within the command.
|
||||
argument-based-command-permissions: false
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Permission Calculation | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
# If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered
|
||||
# permissions matching the wildcard.
|
||||
apply-wildcards: true
|
||||
|
||||
# If the plugin should parse regex permissions.
|
||||
# If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the
|
||||
# node, and resolve & apply all registered permissions matching the regex.
|
||||
apply-regex: true
|
||||
|
||||
# If the plugin should complete and apply shorthand permissions.
|
||||
# If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||
apply-shorthand: true
|
||||
|
||||
# If the plugin should apply the permissions & groups defined in the BungeeCord config.yml
|
||||
# If set to false, LuckPerms will ignore these values.
|
||||
apply-bungee-config-permissions: false
|
||||
|
||||
# The algorithm LuckPerms should use when traversing the "inheritance tree".
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
#
|
||||
# The valid options are:
|
||||
# - breadth-first
|
||||
# - depth-first-pre-order
|
||||
# - depth-first-post-order
|
||||
# - Notifications are only sent to those with the appropriate permission to receive them
|
||||
# - They can also be temporarily enabled/disabled on a per-user basis using
|
||||
# '/lp log notify <on|off>'
|
||||
log-notify: true
|
||||
|
||||
# Defines the options for prefix and suffix stacking.
|
||||
#
|
||||
# See here for information about the differences between each algorithm.
|
||||
# - https://en.wikipedia.org/wiki/Breadth-first_search
|
||||
# - https://en.wikipedia.org/wiki/Depth-first_search
|
||||
inheritance-traversal-algorithm: depth-first-pre-order
|
||||
|
||||
# Define special group weights for this server.
|
||||
# Default is just 0.
|
||||
group-weight:
|
||||
# admin: 10
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Meta Formatting & Stacking | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# Allows you to setup prefix/suffix stacking options.
|
||||
# - The feature allows you to display multiple prefixes or suffixes alongside a players username in
|
||||
# chat.
|
||||
# - It is explained and documented in more detail on the wiki under "Prefix & Suffix Stacking".
|
||||
#
|
||||
# Available formats:
|
||||
# - highest
|
||||
# - lowest
|
||||
# - highest_own
|
||||
# - lowest_own
|
||||
# - highest_inherited
|
||||
# - lowest_inherited
|
||||
# - highest_on_track_<track>
|
||||
# - lowest_on_track_<track>
|
||||
# - highest_not_on_track_<track>
|
||||
# - lowest_not_on_track_<track>
|
||||
# - The options are divided into separate sections for prefixes and suffixes.
|
||||
# - 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.
|
||||
#
|
||||
# Each element is added in the order listed.
|
||||
# - Possible format options:
|
||||
# => highest Selects the value with the highest weight, from all values
|
||||
# held by or inherited by the player.
|
||||
#
|
||||
# => lowest Same as above, except takes the one with the lowest weight.
|
||||
#
|
||||
# => highest_own Selects the value with the highest weight, but will not
|
||||
# accept any inherited values.
|
||||
#
|
||||
# => lowest_own Same as above, except takes the value with the lowest weight.
|
||||
#
|
||||
# => highest_inherited Selects the value with the highest weight, but will only
|
||||
# accept inherited values.
|
||||
#
|
||||
# => lowest_inherited Same as above, except takes the value with the lowest weight.
|
||||
#
|
||||
# => highest_on_track_<track> Selects the value with the highest weight, but only if the
|
||||
# value was inherited from a group on the given track.
|
||||
#
|
||||
# => lowest_on_track_<track> Same as above, except takes the value with the lowest weight.
|
||||
#
|
||||
# => highest_not_on_track_<track> Selects the value with the highest weight, but only if the
|
||||
# value was inherited from a group not on the given track.
|
||||
#
|
||||
# => lowest_not_on_track_<track> Same as above, except takes the value with the lowest weight.
|
||||
meta-formatting:
|
||||
prefix:
|
||||
format:
|
||||
@@ -188,147 +350,124 @@ meta-formatting:
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Storage | #
|
||||
# | | #
|
||||
# | PERMISSION CALCULATION AND INHERITANCE | #
|
||||
# | | #
|
||||
# | Modify the way permission checks, meta lookups and inheritance resolutions are handled. | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# The algorithm LuckPerms should use when traversing the "inheritance tree".
|
||||
#
|
||||
# See: https://github.com/lucko/LuckPerms/wiki/Choosing-a-Storage-type
|
||||
# Currently supported: mysql, mariadb, postgresql, sqlite, h2, json, yaml, hocon, mongodb
|
||||
# - Possible options:
|
||||
# => breadth-first See: https://en.wikipedia.org/wiki/Breadth-first_search
|
||||
# => depth-first-pre-order See: https://en.wikipedia.org/wiki/Depth-first_search
|
||||
# => depth-first-post-order See: https://en.wikipedia.org/wiki/Depth-first_search
|
||||
inheritance-traversal-algorithm: depth-first-pre-order
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Permission resolution settings | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# If users on this server should have their global permissions applied.
|
||||
# When set to false, only server specific permissions will apply for users on this server
|
||||
include-global: true
|
||||
|
||||
# If users on this server should have their global world permissions applied.
|
||||
# When set to false, only world specific permissions will apply for users on this server
|
||||
include-global-world: true
|
||||
|
||||
# If users on this server should have global (non-server specific) groups applied
|
||||
apply-global-groups: true
|
||||
|
||||
# If users on this server should have global (non-world specific) groups applied
|
||||
apply-global-world-groups: true
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Inheritance settings | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
#
|
||||
# Fill out connection info below if you're using MySQL, MariaDB, PostgreSQL or MongoDB
|
||||
# If your MySQL server supports it, the "mariadb" option is preferred over "mysql".
|
||||
storage-method: h2
|
||||
# - If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered
|
||||
# permissions matching the wildcard.
|
||||
apply-wildcards: true
|
||||
|
||||
# When using a file-based storage type, LuckPerms can monitor the data files for changes, and then
|
||||
# schedule automatic updates when changes are detected.
|
||||
# If the plugin should parse regex permissions.
|
||||
#
|
||||
# If you don't want this to happen, set this option to false.
|
||||
watch-files: true
|
||||
# - If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the
|
||||
# node, and resolve & apply all registered permissions matching the regex.
|
||||
apply-regex: true
|
||||
|
||||
# This block enables support for split datastores.
|
||||
split-storage:
|
||||
enabled: false
|
||||
methods:
|
||||
user: h2
|
||||
group: h2
|
||||
track: h2
|
||||
uuid: h2
|
||||
log: h2
|
||||
|
||||
data:
|
||||
# Uses standard DB engine port by default
|
||||
# MySQL: 3306, PostgreSQL: 5432, MongoDB: 27017
|
||||
# Specify as "host:port" if differs
|
||||
address: localhost
|
||||
|
||||
database: minecraft
|
||||
username: root
|
||||
password: ''
|
||||
|
||||
# These settings apply to the MySQL connection pool.
|
||||
# The default values will be suitable for the majority of users.
|
||||
# Do not change these settings unless you know what you're doing!
|
||||
pool-settings:
|
||||
|
||||
# Sets the maximum size of the MySQL connection pool.
|
||||
# Basically this value will determine the maximum number of actual
|
||||
# connections to the database backend.
|
||||
#
|
||||
# More information about determining the size of connection pools can be found here:
|
||||
# https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
|
||||
maximum-pool-size: 10
|
||||
|
||||
# Sets the minimum number of idle connections that the pool will try to maintain.
|
||||
#
|
||||
# For maximum performance and responsiveness to spike demands, it is recommended to not set
|
||||
# this value and instead allow the pool to act as a fixed size connection pool.
|
||||
# (set this value to the same as 'maximum-pool-size')
|
||||
minimum-idle: 10
|
||||
|
||||
# This setting controls the maximum lifetime of a connection in the pool in milliseconds.
|
||||
# The value should be at least 30 seconds less than any database or infrastructure imposed
|
||||
# connection time limit.
|
||||
maximum-lifetime: 1800000 # 30 minutes
|
||||
|
||||
# This setting controls the maximum number of milliseconds that the plugin will wait for a
|
||||
# connection from the pool, before timing out.
|
||||
connection-timeout: 5000 # 5 seconds
|
||||
|
||||
# This setting allows you to define extra properties for connections.
|
||||
properties:
|
||||
useUnicode: true
|
||||
characterEncoding: utf8
|
||||
|
||||
# The prefix for all LuckPerms tables. Change this is you want to use different tables for
|
||||
# different servers.
|
||||
#
|
||||
# This should *not* be set to "lp_" if you have previously ran LuckPerms v2.16.81 or earlier with
|
||||
# this database.
|
||||
table_prefix: 'luckperms_'
|
||||
|
||||
# The prefix to use for all LuckPerms collections. Change this if you want to use different
|
||||
# collections for different servers. The default is no prefix.
|
||||
mongodb_collection_prefix: ''
|
||||
|
||||
# MongoDB ClientConnectionURI for use with replicasets and custom connection options
|
||||
# See https://docs.mongodb.com/manual/reference/connection-string/
|
||||
mongodb_connection_URI: ''
|
||||
|
||||
# This option controls how frequently LuckPerms will perform a sync task.
|
||||
# A sync task will refresh all data from the storage, and ensure that the most up-to-date data is
|
||||
# being used by the plugin.
|
||||
#
|
||||
# This is disabled by default, as most users will not need it. However, if you're using a remote
|
||||
# storage type without a messaging service setup, you may wish to set this value to something like
|
||||
# 3.
|
||||
#
|
||||
# Set to -1 to disable the task completely.
|
||||
sync-minutes: -1
|
||||
|
||||
# Settings for the messaging service
|
||||
# If the plugin should complete and apply shorthand permissions.
|
||||
#
|
||||
# If enabled and configured, LuckPerms will use the messaging system to inform other
|
||||
# connected servers of changes. Use the command "/luckpermsbungee networksync" to push changes.
|
||||
# Data is NOT stored using this service. It is only used as a messaging platform.
|
||||
# - If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||
apply-shorthand: true
|
||||
|
||||
# If the plugin should apply the permissions & groups defined in the BungeeCord config.yml
|
||||
#
|
||||
# If you decide to enable this feature, you should set "sync-minutes" to -1, as there is no need for
|
||||
# LuckPerms to poll the database for changes.
|
||||
# - If set to false, LuckPerms will ignore these values.
|
||||
apply-bungee-config-permissions: false
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Extra settings | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# Allows you to set "aliases" for the worlds sent forward for context calculation.
|
||||
#
|
||||
# Available options:
|
||||
# -> bungee uses the plugin messaging channels. Must be enabled on all connected servers to
|
||||
# work.
|
||||
# -> redis uses redis pub sub to push changes. Your redis server must be configured below.
|
||||
# -> redisbungee uses redis pub sub to push changes, using RedisBungee's API. You need to have the
|
||||
# RedisBungee plugin installed.
|
||||
# -> none nothing
|
||||
messaging-service: none
|
||||
# - These aliases are provided in addition to the real world name. Applied recursively.
|
||||
# - Remove the comment characters for the default aliases to apply.
|
||||
world-rewrite:
|
||||
# world_nether: world
|
||||
# world_the_end: world
|
||||
|
||||
# If LuckPerms should automatically push updates after a change has been made with a command.
|
||||
auto-push-updates: true
|
||||
|
||||
# If LuckPerms should push logging entries to connected servers via the messaging service.
|
||||
push-log-entries: true
|
||||
|
||||
# If LuckPerms should broadcast received logging entries to players on this platform.
|
||||
# Define special group weights for this server.
|
||||
#
|
||||
# If you have LuckPerms installed on your backend servers as well as a BungeeCord proxy, you should
|
||||
# set this option to false on either your backends or your proxies, to avoid players being messaged
|
||||
# twice about log entries.
|
||||
broadcast-received-log-entries: false
|
||||
|
||||
# Settings for Redis.
|
||||
# Port 6379 is used by default; set address to "host:port" if differs
|
||||
redis:
|
||||
enabled: false
|
||||
address: localhost
|
||||
password: ''
|
||||
# - Group weights can also be applied directly to group data, using the setweight command.
|
||||
# - This section allows weights to be set on a per-server basis.
|
||||
group-weight:
|
||||
# admin: 10
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Default Assignments | #
|
||||
# | | #
|
||||
# | FINE TUNING OPTIONS | #
|
||||
# | | #
|
||||
# | A number of more niche settings for tweaking and changing behaviour. The section also | #
|
||||
# | contains toggles for some more specialised features. It is only necessary to make changes to | #
|
||||
# | these options if you want to fine-tune LuckPerms behaviour. | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | Miscellaneous (and rarely used) settings | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# If LuckPerms should produce extra logging output when it handles logins.
|
||||
#
|
||||
# - Useful if you're having issues with UUID forwarding or data not being loaded.
|
||||
debug-logins: false
|
||||
|
||||
# If LuckPerms should allow usernames with non alphanumeric characters.
|
||||
#
|
||||
# - Note that due to the design of the storage implementation, usernames must still be 16 characters
|
||||
# or less.
|
||||
allow-invalid-usernames: false
|
||||
|
||||
# If LuckPerms should allow a users primary group to be removed with the 'parent remove' command.
|
||||
#
|
||||
# - When this happens, the plugin will set their primary group back to default.
|
||||
prevent-primary-group-removal: false
|
||||
|
||||
|
||||
|
||||
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
# | | #
|
||||
# | DEFAULT ASSIGNMENTS | #
|
||||
# | | #
|
||||
# +----------------------------------------------------------------------------------------------+ #
|
||||
|
||||
# This section allows you to define defaults to give users whenever they connect to the server.
|
||||
|
||||
@@ -2,5 +2,5 @@ name: LuckPerms
|
||||
version: ${full.version}
|
||||
description: A permissions plugin
|
||||
author: Luck
|
||||
main: me.lucko.luckperms.bungee.LPBungeePlugin
|
||||
main: me.lucko.luckperms.bungee.LPBungeeBootstrap
|
||||
softDepends: ["RedisBungee"]
|
||||
+27
-14
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>4.1-SNAPSHOT</version>
|
||||
<version>4.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -89,29 +89,29 @@
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>2.6.1</version>
|
||||
<version>2.6.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- okhttp -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>3.9.1</version>
|
||||
<version>3.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- okio -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okio</groupId>
|
||||
<artifactId>okio</artifactId>
|
||||
<version>1.13.0</version>
|
||||
<version>1.14.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- configurate -->
|
||||
<dependency>
|
||||
<groupId>ninja.leaping.configurate</groupId>
|
||||
<groupId>me.lucko.configurate</groupId>
|
||||
<artifactId>configurate-core</artifactId>
|
||||
<version>3.3</version>
|
||||
<version>3.4</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -122,9 +122,9 @@
|
||||
</dependency>
|
||||
<!-- configurate yaml -->
|
||||
<dependency>
|
||||
<groupId>ninja.leaping.configurate</groupId>
|
||||
<groupId>me.lucko.configurate</groupId>
|
||||
<artifactId>configurate-yaml</artifactId>
|
||||
<version>3.3</version>
|
||||
<version>3.4</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -135,9 +135,9 @@
|
||||
</dependency>
|
||||
<!-- configurate gson -->
|
||||
<dependency>
|
||||
<groupId>ninja.leaping.configurate</groupId>
|
||||
<groupId>me.lucko.configurate</groupId>
|
||||
<artifactId>configurate-gson</artifactId>
|
||||
<version>3.3</version>
|
||||
<version>3.4</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -148,16 +148,29 @@
|
||||
</dependency>
|
||||
<!-- configurate hocon -->
|
||||
<dependency>
|
||||
<groupId>ninja.leaping.configurate</groupId>
|
||||
<groupId>me.lucko.configurate</groupId>
|
||||
<artifactId>configurate-hocon</artifactId>
|
||||
<version>3.3</version>
|
||||
<version>3.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- configurate toml -->
|
||||
<dependency>
|
||||
<groupId>me.lucko.configurate</groupId>
|
||||
<artifactId>configurate-toml</artifactId>
|
||||
<version>3.4</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.moandjiezana.toml</groupId>
|
||||
<artifactId>toml4j</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- HikariCP -->
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>2.7.6</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Jedis -->
|
||||
@@ -171,7 +184,7 @@
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<version>3.6.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- SnakeYAML -->
|
||||
|
||||
@@ -30,13 +30,12 @@ import com.google.common.base.Strings;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.DateUtil;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
@@ -70,8 +69,8 @@ public class ExtendedLogEntry implements LogEntry {
|
||||
*
|
||||
* @return a new builder
|
||||
*/
|
||||
public static ExtendedLogEntryBuilder build() {
|
||||
return new ExtendedLogEntryBuilder();
|
||||
public static Builder build() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
private final long timestamp;
|
||||
@@ -207,7 +206,7 @@ public class ExtendedLogEntry implements LogEntry {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class ExtendedLogEntryBuilder implements LogEntry.Builder {
|
||||
public static class Builder implements LogEntry.Builder {
|
||||
|
||||
private long timestamp = 0L;
|
||||
private UUID actor = null;
|
||||
@@ -219,88 +218,88 @@ public class ExtendedLogEntry implements LogEntry {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ExtendedLogEntryBuilder setTimestamp(long timestamp) {
|
||||
public Builder setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ExtendedLogEntryBuilder setActor(@Nonnull UUID actor) {
|
||||
public Builder setActor(@Nonnull UUID actor) {
|
||||
this.actor = Objects.requireNonNull(actor, "actor");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ExtendedLogEntryBuilder setActorName(@Nonnull String actorName) {
|
||||
public Builder setActorName(@Nonnull String actorName) {
|
||||
this.actorName = Objects.requireNonNull(actorName, "actorName");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ExtendedLogEntryBuilder setType(@Nonnull Type type) {
|
||||
public Builder setType(@Nonnull Type type) {
|
||||
this.type = Objects.requireNonNull(type, "type");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ExtendedLogEntryBuilder setActed(UUID acted) {
|
||||
public Builder setActed(UUID acted) {
|
||||
this.acted = acted; // nullable
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ExtendedLogEntryBuilder setActedName(@Nonnull String actedName) {
|
||||
public Builder setActedName(@Nonnull String actedName) {
|
||||
this.actedName = Objects.requireNonNull(actedName, "actedName");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ExtendedLogEntryBuilder setAction(@Nonnull String action) {
|
||||
public Builder setAction(@Nonnull String action) {
|
||||
this.action = Objects.requireNonNull(action, "action");
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder timestamp(long timestamp) {
|
||||
public Builder timestamp(long timestamp) {
|
||||
return setTimestamp(timestamp);
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder actor(UUID actor) {
|
||||
public Builder actor(UUID actor) {
|
||||
return setActor(actor);
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder actorName(String actorName) {
|
||||
public Builder actorName(String actorName) {
|
||||
return setActorName(actorName);
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder type(Type type) {
|
||||
public Builder type(Type type) {
|
||||
return setType(type);
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder acted(UUID acted) {
|
||||
public Builder acted(UUID acted) {
|
||||
return setActed(acted);
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder actedName(String actedName) {
|
||||
public Builder actedName(String actedName) {
|
||||
return setActedName(actedName);
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder action(String action) {
|
||||
public Builder action(String action) {
|
||||
return setAction(action);
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder actor(Sender actor) {
|
||||
public Builder actor(Sender actor) {
|
||||
actorName(actor.getNameWithLocation());
|
||||
actor(actor.getUuid());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder acted(PermissionHolder acted) {
|
||||
public Builder acted(PermissionHolder acted) {
|
||||
if (acted.getType().isUser()) {
|
||||
actedName(((User) acted).getName().orElse("null"));
|
||||
acted(((User) acted).getUuid());
|
||||
@@ -312,13 +311,13 @@ public class ExtendedLogEntry implements LogEntry {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder acted(Track track) {
|
||||
public Builder acted(Track track) {
|
||||
actedName(track.getName());
|
||||
type(Type.TRACK);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExtendedLogEntryBuilder action(Object... args) {
|
||||
public Builder action(Object... args) {
|
||||
List<String> parts = new ArrayList<>();
|
||||
|
||||
for (Object o : args) {
|
||||
@@ -353,7 +352,7 @@ public class ExtendedLogEntry implements LogEntry {
|
||||
@Override
|
||||
public ExtendedLogEntry build() {
|
||||
if (this.timestamp == 0L) {
|
||||
timestamp(DateUtil.unixSecondsNow());
|
||||
timestamp(System.currentTimeMillis() / 1000L);
|
||||
}
|
||||
|
||||
Objects.requireNonNull(this.actor, "actor");
|
||||
@@ -367,7 +366,7 @@ public class ExtendedLogEntry implements LogEntry {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExtendedLogEntry.ExtendedLogEntryBuilder(" +
|
||||
return "ExtendedLogEntry.Builder(" +
|
||||
"timestamp=" + this.timestamp + ", " +
|
||||
"actor=" + this.actor + ", " +
|
||||
"actorName=" + this.actorName + ", " +
|
||||
|
||||
@@ -44,7 +44,7 @@ public class Log {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public synchronized static Log empty() {
|
||||
public static synchronized Log empty() {
|
||||
if (empty == null) {
|
||||
empty = builder().build();
|
||||
}
|
||||
|
||||
@@ -27,13 +27,13 @@ package me.lucko.luckperms.common.actionlog;
|
||||
|
||||
import me.lucko.luckperms.api.event.log.LogBroadcastEvent;
|
||||
import me.lucko.luckperms.api.event.log.LogNotifyEvent;
|
||||
import me.lucko.luckperms.common.commands.CommandPermission;
|
||||
import me.lucko.luckperms.common.commands.impl.log.LogNotify;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.commands.log.LogNotify;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.messaging.InternalMessagingService;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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.common.api;
|
||||
|
||||
import me.lucko.luckperms.api.DemotionResult;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Utility class for creating instances of {@link DemotionResult}.
|
||||
*/
|
||||
public final class DemotionResults {
|
||||
|
||||
public static DemotionResult success(String groupFrom, String groupTo) {
|
||||
return new Impl(DemotionResult.Status.SUCCESS, groupFrom, groupTo);
|
||||
}
|
||||
|
||||
public static DemotionResult removedFromFirst(String groupFrom) {
|
||||
return new Impl(DemotionResult.Status.REMOVED_FROM_FIRST_GROUP, groupFrom, null);
|
||||
}
|
||||
|
||||
public static DemotionResult malformedTrack(String groupTo) {
|
||||
return new Impl(DemotionResult.Status.MALFORMED_TRACK, null, groupTo);
|
||||
}
|
||||
|
||||
public static DemotionResult notOnTrack() {
|
||||
return new Impl(DemotionResult.Status.NOT_ON_TRACK);
|
||||
}
|
||||
|
||||
public static DemotionResult ambiguousCall() {
|
||||
return new Impl(DemotionResult.Status.AMBIGUOUS_CALL);
|
||||
}
|
||||
|
||||
public static DemotionResult undefinedFailure() {
|
||||
return new Impl(DemotionResult.Status.UNDEFINED_FAILURE);
|
||||
}
|
||||
|
||||
private static final class Impl implements DemotionResult {
|
||||
private final Status status;
|
||||
private final String groupFrom;
|
||||
private final String groupTo;
|
||||
|
||||
private Impl(Status status, String groupFrom, String groupTo) {
|
||||
this.status = status;
|
||||
this.groupFrom = groupFrom;
|
||||
this.groupTo = groupTo;
|
||||
}
|
||||
|
||||
private Impl(Status status) {
|
||||
this(status, null, null);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Status getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Optional<String> getGroupFrom() {
|
||||
return Optional.ofNullable(this.groupFrom);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Optional<String> getGroupTo() {
|
||||
return Optional.ofNullable(this.groupTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Impl that = (Impl) o;
|
||||
return this.status == that.status &&
|
||||
Objects.equals(this.groupFrom, that.groupFrom) &&
|
||||
Objects.equals(this.groupTo, that.groupTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.status, this.groupFrom, this.groupTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DemotionResult(" +
|
||||
"status=" + this.status + ", " +
|
||||
"groupFrom='" + this.groupFrom + "', " +
|
||||
"groupTo='" + this.groupTo + "')";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private DemotionResults() {}
|
||||
|
||||
}
|
||||
Loaded 100 of 507 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user