Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
383276f47a | ||
|
|
33c78e4a17 | ||
|
|
55a0de7899 | ||
|
|
6b3aab66bf | ||
|
|
77e70ef8d3 | ||
|
|
9b92143501 | ||
|
|
87f94f6b8f | ||
|
|
5d955e77b6 | ||
|
|
270a276b98 | ||
|
|
be7d914e39 | ||
|
|
37fc00cce8 | ||
|
|
0d515abadb | ||
|
|
daef01194e | ||
|
|
258bf1cc41 | ||
|
|
ce3d7829d7 | ||
|
|
c66a01c1a6 | ||
|
|
d113a92ce5 | ||
|
|
7b655d12df | ||
|
|
a4c872f1e8 | ||
|
|
0e7d9bf9c1 | ||
|
|
6252a5bc75 | ||
|
|
e4e80c9c31 | ||
|
|
165c5610c3 | ||
|
|
13fbc7dd39 | ||
|
|
02a75fc32a | ||
|
|
699c4d107b | ||
|
|
e4810302e1 | ||
|
|
73f10cad66 | ||
|
|
f1d670dc46 | ||
|
|
045539c752 | ||
|
|
782c09b686 | ||
|
|
6109718c67 | ||
|
|
cd758d7e48 | ||
|
|
fcb0fcadeb | ||
|
|
26fb506560 | ||
|
|
b6c4239322 | ||
|
|
74f9283f18 | ||
|
|
60e6ae6e23 | ||
|
|
83d9229295 | ||
|
|
e079b0f3ed | ||
|
|
d433a5461d | ||
|
|
2c43f6bf21 | ||
|
|
ac57509a29 | ||
|
|
c5ce655cf6 | ||
|
|
9fe05efb4e | ||
|
|
dcf207f5e5 | ||
|
|
11facab71c | ||
|
|
5b4975f34c | ||
|
|
069e535f1a | ||
|
|
1eb053447e | ||
|
|
93c7c06b2d | ||
|
|
b0085bc1e1 | ||
|
|
9133951446 | ||
|
|
7853d4686a | ||
|
|
ed5892eb56 | ||
|
|
687804de2c | ||
|
|
9d166041ab | ||
|
|
924041bff4 | ||
|
|
e9216d3e0f | ||
|
|
db8f1bca66 | ||
|
|
2429831153 | ||
|
|
80d2246634 | ||
|
|
56df2477ca | ||
|
|
9b4384dc33 | ||
|
|
bc65857831 | ||
|
|
de462d2385 | ||
|
|
90150428be | ||
|
|
2a7f951f4f | ||
|
|
82789328c1 | ||
|
|
13bccd1d3f | ||
|
|
43c514132d | ||
|
|
9e0fdcbfee | ||
|
|
008dc3fc52 | ||
|
|
9fde237d9b | ||
|
|
d626c08b4c | ||
|
|
58e223e74b | ||
|
|
1da1df156e | ||
|
|
3442372281 | ||
|
|
1b3b50c113 | ||
|
|
18e126b781 | ||
|
|
c88600adda | ||
|
|
4787361e66 | ||
|
|
b5ece8b5bd | ||
|
|
7ee3116f29 | ||
|
|
1fc0d77971 | ||
|
|
a32ab4bf7f | ||
|
|
2d8083bf18 | ||
|
|
63b9be9845 | ||
|
|
85a83d8c71 | ||
|
|
71b33a296c | ||
|
|
becdfd6f03 | ||
|
|
41744f9416 | ||
|
|
cb89a92ba9 | ||
|
|
93d54373c6 | ||
|
|
385addfe08 | ||
|
|
4c21957b04 | ||
|
|
ab6b011225 | ||
|
|
e72d91503c | ||
|
|
b9ee206908 | ||
|
|
4c9abba5fa | ||
|
|
3424b0542a | ||
|
|
fec90b8958 | ||
|
|
4da7fe4ff9 | ||
|
|
c53623dd67 | ||
|
|
6540ffa4dd | ||
|
|
5ee6db02ff | ||
|
|
d8221f466a | ||
|
|
462bea2a09 | ||
|
|
f452a97278 | ||
|
|
eb9d2be587 | ||
|
|
df1e747861 | ||
|
|
f48595b1ff | ||
|
|
12cd4e19cb | ||
|
|
a195e94522 | ||
|
|
02abb39dc2 | ||
|
|
f7a0b1ef78 | ||
|
|
7678f25879 | ||
|
|
fa9324bda8 | ||
|
|
1e72f9d8fe | ||
|
|
50fd954599 | ||
|
|
b1e34b55f8 | ||
|
|
cff1b8a411 | ||
|
|
6ffa6720be | ||
|
|
f52a106165 | ||
|
|
bf247b71e1 | ||
|
|
66818e4c82 | ||
|
|
23d53d39b4 | ||
|
|
30ea5a5b69 | ||
|
|
e7a210dc06 | ||
|
|
497de9824a | ||
|
|
be74b50762 | ||
|
|
f2e06b56e7 | ||
|
|
f6aa20c300 | ||
|
|
5e16134f6f | ||
|
|
6165fcbb21 | ||
|
|
831e882db0 | ||
|
|
feb8bf4bd3 | ||
|
|
ce3ee866ca | ||
|
|
d29dd35689 | ||
|
|
3a0a89853f | ||
|
|
e7ca79d251 | ||
|
|
22426bab33 | ||
|
|
116094ea96 | ||
|
|
9df39a9545 | ||
|
|
b8f44df723 | ||
|
|
74f275eb69 | ||
|
|
1142cbcb2c | ||
|
|
37749e5829 | ||
|
|
f9025c7a51 | ||
|
|
c7bfc38477 | ||
|
|
7ca394d7b9 | ||
|
|
31884ea59d | ||
|
|
e79b7c7023 | ||
|
|
1fdb4e8ade | ||
|
|
53db8c5928 | ||
|
|
07514000a4 | ||
|
|
f28721e55a | ||
|
|
fc230291d3 | ||
|
|
89ff4cfa40 | ||
|
|
d786b6abb2 | ||
|
|
fb0e694155 | ||
|
|
cd6cac1fb6 | ||
|
|
ea07f05097 | ||
|
|
d84767af68 | ||
|
|
aab73a8d81 | ||
|
|
995fc2ccd8 | ||
|
|
60bcd5f643 | ||
|
|
ba04fb320b | ||
|
|
770b7dc282 | ||
|
|
ed85eee36c | ||
|
|
23df8a2df8 | ||
|
|
36cd388607 | ||
|
|
4d48ef1939 | ||
|
|
7970e2a1c6 | ||
|
|
cee96d7daa | ||
|
|
861c1ddd69 | ||
|
|
5dec5a54cb | ||
|
|
5c760aabd4 | ||
|
|
1a2fa5d8c3 | ||
|
|
ef0c53da82 | ||
|
|
3fd62a80e2 | ||
|
|
5c19dd8b15 | ||
|
|
1fc88e147f | ||
|
|
9b4bbe0500 | ||
|
|
b37fdd3619 | ||
|
|
ab00c41452 | ||
|
|
c15727377b | ||
|
|
1e6f32bdc4 | ||
|
|
42e69c98a7 | ||
|
|
a217727bb4 | ||
|
|
ba10b1c06e | ||
|
|
075ba33e8b | ||
|
|
19dbc7d90a | ||
|
|
ade70bb7ba | ||
|
|
4b67913eee | ||
|
|
75858c1555 | ||
|
|
659baaf5fb | ||
|
|
3c83c578eb | ||
|
|
3ddbf1da87 | ||
|
|
35cb5b81dc | ||
|
|
02d9b996a7 | ||
|
|
d4cf6a5ad7 | ||
|
|
9fdb4fa25f | ||
|
|
d5bc1cdf5d | ||
|
|
f5995c0afa | ||
|
|
2cc65160b4 |
No files matched your search
@@ -1,5 +1,6 @@
|
||||

|
||||
# LuckPerms [](https://ci.lucko.me/job/LuckPerms/)
|
||||
A permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
|
||||
An advanced permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
|
||||
|
||||
## Links
|
||||
* **Development Builds** - <https://ci.lucko.me/job/LuckPerms>
|
||||
@@ -9,9 +10,20 @@ A permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
|
||||
## Description
|
||||
LuckPerms is an advanced permissions implementation aiming to be a flexible, performant and reliable alternative to other permission systems, providing all the features you could ever possibly need in a permissions plugin, along with an extensive and well documented API for developers.
|
||||
|
||||
* [Spigot Plugin Page](https://www.spigotmc.org/resources/luckperms-an-advanced-permissions-system.28140/ "Spigot Plugin Page")
|
||||
* [Sponge Plugin Page](https://forums.spongepowered.org/t/luckperms-an-advanced-permissions-system/14274 "Sponge Plugin Page")
|
||||
|
||||
## LuckPerms vs Other Plugins
|
||||
### Bukkit
|
||||

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

|
||||
_Features checked on 8th Oct 2016. If you find any inaccuracies, please do let me know. I tried to be as fair as possible, and copy all major features from the respective plugin pages._
|
||||
## License
|
||||
See LICENSE.md.
|
||||
LuckPerms is licensed under the permissive MIT license. See LICENSE.md for more info.
|
||||
|
||||
## Thanks to:
|
||||
[](http://www.ej-technologies.com/products/jprofiler/overview.html)
|
||||
|
||||
Thanks to ej-technologies for granting LuckPerms an open source licence to their [Java Profiling Software](http://www.ej-technologies.com/products/jprofiler/overview.html "Java Profiler").
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>2.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents the context and options for a permission lookup.
|
||||
* All values are immutable.
|
||||
* @since 2.11
|
||||
*/
|
||||
public class Contexts {
|
||||
public static final String SERVER_KEY = "server";
|
||||
public static final String WORLD_KEY = "world";
|
||||
|
||||
/**
|
||||
* Gets a context that will allow all nodes
|
||||
* @return a context that will not apply any filters
|
||||
*/
|
||||
public static Contexts allowAll() {
|
||||
return new Contexts(ContextSet.empty(), true, true, true, true, true, true);
|
||||
}
|
||||
|
||||
public static Contexts of(ContextSet context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
|
||||
return new Contexts(context, includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups, op);
|
||||
}
|
||||
|
||||
public Contexts(ContextSet context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
|
||||
if (context == null) {
|
||||
throw new NullPointerException("context");
|
||||
}
|
||||
|
||||
this.context = context.makeImmutable();
|
||||
this.includeGlobal = includeGlobal;
|
||||
this.includeGlobalWorld = includeGlobalWorld;
|
||||
this.applyGroups = applyGroups;
|
||||
this.applyGlobalGroups = applyGlobalGroups;
|
||||
this.applyGlobalWorldGroups = applyGlobalWorldGroups;
|
||||
this.op = op;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
public static Contexts of(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups) {
|
||||
return new Contexts(context, includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
public static Contexts of(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
|
||||
return new Contexts(context, includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups, op);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Contexts(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
|
||||
this(context == null ? null : ContextSet.fromMap(context), includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups, op);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
public Contexts(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups) {
|
||||
this(context, includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The contexts that apply for this lookup
|
||||
* The keys for servers and worlds are defined as static values.
|
||||
*/
|
||||
private final ContextSet context;
|
||||
|
||||
/**
|
||||
* The mode to parse defaults on Bukkit
|
||||
* @since 2.12
|
||||
*/
|
||||
private final boolean op;
|
||||
|
||||
/**
|
||||
* If global or non server specific nodes should be applied
|
||||
*/
|
||||
private final boolean includeGlobal;
|
||||
|
||||
/**
|
||||
* If global or non world specific nodes should be applied
|
||||
*/
|
||||
private final boolean includeGlobalWorld;
|
||||
|
||||
/**
|
||||
* If parent groups should be applied
|
||||
*/
|
||||
private final boolean applyGroups;
|
||||
|
||||
/**
|
||||
* If global or non server specific group memberships should be applied
|
||||
*/
|
||||
private final boolean applyGlobalGroups;
|
||||
|
||||
/**
|
||||
* If global or non world specific group memberships should be applied
|
||||
*/
|
||||
private final boolean applyGlobalWorldGroups;
|
||||
|
||||
/**
|
||||
* Gets the contexts that apply for this lookup
|
||||
* @return an immutable set of context key value pairs
|
||||
* @since 2.13
|
||||
*/
|
||||
public ContextSet getContexts() {
|
||||
return this.context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the contexts that apply for this lookup
|
||||
* @return an immutable map of context key value pairs
|
||||
* @deprecated in favour of {@link #getContexts()}
|
||||
*/
|
||||
@Deprecated
|
||||
public Map<String, String> getContext() {
|
||||
return this.context.toMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if OP defaults should be included
|
||||
* @return true if op defaults should be included
|
||||
*/
|
||||
public boolean isOp() {
|
||||
return this.op;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non server specific nodes should be applied
|
||||
* @return true if global or non server specific nodes should be applied
|
||||
*/
|
||||
public boolean isIncludeGlobal() {
|
||||
return this.includeGlobal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non world specific nodes should be applied
|
||||
* @return true if global or non world specific nodes should be applied
|
||||
*/
|
||||
public boolean isIncludeGlobalWorld() {
|
||||
return this.includeGlobalWorld;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if parent groups should be applied
|
||||
* @return true if parent groups should be applied
|
||||
*/
|
||||
public boolean isApplyGroups() {
|
||||
return this.applyGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non server specific group memberships should be applied
|
||||
* @return true if global or non server specific group memberships should be applied
|
||||
*/
|
||||
public boolean isApplyGlobalGroups() {
|
||||
return this.applyGlobalGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if global or non world specific group memberships should be applied
|
||||
* @return true if global or non world specific group memberships should be applied
|
||||
*/
|
||||
public boolean isApplyGlobalWorldGroups() {
|
||||
return this.applyGlobalWorldGroups;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Contexts(" +
|
||||
"context=" + this.getContexts() + ", " +
|
||||
"op=" + this.isOp() + ", " +
|
||||
"includeGlobal=" + this.isIncludeGlobal() + ", " +
|
||||
"includeGlobalWorld=" + this.isIncludeGlobalWorld() + ", " +
|
||||
"applyGroups=" + this.isApplyGroups() + ", " +
|
||||
"applyGlobalGroups=" + this.isApplyGlobalGroups() + ", " +
|
||||
"applyGlobalWorldGroups=" + this.isApplyGlobalWorldGroups() +
|
||||
")";
|
||||
}
|
||||
|
||||
/*
|
||||
* Ugly auto-generated lombok code
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check for equality
|
||||
* @param o the other
|
||||
* @return true if equal
|
||||
* @since 2.12
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof Contexts)) return false;
|
||||
final Contexts other = (Contexts) o;
|
||||
final Object this$context = this.getContexts();
|
||||
final Object other$context = other.getContexts();
|
||||
if (this$context == null ? other$context != null : !this$context.equals(other$context)) return false;
|
||||
if (this.isOp() != other.isOp()) return false;
|
||||
if (this.isIncludeGlobal() != other.isIncludeGlobal()) return false;
|
||||
if (this.isIncludeGlobalWorld() != other.isIncludeGlobalWorld()) return false;
|
||||
if (this.isApplyGroups() != other.isApplyGroups()) return false;
|
||||
if (this.isApplyGlobalGroups() != other.isApplyGlobalGroups()) return false;
|
||||
if (this.isApplyGlobalWorldGroups() != other.isApplyGlobalWorldGroups()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hashcode
|
||||
* @return the hashcode
|
||||
* @since 2.12
|
||||
*/
|
||||
public int hashCode() {
|
||||
final int PRIME = 59;
|
||||
int result = 1;
|
||||
final Object $context = this.getContexts();
|
||||
result = result * PRIME + ($context == null ? 43 : $context.hashCode());
|
||||
result = result * PRIME + (this.isOp() ? 79 : 97);
|
||||
result = result * PRIME + (this.isIncludeGlobal() ? 79 : 97);
|
||||
result = result * PRIME + (this.isIncludeGlobalWorld() ? 79 : 97);
|
||||
result = result * PRIME + (this.isApplyGroups() ? 79 : 97);
|
||||
result = result * PRIME + (this.isApplyGlobalGroups() ? 79 : 97);
|
||||
result = result * PRIME + (this.isApplyGlobalWorldGroups() ? 79 : 97);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Wrapper interface for the internal Datastore instance
|
||||
* Interface for the internal Datastore instance
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Datastore {
|
||||
@@ -55,7 +55,7 @@ public interface Datastore {
|
||||
Async async();
|
||||
|
||||
/**
|
||||
* Gets the {@link Future} interface
|
||||
* Gets the {@link Future} interface.
|
||||
*
|
||||
* All operations through this interface are called in a new, separate asynchronous thread, similar to {@link Async}.
|
||||
* The only difference is that instead of providing a callback, a {@link java.util.concurrent.Future} is returned.
|
||||
@@ -112,7 +112,7 @@ public interface Datastore {
|
||||
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
|
||||
* @return if the operation was performed successfully
|
||||
* @throws NullPointerException if uuid or username is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
boolean loadUser(UUID uuid, String username);
|
||||
|
||||
@@ -128,14 +128,14 @@ public interface Datastore {
|
||||
/**
|
||||
* Removes users from the datastore who are "default". This is called every time the plugin loads.
|
||||
* @return true if the operation completed successfully
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
boolean cleanupUsers();
|
||||
|
||||
/**
|
||||
* Gets a set all user's UUIDs who are "unique", and aren't just a member of the "default" group.
|
||||
* @return a set of uuids, or null if the operation failed.
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<UUID> getUniqueUsers();
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal Group instances
|
||||
* Interface for internal Group instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Group extends PermissionHolder {
|
||||
|
||||
@@ -25,6 +25,8 @@ package me.lucko.luckperms.api;
|
||||
import me.lucko.luckperms.api.data.DatastoreConfiguration;
|
||||
import me.lucko.luckperms.api.data.MySQLConfiguration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A wrapper interface for the internal LuckPerms configuration, providing read only access.
|
||||
*/
|
||||
@@ -43,14 +45,14 @@ public interface LPConfiguration {
|
||||
|
||||
/**
|
||||
* @return the default group, in a node representation
|
||||
* @deprecated as of 1.6, the default group is always "default"
|
||||
* @deprecated as of 2.6, the default group is always "default"
|
||||
*/
|
||||
@Deprecated
|
||||
String getDefaultGroupNode();
|
||||
|
||||
/**
|
||||
* @return the name of the default group
|
||||
* @deprecated as of 1.6, the default group is always "default"
|
||||
* @deprecated as of 2.6, the default group is always "default"
|
||||
*/
|
||||
@Deprecated
|
||||
String getDefaultGroupName();
|
||||
@@ -60,6 +62,24 @@ public interface LPConfiguration {
|
||||
*/
|
||||
boolean getIncludeGlobalPerms();
|
||||
|
||||
/**
|
||||
* @return if the users on this server will have their global world permissions applied
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getIncludeGlobalWorldPerms();
|
||||
|
||||
/**
|
||||
* @return true if the platform is applying global groups
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getApplyGlobalGroups();
|
||||
|
||||
/**
|
||||
* @return true if the platform is applying global world groups
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getApplyGlobalWorldGroups();
|
||||
|
||||
/**
|
||||
* @return the online mode setting in the config
|
||||
*/
|
||||
@@ -80,6 +100,48 @@ public interface LPConfiguration {
|
||||
*/
|
||||
boolean getApplyShorthand();
|
||||
|
||||
/**
|
||||
* @return if LuckPerms will send notifications to users when permissions are modified
|
||||
* @since 2.7
|
||||
*/
|
||||
boolean getLogNotify();
|
||||
|
||||
/**
|
||||
* @return true if permission checks are being recorded / debugged
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getDebugPermissionChecks();
|
||||
|
||||
/**
|
||||
* @return true if the vanilla op system is enabled
|
||||
* @since 2.8
|
||||
*/
|
||||
boolean getEnableOps();
|
||||
|
||||
/**
|
||||
* @return true if opped players are allowed to use LuckPerms commands
|
||||
* @since 2.8
|
||||
*/
|
||||
boolean getCommandsAllowOp();
|
||||
|
||||
/**
|
||||
* @return true if auto op is enabled
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getAutoOp();
|
||||
|
||||
/**
|
||||
* @return the name of the server used within Vault operations
|
||||
* @since 2.7
|
||||
*/
|
||||
String getVaultServer();
|
||||
|
||||
/**
|
||||
* @return true if global permissions should be considered when retrieving meta or player groups
|
||||
* @since 2.7
|
||||
*/
|
||||
boolean getVaultIncludeGlobal();
|
||||
|
||||
/**
|
||||
* @return the database values set in the configuration
|
||||
* @deprecated use {@link #getDatastoreConfig()}
|
||||
@@ -98,4 +160,17 @@ public interface LPConfiguration {
|
||||
*/
|
||||
String getStorageMethod();
|
||||
|
||||
/**
|
||||
* @return true if split storage is enabled
|
||||
* @since 2.7
|
||||
*/
|
||||
boolean getSplitStorage();
|
||||
|
||||
/**
|
||||
* @return a map of split storage options, where the key is the storage section, and the value is the storage method.
|
||||
* For example: key = user, value = json
|
||||
* @since 2.7
|
||||
*/
|
||||
Map<String, String> getSplitStorageOptions();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
/**
|
||||
* Represents a Node and where it was inherited from.
|
||||
* @since 2.11
|
||||
*/
|
||||
public interface LocalizedNode extends Node {
|
||||
|
||||
/**
|
||||
* Gets the node
|
||||
* @return the node this instance is representing
|
||||
*/
|
||||
Node getNode();
|
||||
|
||||
/**
|
||||
* Gets the location where the {@link Node} is inherited from
|
||||
* @return where the node was inherited from. Will not return null.
|
||||
* @see PermissionHolder#getObjectName()
|
||||
*/
|
||||
String getLocation();
|
||||
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import java.util.UUID;
|
||||
/**
|
||||
* Represents a single entry in a log
|
||||
*/
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
public class LogEntry implements Comparable<LogEntry> {
|
||||
public static LogEntryBuilder builder() {
|
||||
return new LogEntryBuilder();
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
/**
|
||||
* A wrapper class for platform logger instances.
|
||||
* A wrapper interface for platform logger instances.
|
||||
*
|
||||
* <p> Bukkit/Bungee both use java.util.logging, and Sponge uses org.slf4j. This class wraps those classes so the commons
|
||||
* module can access a logger.
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextListener;
|
||||
import me.lucko.luckperms.api.context.IContextCalculator;
|
||||
import me.lucko.luckperms.api.event.LPListener;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -41,7 +43,7 @@ public interface LuckPermsApi {
|
||||
|
||||
/**
|
||||
* @return the version of the API running on the platform
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
double getApiVersion();
|
||||
|
||||
@@ -50,6 +52,12 @@ public interface LuckPermsApi {
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* @return the platform LuckPerms is running on
|
||||
* @since 2.7
|
||||
*/
|
||||
PlatformType getPlatformType();
|
||||
|
||||
/**
|
||||
* Registers a listener to be sent LuckPerms events
|
||||
* @param listener the listener instance
|
||||
@@ -138,7 +146,7 @@ public interface LuckPermsApi {
|
||||
* Unload a user from the internal storage, if they're not currently online.
|
||||
* @param user the user to unload
|
||||
* @throws NullPointerException if the user is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
void cleanupUser(User user);
|
||||
|
||||
@@ -181,7 +189,7 @@ public interface LuckPermsApi {
|
||||
Track getTrack(String name);
|
||||
|
||||
/**
|
||||
* Gets a wrapped tracj object from the track storage. This method does not return null, unlike {@link #getTrack}
|
||||
* Gets a wrapped track object from the track storage. This method does not return null, unlike {@link #getTrack}
|
||||
* @param name the name of the track to get
|
||||
* @return an optional {@link Track} object
|
||||
* @throws NullPointerException if the name is null
|
||||
@@ -208,8 +216,22 @@ public interface LuckPermsApi {
|
||||
* @return a {@link Node.Builder} instance
|
||||
* @throws IllegalArgumentException if the permission is invalid
|
||||
* @throws NullPointerException if the permission is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Node.Builder buildNode(String permission) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Register a custom context calculator to the server
|
||||
* @param contextCalculator the context calculator to register. The type MUST be the player class of the platform.
|
||||
* @throws ClassCastException if the type is not the player class of the platform.
|
||||
*/
|
||||
void registerContextCalculator(IContextCalculator<?> contextCalculator);
|
||||
|
||||
/**
|
||||
* Registers a custom context listener to the server,
|
||||
* @param contextListener the context listener to register. The type MUST be the player class of the platform.
|
||||
* @throws ClassCastException if the type is not the player class of the platform.
|
||||
*/
|
||||
void registerContextListener(ContextListener<?> contextListener);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.LuckPerms;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A collection of utilities to help retrieve meta values for {@link PermissionHolder}s
|
||||
* @since 2.7
|
||||
*/
|
||||
public class MetaUtils {
|
||||
|
||||
private MetaUtils(){}
|
||||
|
||||
/**
|
||||
* Escapes special characters used within LuckPerms, so the string can be saved without issues
|
||||
* @param s the string to escape
|
||||
* @return an escaped string
|
||||
* @throws NullPointerException if the string is null
|
||||
*/
|
||||
public static String escapeCharacters(String s) {
|
||||
if (s == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
s = s.replace(".", "{SEP}");
|
||||
s = s.replace("/", "{FSEP}");
|
||||
s = s.replace("$", "{DSEP}");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescapes special characters used within LuckPerms, the inverse of {@link #escapeCharacters(String)}
|
||||
* @param s the string to unescape
|
||||
* @return an unescaped string
|
||||
* @throws NullPointerException if the string is null
|
||||
*/
|
||||
public static String unescapeCharacters(String s) {
|
||||
if (s == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
s = s.replace("{SEP}", ".");
|
||||
s = s.replace("{FSEP}", "/");
|
||||
s = s.replace("{DSEP}", "$");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a meta value on a holder
|
||||
* @param holder the holder to apply the meta node to
|
||||
* @param server the server to apply the meta on, can be null
|
||||
* @param world the world to apply the meta on, can be null
|
||||
* @param node the meta node
|
||||
* @param value the meta value
|
||||
* @throws NullPointerException if the holder, node or value is null
|
||||
* @throws IllegalArgumentException if the node or value is empty
|
||||
*/
|
||||
public static void setMeta(PermissionHolder holder, String server, String world, String node, String value) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
|
||||
if (node == null) {
|
||||
throw new NullPointerException("node");
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
if (node.equals("")) {
|
||||
throw new IllegalArgumentException("node is empty");
|
||||
}
|
||||
|
||||
if (value.equals("")) {
|
||||
throw new IllegalArgumentException("value is empty");
|
||||
}
|
||||
|
||||
if (server == null || server.equals("")) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
node = escapeCharacters(node);
|
||||
value = escapeCharacters(value);
|
||||
|
||||
Set<Node> toRemove = new HashSet<>();
|
||||
for (Node n : holder.getEnduringPermissions()) {
|
||||
if (n.isMeta() && n.getMeta().getKey().equals(node)) {
|
||||
toRemove.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
for (Node n : toRemove) {
|
||||
try {
|
||||
holder.unsetPermission(n);
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
}
|
||||
|
||||
Node.Builder metaNode = LuckPerms.getApi().buildNode("meta." + node + "." + value).setValue(true);
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
metaNode.setServer(server);
|
||||
}
|
||||
if (world != null && !world.equals("")) {
|
||||
metaNode.setServer(server).setWorld(world);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(metaNode.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a meta value for the holder
|
||||
* @param holder the holder to get the meta from
|
||||
* @param server the server to retrieve the meta on, can be null
|
||||
* @param world the world to retrieve the meta on, can be null
|
||||
* @param node the node to get
|
||||
* @param defaultValue the default value to return if the node is not set
|
||||
* @param includeGlobal if global nodes should be considered when retrieving the meta
|
||||
* @return a meta string, or the default value if the user does not have the meta node
|
||||
* @throws NullPointerException if the holder or node is null
|
||||
* @throws IllegalArgumentException if the node is empty
|
||||
*/
|
||||
public static String getMeta(PermissionHolder holder, String server, String world, String node, String defaultValue, boolean includeGlobal) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
|
||||
if (server == null || server.equals("")) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
if (node == null) {
|
||||
throw new NullPointerException("node");
|
||||
}
|
||||
|
||||
if (node.equals("")) {
|
||||
throw new IllegalArgumentException("node is empty");
|
||||
}
|
||||
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
if (!n.shouldApplyOnServer(server, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
return unescapeCharacters(meta.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static void setChatMeta(boolean prefix, PermissionHolder holder, String value, int priority, String server, String world) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
|
||||
if (value == null || value.equals("")) {
|
||||
throw new IllegalArgumentException("value is null/empty");
|
||||
}
|
||||
|
||||
Node.Builder node = LuckPerms.getApi().buildNode(prefix ? "prefix" : "suffix" + "." + priority + "." + escapeCharacters(value));
|
||||
node.setValue(true);
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
node.setServer(server);
|
||||
}
|
||||
if (world != null && !world.equals("")) {
|
||||
node.setServer(server).setWorld(world);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(node.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a prefix to a holder on a specific server and world
|
||||
* @param holder the holder to set the prefix for
|
||||
* @param prefix the prefix value
|
||||
* @param priority the priority to set the prefix at
|
||||
* @param server the server to set the prefix on, can be null
|
||||
* @param world the world to set the prefix on, can be null
|
||||
* @throws NullPointerException if the holder is null
|
||||
* @throws IllegalArgumentException if the prefix is null or empty
|
||||
*/
|
||||
public static void setPrefix(PermissionHolder holder, String prefix, int priority, String server, String world) {
|
||||
setChatMeta(true, holder, prefix, priority, server, world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a suffix to a holder on a specific server and world
|
||||
* @param holder the holder to set the suffix for
|
||||
* @param suffix the suffix value
|
||||
* @param priority the priority to set the suffix at
|
||||
* @param server the server to set the suffix on, can be null
|
||||
* @param world the world to set the suffix on, can be null
|
||||
* @throws NullPointerException if the holder is null
|
||||
* @throws IllegalArgumentException if the suffix is null or empty
|
||||
*/
|
||||
public static void setSuffix(PermissionHolder holder, String suffix, int priority, String server, String world) {
|
||||
setChatMeta(false, holder, suffix, priority, server, world);
|
||||
}
|
||||
|
||||
private static String getChatMeta(boolean prefix, PermissionHolder holder, String server, String world, boolean includeGlobal) {
|
||||
if (holder == null) {
|
||||
throw new NullPointerException("holder");
|
||||
}
|
||||
if (server == null) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
int priority = Integer.MIN_VALUE;
|
||||
String meta = null;
|
||||
for (Node n : holder.getAllNodes(Contexts.allowAll())) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!server.equalsIgnoreCase("global")) {
|
||||
if (!n.shouldApplyOnServer(server, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, includeGlobal, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix ? !n.isPrefix() : !n.isSuffix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> value = prefix ? n.getPrefix() : n.getSuffix();
|
||||
if (value.getKey() > priority) {
|
||||
meta = value.getValue();
|
||||
priority = value.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return meta == null ? "" : unescapeCharacters(meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a holders highest priority prefix, if they have one
|
||||
* @param holder the holder
|
||||
* @param server the server to retrieve the prefix on
|
||||
* @param world the world to retrieve the prefix on
|
||||
* @param includeGlobal if global nodes should be considered when retrieving the prefix
|
||||
* @return a prefix string, if the holder has one, or an empty string if not.
|
||||
* @throws NullPointerException if the holder is null
|
||||
*/
|
||||
public static String getPrefix(PermissionHolder holder, String server, String world, boolean includeGlobal) {
|
||||
return getChatMeta(true, holder, server, world, includeGlobal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a holders highest priority suffix, if they have one
|
||||
* @param holder the holder
|
||||
* @param server the server to retrieve the suffix on
|
||||
* @param world the world to retrieve the suffix on
|
||||
* @param includeGlobal if global nodes should be considered when retrieving the suffix
|
||||
* @return a suffix string, if the holder has one, or an empty string if not.
|
||||
* @throws NullPointerException if the holder is null
|
||||
*/
|
||||
public static String getSuffix(PermissionHolder holder, String server, String world, boolean includeGlobal) {
|
||||
return getChatMeta(false, holder, server, world, includeGlobal);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,16 +22,16 @@
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Represents an immutable node object
|
||||
* <p> Use {@link LuckPermsApi#buildNode(String)} to get an instance.
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Node extends Map.Entry<String, Boolean> {
|
||||
|
||||
/**
|
||||
@@ -104,11 +104,44 @@ public interface Node extends Map.Entry<String, Boolean> {
|
||||
boolean shouldApplyOnWorld(String world, boolean includeGlobal, boolean applyRegex);
|
||||
|
||||
/**
|
||||
* If this node should apply given the specific context
|
||||
* If this node should apply in the given context
|
||||
* @param context the context key value pairs
|
||||
* @param worldAndServer if world and server contexts should be checked
|
||||
* @return true if the node should apply
|
||||
* @since 2.13
|
||||
*/
|
||||
boolean shouldApplyWithContext(ContextSet context, boolean worldAndServer);
|
||||
|
||||
/**
|
||||
* If this node should apply in the given context
|
||||
* @param context the context key value pairs
|
||||
* @return true if the node should apply
|
||||
* @since 2.13
|
||||
*/
|
||||
boolean shouldApplyWithContext(Map<String, String> context);
|
||||
boolean shouldApplyWithContext(ContextSet context);
|
||||
|
||||
/**
|
||||
* If this node should apply in the given context
|
||||
* @param context the context key value pairs
|
||||
* @param worldAndServer if world and server contexts should be checked
|
||||
* @return true if the node should apply
|
||||
* @deprecated in favour of {@link #shouldApplyWithContext(ContextSet, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean shouldApplyWithContext(Map<String, String> context, boolean worldAndServer) {
|
||||
return shouldApplyWithContext(ContextSet.fromMap(context), worldAndServer);
|
||||
}
|
||||
|
||||
/**
|
||||
* If this node should apply in the given context
|
||||
* @param context the context key value pairs
|
||||
* @return true if the node should apply
|
||||
* @deprecated in favour of {@link #shouldApplyWithContext(ContextSet)}
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean shouldApplyWithContext(Map<String, String> context) {
|
||||
return shouldApplyWithContext(ContextSet.fromMap(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link #shouldApplyOnServer(String, boolean, boolean)}, except this method accepts a List
|
||||
@@ -177,8 +210,18 @@ public interface Node extends Map.Entry<String, Boolean> {
|
||||
|
||||
/**
|
||||
* @return the extra contexts required for this node to apply
|
||||
* @deprecated in favour of {@link #getContexts()}
|
||||
*/
|
||||
Map<String, String> getExtraContexts();
|
||||
@Deprecated
|
||||
default Map<String, String> getExtraContexts() {
|
||||
return getContexts().toMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the extra contexts required for this node to apply
|
||||
* @since 2.13
|
||||
*/
|
||||
ContextSet getContexts();
|
||||
|
||||
/**
|
||||
* Converts this node into a serialized form
|
||||
@@ -246,19 +289,38 @@ public interface Node extends Map.Entry<String, Boolean> {
|
||||
Map.Entry<Integer, String> getSuffix();
|
||||
|
||||
/**
|
||||
* Similar to {@link #equals(Object)}, except doesn't take note of the value
|
||||
* @param node the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
* Checks if this Node is equal to another node
|
||||
* @param obj the other node
|
||||
* @return true if this node is equal to the other provided
|
||||
* @see #equalsIgnoringValue(Node) for a less strict implementation of this method
|
||||
*/
|
||||
boolean equalsIgnoringValue(Node node);
|
||||
boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* Similar to {@link #equals(Object)}, except doesn't take note of the expiry time or value
|
||||
* @param node the other node
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the value
|
||||
* @param other the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
*/
|
||||
boolean almostEquals(Node node);
|
||||
boolean equalsIgnoringValue(Node other);
|
||||
|
||||
/**
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the expiry time or value
|
||||
* @param other the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
*/
|
||||
boolean almostEquals(Node other);
|
||||
|
||||
/**
|
||||
* Similar to {@link Node#equals(Object)}, except doesn't take note of the value or if the node is temporary
|
||||
* @param other the other node
|
||||
* @return true if the two nodes are almost equal
|
||||
* @since 2.8
|
||||
*/
|
||||
boolean equalsIgnoringValueOrTemp(Node other);
|
||||
|
||||
/**
|
||||
* Builds a Node instance
|
||||
*/
|
||||
interface Builder {
|
||||
Builder setNegated(boolean negated);
|
||||
Builder setValue(boolean value);
|
||||
@@ -274,7 +336,9 @@ public interface Node extends Map.Entry<String, Boolean> {
|
||||
Builder setServer(String server) throws IllegalArgumentException;
|
||||
Builder withExtraContext(String key, String value);
|
||||
Builder withExtraContext(Map<String, String> map);
|
||||
Builder withExtraContext(Set<Map.Entry<String, String>> context);
|
||||
Builder withExtraContext(Map.Entry<String, String> entry);
|
||||
Builder withExtraContext(ContextSet set);
|
||||
Node build();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal PermissionHolder (user/group) instances
|
||||
* Interface for internal PermissionHolder (user/group) instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface PermissionHolder {
|
||||
@@ -45,21 +45,21 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Gets an immutable Set of the objects permission nodes
|
||||
* @return an immutable set of permissions in priority order
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
SortedSet<Node> getPermissions();
|
||||
SortedSet<? extends Node> getPermissions();
|
||||
|
||||
/**
|
||||
* Similar to {@link #getPermissions()}, except excluding transient permissions
|
||||
* @return a set of nodes
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getEnduringPermissions();
|
||||
|
||||
/**
|
||||
* Similar to {@link #getPermissions()}, except excluding non-transient permissions
|
||||
* @return a set of nodes
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getTransientPermissions();
|
||||
|
||||
@@ -67,10 +67,35 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Gets an immutable set of the nodes that this object has and inherits
|
||||
* @return an immutable set of permissions
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
* @deprecated in favour of {@link #getAllNodes(Contexts)}
|
||||
*/
|
||||
@Deprecated
|
||||
Set<Node> getAllNodes();
|
||||
|
||||
/**
|
||||
* Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context
|
||||
* Unlike {@link #getAllNodesFiltered(Contexts)}, this method will not filter individual nodes. The context is only
|
||||
* used to determine which groups should apply.
|
||||
* Nodes are sorted into priority order.
|
||||
* @param contexts the context for the lookup,
|
||||
* @return a mutable sorted set of permissions
|
||||
* @throws NullPointerException if the context is null
|
||||
* @since 2.11
|
||||
*/
|
||||
SortedSet<LocalizedNode> getAllNodes(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Gets a mutable set of the nodes that is objects has and inherits, filtered by context.
|
||||
* Unlike {@link #getAllNodes(Contexts)}, this method WILL filter individual nodes, and only return ones that fully
|
||||
* meet the context provided.
|
||||
* @param contexts the context for the lookup
|
||||
* @return a mutable set of permissions
|
||||
* @throws NullPointerException if the context is null
|
||||
* @since 2.11
|
||||
*/
|
||||
Set<LocalizedNode> getAllNodesFiltered(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Gets an immutable Map of the objects permission nodes
|
||||
* @return an immutable map of permissions
|
||||
@@ -84,7 +109,7 @@ public interface PermissionHolder {
|
||||
* @param node the node to check for
|
||||
* @return a Tristate for the holders permission status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Tristate hasPermission(Node node);
|
||||
|
||||
@@ -93,7 +118,7 @@ public interface PermissionHolder {
|
||||
* @param node the node to check for
|
||||
* @return a Tristate for the holders permission status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Tristate hasTransientPermission(Node node);
|
||||
|
||||
@@ -171,7 +196,7 @@ public interface PermissionHolder {
|
||||
* @param node the node to check for
|
||||
* @return a Tristate for the holders inheritance status for the node
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Tristate inheritsPermission(Node node);
|
||||
|
||||
@@ -249,7 +274,7 @@ public interface PermissionHolder {
|
||||
* @param node The node to be set
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
void setPermission(Node node) throws ObjectAlreadyHasException;
|
||||
|
||||
@@ -267,7 +292,7 @@ public interface PermissionHolder {
|
||||
* @param node The node to be set
|
||||
* @throws ObjectAlreadyHasException if the object already has the permission
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
void setTransientPermission(Node node) throws ObjectAlreadyHasException;
|
||||
|
||||
@@ -357,7 +382,7 @@ public interface PermissionHolder {
|
||||
* @param node The node to be unset
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
void unsetPermission(Node node) throws ObjectLacksException;
|
||||
|
||||
@@ -366,7 +391,7 @@ public interface PermissionHolder {
|
||||
* @param node The node to be unset
|
||||
* @throws ObjectLacksException if the node wasn't already set
|
||||
* @throws NullPointerException if the node is null
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
void unsetTransientPermission(Node node) throws ObjectLacksException;
|
||||
|
||||
@@ -498,8 +523,10 @@ public interface PermissionHolder {
|
||||
* @param possibleNodes a list of possible permissions for resolving wildcards
|
||||
* @param applyGroups if inherited group permissions should be included
|
||||
* @return a map of permissions
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
* @deprecated in favour of {@link #getAllNodesFiltered(Contexts)}
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, Boolean> getPermissions(String server, String world, Map<String, String> extraContext, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups);
|
||||
|
||||
/**
|
||||
@@ -513,7 +540,7 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Processes the nodes and returns the temporary ones.
|
||||
* @return a set of temporary nodes
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getTemporaryPermissionNodes();
|
||||
|
||||
@@ -528,7 +555,7 @@ public interface PermissionHolder {
|
||||
/**
|
||||
* Processes the nodes and returns the non-temporary ones.
|
||||
* @return a set of permanent nodes
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
Set<Node> getPermanentPermissionNodes();
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
/**
|
||||
* Represents the platform type that LuckPerms is running on
|
||||
* @since 2.7
|
||||
*/
|
||||
public enum PlatformType {
|
||||
|
||||
BUKKIT("Bukkit"),
|
||||
BUNGEE("Bungee"),
|
||||
SPONGE("Sponge"),
|
||||
|
||||
/**
|
||||
* @since 2.9
|
||||
*/
|
||||
STANDALONE("Standalone");
|
||||
|
||||
private final String friendlyName;
|
||||
|
||||
PlatformType(String friendlyName) {
|
||||
this.friendlyName = friendlyName;
|
||||
}
|
||||
|
||||
public String getFriendlyName() {
|
||||
return friendlyName;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal Track instances
|
||||
* Interface for internal Track instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Track {
|
||||
|
||||
@@ -22,14 +22,16 @@
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.caching.UserData;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Wrapper interface for internal User instances
|
||||
* Interface for internal User instances
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface User extends PermissionHolder {
|
||||
@@ -64,6 +66,13 @@ public interface User extends PermissionHolder {
|
||||
*/
|
||||
void refreshPermissions();
|
||||
|
||||
/**
|
||||
* Gets the user's {@link UserData} cache, if they have one setup.
|
||||
* @return an optional, possibly containing the user's cached lookup data.
|
||||
* @since 2.13
|
||||
*/
|
||||
Optional<UserData> getUserDataCache();
|
||||
|
||||
/**
|
||||
* Check to see if the user is a member of a group
|
||||
* @param group The group to check membership of
|
||||
|
||||
@@ -25,7 +25,9 @@ package me.lucko.luckperms.api;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This UuidCache is a means of allowing users to have the same internal UUID across a network of offline mode servers
|
||||
* A UUID cache for online users, between external Mojang UUIDs, and internal LuckPerms UUIDs.
|
||||
*
|
||||
* <p> This UuidCache is a means of allowing users to have the same internal UUID across a network of offline mode servers
|
||||
* or mixed offline mode and online mode servers. Platforms running in offline mode generate a random UUID for a user when
|
||||
* they first join the server, but this UUID will then not be consistent across the network. LuckPerms will instead check
|
||||
* the datastore cache, to get a UUID for a user that is consistent across an entire network.
|
||||
@@ -35,6 +37,7 @@ import java.util.UUID;
|
||||
*
|
||||
* <p> WARNING: THIS IS ONLY EFFECTIVE FOR ONLINE PLAYERS. USE THE DATASTORE METHODS FOR OFFLINE PLAYERS.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface UuidCache {
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.caching;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
|
||||
/**
|
||||
* Holds cached Meta lookup data for a specific set of contexts
|
||||
* @since 2.13
|
||||
*/
|
||||
public interface MetaData {
|
||||
|
||||
/**
|
||||
* Gets an immutable copy of the meta this user has
|
||||
* @return an immutable map of meta
|
||||
*/
|
||||
Map<String, String> getMeta();
|
||||
|
||||
/**
|
||||
* Gets an immutable sorted map of all of the prefixes the user has, whereby the first value is the highest priority prefix.
|
||||
* @return a sorted map of prefixes
|
||||
*/
|
||||
SortedMap<Integer, String> getPrefixes();
|
||||
|
||||
/**
|
||||
* Gets an immutable sorted map of all of the suffixes the user has, whereby the first value is the highest priority suffix.
|
||||
* @return a sorted map of suffixes
|
||||
*/
|
||||
SortedMap<Integer, String> getSuffixes();
|
||||
|
||||
/**
|
||||
* Gets the user's highest priority prefix, or null if the user has no prefixes
|
||||
* @return a prefix string, or null
|
||||
*/
|
||||
String getPrefix();
|
||||
|
||||
/**
|
||||
* Gets the user's highest priority suffix, or null if the user has no suffixes
|
||||
* @return a suffix string, or null
|
||||
*/
|
||||
String getSuffix();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.caching;
|
||||
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Holds cached Permission lookup data for a specific set of contexts
|
||||
* @since 2.13
|
||||
*/
|
||||
public interface PermissionData {
|
||||
|
||||
/**
|
||||
* Gets a permission value for the given permission node
|
||||
* @param permission the permission node
|
||||
* @return a tristate result
|
||||
* @throws NullPointerException if permission is null
|
||||
*/
|
||||
Tristate getPermissionValue(String permission);
|
||||
|
||||
/**
|
||||
* Invalidates the underlying permission calculator cache.
|
||||
* Can be called to allow for an update in defaults.
|
||||
*/
|
||||
void invalidateCache();
|
||||
|
||||
/**
|
||||
* Gets an immutable copy of the permission map backing the permission calculator
|
||||
* @return an immutable set of permissions
|
||||
*/
|
||||
Map<String, Boolean> getImmutableBacking();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.caching;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Holds cached permission and meta lookup data for a {@link me.lucko.luckperms.api.User}.
|
||||
* Data is only likely to be available for online users. All calls will account for inheritance, as well as any
|
||||
* default data provided by the platform. This calls are heavily cached and are therefore fast.
|
||||
*
|
||||
* @since 2.13
|
||||
*/
|
||||
public interface UserData {
|
||||
|
||||
/**
|
||||
* Gets PermissionData from the cache, given a specified context.
|
||||
* If the data is not cached, it is calculated. Therefore, this call could be costly.
|
||||
* @param contexts the contexts to get the permission data in
|
||||
* @return a permission data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
PermissionData getPermissionData(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Gets MetaData from the cache, given a specified context.
|
||||
* If the data is not cached, it is calculated. Therefore, this call could be costly.
|
||||
* @param contexts the contexts to get the permission data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
MetaData getMetaData(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates permission data, bypassing the cache.
|
||||
* @param contexts the contexts to get permission data in
|
||||
* @return a permission data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
PermissionData calculatePermissions(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates meta data, bypassing the cache.
|
||||
* @param contexts the contexts to get meta data in
|
||||
* @return a meta data instance
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
MetaData calculateMeta(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates permission data and stores it in the cache. If there is already data cached for the given contexts,
|
||||
* and if the resultant output is different, the cached value is updated.
|
||||
* @param contexts the contexts to recalculate in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void recalculatePermissions(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calculates meta data and stores it in the cache. If there is already data cached for the given contexts,
|
||||
* and if the resultant output is different, the cached value is updated.
|
||||
* @param contexts the contexts to recalculate in.
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void recalculateMeta(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Calls {@link #recalculatePermissions(Contexts)} for all current loaded contexts
|
||||
*/
|
||||
void recalculatePermissions();
|
||||
|
||||
/**
|
||||
* Calls {@link #recalculateMeta(Contexts)} for all current loaded contexts
|
||||
*/
|
||||
void recalculateMeta();
|
||||
|
||||
/**
|
||||
* Calls {@link #preCalculate(Contexts)} for the given contexts
|
||||
* @param contexts a set of contexts
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void preCalculate(Set<Contexts> contexts);
|
||||
|
||||
/**
|
||||
* Ensures that PermissionData and MetaData is cached for a context. If the cache does not contain any data for the
|
||||
* context, it will be calculated and saved.
|
||||
* @param contexts the contexts to pre-calculate for
|
||||
* @throws NullPointerException if contexts is null
|
||||
*/
|
||||
void preCalculate(Contexts contexts);
|
||||
|
||||
/**
|
||||
* Invalidates all of the underlying Permission calculators.
|
||||
* Can be called to allow for an update in defaults.
|
||||
*/
|
||||
void invalidatePermissionCalculators();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* A simple implementation of the listener aspects of {@link IContextCalculator}
|
||||
* @param <T> the subject type
|
||||
*/
|
||||
public abstract class ContextCalculator<T> implements IContextCalculator<T> {
|
||||
private final List<ContextListener<T>> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
/**
|
||||
* Pushes an update to all registered {@link ContextListener}s.
|
||||
* Make sure any changes are applied internally before this method is called.
|
||||
* @param subject the subject that changed
|
||||
* @param before the context state before the change
|
||||
* @param current the context state after the change (now)
|
||||
* @throws NullPointerException if any parameters are null
|
||||
*/
|
||||
protected void pushUpdate(T subject, Map.Entry<String, String> before, Map.Entry<String, String> current) {
|
||||
if (subject == null) {
|
||||
throw new NullPointerException("subject");
|
||||
}
|
||||
if (before == null) {
|
||||
throw new NullPointerException("before");
|
||||
}
|
||||
if (current == null) {
|
||||
throw new NullPointerException("current");
|
||||
}
|
||||
|
||||
for (ContextListener<T> listener : listeners) {
|
||||
try {
|
||||
listener.onContextChange(subject, before, current);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception whilst passing context change to listener: " + listener);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(ContextListener<T> listener) {
|
||||
if (listener == null) {
|
||||
throw new NullPointerException("listener");
|
||||
}
|
||||
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Listens to context changes
|
||||
* @param <T> the subject type, Is ALWAYS the player class of the platform.
|
||||
*/
|
||||
public interface ContextListener<T> {
|
||||
|
||||
/**
|
||||
* Called whenever a context changes on the
|
||||
* @param subject the subject that had context changed
|
||||
* @param before the context state before the change
|
||||
* @param current the context state after the change (now)
|
||||
*/
|
||||
void onContextChange(T subject, Map.Entry<String, String> before, Map.Entry<String, String> current) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Holds contexts.
|
||||
* All contained contexts are immutable, and unlike {@link MutableContextSet}, contexts cannot be added or removed.
|
||||
*
|
||||
* @since 2.13
|
||||
*/
|
||||
public class ContextSet {
|
||||
|
||||
/**
|
||||
* Make a singleton ContextSet from a context pair
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return a new ContextSet containing one KV pair
|
||||
* @throws NullPointerException if key or value is null
|
||||
*/
|
||||
public static ContextSet singleton(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.add(key, value);
|
||||
return set.immutableCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ContextSet from an existing map
|
||||
* @param map the map to copy from
|
||||
* @return a new ContextSet representing the pairs from the map
|
||||
* @throws NullPointerException if the map is null
|
||||
*/
|
||||
public static ContextSet fromMap(Map<String, String> map) {
|
||||
if (map == null) {
|
||||
throw new NullPointerException("map");
|
||||
}
|
||||
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(map);
|
||||
return set.immutableCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ContextSet from an existing iterable of Map Entries
|
||||
* @param iterable the iterable to copy from
|
||||
* @return a new ContextSet representing the pairs in the iterable
|
||||
* @throws NullPointerException if the iterable is null
|
||||
*/
|
||||
public static ContextSet fromEntries(Iterable<Map.Entry<String, String>> iterable) {
|
||||
if (iterable == null) {
|
||||
throw new NullPointerException("iterable");
|
||||
}
|
||||
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(iterable);
|
||||
return set.immutableCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ContextSet from an existing set.
|
||||
* Only really useful for converting between mutable and immutable types.
|
||||
* @param contextSet the context set to copy from
|
||||
* @return a new ContextSet with the same content and the one provided
|
||||
* @throws NullPointerException if contextSet is null
|
||||
*/
|
||||
public static ContextSet fromSet(ContextSet contextSet) {
|
||||
if (contextSet == null) {
|
||||
throw new NullPointerException("contextSet");
|
||||
}
|
||||
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(contextSet.toSet());
|
||||
return set.immutableCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new empty ContextSet.
|
||||
* @return a new ContextSet
|
||||
*/
|
||||
public static ContextSet empty() {
|
||||
return new ContextSet();
|
||||
}
|
||||
|
||||
final Set<Map.Entry<String, String>> contexts;
|
||||
|
||||
public ContextSet() {
|
||||
this.contexts = new HashSet<>();
|
||||
}
|
||||
|
||||
protected ContextSet(Set<Map.Entry<String, String>> contexts) {
|
||||
this.contexts = contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if this set is in an immutable form
|
||||
* @return true if the set is immutable
|
||||
*/
|
||||
public boolean isImmutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the set is mutable, this method will return an immutable copy. Otherwise just returns itself.
|
||||
* @return an immutable ContextSet
|
||||
*/
|
||||
public ContextSet makeImmutable() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this ContextSet to an immutable {@link Set} of {@link Map.Entry}s.
|
||||
* @return an immutable set
|
||||
*/
|
||||
public Set<Map.Entry<String, String>> toSet() {
|
||||
synchronized (contexts) {
|
||||
return ImmutableSet.copyOf(contexts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this ContextSet to an immutable {@link Map}
|
||||
*
|
||||
* <b>NOTE: Use of this method may result in data being lost. ContextSets can contain lots of different values for
|
||||
* one key.</b>
|
||||
*
|
||||
* @return an immutable map
|
||||
*/
|
||||
public Map<String, String> toMap() {
|
||||
synchronized (contexts) {
|
||||
return ImmutableMap.copyOf(contexts.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the set contains at least one value for the given key.
|
||||
* @param key the key to check for
|
||||
* @return true if the set contains a value for the key
|
||||
* @throws NullPointerException if the key is null
|
||||
*/
|
||||
public boolean containsKey(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
for (Map.Entry<String, String> e : contexts) {
|
||||
if (e.getKey().equalsIgnoreCase(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a set of all of the values mapped to the given key
|
||||
* @param key the key to find values for
|
||||
* @return a set of values
|
||||
* @throws NullPointerException if the key is null
|
||||
*/
|
||||
public Set<String> getValues(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
return ImmutableSet.copyOf(contexts.stream()
|
||||
.filter(e -> e.getKey().equalsIgnoreCase(key))
|
||||
.map(Map.Entry::getValue)
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if thr set contains a given key mapped to a given value
|
||||
* @param key the key to look for
|
||||
* @param value the value to look for (case sensitive)
|
||||
* @return true if the set contains the KV pair
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public boolean has(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
for (Map.Entry<String, String> e : contexts) {
|
||||
if (!e.getKey().equalsIgnoreCase(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!e.getValue().equals(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #has(String, String)}, except ignores the case of the value.
|
||||
* @param key the key to look for
|
||||
* @param value the value to look for
|
||||
* @return true if the set contains the KV pair
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public boolean hasIgnoreCase(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
for (Map.Entry<String, String> e : contexts) {
|
||||
if (!e.getKey().equalsIgnoreCase(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!e.getValue().equalsIgnoreCase(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the set is empty
|
||||
* @return true if the set is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
synchronized (contexts) {
|
||||
return contexts.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of key-value context pairs in the set
|
||||
* @return the size of the set
|
||||
*/
|
||||
public int size() {
|
||||
synchronized (contexts) {
|
||||
return contexts.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof ContextSet)) return false;
|
||||
final ContextSet other = (ContextSet) o;
|
||||
|
||||
final Object thisContexts = this.contexts;
|
||||
final Object otherContexts = other.contexts;
|
||||
return thisContexts == null ? otherContexts == null : thisContexts.equals(otherContexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 59 + (this.contexts == null ? 43 : this.contexts.hashCode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Calculates whether contexts are applicable to {@link T}
|
||||
*
|
||||
* <p>Somewhat inspired by the system used on Sponge.
|
||||
* @param <T> the subject type. Is ALWAYS the player class of the platform.
|
||||
*/
|
||||
public interface IContextCalculator<T> {
|
||||
|
||||
/**
|
||||
* Gives the subject all of the applicable contexts they meet
|
||||
* @param subject the subject to add contexts to
|
||||
* @param accumulator a map of contexts to add to
|
||||
* @return the map
|
||||
* @deprecated in favour of {@link #giveApplicableContext(Object, MutableContextSet)}. Older implementations of this interface
|
||||
* will still work, as the replacement method is given as a default, and falls back to using this method.
|
||||
*/
|
||||
@Deprecated
|
||||
default Map<String, String> giveApplicableContext(T subject, Map<String, String> accumulator) {
|
||||
MutableContextSet acc = new MutableContextSet();
|
||||
giveApplicableContext(subject, acc);
|
||||
|
||||
accumulator.putAll(acc.toMap());
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the subject all of the applicable contexts they meet
|
||||
*
|
||||
* <p><b>You MUST implement this method. The default is only provided for backwards compatibility with
|
||||
* {@link #giveApplicableContext(Object, Map)}.</b>
|
||||
*
|
||||
* @param subject the subject to add contexts to
|
||||
* @param accumulator a map of contexts to add to
|
||||
* @return the map
|
||||
* @since 2.13
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
default MutableContextSet giveApplicableContext(T subject, MutableContextSet accumulator) {
|
||||
Map<String, String> acc = new HashMap<>();
|
||||
giveApplicableContext(subject, acc);
|
||||
|
||||
accumulator.addAll(acc.entrySet());
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a context is applicable to a subject
|
||||
* @param subject the subject to check against
|
||||
* @param context the context to check for
|
||||
* @return true if met, or false if not. If this calculator does not calculate the given context, return false.
|
||||
*/
|
||||
boolean isContextApplicable(T subject, Map.Entry<String, String> context);
|
||||
|
||||
/**
|
||||
* Adds a listener to be called whenever a context handled by this calculator changes
|
||||
* @param listener the listener instance
|
||||
* @throws NullPointerException if listener is null
|
||||
*/
|
||||
void addListener(ContextListener<T> listener);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.context;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Holds contexts
|
||||
* All contained contexts are immutable, but contexts can be added or removed from the set.
|
||||
*
|
||||
* @since 2.13
|
||||
*/
|
||||
public class MutableContextSet extends ContextSet {
|
||||
|
||||
/**
|
||||
* Make a singleton MutableContextSet from a context pair
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return a new MutableContextSet containing one KV pair
|
||||
* @throws NullPointerException if key or value is null
|
||||
*/
|
||||
public static MutableContextSet singleton(String key, String value) {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.add(key, value);
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MutableContextSet from an existing map
|
||||
* @param map the map to copy from
|
||||
* @return a new MutableContextSet representing the pairs from the map
|
||||
* @throws NullPointerException if the map is null
|
||||
*/
|
||||
public static MutableContextSet fromMap(Map<String, String> map) {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(map);
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MutableContextSet from an existing iterable of Map Entries
|
||||
* @param iterable the iterable to copy from
|
||||
* @return a new MutableContextSet representing the pairs in the iterable
|
||||
* @throws NullPointerException if the iterable is null
|
||||
*/
|
||||
public static MutableContextSet fromEntries(Iterable<Map.Entry<String, String>> iterable) {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(iterable);
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new MutableContextSet from an existing set.
|
||||
* Only really useful for converting between mutable and immutable types.
|
||||
* @param contextSet the context set to copy from
|
||||
* @return a new MutableContextSet with the same content and the one provided
|
||||
* @throws NullPointerException if contextSet is null
|
||||
*/
|
||||
public static MutableContextSet fromSet(ContextSet contextSet) {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.addAll(contextSet.toSet());
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new empty MutableContextSet.
|
||||
* @return a new MutableContextSet
|
||||
*/
|
||||
public static MutableContextSet empty() {
|
||||
return new MutableContextSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextSet makeImmutable() {
|
||||
return immutableCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable copy of this set.
|
||||
* @return an immutable copy of this set
|
||||
*/
|
||||
public ContextSet immutableCopy() {
|
||||
synchronized (contexts) {
|
||||
return new ContextSet(new HashSet<>(contexts));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new key value pair to the set
|
||||
* @param key the key to add
|
||||
* @param value the value to add
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void add(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
contexts.add(Maps.immutableEntry(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new key value pair to the set
|
||||
* @param entry the entry to add
|
||||
* @throws NullPointerException if the entry is null
|
||||
*/
|
||||
public void add(Map.Entry<String, String> entry) {
|
||||
if (entry == null) {
|
||||
throw new NullPointerException("context");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
contexts.add(Maps.immutableEntry(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an iterable containing contexts to the set
|
||||
* @param iterable an iterable of key value context pairs
|
||||
* @throws NullPointerException if iterable is null
|
||||
*/
|
||||
public void addAll(Iterable<Map.Entry<String, String>> iterable) {
|
||||
if (iterable == null) {
|
||||
throw new NullPointerException("contexts");
|
||||
}
|
||||
|
||||
synchronized (this.contexts) {
|
||||
for (Map.Entry<String, String> e : iterable) {
|
||||
this.contexts.add(Maps.immutableEntry(e.getKey(), e.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the entry set of a map to the set
|
||||
* @param map the map to add from
|
||||
* @throws NullPointerException if the map is null
|
||||
*/
|
||||
public void addAll(Map<String, String> map) {
|
||||
if (map == null) {
|
||||
throw new NullPointerException("contexts");
|
||||
}
|
||||
addAll(map.entrySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds of of the values in another ContextSet to this set
|
||||
* @param contextSet the set to add from
|
||||
* @throws NullPointerException if the contextSet is null
|
||||
*/
|
||||
public void addAll(ContextSet contextSet) {
|
||||
if (contextSet == null) {
|
||||
throw new NullPointerException("contextSet");
|
||||
}
|
||||
|
||||
synchronized (this.contexts) {
|
||||
this.contexts.addAll(contextSet.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a key value pair from this set
|
||||
* @param key the key to remove
|
||||
* @param value the value to remove (case sensitive)
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void remove(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
contexts.removeIf(e -> e.getKey().equalsIgnoreCase(key) && e.getValue().equals(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #remove(String, String)}, except ignores the case of the value
|
||||
* @param key the key to remove
|
||||
* @param value the value to remove
|
||||
* @throws NullPointerException if the key or value is null
|
||||
*/
|
||||
public void removeIgnoreCase(String key, String value) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
contexts.removeIf(e -> e.getKey().equalsIgnoreCase(key) && e.getValue().equalsIgnoreCase(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all pairs with the given key
|
||||
* @param key the key to remove
|
||||
* @throws NullPointerException if the key is null
|
||||
*/
|
||||
public void removeAll(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
|
||||
synchronized (contexts) {
|
||||
contexts.removeIf(e -> e.getKey().equalsIgnoreCase(key));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the set
|
||||
*/
|
||||
public void clear() {
|
||||
synchronized (contexts) {
|
||||
contexts.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof ContextSet)) return false;
|
||||
final ContextSet other = (ContextSet) o;
|
||||
|
||||
final Object thisContexts = this.contexts;
|
||||
final Object otherContexts = other.contexts;
|
||||
return thisContexts == null ? otherContexts == null : thisContexts.equals(otherContexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 59 + (this.contexts == null ? 43 : this.contexts.hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
|
||||
/**
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
public class AbstractPermissionEvent extends TargetedEvent<PermissionHolder> {
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ import me.lucko.luckperms.api.event.AbstractPermissionEvent;
|
||||
|
||||
/**
|
||||
* Called when a temporary permission node expires
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
public class PermissionNodeExpireEvent extends AbstractPermissionEvent {
|
||||
public PermissionNodeExpireEvent(PermissionHolder target, Node node) {
|
||||
|
||||
@@ -28,7 +28,7 @@ import me.lucko.luckperms.api.event.AbstractPermissionEvent;
|
||||
|
||||
/**
|
||||
* Called when a permission node is set on a holder
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
public class PermissionNodeSetEvent extends AbstractPermissionEvent {
|
||||
public PermissionNodeSetEvent(PermissionHolder target, Node node) {
|
||||
|
||||
@@ -28,7 +28,7 @@ import me.lucko.luckperms.api.event.AbstractPermissionEvent;
|
||||
|
||||
/**
|
||||
* Called when a permission node is unset from a holder
|
||||
* @since 1.6
|
||||
* @since 2.6
|
||||
*/
|
||||
public class PermissionNodeUnsetEvent extends AbstractPermissionEvent {
|
||||
public PermissionNodeUnsetEvent(PermissionHolder target, Node node) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.exceptions;
|
||||
|
||||
/**
|
||||
* Thrown when a permission holding object doesn't / already has a permission or isn't / is already is a member of a group
|
||||
* @since 2.7
|
||||
*/
|
||||
public abstract class MembershipException extends Exception {
|
||||
}
|
||||
@@ -26,5 +26,5 @@ package me.lucko.luckperms.exceptions;
|
||||
* Thrown when a permission holding object already has a permission, is already a member of a group, or when a track
|
||||
* already contains a group.
|
||||
*/
|
||||
public class ObjectAlreadyHasException extends Exception {
|
||||
public class ObjectAlreadyHasException extends MembershipException {
|
||||
}
|
||||
@@ -26,5 +26,5 @@ package me.lucko.luckperms.exceptions;
|
||||
* Thrown when a permission holding object does not already have a permission, is not already a member of a group,
|
||||
* or when a track doesn't contain a group.
|
||||
*/
|
||||
public class ObjectLacksException extends Exception {
|
||||
public class ObjectLacksException extends MembershipException {
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>luckperms-bukkit-legacy</artifactId>
|
||||
<build>
|
||||
<defaultGoal>clean package</defaultGoal>
|
||||
<finalName>LuckPerms-bukkit-legacy-${release.version}.${git.closest.tag.commit.count}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.xerial:*</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.slf4j</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.slf4j</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.zaxxer.hikari</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mongodb</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bson</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.common</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.guava</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.gson</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.gson</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>revision</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<injectAllReactorProjects>true</injectAllReactorProjects>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- LuckPerms Bukkit -->
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-bukkit</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Shade gson and guava, as they are not included in earlier Bukkit releases -->
|
||||
<!-- gson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- guava -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>19.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>2.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
<version>2.8</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- BukkitAPI -->
|
||||
<dependency>
|
||||
|
||||
+13
-79
@@ -25,15 +25,11 @@ package me.lucko.luckperms.api.placeholders;
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.clip.placeholderapi.util.TimeUtil;
|
||||
import me.lucko.luckperms.api.LuckPermsApi;
|
||||
import me.lucko.luckperms.api.Track;
|
||||
import me.lucko.luckperms.api.User;
|
||||
import me.lucko.luckperms.api.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/*
|
||||
* PlaceholderAPI Expansion for LuckPerms, implemented using the LuckPerms API.
|
||||
@@ -51,7 +47,6 @@ import java.util.regex.Pattern;
|
||||
* - suffix
|
||||
* - meta_<node>
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
private static final String IDENTIFIER = "luckperms";
|
||||
private static final String PLUGIN_NAME = "LuckPerms";
|
||||
@@ -76,7 +71,7 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return api == null ? "null" : api.getVersion();
|
||||
return "2.8";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,7 +80,7 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
return "";
|
||||
}
|
||||
|
||||
Optional<User> u = api.getUserSafe(player.getUniqueId());
|
||||
Optional<User> u = api.getUserSafe(api.getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (!u.isPresent()) {
|
||||
return "";
|
||||
}
|
||||
@@ -128,17 +123,11 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
|
||||
if (identifier.startsWith("expiry_time_") && identifier.length() > "expiry_time_".length()) {
|
||||
String node = identifier.substring("expiry_time_".length());
|
||||
|
||||
|
||||
long currentTime = System.currentTimeMillis() / 1000L;
|
||||
Map<Map.Entry<String, Boolean>, Long> temps = user.getTemporaryNodes();
|
||||
|
||||
for (Map.Entry<Map.Entry<String, Boolean>, Long> e : temps.entrySet()) {
|
||||
if (!e.getKey().getKey().equalsIgnoreCase(node)) {
|
||||
continue;
|
||||
for (Node n : user.getTemporaryPermissionNodes()) {
|
||||
if (n.getPermission().equalsIgnoreCase(node)) {
|
||||
return TimeUtil.getTime((int) (n.getExpiryUnixTime() - currentTime));
|
||||
}
|
||||
|
||||
return TimeUtil.getTime((int) (e.getValue() - currentTime));
|
||||
}
|
||||
|
||||
return "";
|
||||
@@ -146,42 +135,27 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
|
||||
if (identifier.startsWith("group_expiry_time_") && identifier.length() > "group_expiry_time_".length()) {
|
||||
String node = "group." + identifier.substring("group_expiry_time_".length());
|
||||
|
||||
long currentTime = System.currentTimeMillis() / 1000L;
|
||||
Map<Map.Entry<String, Boolean>, Long> temps = user.getTemporaryNodes();
|
||||
|
||||
for (Map.Entry<Map.Entry<String, Boolean>, Long> e : temps.entrySet()) {
|
||||
if (!e.getKey().getKey().equalsIgnoreCase(node)) {
|
||||
continue;
|
||||
for (Node n : user.getTemporaryPermissionNodes()) {
|
||||
if (n.getPermission().equalsIgnoreCase(node)) {
|
||||
return TimeUtil.getTime((int) (n.getExpiryUnixTime() - currentTime));
|
||||
}
|
||||
|
||||
return TimeUtil.getTime((int) (e.getValue() - currentTime));
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
if (identifier.equalsIgnoreCase("prefix")) {
|
||||
return getChatMeta(PREFIX_PATTERN, user);
|
||||
return MetaUtils.getPrefix(user, null, null, true);
|
||||
}
|
||||
|
||||
if (identifier.equalsIgnoreCase("suffix")) {
|
||||
return getChatMeta(SUFFIX_PATTERN, user);
|
||||
return MetaUtils.getSuffix(user, null, null, true);
|
||||
}
|
||||
|
||||
if (identifier.startsWith("meta_") && identifier.length() > "meta_".length()) {
|
||||
String node = "meta." + escapeCharacters(identifier.substring("meta_".length())) + ".";
|
||||
Map<String, Boolean> nodes = user.getNodes();
|
||||
|
||||
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
if (!e.getKey().toLowerCase().startsWith(node)) continue;
|
||||
|
||||
String meta = e.getKey().substring(node.length());
|
||||
return unescapeCharacters(meta);
|
||||
}
|
||||
|
||||
return "";
|
||||
String node = identifier.substring("meta_".length());
|
||||
return MetaUtils.getMeta(user, null, null, node, "", true);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -205,44 +179,4 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
private static String formatBoolean(boolean b) {
|
||||
return b ? PlaceholderAPIPlugin.booleanTrue() : PlaceholderAPIPlugin.booleanFalse();
|
||||
}
|
||||
|
||||
private static String escapeCharacters(String s) {
|
||||
s = s.replace(".", "{SEP}");
|
||||
s = s.replace("/", "{FSEP}");
|
||||
s = s.replace("$", "{DSEP}");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static String unescapeCharacters(String s) {
|
||||
s = s.replace("{SEP}", ".");
|
||||
s = s.replace("{FSEP}", "/");
|
||||
s = s.replace("{DSEP}", "$");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static final Pattern PREFIX_PATTERN = Pattern.compile("(?i)prefix\\.\\d+\\..*");
|
||||
private static final Pattern SUFFIX_PATTERN = Pattern.compile("(?i)suffix\\.\\d+\\..*");
|
||||
private static final Pattern DOT_PATTERN = Pattern.compile("\\.");
|
||||
|
||||
private static String getChatMeta(Pattern pattern, User user) {
|
||||
int priority = 0;
|
||||
String meta = null;
|
||||
for (Map.Entry<String, Boolean> e : user.getLocalPermissions(null, null).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
if (pattern.matcher(e.getKey()).matches()) {
|
||||
String[] parts = DOT_PATTERN.split(e.getKey(), 3);
|
||||
int p = Integer.parseInt(parts[1]);
|
||||
|
||||
if (meta == null || p > priority) {
|
||||
meta = parts[2];
|
||||
priority = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return meta == null ? "" : unescapeCharacters(meta);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>2.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.users.BukkitUser;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.AbstractListener;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.*;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
class BukkitListener extends AbstractListener implements Listener {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
BukkitListener(LPBukkitPlugin plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
|
||||
if (!plugin.getDatastore().isAcceptingLogins()) {
|
||||
// Datastore is disabled, prevent players from joining the server
|
||||
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
onAsyncLogin(e.getUniqueId(), e.getName());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerLogin(PlayerLoginEvent e) {
|
||||
final Player player = e.getPlayer();
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
|
||||
if (user == null) {
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (user instanceof BukkitUser) {
|
||||
BukkitUser u = (BukkitUser) user;
|
||||
|
||||
PermissionAttachment attachment = player.addAttachment(plugin);
|
||||
try {
|
||||
BukkitUser.getPermissionsField().set(attachment, new ConcurrentHashMap<>());
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
||||
u.setAttachment(attachment);
|
||||
}
|
||||
|
||||
plugin.doAsync(user::refreshPermissions);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent e) {
|
||||
// Refresh permissions again
|
||||
plugin.getUserManager().getWorldCache().put(e.getPlayer().getUniqueId(), e.getPlayer().getWorld().getName());
|
||||
plugin.doAsync(() -> refreshPlayer(e.getPlayer().getUniqueId()));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
|
||||
plugin.getUserManager().getWorldCache().put(e.getPlayer().getUniqueId(), e.getPlayer().getWorld().getName());
|
||||
plugin.doAsync(() -> refreshPlayer(e.getPlayer().getUniqueId()));
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||
plugin.getUserManager().getWorldCache().remove(e.getPlayer().getUniqueId());
|
||||
onLeave(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.LuckPermsApi;
|
||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||
import me.lucko.luckperms.api.vault.VaultHook;
|
||||
import me.lucko.luckperms.commands.ConsecutiveExecutor;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import me.lucko.luckperms.core.UuidCache;
|
||||
import me.lucko.luckperms.data.Importer;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.runnables.ExpireTemporaryTask;
|
||||
import me.lucko.luckperms.runnables.UpdateTask;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.storage.StorageFactory;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.BukkitUserManager;
|
||||
import me.lucko.luckperms.utils.LogFactory;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
|
||||
private LPConfiguration configuration;
|
||||
private BukkitUserManager userManager;
|
||||
private GroupManager groupManager;
|
||||
private TrackManager trackManager;
|
||||
private Datastore datastore;
|
||||
private UuidCache uuidCache;
|
||||
private ApiProvider apiProvider;
|
||||
private Logger log;
|
||||
private Importer importer;
|
||||
private ConsecutiveExecutor consecutiveExecutor;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
log = LogFactory.wrap(getLogger());
|
||||
|
||||
getLog().info("Loading configuration...");
|
||||
configuration = new BukkitConfig(this);
|
||||
|
||||
// register events
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new BukkitListener(this), this);
|
||||
|
||||
// register commands
|
||||
getLog().info("Registering commands...");
|
||||
BukkitCommand commandManager = new BukkitCommand(this);
|
||||
PluginCommand main = getServer().getPluginCommand("luckperms");
|
||||
main.setExecutor(commandManager);
|
||||
main.setTabCompleter(commandManager);
|
||||
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
|
||||
|
||||
datastore = StorageFactory.getDatastore(this, "h2");
|
||||
|
||||
getLog().info("Loading internal permission managers...");
|
||||
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
|
||||
userManager = new BukkitUserManager(this);
|
||||
groupManager = new GroupManager(this);
|
||||
trackManager = new TrackManager();
|
||||
importer = new Importer(commandManager);
|
||||
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
|
||||
|
||||
int mins = getConfiguration().getSyncTime();
|
||||
if (mins > 0) {
|
||||
long ticks = mins * 60 * 20;
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, new UpdateTask(this), ticks, ticks);
|
||||
}
|
||||
|
||||
getServer().getScheduler().runTaskTimer(this, BukkitSenderFactory.get(), 1L, 1L);
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpireTemporaryTask(this), 60L, 60L);
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, consecutiveExecutor, 20L, 20L);
|
||||
|
||||
// Provide vault support
|
||||
getLog().info("Attempting to hook into Vault...");
|
||||
try {
|
||||
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
|
||||
VaultHook.hook(this);
|
||||
getLog().info("Registered Vault permission & chat hook.");
|
||||
} else {
|
||||
getLog().info("Vault not found.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
getLog().severe("Error occurred whilst hooking into Vault.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
getLog().info("Registering API...");
|
||||
apiProvider = new ApiProvider(this);
|
||||
LuckPerms.registerProvider(apiProvider);
|
||||
getServer().getServicesManager().register(LuckPermsApi.class, apiProvider, this, ServicePriority.Normal);
|
||||
|
||||
// Run update task to refresh any online users
|
||||
getLog().info("Scheduling Update Task to refresh any online users.");
|
||||
try {
|
||||
new UpdateTask(this).run();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
getLog().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLog().info("Closing datastore...");
|
||||
datastore.shutdown();
|
||||
|
||||
getLog().info("Unregistering API...");
|
||||
LuckPerms.unregisterProvider();
|
||||
getServer().getServicesManager().unregisterAll(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
getServer().getScheduler().runTaskAsynchronously(this, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
getServer().getScheduler().runTask(this, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.BUKKIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getMainDir() {
|
||||
return getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getPlayerStatus(UUID uuid) {
|
||||
return getServer().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getServer().getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPlayerList() {
|
||||
return getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getSenders() {
|
||||
return getServer().getOnlinePlayers().stream().map(p -> BukkitSenderFactory.get().wrap(p)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return BukkitSenderFactory.get().wrap(getServer().getConsoleSender());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPossiblePermissions() {
|
||||
final List<String> perms = new ArrayList<>();
|
||||
|
||||
getServer().getPluginManager().getPermissions().forEach(p -> {
|
||||
perms.add(p.getName());
|
||||
p.getChildren().keySet().forEach(perms::add);
|
||||
});
|
||||
|
||||
return perms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPlugin(String name) {
|
||||
return getServer().getPluginManager().getPlugin(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getService(Class clazz) {
|
||||
return getServer().getServicesManager().load(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginLoaded(String name) {
|
||||
return getServer().getPluginManager().isPluginEnabled(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runUpdateTask() {
|
||||
getServer().getScheduler().runTaskAsynchronously(this, new UpdateTask(this));
|
||||
}
|
||||
}
|
||||
@@ -1,410 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.vault;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static me.lucko.luckperms.utils.ArgumentChecker.escapeCharacters;
|
||||
import static me.lucko.luckperms.utils.ArgumentChecker.unescapeCharacters;
|
||||
|
||||
/**
|
||||
* Provides the Vault Chat service through the use of normal permission nodes.
|
||||
*
|
||||
* Prefixes / Suffixes:
|
||||
* Normal inheritance rules apply.
|
||||
* Permission Nodes = prefix.priority.value OR suffix.priority.value
|
||||
* If a user/group has / inherits multiple prefixes and suffixes, the one with the highest priority is the one that
|
||||
* will apply.
|
||||
*
|
||||
* Meta:
|
||||
* Normal inheritance rules DO NOT apply.
|
||||
* Permission Nodes = meta.node.value
|
||||
*
|
||||
* Node that special characters used within LuckPerms are escaped:
|
||||
* See {@link me.lucko.luckperms.utils.ArgumentChecker#escapeCharacters(String)}
|
||||
*
|
||||
* Registered on normal priority so other plugins can override.
|
||||
*/
|
||||
public class VaultChatHook extends Chat {
|
||||
|
||||
@Setter
|
||||
private LPBukkitPlugin plugin;
|
||||
private final VaultPermissionHook perms;
|
||||
|
||||
VaultChatHook(VaultPermissionHook perms) {
|
||||
super(perms);
|
||||
this.perms = perms;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return perms.getName();
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return perms.isEnabled();
|
||||
}
|
||||
|
||||
private void saveMeta(PermissionHolder holder, String world, String node, String value) {
|
||||
if (holder == null) return;
|
||||
if (node.equals("")) return;
|
||||
node = escapeCharacters(node);
|
||||
value = escapeCharacters(value);
|
||||
|
||||
if (world == null || world.equals("")) {
|
||||
try {
|
||||
holder.setPermission("meta." + node + "." + value, true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
} else {
|
||||
try {
|
||||
holder.setPermission("meta." + node + "." + value, true, "global", world);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
}
|
||||
|
||||
perms.objectSave(holder);
|
||||
}
|
||||
|
||||
private static int getMeta(PermissionHolder holder, String world, String node, int defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, true, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
|
||||
try {
|
||||
return Integer.parseInt(unescapeCharacters(meta.getValue()));
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static double getMeta(PermissionHolder holder, String world, String node, double defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, true, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
|
||||
try {
|
||||
return Double.parseDouble(unescapeCharacters(meta.getValue()));
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static boolean getMeta(PermissionHolder holder, String world, String node, boolean defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, true, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
|
||||
try {
|
||||
return Boolean.parseBoolean(unescapeCharacters(meta.getValue()));
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static String getMeta(PermissionHolder holder, String world, String node, String defaultValue) {
|
||||
if (holder == null) return defaultValue;
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
for (Node n : holder.getPermissions()) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, true, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
|
||||
try {
|
||||
return unescapeCharacters(meta.getValue());
|
||||
} catch (Throwable t) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static String getChatMeta(boolean prefix, PermissionHolder holder, String world) {
|
||||
if (holder == null) return "";
|
||||
|
||||
int priority = -1000;
|
||||
String meta = null;
|
||||
|
||||
for (Node n : holder.getAllNodes(null)) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, true, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
if (!n.isPrefix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> prefixValue = n.getPrefix();
|
||||
if (prefixValue.getKey() > priority) {
|
||||
meta = prefixValue.getValue();
|
||||
priority = prefixValue.getKey();
|
||||
}
|
||||
} else {
|
||||
if (!n.isSuffix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> suffixValue = n.getSuffix();
|
||||
if (suffixValue.getKey() > priority) {
|
||||
meta = suffixValue.getValue();
|
||||
priority = suffixValue.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return meta == null ? "" : unescapeCharacters(meta);
|
||||
}
|
||||
|
||||
public String getPlayerPrefix(String world, @NonNull String player) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getChatMeta(true, user, world);
|
||||
}
|
||||
|
||||
public void setPlayerPrefix(String world, @NonNull String player, @NonNull String prefix) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return;
|
||||
|
||||
if (prefix.equals("")) return;
|
||||
|
||||
try {
|
||||
user.setPermission("prefix.1000." + escapeCharacters(prefix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(user);
|
||||
}
|
||||
|
||||
public String getPlayerSuffix(String world, @NonNull String player) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getChatMeta(false, user, world);
|
||||
}
|
||||
|
||||
public void setPlayerSuffix(String world, @NonNull String player, @NonNull String suffix) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return;
|
||||
|
||||
if (suffix.equals("")) return;
|
||||
|
||||
try {
|
||||
user.setPermission("suffix.1000." + escapeCharacters(suffix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(user);
|
||||
}
|
||||
|
||||
public String getGroupPrefix(String world, @NonNull String group) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getChatMeta(false, g, world);
|
||||
}
|
||||
|
||||
public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
if (g == null) return;
|
||||
|
||||
if (prefix.equals("")) return;
|
||||
|
||||
try {
|
||||
g.setPermission("prefix.1000." + escapeCharacters(prefix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(g);
|
||||
}
|
||||
|
||||
public String getGroupSuffix(String world, @NonNull String group) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getChatMeta(false, g, world);
|
||||
}
|
||||
|
||||
public void setGroupSuffix(String world, @NonNull String group, @NonNull String suffix) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
if (g == null) return;
|
||||
|
||||
if (suffix.equals("")) return;
|
||||
|
||||
try {
|
||||
g.setPermission("suffix.1000." + escapeCharacters(suffix), true);
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.objectSave(g);
|
||||
}
|
||||
|
||||
public int getPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int defaultValue) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int value) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
saveMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public int getGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int defaultValue) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int value) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
saveMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public double getPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double defaultValue) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double value) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
saveMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public double getGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double defaultValue) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double value) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
saveMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public boolean getPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean defaultValue) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean value) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
saveMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public boolean getGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean defaultValue) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean value) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
saveMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public String getPlayerInfoString(String world, @NonNull String player, @NonNull String node, String defaultValue) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return getMeta(user, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setPlayerInfoString(String world, @NonNull String player, @NonNull String node, String value) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
saveMeta(user, world, node, value);
|
||||
}
|
||||
|
||||
public String getGroupInfoString(String world, @NonNull String group, @NonNull String node, String defaultValue) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
return getMeta(g, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setGroupInfoString(String world, @NonNull String group, @NonNull String node, String value) {
|
||||
final Group g = plugin.getGroupManager().get(group);
|
||||
saveMeta(g, world, node, value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.vault;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
|
||||
public class VaultPermissionHook extends Permission {
|
||||
|
||||
@Setter
|
||||
private LPBukkitPlugin plugin;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "LuckPerms";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return plugin.getDatastore().isAcceptingLogins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSuperPermsCompat() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean objectHas(String world, PermissionHolder object, String permission) {
|
||||
if (object == null) return false;
|
||||
|
||||
if (world != null && !world.equals("")) {
|
||||
return object.hasPermission(permission, true, "global", world);
|
||||
} else {
|
||||
return object.hasPermission(permission, true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean objectAdd(String world, PermissionHolder object, String permission) {
|
||||
if (object == null) return false;
|
||||
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
object.setPermission(permission, true, "global", world);
|
||||
} else {
|
||||
object.setPermission(permission, true);
|
||||
}
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
objectSave(object);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean objectRemove(String world, PermissionHolder object, String permission) {
|
||||
if (object == null) return false;
|
||||
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
object.unsetPermission(permission, "global", world);
|
||||
} else {
|
||||
object.unsetPermission(permission);
|
||||
}
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
|
||||
objectSave(object);
|
||||
return true;
|
||||
}
|
||||
|
||||
void objectSave(PermissionHolder t) {
|
||||
if (t instanceof User) {
|
||||
((User) t).refreshPermissions();
|
||||
plugin.getDatastore().saveUser(((User) t), Callback.empty());
|
||||
}
|
||||
if (t instanceof Group) {
|
||||
plugin.getDatastore().saveGroup(((Group) t), c -> plugin.runUpdateTask());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHas(String world, @NonNull String player, @NonNull String permission) {
|
||||
return objectHas(world, plugin.getUserManager().get(player), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAdd(String world, @NonNull String player, @NonNull String permission) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return objectAdd(world, user, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemove(String world, @NonNull String player, @NonNull String permission) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return objectRemove(world, user, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupHas(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
return objectHas(world, group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupAdd(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
return objectAdd(world, group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupRemove(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
return objectRemove(world, group, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerInGroup(String world, @NonNull String player, @NonNull String group) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
final Group group1 = plugin.getGroupManager().get(group);
|
||||
if (group1 == null) return false;
|
||||
|
||||
if (world != null && !world.equals("")) {
|
||||
return user.isInGroup(group1, "global", world);
|
||||
} else {
|
||||
return user.isInGroup(group1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAddGroup(String world, @NonNull String player, @NonNull String groupName) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
user.addGroup(group, "global", world);
|
||||
} else {
|
||||
user.addGroup(group);
|
||||
}
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
objectSave(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemoveGroup(String world, @NonNull String player, @NonNull String groupName) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
user.removeGroup(group, "global", world);
|
||||
} else {
|
||||
user.removeGroup(group);
|
||||
}
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
objectSave(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPlayerGroups(String world, @NonNull String player) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return (user == null) ? new String[0] :
|
||||
world != null && !world.equals("") ? user.getLocalGroups("global", world).toArray(new String[0]) :
|
||||
user.getGroupNames().toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimaryGroup(String world, @NonNull String player) {
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return (user == null) ? null : user.getPrimaryGroup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return plugin.getGroupManager().getAll().keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGroupSupport() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.bukkit.calculators.AttachmentProcessor;
|
||||
import me.lucko.luckperms.bukkit.calculators.DefaultsProcessor;
|
||||
import me.lucko.luckperms.bukkit.inject.Injector;
|
||||
import me.lucko.luckperms.bukkit.inject.LPPermissible;
|
||||
import me.lucko.luckperms.common.calculators.*;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class BukkitCalculatorFactory implements CalculatorFactory {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
@Override
|
||||
public PermissionCalculator build(Contexts contexts, User user, Map<String, Boolean> map) {
|
||||
UUID uuid = plugin.getUuidCache().getExternalUUID(user.getUuid());
|
||||
|
||||
List<PermissionProcessor> processors = new ArrayList<>(5);
|
||||
processors.add(new MapProcessor(map));
|
||||
processors.add(new AttachmentProcessor(() -> {
|
||||
LPPermissible permissible = Injector.getPermissible(uuid);
|
||||
return permissible == null ? null : permissible.getAttachmentPermissions();
|
||||
}));
|
||||
if (plugin.getConfiguration().isApplyingWildcards()) {
|
||||
processors.add(new WildcardProcessor(map));
|
||||
}
|
||||
if (plugin.getConfiguration().isApplyingRegex()) {
|
||||
processors.add(new RegexProcessor(map));
|
||||
}
|
||||
processors.add(new DefaultsProcessor(contexts.isOp(), plugin.getDefaultsProvider()));
|
||||
|
||||
return new PermissionCalculator(plugin, user.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors);
|
||||
}
|
||||
}
|
||||
+14
-4
@@ -20,10 +20,15 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.Util;
|
||||
import me.lucko.luckperms.common.constants.Patterns;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -39,13 +44,18 @@ class BukkitCommand extends CommandManager implements CommandExecutor, TabExecut
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
onCommand(BukkitSenderFactory.get().wrap(sender), label, Arrays.asList(args), Callback.empty());
|
||||
onCommand(
|
||||
BukkitSenderFactory.get(getPlugin()).wrap(sender),
|
||||
label,
|
||||
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
|
||||
Callback.empty()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
|
||||
return onTabComplete(BukkitSenderFactory.get().wrap(sender), Arrays.asList(args));
|
||||
return onTabComplete(BukkitSenderFactory.get(getPlugin()).wrap(sender), Arrays.asList(args));
|
||||
}
|
||||
}
|
||||
+41
-17
@@ -20,16 +20,20 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import me.lucko.luckperms.common.config.AbstractConfiguration;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class BukkitConfig extends LPConfiguration<LPBukkitPlugin> {
|
||||
class BukkitConfig extends AbstractConfiguration<LPBukkitPlugin> {
|
||||
private YamlConfiguration configuration;
|
||||
|
||||
BukkitConfig(LPBukkitPlugin plugin) {
|
||||
@@ -46,18 +50,7 @@ class BukkitConfig extends LPConfiguration<LPBukkitPlugin> {
|
||||
getPlugin().saveResource("config.yml", false);
|
||||
}
|
||||
|
||||
configuration = new YamlConfiguration();
|
||||
|
||||
try {
|
||||
configuration.load(configFile);
|
||||
} catch (InvalidConfigurationException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void set(String path, Object value) {
|
||||
configuration.set(path, value);
|
||||
configuration = YamlConfiguration.loadConfiguration(configFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,4 +67,35 @@ class BukkitConfig extends LPConfiguration<LPBukkitPlugin> {
|
||||
protected boolean getBoolean(String path, boolean def) {
|
||||
return configuration.getBoolean(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getList(String path, List<String> def) {
|
||||
return Optional.ofNullable(configuration.getStringList(path)).orElse(def);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getObjectList(String path, List<String> def) {
|
||||
ConfigurationSection section = configuration.getConfigurationSection(path);
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return Optional.ofNullable(section.getKeys(false).stream().collect(Collectors.toList())).orElse(def);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected Map<String, String> getMap(String path, Map<String, String> def) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
ConfigurationSection section = configuration.getConfigurationSection(path);
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
for (String key : section.getKeys(false)) {
|
||||
map.put(key, section.getString(key));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import me.lucko.luckperms.bukkit.inject.Injector;
|
||||
import me.lucko.luckperms.bukkit.inject.LPPermissible;
|
||||
import me.lucko.luckperms.common.constants.Message;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.utils.AbstractListener;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
class BukkitListener extends AbstractListener implements Listener {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
BukkitListener(LPBukkitPlugin plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
|
||||
if (!plugin.isStarted() || !plugin.getDatastore().isAcceptingLogins()) {
|
||||
|
||||
// The datastore is disabled, prevent players from joining the server
|
||||
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
// Process login
|
||||
onAsyncLogin(e.getUniqueId(), e.getName());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerPreLoginMonitor(AsyncPlayerPreLoginEvent e) {
|
||||
if (plugin.isStarted() && plugin.getDatastore().isAcceptingLogins() && e.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
||||
|
||||
// Login event was cancelled by another plugin
|
||||
onLeave(e.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerLogin(PlayerLoginEvent e) {
|
||||
final Player player = e.getPlayer();
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
|
||||
if (user == null) {
|
||||
// User wasn't loaded for whatever reason.
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Make a new permissible for the user
|
||||
LPPermissible lpPermissible = new LPPermissible(player, user, plugin);
|
||||
|
||||
// Inject into the player
|
||||
Injector.inject(player, lpPermissible);
|
||||
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
||||
if (player.isOp()) {
|
||||
|
||||
// We assume all users are not op, but those who are need extra calculation.
|
||||
plugin.doAsync(() -> user.getUserData().preCalculate(plugin.getPreProcessContexts(true)));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerLoginMonitor(PlayerLoginEvent e) {
|
||||
if (e.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||
|
||||
// The player got denied on sync login.
|
||||
onLeave(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST) // Allow other plugins to see data when this event gets called.
|
||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||
final Player player = e.getPlayer();
|
||||
final UUID internal = plugin.getUuidCache().getUUID(player.getUniqueId());
|
||||
|
||||
// Remove from World cache
|
||||
plugin.getWorldCalculator().getWorldCache().remove(internal);
|
||||
|
||||
// Remove the custom permissible
|
||||
Injector.unInject(player);
|
||||
|
||||
// Handle auto op
|
||||
if (plugin.getConfiguration().isAutoOp()) {
|
||||
player.setOp(false);
|
||||
}
|
||||
|
||||
// Call internal leave handling
|
||||
onLeave(player.getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerCommand(PlayerCommandPreprocessEvent e) {
|
||||
if (plugin.getConfiguration().isOpsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String s = e.getMessage()
|
||||
.replace("/", "")
|
||||
.replace("bukkit:", "")
|
||||
.replace("spigot:", "")
|
||||
.replace("minecraft:", "");
|
||||
|
||||
if (s.startsWith("op") || s.startsWith("deop")) {
|
||||
e.setCancelled(true);
|
||||
e.getPlayer().sendMessage(Message.OP_DISABLED.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-9
@@ -20,23 +20,26 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import me.lucko.luckperms.commands.SenderFactory;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.commands.SenderFactory;
|
||||
import me.lucko.luckperms.common.constants.Constants;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class BukkitSenderFactory extends SenderFactory<CommandSender> {
|
||||
private static BukkitSenderFactory instance = null;
|
||||
public static BukkitSenderFactory get() {
|
||||
if (instance == null){
|
||||
instance = new BukkitSenderFactory();
|
||||
|
||||
private BukkitSenderFactory(LuckPermsPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
public static synchronized BukkitSenderFactory get(LuckPermsPlugin plugin) {
|
||||
if (instance == null) {
|
||||
instance = new BukkitSenderFactory(plugin);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.ApiHandler;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.LuckPermsApi;
|
||||
import me.lucko.luckperms.api.PlatformType;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.bukkit.calculators.AutoOPListener;
|
||||
import me.lucko.luckperms.bukkit.calculators.DefaultsProvider;
|
||||
import me.lucko.luckperms.bukkit.vault.VaultHook;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.api.ApiProvider;
|
||||
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||
import me.lucko.luckperms.common.commands.ConsecutiveExecutor;
|
||||
import me.lucko.luckperms.common.commands.Sender;
|
||||
import me.lucko.luckperms.common.config.LPConfiguration;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.contexts.ContextManager;
|
||||
import me.lucko.luckperms.common.contexts.ServerCalculator;
|
||||
import me.lucko.luckperms.common.core.UuidCache;
|
||||
import me.lucko.luckperms.common.data.Importer;
|
||||
import me.lucko.luckperms.common.groups.GroupManager;
|
||||
import me.lucko.luckperms.common.runnables.ExpireTemporaryTask;
|
||||
import me.lucko.luckperms.common.runnables.UpdateTask;
|
||||
import me.lucko.luckperms.common.storage.Datastore;
|
||||
import me.lucko.luckperms.common.storage.StorageFactory;
|
||||
import me.lucko.luckperms.common.tracks.TrackManager;
|
||||
import me.lucko.luckperms.common.users.UserManager;
|
||||
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||
import me.lucko.luckperms.common.utils.LocaleManager;
|
||||
import me.lucko.luckperms.common.utils.LogFactory;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
private VaultHook vaultHook = null;
|
||||
|
||||
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
|
||||
private LPConfiguration configuration;
|
||||
private UserManager userManager;
|
||||
private GroupManager groupManager;
|
||||
private TrackManager trackManager;
|
||||
private Datastore datastore;
|
||||
private UuidCache uuidCache;
|
||||
private ApiProvider apiProvider;
|
||||
private Logger log;
|
||||
private Importer importer;
|
||||
private ConsecutiveExecutor consecutiveExecutor;
|
||||
private DefaultsProvider defaultsProvider;
|
||||
private LocaleManager localeManager;
|
||||
private ContextManager<Player> contextManager;
|
||||
private WorldCalculator worldCalculator;
|
||||
private CalculatorFactory calculatorFactory;
|
||||
private BufferedRequest<Void> updateTaskBuffer;
|
||||
private boolean started = false;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
log = LogFactory.wrap(getLogger());
|
||||
|
||||
getLog().info("Loading configuration...");
|
||||
configuration = new BukkitConfig(this);
|
||||
|
||||
localeManager = new LocaleManager();
|
||||
File locale = new File(getDataFolder(), "lang.yml");
|
||||
if (locale.exists()) {
|
||||
getLog().info("Found locale file. Attempting to load from it.");
|
||||
try {
|
||||
localeManager.loadFromFile(locale);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
defaultsProvider = new DefaultsProvider();
|
||||
getServer().getScheduler().runTaskLater(this, () -> defaultsProvider.refresh(), 1L);
|
||||
|
||||
// register events
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new BukkitListener(this), this);
|
||||
|
||||
// register commands
|
||||
getLog().info("Registering commands...");
|
||||
BukkitCommand commandManager = new BukkitCommand(this);
|
||||
PluginCommand main = getServer().getPluginCommand("luckperms");
|
||||
main.setExecutor(commandManager);
|
||||
main.setTabCompleter(commandManager);
|
||||
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
|
||||
|
||||
datastore = StorageFactory.getDatastore(this, "h2");
|
||||
|
||||
getLog().info("Loading internal permission managers...");
|
||||
uuidCache = new UuidCache(getConfiguration().isOnlineMode());
|
||||
userManager = new UserManager(this);
|
||||
groupManager = new GroupManager(this);
|
||||
trackManager = new TrackManager();
|
||||
importer = new Importer(commandManager);
|
||||
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
|
||||
calculatorFactory = new BukkitCalculatorFactory(this);
|
||||
|
||||
contextManager = new ContextManager<>();
|
||||
worldCalculator = new WorldCalculator(this);
|
||||
pm.registerEvents(worldCalculator, this);
|
||||
contextManager.registerCalculator(worldCalculator);
|
||||
contextManager.registerCalculator(new ServerCalculator<>(getConfiguration().getServer()));
|
||||
|
||||
if (getConfiguration().isAutoOp()) {
|
||||
contextManager.registerListener(new AutoOPListener());
|
||||
}
|
||||
|
||||
final LPBukkitPlugin i = this;
|
||||
updateTaskBuffer = new BufferedRequest<Void>(6000L, this::doAsync) {
|
||||
@Override
|
||||
protected Void perform() {
|
||||
getServer().getScheduler().runTaskAsynchronously(i, new UpdateTask(i));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
int mins = getConfiguration().getSyncTime();
|
||||
if (mins > 0) {
|
||||
long ticks = mins * 60 * 20;
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, () -> updateTaskBuffer.request(), ticks, ticks);
|
||||
}
|
||||
|
||||
getServer().getScheduler().runTaskTimer(this, BukkitSenderFactory.get(this), 1L, 1L);
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpireTemporaryTask(this), 60L, 60L);
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, consecutiveExecutor, 20L, 20L);
|
||||
|
||||
// Provide vault support
|
||||
getLog().info("Attempting to hook into Vault...");
|
||||
try {
|
||||
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
|
||||
vaultHook = new VaultHook();
|
||||
vaultHook.hook(this);
|
||||
getLog().info("Registered Vault permission & chat hook.");
|
||||
} else {
|
||||
getLog().info("Vault not found.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
getLog().severe("Error occurred whilst hooking into Vault.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
getLog().info("Registering API...");
|
||||
apiProvider = new ApiProvider(this);
|
||||
ApiHandler.registerProvider(apiProvider);
|
||||
getServer().getServicesManager().register(LuckPermsApi.class, apiProvider, this, ServicePriority.Normal);
|
||||
|
||||
// Run update task to refresh any online users
|
||||
getLog().info("Scheduling Update Task to refresh any online users.");
|
||||
updateTaskBuffer.request();
|
||||
|
||||
registerPermissions(getConfiguration().isCommandsAllowOp() ? PermissionDefault.OP : PermissionDefault.FALSE);
|
||||
if (!getConfiguration().isOpsEnabled()) {
|
||||
getServer().getOperators().forEach(o -> o.setOp(false));
|
||||
}
|
||||
|
||||
started = true;
|
||||
getLog().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
started = false;
|
||||
getLog().info("Closing datastore...");
|
||||
datastore.shutdown();
|
||||
|
||||
getLog().info("Unregistering API...");
|
||||
ApiHandler.unregisterProvider();
|
||||
getServer().getServicesManager().unregisterAll(this);
|
||||
|
||||
if (vaultHook != null) {
|
||||
vaultHook.unhook(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
getServer().getScheduler().runTaskAsynchronously(this, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
getServer().getScheduler().runTask(this, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsyncRepeating(Runnable r, long interval) {
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, r, interval, interval);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformType getType() {
|
||||
return PlatformType.BUKKIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getMainDir() {
|
||||
return getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getServer().getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPlayerList() {
|
||||
return getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getOnlinePlayers() {
|
||||
return getServer().getOnlinePlayers().stream().map(Player::getUniqueId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline(UUID external) {
|
||||
return getServer().getPlayer(external) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getNotifyListeners() {
|
||||
return getServer().getOnlinePlayers().stream()
|
||||
.map(p -> BukkitSenderFactory.get(this).wrap(p, Collections.singleton(Permission.LOG_NOTIFY)))
|
||||
.filter(Permission.LOG_NOTIFY::isAuthorized)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return BukkitSenderFactory.get(this).wrap(getServer().getConsoleSender());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Contexts> getPreProcessContexts(boolean op) {
|
||||
Set<ContextSet> c = new HashSet<>();
|
||||
c.add(ContextSet.empty());
|
||||
c.add(ContextSet.singleton("server", getConfiguration().getServer()));
|
||||
|
||||
// Pre process all worlds
|
||||
c.addAll(getServer().getWorlds().stream()
|
||||
.map(World::getName)
|
||||
.map(s -> {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.add("server", getConfiguration().getServer());
|
||||
set.add("world", s);
|
||||
return set.makeImmutable();
|
||||
})
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
|
||||
// Pre process the separate Vault server, if any
|
||||
if (!getConfiguration().getServer().equals(getConfiguration().getVaultServer())) {
|
||||
c.add(ContextSet.singleton("server", getConfiguration().getVaultServer()));
|
||||
c.addAll(getServer().getWorlds().stream()
|
||||
.map(World::getName)
|
||||
.map(s -> {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.add("server", getConfiguration().getVaultServer());
|
||||
set.add("world", s);
|
||||
return set.makeImmutable();
|
||||
})
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
Set<Contexts> contexts = new HashSet<>();
|
||||
|
||||
// Convert to full Contexts
|
||||
contexts.addAll(c.stream()
|
||||
.map(set -> new Contexts(
|
||||
set,
|
||||
getConfiguration().isIncludingGlobalPerms(),
|
||||
getConfiguration().isIncludingGlobalWorldPerms(),
|
||||
true,
|
||||
getConfiguration().isApplyingGlobalGroups(),
|
||||
getConfiguration().isApplyingGlobalWorldGroups(),
|
||||
op
|
||||
))
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
|
||||
// Check for and include varying Vault config options
|
||||
try {
|
||||
assert getConfiguration().isVaultIncludingGlobal() == getConfiguration().isIncludingGlobalPerms();
|
||||
assert getConfiguration().isIncludingGlobalWorldPerms();
|
||||
assert getConfiguration().isApplyingGlobalGroups();
|
||||
assert getConfiguration().isApplyingGlobalWorldGroups();
|
||||
} catch (AssertionError e) {
|
||||
contexts.addAll(c.stream()
|
||||
.map(map -> new Contexts(map, getConfiguration().isVaultIncludingGlobal(), true, true, true, true, op))
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
}
|
||||
|
||||
return contexts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPlugin(String name) {
|
||||
return getServer().getPluginManager().getPlugin(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getService(Class clazz) {
|
||||
return getServer().getServicesManager().load(clazz);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public UUID getUUID(String playerName) {
|
||||
try {
|
||||
return getServer().getOfflinePlayer(playerName).getUniqueId();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginLoaded(String name) {
|
||||
return getServer().getPluginManager().isPluginEnabled(name);
|
||||
}
|
||||
|
||||
private void registerPermissions(PermissionDefault def) {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
|
||||
for (Permission p : Permission.values()) {
|
||||
for (String node : p.getNodes()) {
|
||||
pm.addPermission(new org.bukkit.permissions.Permission(node, def));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.api.context.ContextCalculator;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class WorldCalculator extends ContextCalculator<Player> implements Listener {
|
||||
private static final String WORLD_KEY = "world";
|
||||
|
||||
private final LuckPermsPlugin plugin;
|
||||
|
||||
@Getter
|
||||
private final Map<UUID, String> worldCache = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public MutableContextSet giveApplicableContext(Player subject, MutableContextSet accumulator) {
|
||||
String world = getWorld(subject);
|
||||
|
||||
if (world != null) {
|
||||
accumulator.add(Maps.immutableEntry(WORLD_KEY, world));
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isContextApplicable(Player subject, Map.Entry<String, String> context) {
|
||||
if (!context.getKey().equals(WORLD_KEY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String world = getWorld(subject);
|
||||
return world != null && world.equals(context.getValue());
|
||||
}
|
||||
|
||||
private String getWorld(Player player) {
|
||||
UUID internal = plugin.getUuidCache().getUUID(player.getUniqueId());
|
||||
if (!worldCache.containsKey(internal)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String world = worldCache.get(internal);
|
||||
return plugin.getConfiguration().getWorldRewrites().getOrDefault(world, world);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerJoin(PlayerLoginEvent e) {
|
||||
UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
|
||||
worldCache.put(internal, e.getPlayer().getWorld().getName());
|
||||
pushUpdate(
|
||||
e.getPlayer(),
|
||||
Maps.immutableEntry(WORLD_KEY, null),
|
||||
Maps.immutableEntry(WORLD_KEY, e.getPlayer().getWorld().getName())
|
||||
);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
|
||||
UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
|
||||
worldCache.put(internal, e.getPlayer().getWorld().getName());
|
||||
pushUpdate(
|
||||
e.getPlayer(),
|
||||
Maps.immutableEntry(WORLD_KEY, e.getFrom().getName()),
|
||||
Maps.immutableEntry(WORLD_KEY, e.getPlayer().getWorld().getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.calculators;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.common.calculators.PermissionProcessor;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class AttachmentProcessor implements PermissionProcessor {
|
||||
|
||||
@Getter
|
||||
private final Supplier<Map<String, PermissionAttachmentInfo>> map;
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
Map<String, PermissionAttachmentInfo> m = map.get();
|
||||
if (m == null) {
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
|
||||
PermissionAttachmentInfo pai = m.get(permission);
|
||||
return pai == null ? Tristate.UNDEFINED : Tristate.fromBoolean(pai.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.calculators;
|
||||
|
||||
import me.lucko.luckperms.api.context.ContextListener;
|
||||
import me.lucko.luckperms.bukkit.inject.Injector;
|
||||
import me.lucko.luckperms.bukkit.inject.LPPermissible;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class AutoOPListener implements ContextListener<Player> {
|
||||
|
||||
@Override
|
||||
public void onContextChange(Player subject, Map.Entry<String, String> before, Map.Entry<String, String> current) throws Exception {
|
||||
LPPermissible permissible = Injector.getPermissible(subject.getUniqueId());
|
||||
if (permissible == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Boolean> backing = permissible.getUser().getUserData().getPermissionData(permissible.calculateContexts()).getImmutableBacking();
|
||||
boolean op = Optional.ofNullable(backing.get("luckperms.autoop")).orElse(false);
|
||||
subject.setOp(op);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.calculators;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.common.calculators.PermissionProcessor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.permissions.Permission;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class DefaultsProcessor implements PermissionProcessor {
|
||||
private final boolean isOp;
|
||||
private final DefaultsProvider defaultsProvider;
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
Tristate t = defaultsProvider.hasDefault(permission, isOp);
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return t;
|
||||
}
|
||||
|
||||
Permission defPerm = Bukkit.getServer().getPluginManager().getPermission(permission);
|
||||
return defPerm == null ? Tristate.UNDEFINED : Tristate.fromBoolean(defPerm.getDefault().getValue(isOp));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.calculators;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class DefaultsProvider {
|
||||
|
||||
private final DummyPermissible opDummy = new DummyPermissible(this::refreshOp);
|
||||
private final DummyPermissible nonOpDummy = new DummyPermissible(this::refreshNonOp);
|
||||
|
||||
private final Map<String, Boolean> op = new HashMap<>();
|
||||
private final Map<String, Boolean> nonOp = new HashMap<>();
|
||||
|
||||
public void refresh() {
|
||||
refreshOp();
|
||||
refreshNonOp();
|
||||
}
|
||||
|
||||
private void refreshOp() {
|
||||
calculateDefaults(op, opDummy, true);
|
||||
}
|
||||
|
||||
private void refreshNonOp() {
|
||||
calculateDefaults(nonOp, nonOpDummy, false);
|
||||
}
|
||||
|
||||
private static void calculateDefaults(Map<String, Boolean> map, DummyPermissible p, boolean op) {
|
||||
Set<String> perms = map.keySet();
|
||||
|
||||
for (String name : perms) {
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromPermission(name, p);
|
||||
}
|
||||
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(false, p);
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(true, p);
|
||||
|
||||
map.clear();
|
||||
|
||||
Set<Permission> defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(op);
|
||||
Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(op, p);
|
||||
|
||||
for (Permission perm : defaults) {
|
||||
String name = perm.getName().toLowerCase();
|
||||
map.put(name, true);
|
||||
Bukkit.getServer().getPluginManager().subscribeToPermission(name, p);
|
||||
calculateChildPermissions(map, p, perm.getChildren(), false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void calculateChildPermissions(Map<String, Boolean> map, DummyPermissible p, Map<String, Boolean> children, boolean invert) {
|
||||
for (Map.Entry<String, Boolean> e : children.entrySet()) {
|
||||
Permission perm = Bukkit.getServer().getPluginManager().getPermission(e.getKey());
|
||||
boolean value = e.getValue() ^ invert;
|
||||
String lName = e.getKey().toLowerCase();
|
||||
|
||||
map.put(lName, value);
|
||||
Bukkit.getServer().getPluginManager().subscribeToPermission(e.getKey(), p);
|
||||
|
||||
if (perm != null) {
|
||||
calculateChildPermissions(map, p, perm.getChildren(), !value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Tristate hasDefault(String permission, boolean isOp) {
|
||||
Map<String, Boolean> map = isOp ? op : nonOp;
|
||||
|
||||
Boolean b = map.get(permission);
|
||||
return b == null ? Tristate.UNDEFINED : Tristate.fromBoolean(b);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private static class DummyPermissible implements Permissible {
|
||||
private final Runnable onRefresh;
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions() {
|
||||
onRefresh.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(Permission perm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Permission perm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttachment(PermissionAttachment attachment) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOp(boolean value) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.inject;
|
||||
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public class DummyPermissibleBase extends PermissibleBase {
|
||||
public DummyPermissibleBase() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOp(boolean value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(Permission perm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String inName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Permission perm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttachment(PermissionAttachment attachment) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void clearPermissions() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.inject;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Injects a {@link LPPermissible} into a {@link Player}
|
||||
*/
|
||||
@UtilityClass
|
||||
public class Injector {
|
||||
private static final Map<UUID, LPPermissible> INJECTED_PERMISSIBLES = new ConcurrentHashMap<>();
|
||||
private static Field HUMAN_ENTITY_FIELD;
|
||||
|
||||
static {
|
||||
try {
|
||||
HUMAN_ENTITY_FIELD = Class.forName(getVersionedClassName("entity.CraftHumanEntity")).getDeclaredField("perm");
|
||||
HUMAN_ENTITY_FIELD.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean inject(Player player, LPPermissible permissible) {
|
||||
try {
|
||||
HUMAN_ENTITY_FIELD.set(player, permissible);
|
||||
INJECTED_PERMISSIBLES.put(player.getUniqueId(), permissible);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean unInject(Player player) {
|
||||
try {
|
||||
Permissible permissible = (Permissible) HUMAN_ENTITY_FIELD.get(player);
|
||||
if (permissible instanceof LPPermissible) {
|
||||
/* The player is most likely leaving. Bukkit will attempt to call #clearPermissions, so we cannot set to null.
|
||||
However, there's no need to re-inject a real PermissibleBase, so we just inject a dummy instead.
|
||||
This saves tick time, pointlessly recalculating defaults when the instance will never be used. */
|
||||
HUMAN_ENTITY_FIELD.set(player, new DummyPermissibleBase());
|
||||
}
|
||||
INJECTED_PERMISSIBLES.remove(player.getUniqueId());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static LPPermissible getPermissible(UUID uuid) {
|
||||
return INJECTED_PERMISSIBLES.get(uuid);
|
||||
}
|
||||
|
||||
private static String getVersionedClassName(String className) {
|
||||
Class server = Bukkit.getServer().getClass();
|
||||
if (!server.getSimpleName().equals("CraftServer")) {
|
||||
throw new RuntimeException("Couldn't inject into server " + server);
|
||||
}
|
||||
|
||||
String version;
|
||||
if (server.getName().equals("org.bukkit.craftbukkit.CraftServer")) {
|
||||
// Non versioned class
|
||||
version = ".";
|
||||
} else {
|
||||
version = server.getName().substring("org.bukkit.craftbukkit".length());
|
||||
version = version.substring(0, version.length() - "CraftServer".length());
|
||||
}
|
||||
|
||||
return "org.bukkit.craftbukkit" + version + className;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.inject;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.*;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Modified PermissibleBase for LuckPerms
|
||||
*/
|
||||
public class LPPermissible extends PermissibleBase {
|
||||
|
||||
@Getter
|
||||
private final User user;
|
||||
|
||||
@Getter
|
||||
private final Player parent;
|
||||
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
// Attachment stuff.
|
||||
@Getter
|
||||
private final Map<String, PermissionAttachmentInfo> attachmentPermissions = new HashMap<>();
|
||||
private final List<PermissionAttachment> attachments = new LinkedList<>();
|
||||
|
||||
public LPPermissible(@NonNull Player parent, User user, LPBukkitPlugin plugin) {
|
||||
super(parent);
|
||||
this.user = user;
|
||||
this.parent = parent;
|
||||
this.plugin = plugin;
|
||||
|
||||
recalculatePermissions();
|
||||
}
|
||||
|
||||
public Contexts calculateContexts() {
|
||||
return new Contexts(
|
||||
plugin.getContextManager().giveApplicableContext(parent, new MutableContextSet()),
|
||||
plugin.getConfiguration().isIncludingGlobalPerms(),
|
||||
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
|
||||
true,
|
||||
plugin.getConfiguration().isApplyingGlobalGroups(),
|
||||
plugin.getConfiguration().isApplyingGlobalWorldGroups(),
|
||||
parent.isOp()
|
||||
);
|
||||
}
|
||||
|
||||
private boolean hasData() {
|
||||
return user.getUserData() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOp(boolean value) {
|
||||
parent.setOp(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NonNull String name) {
|
||||
return hasData() && user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(name) != Tristate.UNDEFINED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NonNull Permission perm) {
|
||||
return isPermissionSet(perm.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull String name) {
|
||||
if (hasData()) {
|
||||
Tristate ts = user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(name);
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
return ts.asBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
return Permission.DEFAULT_PERMISSION.getValue(isOp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull Permission perm) {
|
||||
if (hasData()) {
|
||||
Tristate ts = user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(perm.getName());
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
return ts.asBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
return perm.getDefault().getValue(isOp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
||||
Set<PermissionAttachmentInfo> perms = new HashSet<>();
|
||||
perms.addAll(attachmentPermissions.values());
|
||||
|
||||
if (hasData()) {
|
||||
perms.addAll(
|
||||
user.getUserData().getPermissionData(calculateContexts()).getImmutableBacking().entrySet().stream()
|
||||
.map(e -> new PermissionAttachmentInfo(parent, e.getKey(), null, e.getValue()))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
return perms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, @NonNull String name, boolean value) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = addAttachment(plugin);
|
||||
result.setPermission(name, value);
|
||||
|
||||
recalculatePermissions();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = new PermissionAttachment(plugin, parent);
|
||||
|
||||
attachments.add(result);
|
||||
recalculatePermissions();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, @NonNull String name, boolean value, int ticks) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = addAttachment(plugin, ticks);
|
||||
if (result != null) {
|
||||
result.setPermission(name, value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, int ticks) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = addAttachment(plugin);
|
||||
if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new RemoveAttachmentRunnable(result), ticks) == -1) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add PermissionAttachment to " + parent + " for plugin " + plugin.getDescription().getFullName() + ": Scheduler returned -1");
|
||||
result.remove();
|
||||
return null;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttachment(@NonNull PermissionAttachment attachment) {
|
||||
if (attachments.contains(attachment)) {
|
||||
attachments.remove(attachment);
|
||||
PermissionRemovedExecutor ex = attachment.getRemovalCallback();
|
||||
|
||||
if (ex != null) {
|
||||
ex.attachmentRemoved(attachment);
|
||||
}
|
||||
|
||||
recalculatePermissions();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Given attachment is not part of Permissible object " + parent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions() {
|
||||
if (attachmentPermissions == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
attachmentPermissions.clear();
|
||||
|
||||
for (PermissionAttachment attachment : attachments) {
|
||||
calculateChildPermissions(attachment.getPermissions(), false, attachment);
|
||||
}
|
||||
|
||||
if (hasData()) {
|
||||
user.getUserData().invalidatePermissionCalculators();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void clearPermissions() {
|
||||
Set<String> perms = attachmentPermissions.keySet();
|
||||
|
||||
for (String name : perms) {
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromPermission(name, parent);
|
||||
}
|
||||
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(false, parent);
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(true, parent);
|
||||
|
||||
attachmentPermissions.clear();
|
||||
}
|
||||
|
||||
private void calculateChildPermissions(Map<String, Boolean> children, boolean invert, PermissionAttachment attachment) {
|
||||
for (Map.Entry<String, Boolean> e : children.entrySet()) {
|
||||
Permission perm = Bukkit.getServer().getPluginManager().getPermission(e.getKey());
|
||||
boolean value = e.getValue() ^ invert;
|
||||
String name = e.getKey().toLowerCase();
|
||||
|
||||
attachmentPermissions.put(name, new PermissionAttachmentInfo(parent, name, attachment, value));
|
||||
Bukkit.getServer().getPluginManager().subscribeToPermission(name, parent);
|
||||
|
||||
if (perm != null) {
|
||||
calculateChildPermissions(perm.getChildren(), !value, attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class RemoveAttachmentRunnable implements Runnable {
|
||||
private PermissionAttachment attachment;
|
||||
|
||||
private RemoveAttachmentRunnable(PermissionAttachment attachment) {
|
||||
this.attachment = attachment;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
attachment.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.vault;
|
||||
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.caching.MetaData;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.common.core.PermissionHolder;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static me.lucko.luckperms.api.MetaUtils.escapeCharacters;
|
||||
import static me.lucko.luckperms.api.MetaUtils.unescapeCharacters;
|
||||
|
||||
/**
|
||||
* Provides the Vault Chat service through the use of normal permission nodes.
|
||||
*
|
||||
* Prefixes / Suffixes:
|
||||
* Normal inheritance rules apply.
|
||||
* Permission Nodes = prefix.priority.value OR suffix.priority.value
|
||||
* If a user/group has / inherits multiple prefixes and suffixes, the one with the highest priority is the one that
|
||||
* will apply.
|
||||
*
|
||||
* Meta:
|
||||
* Normal inheritance rules DO NOT apply.
|
||||
* Permission Nodes = meta.node.value
|
||||
*
|
||||
* Node that special characters used within LuckPerms are escaped:
|
||||
* See {@link me.lucko.luckperms.api.MetaUtils#unescapeCharacters(String)}
|
||||
*/
|
||||
public class VaultChatHook extends Chat {
|
||||
private final VaultPermissionHook perms;
|
||||
|
||||
VaultChatHook(VaultPermissionHook perms) {
|
||||
super(perms);
|
||||
this.perms = perms;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return perms.getName();
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return perms.isEnabled();
|
||||
}
|
||||
|
||||
private void setMeta(PermissionHolder holder, String world, String node, String value) {
|
||||
String finalWorld = perms.isIgnoreWorld() ? null : world;
|
||||
if (holder == null) return;
|
||||
if (node.equals("")) return;
|
||||
|
||||
perms.log("Setting meta: '" + node + "' for " + holder.getObjectName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
perms.getScheduler().scheduleTask(() -> {
|
||||
String k = escapeCharacters(node);
|
||||
String v = escapeCharacters(value);
|
||||
|
||||
List<Node> toRemove = holder.getNodes().stream()
|
||||
.filter(n -> n.isMeta() && n.getMeta().getKey().equals(k))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
toRemove.forEach(n -> {
|
||||
try {
|
||||
holder.unsetPermission(n);
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
});
|
||||
|
||||
Node.Builder metaNode = new me.lucko.luckperms.common.core.Node.Builder("meta." + k + "." + v).setValue(true);
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
metaNode.setServer(perms.getServer());
|
||||
}
|
||||
if (finalWorld != null && !finalWorld.equals("")) {
|
||||
metaNode.setServer(perms.getServer()).setWorld(finalWorld);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(metaNode.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.save(holder);
|
||||
});
|
||||
}
|
||||
|
||||
private void setChatMeta(boolean prefix, PermissionHolder holder, String value, String world) {
|
||||
String finalWorld = perms.isIgnoreWorld() ? null : world;
|
||||
if (holder == null) return;
|
||||
if (value.equals("")) return;
|
||||
|
||||
perms.log("Setting " + (prefix ? "prefix" : "suffix") + " for " + holder.getObjectName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
perms.getScheduler().scheduleTask(() -> {
|
||||
Node.Builder node = new me.lucko.luckperms.common.core.Node.Builder(prefix ? "prefix" : "suffix" + ".1000." + escapeCharacters(value));
|
||||
node.setValue(true);
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
node.setServer(perms.getServer());
|
||||
}
|
||||
|
||||
if (finalWorld != null && !finalWorld.equals("")) {
|
||||
node.setServer(perms.getServer()).setWorld(finalWorld);
|
||||
}
|
||||
|
||||
try {
|
||||
holder.setPermission(node.build());
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
perms.save(holder);
|
||||
});
|
||||
}
|
||||
|
||||
private String getUserMeta(User user, String world, String node, String defaultValue) {
|
||||
if (user == null) return defaultValue;
|
||||
world = perms.isIgnoreWorld() ? null : world;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
perms.log("Getting meta: '" + node + "' for user " + user.getName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
if (user.getUserData() == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return unescapeCharacters(user.getUserData().getMetaData(perms.createContext(perms.getServer(), world)).getMeta().getOrDefault(node, defaultValue));
|
||||
}
|
||||
|
||||
private String getUserChatMeta(boolean prefix, User user, String world) {
|
||||
if (user == null) return "";
|
||||
world = perms.isIgnoreWorld() ? null : world;
|
||||
|
||||
perms.log("Getting " + (prefix ? "prefix" : "suffix") + " for user " + user.getName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
if (user.getUserData() == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
MetaData data = user.getUserData().getMetaData(perms.createContext(perms.getServer(), world));
|
||||
String v = prefix ? data.getPrefix() : data.getSuffix();
|
||||
return v == null ? "" : unescapeCharacters(v);
|
||||
}
|
||||
|
||||
private String getGroupMeta(Group group, String world, String node, String defaultValue) {
|
||||
world = perms.isIgnoreWorld() ? null : world;
|
||||
if (group == null) return defaultValue;
|
||||
if (node.equals("")) return defaultValue;
|
||||
node = escapeCharacters(node);
|
||||
|
||||
perms.log("Getting meta: '" + node + "' for group " + group.getName() + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
for (Node n : group.getPermissions(true)) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.isMeta()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnServer(perms.getServer(), perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<String, String> meta = n.getMeta();
|
||||
if (meta.getKey().equalsIgnoreCase(node)) {
|
||||
return unescapeCharacters(meta.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private String getGroupChatMeta(boolean prefix, Group group, String world) {
|
||||
world = perms.isIgnoreWorld() ? null : world;
|
||||
if (group == null) return "";
|
||||
|
||||
perms.log("Getting " + (prefix ? "prefix" : "suffix") + " for group " + group + " on world " + world + ", server " + perms.getServer());
|
||||
|
||||
int priority = Integer.MIN_VALUE;
|
||||
String meta = null;
|
||||
|
||||
Map<String, String> context = new HashMap<>();
|
||||
context.put("server", perms.getServer());
|
||||
if (world != null) {
|
||||
context.put("world", world);
|
||||
}
|
||||
|
||||
for (Node n : group.getAllNodes(null, new Contexts(ContextSet.fromMap(context), perms.isIncludeGlobal(), true, true, true, true, false))) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix ? !n.isPrefix() : !n.isSuffix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnServer(perms.getServer(), perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map.Entry<Integer, String> value = prefix ? n.getPrefix() : n.getSuffix();
|
||||
if (value.getKey() > priority) {
|
||||
meta = value.getValue();
|
||||
priority = value.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return meta == null ? "" : unescapeCharacters(meta);
|
||||
}
|
||||
|
||||
public String getPlayerPrefix(String world, @NonNull String player) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
return getUserChatMeta(true, user, world);
|
||||
}
|
||||
|
||||
public void setPlayerPrefix(String world, @NonNull String player, @NonNull String prefix) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setChatMeta(true, user, prefix, world);
|
||||
}
|
||||
|
||||
public String getPlayerSuffix(String world, @NonNull String player) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
return getUserChatMeta(false, user, world);
|
||||
}
|
||||
|
||||
public void setPlayerSuffix(String world, @NonNull String player, @NonNull String suffix) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setChatMeta(false, user, suffix, world);
|
||||
}
|
||||
|
||||
public String getGroupPrefix(String world, @NonNull String group) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
return getGroupChatMeta(false, g, world);
|
||||
}
|
||||
|
||||
public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setChatMeta(true, g, prefix, world);
|
||||
}
|
||||
|
||||
public String getGroupSuffix(String world, @NonNull String group) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
return getGroupChatMeta(false, g, world);
|
||||
}
|
||||
|
||||
public void setGroupSuffix(String world, @NonNull String group, @NonNull String suffix) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setChatMeta(false, g, suffix, world);
|
||||
}
|
||||
|
||||
public int getPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int defaultValue) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
try {
|
||||
return Integer.parseInt(getUserMeta(user, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int value) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public int getGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int defaultValue) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
try {
|
||||
return Integer.parseInt(getGroupMeta(g, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int value) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public double getPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double defaultValue) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
try {
|
||||
return Double.parseDouble(getUserMeta(user, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double value) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public double getGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double defaultValue) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
try {
|
||||
return Double.parseDouble(getGroupMeta(g, world, node, String.valueOf(defaultValue)));
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void setGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double value) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public boolean getPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean defaultValue) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
String s = getUserMeta(user, world, node, String.valueOf(defaultValue));
|
||||
if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Boolean.parseBoolean(s);
|
||||
}
|
||||
|
||||
public void setPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean value) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setMeta(user, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public boolean getGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean defaultValue) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
String s = getGroupMeta(g, world, node, String.valueOf(defaultValue));
|
||||
if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Boolean.parseBoolean(s);
|
||||
}
|
||||
|
||||
public void setGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean value) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setMeta(g, world, node, String.valueOf(value));
|
||||
}
|
||||
|
||||
public String getPlayerInfoString(String world, @NonNull String player, @NonNull String node, String defaultValue) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
return getUserMeta(user, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setPlayerInfoString(String world, @NonNull String player, @NonNull String node, String value) {
|
||||
final User user = perms.getPlugin().getUserManager().get(player);
|
||||
setMeta(user, world, node, value);
|
||||
}
|
||||
|
||||
public String getGroupInfoString(String world, @NonNull String group, @NonNull String node, String defaultValue) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
return getGroupMeta(g, world, node, defaultValue);
|
||||
}
|
||||
|
||||
public void setGroupInfoString(String world, @NonNull String group, @NonNull String node, String value) {
|
||||
final Group g = perms.getPlugin().getGroupManager().get(group);
|
||||
setMeta(g, world, node, value);
|
||||
}
|
||||
|
||||
}
|
||||
+25
-9
@@ -20,40 +20,56 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.vault;
|
||||
package me.lucko.luckperms.bukkit.vault;
|
||||
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.ServicesManager;
|
||||
|
||||
@Getter
|
||||
public class VaultHook {
|
||||
private VaultChatHook chatHook = null;
|
||||
private VaultPermissionHook permissionHook = null;
|
||||
|
||||
private static VaultChatHook chatHook = null;
|
||||
private static VaultPermissionHook permissionHook = null;
|
||||
|
||||
public static void hook(LPBukkitPlugin plugin) {
|
||||
public void hook(LPBukkitPlugin plugin) {
|
||||
try {
|
||||
if (permissionHook == null) {
|
||||
permissionHook = new VaultPermissionHook();
|
||||
}
|
||||
permissionHook.setPlugin(plugin);
|
||||
permissionHook.setServer(plugin.getConfiguration().getVaultServer());
|
||||
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIncludingGlobal());
|
||||
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIgnoreWorld());
|
||||
permissionHook.setup();
|
||||
|
||||
if (chatHook == null) {
|
||||
chatHook = new VaultChatHook(permissionHook);
|
||||
}
|
||||
chatHook.setPlugin(plugin);
|
||||
|
||||
final ServicesManager sm = plugin.getServer().getServicesManager();
|
||||
sm.unregisterAll(plugin);
|
||||
sm.register(Permission.class, permissionHook, plugin, ServicePriority.High);
|
||||
sm.register(Chat.class, chatHook, plugin, ServicePriority.Low);
|
||||
sm.register(Chat.class, chatHook, plugin, ServicePriority.High);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void unhook(LPBukkitPlugin plugin) {
|
||||
final ServicesManager sm = plugin.getServer().getServicesManager();
|
||||
if (permissionHook != null) {
|
||||
sm.unregister(Permission.class, permissionHook);
|
||||
}
|
||||
if (chatHook != null) {
|
||||
sm.unregister(Chat.class, chatHook);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isHooked() {
|
||||
return permissionHook != null && chatHook != null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.vault;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.common.core.PermissionHolder;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The LuckPerms Vault Permission implementation
|
||||
* Most lookups are cached.
|
||||
*/
|
||||
public class VaultPermissionHook extends Permission {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private LPBukkitPlugin plugin;
|
||||
|
||||
@Getter
|
||||
private VaultScheduler scheduler;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String server = "global";
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean includeGlobal = true;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean ignoreWorld = false;
|
||||
|
||||
public void setup() {
|
||||
scheduler = new VaultScheduler(plugin);
|
||||
}
|
||||
|
||||
public void log(String s) {
|
||||
if (plugin.getConfiguration().isDebugPermissionChecks()) {
|
||||
plugin.getLog().info("[VAULT] " + s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "LuckPerms";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return plugin.getDatastore().isAcceptingLogins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSuperPermsCompat() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method to add a permission to a holder
|
||||
* @param world the world to add in
|
||||
* @param holder the holder to add the permission to
|
||||
* @param permission the permission to add
|
||||
*/
|
||||
private void add(String world, PermissionHolder holder, String permission) {
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
holder.setPermission(permission, true, server, world);
|
||||
} else {
|
||||
holder.setPermission(permission, true, server);
|
||||
}
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
|
||||
save(holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method to remove a permission from a holder
|
||||
* @param world the world to remove in
|
||||
* @param holder the holder to remove the permission from
|
||||
* @param permission the permission to remove
|
||||
*/
|
||||
private void remove(String world, PermissionHolder holder, String permission) {
|
||||
try {
|
||||
if (world != null && !world.equals("")) {
|
||||
holder.unsetPermission(permission, server, world);
|
||||
} else {
|
||||
holder.unsetPermission(permission, server);
|
||||
}
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
|
||||
save(holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for saving a user or group
|
||||
* @param holder the holder instance
|
||||
*/
|
||||
void save(PermissionHolder holder) {
|
||||
if (holder instanceof User) {
|
||||
|
||||
plugin.getDatastore().saveUser(((User) holder), b -> {
|
||||
((User) holder).getRefreshBuffer().request();
|
||||
});
|
||||
}
|
||||
if (holder instanceof Group) {
|
||||
plugin.getDatastore().saveGroup(((Group) holder), b -> plugin.getUpdateTaskBuffer().request());
|
||||
}
|
||||
}
|
||||
|
||||
Contexts createContext(String server, String world) {
|
||||
Map<String, String> context = new HashMap<>();
|
||||
if (world != null && !world.equals("")) {
|
||||
context.put("world", world);
|
||||
}
|
||||
context.put("server", server);
|
||||
return new Contexts(ContextSet.fromMap(context), isIncludeGlobal(), true, true, true, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHas(String world, @NonNull String player, @NonNull String permission) {
|
||||
world = ignoreWorld ? null : world; // Correct world value
|
||||
log("Checking if player " + player + " has permission: " + permission + " on world " + world + ", server " + server);
|
||||
|
||||
User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
if (user.getUserData() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Effectively fallback to the standard Bukkit #hasPermission check.
|
||||
return user.getUserData().getPermissionData(createContext(server, world)).getPermissionValue(permission).asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAdd(String world, @NonNull String player, @NonNull String permission) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Adding permission to player " + player + ": '" + permission + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> add(finalWorld, user, permission));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemove(String world, @NonNull String player, @NonNull String permission) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Removing permission from player " + player + ": '" + permission + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> remove(finalWorld, user, permission));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupHas(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
world = ignoreWorld ? null : world; // Correct world value
|
||||
log("Checking if group " + groupName + " has permission: " + permission + " on world " + world + ", server " + server);
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
// This is a nasty call. Groups aren't cached. :(
|
||||
Map<String, Boolean> permissions = group.exportNodes(createContext(server, world), true);
|
||||
|
||||
return permissions.containsKey(permission) && permissions.get(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupAdd(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Adding permission to group " + groupName + ": '" + permission + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> add(finalWorld, group, permission));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean groupRemove(String world, @NonNull String groupName, @NonNull String permission) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Removing permission from group " + groupName + ": '" + permission + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> remove(finalWorld, group, permission));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerInGroup(String world, @NonNull String player, @NonNull String group) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Checking if player " + player + " is in group: " + group + " on world " + finalWorld + ", server " + server);
|
||||
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
return user.getNodes().stream()
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false))
|
||||
.filter(n -> n.shouldApplyOnWorld(finalWorld, true, false))
|
||||
.map(Node::getGroupName)
|
||||
.filter(s -> s.equalsIgnoreCase(group))
|
||||
.findAny().isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerAddGroup(String world, @NonNull String player, @NonNull String groupName) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Adding player " + player + " to group: '" + groupName + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> {
|
||||
try {
|
||||
if (finalWorld != null && !finalWorld.equals("")) {
|
||||
user.setInheritGroup(group, server, finalWorld);
|
||||
} else {
|
||||
user.setInheritGroup(group, server);
|
||||
}
|
||||
} catch (ObjectAlreadyHasException ignored) {}
|
||||
save(user);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerRemoveGroup(String world, @NonNull String player, @NonNull String groupName) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Removing player " + player + " from group: '" + groupName + "' on world " + finalWorld + ", server " + server);
|
||||
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return false;
|
||||
|
||||
final Group group = plugin.getGroupManager().get(groupName);
|
||||
if (group == null) return false;
|
||||
|
||||
scheduler.scheduleTask(() -> {
|
||||
try {
|
||||
if (finalWorld != null && !finalWorld.equals("")) {
|
||||
user.unsetInheritGroup(group, server, finalWorld);
|
||||
} else {
|
||||
user.unsetInheritGroup(group, server);
|
||||
}
|
||||
} catch (ObjectLacksException ignored) {}
|
||||
save(user);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPlayerGroups(String world, @NonNull String player) {
|
||||
String finalWorld = ignoreWorld ? null : world; // Correct world value
|
||||
log("Getting groups of player: " + player + ", on world " + finalWorld + ", server " + server);
|
||||
|
||||
User user = plugin.getUserManager().get(player);
|
||||
if (user == null) return new String[0];
|
||||
|
||||
return user.getNodes().stream()
|
||||
.filter(Node::isGroupNode)
|
||||
.filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false))
|
||||
.filter(n -> n.shouldApplyOnWorld(finalWorld, true, false))
|
||||
.map(Node::getGroupName)
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimaryGroup(String world, @NonNull String player) {
|
||||
log("Getting primary group of player: " + player);
|
||||
final User user = plugin.getUserManager().get(player);
|
||||
return (user == null) ? null : user.getPrimaryGroup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return plugin.getGroupManager().getAll().keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGroupSupport() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.vault;
|
||||
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class VaultScheduler implements Runnable {
|
||||
private final List<Runnable> tasks = new ArrayList<>();
|
||||
|
||||
public VaultScheduler(LPBukkitPlugin plugin) {
|
||||
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, this, 1L, 1L);
|
||||
}
|
||||
|
||||
public void scheduleTask(Runnable r) {
|
||||
synchronized (tasks) {
|
||||
tasks.add(r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
List<Runnable> toRun = new ArrayList<>();
|
||||
synchronized (tasks) {
|
||||
toRun.addAll(tasks);
|
||||
tasks.clear();
|
||||
}
|
||||
|
||||
toRun.forEach(Runnable::run);
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.users;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
|
||||
import me.lucko.luckperms.api.implementation.internal.UserLink;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BukkitUser extends User {
|
||||
private static Field permissionsField = null;
|
||||
public static Field getPermissionsField() {
|
||||
if (permissionsField == null) {
|
||||
try {
|
||||
permissionsField = PermissionAttachment.class.getDeclaredField("permissions");
|
||||
permissionsField.setAccessible(true);
|
||||
} catch (SecurityException | NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return permissionsField;
|
||||
}
|
||||
|
||||
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private PermissionAttachment attachment = null;
|
||||
|
||||
BukkitUser(UUID uuid, LPBukkitPlugin plugin) {
|
||||
super(uuid, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
BukkitUser(UUID uuid, String username, LPBukkitPlugin plugin) {
|
||||
super(uuid, username, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void refreshPermissions() {
|
||||
if (attachment == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the permissions that should be applied. This is done async, who cares about how long it takes or how often it's done.
|
||||
Map<String, Boolean> toApply = getLocalPermissions(getPlugin().getConfiguration().getServer(), plugin.getUserManager().getWorldCache().get(getUuid()), null);
|
||||
|
||||
try {
|
||||
// The map in the LP PermissionAttachment is a ConcurrentHashMap. We can modify it's contents async.
|
||||
Map<String, Boolean> existing = (Map<String, Boolean>) getPermissionsField().get(attachment);
|
||||
|
||||
boolean different = false;
|
||||
if (toApply.size() != existing.size()) {
|
||||
different = true;
|
||||
} else {
|
||||
for (Map.Entry<String, Boolean> e : existing.entrySet()) {
|
||||
if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) {
|
||||
continue;
|
||||
}
|
||||
different = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!different) return;
|
||||
|
||||
existing.clear();
|
||||
existing.putAll(toApply);
|
||||
|
||||
/* Must be called sync, as #recalculatePermissions is an unmodified Bukkit API call that is absolutely not thread safe.
|
||||
Shouldn't be too taxing on the server. This only gets called when permissions have actually changed,
|
||||
which is like once per user per login, assuming their permissions don't get modified. */
|
||||
plugin.doSync(() -> attachment.getPermissible().recalculatePermissions());
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.users;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BukkitUserManager extends UserManager {
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
@Getter
|
||||
private final Map<UUID, String> worldCache = new ConcurrentHashMap<>();
|
||||
|
||||
public BukkitUserManager(LPBukkitPlugin plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(User user) {
|
||||
if (user != null) {
|
||||
|
||||
if (user instanceof BukkitUser) {
|
||||
BukkitUser u = (BukkitUser) user;
|
||||
|
||||
if (u.getAttachment() != null) {
|
||||
Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid()));
|
||||
|
||||
if (player != null) {
|
||||
player.removeAttachment(u.getAttachment());
|
||||
}
|
||||
u.setAttachment(null);
|
||||
}
|
||||
}
|
||||
|
||||
getAll().remove(user.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup(User user) {
|
||||
if (plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) {
|
||||
unload(user);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User make(UUID uuid) {
|
||||
return new BukkitUser(uuid, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User make(UUID uuid, String username) {
|
||||
return new BukkitUser(uuid, username, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAllUsers() {
|
||||
// Sometimes called async, so we need to get the players on the Bukkit thread.
|
||||
plugin.doSync(() -> {
|
||||
Set<UUID> players = plugin.getServer().getOnlinePlayers().stream()
|
||||
.map(p -> plugin.getUuidCache().getUUID(p.getUniqueId()))
|
||||
.collect(Collectors.toSet());
|
||||
plugin.doAsync(() -> players.forEach(u -> plugin.getDatastore().loadUser(u, "null")));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -5,51 +5,229 @@
|
||||
# +------------------------------------------------------------------------+ #
|
||||
##############################################################################
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | General | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# The name of the server, used for server specific permissions. Set to 'global' to disable.
|
||||
server: global
|
||||
|
||||
# If users on this server should have their global permissions/groups applied.
|
||||
# If users on this server should have their global permissions applied.
|
||||
# If set to false, only server specific permissions will apply for users on this server
|
||||
include-global: true
|
||||
|
||||
# If users on this server should have their global world permissions applied.
|
||||
# If set to false, only world specific permissions will apply for users on this server
|
||||
include-global-world: true
|
||||
|
||||
# If users on this server should have global (non-server specific) groups applied
|
||||
apply-global-groups: true
|
||||
|
||||
# If users on this server should have global (non-world specific) groups applied
|
||||
apply-global-world-groups: true
|
||||
|
||||
# If this server is in offline or online mode.
|
||||
# This setting allows a player to have the same UUID across a network of offline mode/mixed servers.
|
||||
|
||||
#
|
||||
# You should generally reflect the setting in server.properties here. Except when...
|
||||
|
||||
#
|
||||
# 1. You have Spigot servers connected to a BungeeCord proxy, with online-mode set to false, but 'bungeecord' set to true in the spigot.yml
|
||||
# AND 'ip-forward' set to true in the BungeeCord config.yml
|
||||
# In this case, set online-mode in LuckPerms to true, despite the server being in offline mode.
|
||||
|
||||
#
|
||||
# 2. You are only running one server instance using LuckPerms, (not a network)
|
||||
# In this case, set online-mode to true no matter what is set in server.properties. (we can just fallback to the servers uuid cache)
|
||||
#
|
||||
# 3. If your proxy is running in offline mode, and you are using PaperSpigot (https://ci.destroystokyo.com/job/PaperSpigot/),
|
||||
# you should set "bungee-online-mode" to false in the paper.yml, and set "online-mode" to true in all LuckPerms configs.
|
||||
# This approach is thoroughly recommended for offline mode networks.
|
||||
online-mode: true
|
||||
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
log-notify: true
|
||||
|
||||
# If LuckPerms should print to console every time a plugin checks if a player has a permission
|
||||
debug-permission-checks: 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. This will only work for plugins that define all of their permissions to the server.
|
||||
# the wildcard.
|
||||
apply-wildcards: true
|
||||
|
||||
# If the plugin should parse regex permissions.
|
||||
# If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the node, and resolve &
|
||||
# apply all registered permissions matching the regex. This will only work for plugins that define all of their
|
||||
# permissions to the server.
|
||||
# apply all registered permissions matching the regex.
|
||||
apply-regex: true
|
||||
|
||||
# If the plugin should complete and apply shorthand permissions.
|
||||
# If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||
apply-shorthand: true
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | OP (Server Operator) Settings | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# If the vanilla OP system is enabled. If set to false, all users will be de-opped, and the op/deop commands will be disabled.
|
||||
enable-ops: true
|
||||
|
||||
# If set to true, any user with the permission "luckperms.autoop" will automatically be granted server operator status.
|
||||
# This permission can be inherited, or set on specific servers/worlds, temporarily, etc.
|
||||
# Additionally, setting this to true will force the "enable-ops" option above to false. All users will be de-opped unless
|
||||
# they have the permission node, and the op/deop commands will be disabled.
|
||||
#
|
||||
# It is important to note that this setting is only checked when a player first joins the server, and when they switch
|
||||
# worlds. Therefore, simply removing this permission from a user will not automatically de-op them. A player needs to
|
||||
# relog to have the change take effect.
|
||||
#
|
||||
# It is recommended that you use this option instead of assigning a single '*' permission.
|
||||
auto-op: false
|
||||
|
||||
# If opped players should be allowed to use LuckPerms commands. Set to false to only allow users who have the permissions access to the commands
|
||||
commands-allow-op: true
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | Vault | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# The name of the server used within Vault operations. If you don't want Vault operations to be server specific, set this
|
||||
# to "global".
|
||||
vault-server: global
|
||||
|
||||
# If global permissions should be considered when retrieving meta or player groups
|
||||
vault-include-global: true
|
||||
|
||||
# If Vault operations should ignore any world arguments if supplied.
|
||||
vault-ignore-world: false
|
||||
|
||||
# Mirrors world names. Whenever LuckPerms checks what world a user is in, if the world name is in this list, the value assigned
|
||||
# will be sent forward for permission calculation instead.
|
||||
world-rewrite:
|
||||
# world_nether: world
|
||||
# world_the_end: world
|
||||
|
||||
# Rewrites group names. The underlying name of the group does not change, just the output in commands / placeholders / Vault.
|
||||
group-name-rewrite:
|
||||
# default: Member
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | Storage | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
||||
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
|
||||
# Fill out connection info below if you're using MySQL or MongoDB
|
||||
storage-method: h2
|
||||
|
||||
# This block enables support for split datastores.
|
||||
split-storage:
|
||||
enabled: false
|
||||
methods:
|
||||
user: h2
|
||||
group: h2
|
||||
track: h2
|
||||
uuid: h2
|
||||
log: h2
|
||||
|
||||
data:
|
||||
address: localhost:3306
|
||||
database: minecraft
|
||||
username: root
|
||||
password: ''
|
||||
pool-size: 10 # The size of the MySQL connection pool.
|
||||
|
||||
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
|
||||
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
|
||||
sync-minutes: 3
|
||||
sync-minutes: 3
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | Default Assignments | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# This section allows you to define defaults to give users whenever they connect to the server.
|
||||
# The default assignments are highly configurable and conditional.
|
||||
#
|
||||
# There is one default assignment built into LuckPerms, which will add all users to the "default" group if they
|
||||
# are not a member of any other group. This setting cannot be disabled. However, you can use this section to add more of
|
||||
# your own.
|
||||
#
|
||||
# IMPORTANT:
|
||||
# In order to save storage space, LuckPerms does not store users who have no permissions defined, and are only a member
|
||||
# of the default group. Adding default assignments to this section will negate this effect. It is HIGHLY RECCOMENDED
|
||||
# that instead of assigning defaults here, you add permissions to the "default" group, or set the "default" group to inherit
|
||||
# other groups, and then use the group-name-rewrite rule above.
|
||||
#
|
||||
# It is also important to note that these rules are considered every time a player logs into the server, and are applied
|
||||
# directly to the user's data. Simply removing a rule here will not reserse the effect of that rule on any users who have
|
||||
# already had it applied to them.
|
||||
#
|
||||
# The "has" and "lacks" conditions below support standard boolean logic, using the 'and' & 'or' characters used in Java.
|
||||
# e.g. "(some.other.permission | some.permission.other) & some.thing.else" == a user has 'some.other.permission', or
|
||||
# 'some.permission.other', and they also have 'some.thing.else'
|
||||
#
|
||||
# Groups are represented by the permission node: group.<group name>
|
||||
# Per server and per world nodes are represented by: "server-world/permission" or "server/permission"
|
||||
#
|
||||
# Within conditions, permission nodes MUST be escaped using "<" and ">". See the example below.
|
||||
#
|
||||
# Explaination of the examples below: (they're just to demonstrate the features & use cases)
|
||||
#
|
||||
# rule1:
|
||||
# If a user is either in the vip or vip+ group, and they have the "titles.titlecollector" permission set to true, and the
|
||||
# "some.random.permission" set to false... if they're not in the group "prison_titlepack" on the "prison" server, then
|
||||
# give add them to the "prison_titlepack" group on the "prison" server, and remove "some.random.permission".
|
||||
#
|
||||
# rule2:
|
||||
# If the user isn't in any of the following groups on the skyblock server: sb_level1, sb_level2, sb_level3, then add
|
||||
# them to sb_level1 on the skyblock server.
|
||||
#
|
||||
# rule3:
|
||||
# If the user is a member of the default group, remove them from default, add them to member, and set their primary group
|
||||
# to member.
|
||||
#
|
||||
# WARNING: Unlike internal commands, this system does not ensure that a group exists before adding a user to it.
|
||||
# It also does not unsure that a user is a member of a group before making that group their primary group.
|
||||
#
|
||||
# Before you use "give: group.<name>" or "set-primary-group", make sure that the group exists, and that the user is
|
||||
# a member of the group.
|
||||
default-assignments:
|
||||
# rule1:
|
||||
# if:
|
||||
# has-true: (<group.vip> | <group.vip+>) & <titles.tilecollector>
|
||||
# has-false: <some.random.permission>
|
||||
# lacks: <prison/group.prison_titlepack>
|
||||
# give:
|
||||
# - prison/group.prison_titlepack
|
||||
# take:
|
||||
# - some.random.permission
|
||||
# rule2:
|
||||
# if:
|
||||
# lacks: <skyblock/group.sb_level1> & <skyblock/group.sb_level2> & <skyblock/group.sb_level3>
|
||||
# give:
|
||||
# - skyblock/group.sb_level1
|
||||
# rule3:
|
||||
# if:
|
||||
# has-true: <group.default>
|
||||
# take:
|
||||
# - group.default
|
||||
# give:
|
||||
# - group.member
|
||||
# set-primary-group: member
|
||||
@@ -1,130 +1,16 @@
|
||||
name: LuckPerms
|
||||
author: Luck
|
||||
version: ${release.version}.${git.closest.tag.commit.count}
|
||||
main: me.lucko.luckperms.LPBukkitPlugin
|
||||
softdepend: [Vault, PermissionsEx, GroupManager, PowerfulPerms, zPermissions] # For migration
|
||||
description: A permissions plugin
|
||||
author: Luck
|
||||
website: https://github.com/lucko/LuckPerms
|
||||
|
||||
main: me.lucko.luckperms.bukkit.LPBukkitPlugin
|
||||
softdepend: [Vault, PermissionsEx, GroupManager, PowerfulPerms, zPermissions, bPermissions] # For migration
|
||||
|
||||
commands:
|
||||
luckperms:
|
||||
description: Manage permissions
|
||||
aliases: [perms, permissions, lp, p, perm]
|
||||
permissions:
|
||||
luckperms.*:
|
||||
description: Gives access to all LuckPerms commands
|
||||
children:
|
||||
luckperms.sync: true
|
||||
luckperms.info: true
|
||||
luckperms.debug: true
|
||||
luckperms.import: true
|
||||
luckperms.creategroup: true
|
||||
luckperms.deletegroup: true
|
||||
luckperms.listgroups: true
|
||||
luckperms.createtrack: true
|
||||
luckperms.deletetrack: true
|
||||
luckperms.listtracks: true
|
||||
luckperms.user.info: true
|
||||
luckperms.user.getuuid: true
|
||||
luckperms.user.listnodes: true
|
||||
luckperms.user.haspermission: true
|
||||
luckperms.user.inheritspermission: true
|
||||
luckperms.user.setpermission: true
|
||||
luckperms.user.unsetpermission: true
|
||||
luckperms.user.addgroup: true
|
||||
luckperms.user.removegroup: true
|
||||
luckperms.user.settemppermission: true
|
||||
luckperms.user.unsettemppermission: true
|
||||
luckperms.user.addtempgroup: true
|
||||
luckperms.user.removetempgroup: true
|
||||
luckperms.user.setprimarygroup: true
|
||||
luckperms.user.showtracks: true
|
||||
luckperms.user.promote: true
|
||||
luckperms.user.demote: true
|
||||
luckperms.user.showpos: true
|
||||
luckperms.user.clear: true
|
||||
luckperms.group.info: true
|
||||
luckperms.group.listnodes: true
|
||||
luckperms.group.haspermission: true
|
||||
luckperms.group.inheritspermission: true
|
||||
luckperms.group.setpermission: true
|
||||
luckperms.group.unsetpermission: true
|
||||
luckperms.group.setinherit: true
|
||||
luckperms.group.unsetinherit: true
|
||||
luckperms.group.settemppermission: true
|
||||
luckperms.group.unsettemppermission: true
|
||||
luckperms.group.settempinherit: true
|
||||
luckperms.group.unsettempinherit: true
|
||||
luckperms.group.showtracks: true
|
||||
luckperms.group.clear: true
|
||||
luckperms.group.rename: true
|
||||
luckperms.track.info: true
|
||||
luckperms.track.append: true
|
||||
luckperms.track.insert: true
|
||||
luckperms.track.remove: true
|
||||
luckperms.track.clear: true
|
||||
luckperms.track.rename: true
|
||||
luckperms.log.export: true
|
||||
luckperms.log.userhistory: true
|
||||
luckperms.log.grouphistory: true
|
||||
luckperms.log.trackhistory: true
|
||||
luckperms.log.notify: true
|
||||
luckperms.log.recent: true
|
||||
luckperms.log.search: true
|
||||
luckperms.user.*:
|
||||
description: Gives access to all LuckPerms user commands
|
||||
children:
|
||||
luckperms.user.info: true
|
||||
luckperms.user.getuuid: true
|
||||
luckperms.user.listnodes: true
|
||||
luckperms.user.haspermission: true
|
||||
luckperms.user.inheritspermission: true
|
||||
luckperms.user.setpermission: true
|
||||
luckperms.user.unsetpermission: true
|
||||
luckperms.user.addgroup: true
|
||||
luckperms.user.removegroup: true
|
||||
luckperms.user.settemppermission: true
|
||||
luckperms.user.unsettemppermission: true
|
||||
luckperms.user.addtempgroup: true
|
||||
luckperms.user.removetempgroup: true
|
||||
luckperms.user.setprimarygroup: true
|
||||
luckperms.user.showtracks: true
|
||||
luckperms.user.promote: true
|
||||
luckperms.user.demote: true
|
||||
luckperms.user.showpos: true
|
||||
luckperms.user.clear: true
|
||||
luckperms.group.*:
|
||||
description: Gives access to all LuckPerms group commands
|
||||
children:
|
||||
luckperms.group.info: true
|
||||
luckperms.group.listnodes: true
|
||||
luckperms.group.haspermission: true
|
||||
luckperms.group.inheritspermission: true
|
||||
luckperms.group.setpermission: true
|
||||
luckperms.group.unsetpermission: true
|
||||
luckperms.group.setinherit: true
|
||||
luckperms.group.unsetinherit: true
|
||||
luckperms.group.settemppermission: true
|
||||
luckperms.group.unsettemppermission: true
|
||||
luckperms.group.settempinherit: true
|
||||
luckperms.group.unsettempinherit: true
|
||||
luckperms.group.showtracks: true
|
||||
luckperms.group.clear: true
|
||||
luckperms.group.rename: true
|
||||
luckperms.track.*:
|
||||
description: Gives access to all LuckPerms track commands
|
||||
children:
|
||||
luckperms.track.info: true
|
||||
luckperms.track.append: true
|
||||
luckperms.track.insert: true
|
||||
luckperms.track.remove: true
|
||||
luckperms.track.clear: true
|
||||
luckperms.track.rename: true
|
||||
luckperms.log.*:
|
||||
description: Gives access to all LuckPerms log commands
|
||||
children:
|
||||
luckperms.log.export: true
|
||||
luckperms.log.userhistory: true
|
||||
luckperms.log.grouphistory: true
|
||||
luckperms.log.trackhistory: true
|
||||
luckperms.log.notify: true
|
||||
luckperms.log.recent: true
|
||||
luckperms.log.search: true
|
||||
|
||||
|
||||
# Permissions are registered programmatically instead of here.
|
||||
+5
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>2.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -65,6 +65,10 @@
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.sqlite</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.sqlite</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.commands.ConsecutiveExecutor;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import me.lucko.luckperms.core.UuidCache;
|
||||
import me.lucko.luckperms.data.Importer;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.runnables.ExpireTemporaryTask;
|
||||
import me.lucko.luckperms.runnables.UpdateTask;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.storage.StorageFactory;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.BungeeUserManager;
|
||||
import me.lucko.luckperms.users.UserManager;
|
||||
import me.lucko.luckperms.utils.LogFactory;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
|
||||
private LPConfiguration configuration;
|
||||
private UserManager userManager;
|
||||
private GroupManager groupManager;
|
||||
private TrackManager trackManager;
|
||||
private Datastore datastore;
|
||||
private UuidCache uuidCache;
|
||||
private ApiProvider apiProvider;
|
||||
private Logger log;
|
||||
private Importer importer;
|
||||
private ConsecutiveExecutor consecutiveExecutor;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
log = LogFactory.wrap(getLogger());
|
||||
|
||||
getLog().info("Loading configuration...");
|
||||
configuration = new BungeeConfig(this);
|
||||
|
||||
// register events
|
||||
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
|
||||
|
||||
// register commands
|
||||
getLog().info("Registering commands...");
|
||||
CommandManager commandManager = new CommandManager(this);
|
||||
getProxy().getPluginManager().registerCommand(this, new BungeeCommand(commandManager));
|
||||
|
||||
// disable the default Bungee /perms command so it gets handled by the Bukkit plugin
|
||||
getProxy().getDisabledCommands().add("perms");
|
||||
|
||||
datastore = StorageFactory.getDatastore(this, "h2");
|
||||
|
||||
getLog().info("Loading internal permission managers...");
|
||||
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
|
||||
userManager = new BungeeUserManager(this);
|
||||
groupManager = new GroupManager(this);
|
||||
trackManager = new TrackManager();
|
||||
importer = new Importer(commandManager);
|
||||
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
|
||||
|
||||
int mins = getConfiguration().getSyncTime();
|
||||
if (mins > 0) {
|
||||
getProxy().getScheduler().schedule(this, new UpdateTask(this), mins, mins, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
// 20 times per second (once per "tick")
|
||||
getProxy().getScheduler().schedule(this, BungeeSenderFactory.get(), 50L, 50L, TimeUnit.MILLISECONDS);
|
||||
getProxy().getScheduler().schedule(this, new ExpireTemporaryTask(this), 3L, 3L, TimeUnit.SECONDS);
|
||||
getProxy().getScheduler().schedule(this, consecutiveExecutor, 1L, 1L, TimeUnit.SECONDS);
|
||||
|
||||
getLog().info("Registering API...");
|
||||
apiProvider = new ApiProvider(this);
|
||||
LuckPerms.registerProvider(apiProvider);
|
||||
|
||||
// Run update task to refresh any online users
|
||||
getLog().info("Scheduling Update Task to refresh any online users.");
|
||||
try {
|
||||
new UpdateTask(this).run();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
getLog().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLog().info("Closing datastore...");
|
||||
datastore.shutdown();
|
||||
|
||||
getLog().info("Unregistering API...");
|
||||
LuckPerms.unregisterProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.BUNGEE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getMainDir() {
|
||||
return getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getPlayerStatus(UUID uuid) {
|
||||
return getProxy().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getProxy().getOnlineCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPlayerList() {
|
||||
return getProxy().getPlayers().stream().map(ProxiedPlayer::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getSenders() {
|
||||
return getProxy().getPlayers().stream().map(p -> BungeeSenderFactory.get().wrap(p)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return BungeeSenderFactory.get().wrap(getProxy().getConsole());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPossiblePermissions() {
|
||||
// No such thing on Bungee. Wildcards are processed in the listener instead.
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPlugin(String name) {
|
||||
return getProxy().getPluginManager().getPlugin(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getService(Class clazz) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginLoaded(String name) {
|
||||
return getProxy().getPluginManager().getPlugins().stream()
|
||||
.filter(p -> p.getDescription().getName().equalsIgnoreCase(name))
|
||||
.findAny()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runUpdateTask() {
|
||||
doAsync(new UpdateTask(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
getProxy().getScheduler().runAsync(this, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import me.lucko.luckperms.api.context.ContextCalculator;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ServerSwitchEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BackendServerCalculator extends ContextCalculator<ProxiedPlayer> implements Listener {
|
||||
private static final String WORLD_KEY = "world";
|
||||
|
||||
@Override
|
||||
public MutableContextSet giveApplicableContext(ProxiedPlayer subject, MutableContextSet accumulator) {
|
||||
String server = getServer(subject);
|
||||
|
||||
if (server != null) {
|
||||
accumulator.add(Maps.immutableEntry(WORLD_KEY, server));
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isContextApplicable(ProxiedPlayer subject, Map.Entry<String, String> context) {
|
||||
if (!context.getKey().equals(WORLD_KEY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String server = getServer(subject);
|
||||
return server != null && server.equals(context.getValue());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerServerSwitch(ServerSwitchEvent e) {
|
||||
pushUpdate(e.getPlayer(), Maps.immutableEntry("null", "null"), Maps.immutableEntry(WORLD_KEY, getServer(e.getPlayer())));
|
||||
}
|
||||
|
||||
private static String getServer(ProxiedPlayer player) {
|
||||
return player.getServer() == null ? null : (player.getServer().getInfo() == null ? null : player.getServer().getInfo().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.common.calculators.*;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class BungeeCalculatorFactory implements CalculatorFactory {
|
||||
private final LPBungeePlugin plugin;
|
||||
|
||||
@Override
|
||||
public PermissionCalculator build(Contexts contexts, User user, Map<String, Boolean> map) {
|
||||
List<PermissionProcessor> processors = new ArrayList<>(3);
|
||||
processors.add(new MapProcessor(map));
|
||||
if (plugin.getConfiguration().isApplyingWildcards()) {
|
||||
processors.add(new WildcardProcessor(map));
|
||||
}
|
||||
if (plugin.getConfiguration().isApplyingRegex()) {
|
||||
processors.add(new RegexProcessor(map));
|
||||
}
|
||||
|
||||
return new PermissionCalculator(plugin, user.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors);
|
||||
}
|
||||
}
|
||||
+13
-4
@@ -20,10 +20,14 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.Util;
|
||||
import me.lucko.luckperms.common.constants.Patterns;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
@@ -40,11 +44,16 @@ class BungeeCommand extends Command implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
manager.onCommand(BungeeSenderFactory.get().wrap(sender), "bperms", Arrays.asList(args), Callback.empty());
|
||||
manager.onCommand(
|
||||
BungeeSenderFactory.get(manager.getPlugin()).wrap(sender),
|
||||
"bperms",
|
||||
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
|
||||
Callback.empty()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return manager.onTabComplete(BungeeSenderFactory.get().wrap(sender), Arrays.asList(args));
|
||||
return manager.onTabComplete(BungeeSenderFactory.get(manager.getPlugin()).wrap(sender), Arrays.asList(args));
|
||||
}
|
||||
}
|
||||
+38
-8
@@ -20,9 +20,9 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import me.lucko.luckperms.common.config.AbstractConfiguration;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
import net.md_5.bungee.config.ConfigurationProvider;
|
||||
import net.md_5.bungee.config.YamlConfiguration;
|
||||
@@ -31,8 +31,13 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class BungeeConfig extends LPConfiguration<LPBungeePlugin> {
|
||||
class BungeeConfig extends AbstractConfiguration<LPBungeePlugin> {
|
||||
private Configuration configuration;
|
||||
|
||||
BungeeConfig(LPBungeePlugin plugin) {
|
||||
@@ -62,11 +67,6 @@ class BungeeConfig extends LPConfiguration<LPBungeePlugin> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void set(String path, Object value) {
|
||||
configuration.set(path, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getString(String path, String def) {
|
||||
return configuration.getString(path, def);
|
||||
@@ -81,4 +81,34 @@ class BungeeConfig extends LPConfiguration<LPBungeePlugin> {
|
||||
protected boolean getBoolean(String path, boolean def) {
|
||||
return configuration.getBoolean(path, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getList(String path, List<String> def) {
|
||||
return Optional.ofNullable(configuration.getStringList(path)).orElse(def);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getObjectList(String path, List<String> def) {
|
||||
Configuration section = configuration.getSection(path);
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return Optional.ofNullable(section.getKeys().stream().collect(Collectors.toList())).orElse(def);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getMap(String path, Map<String, String> def) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
Configuration section = configuration.getSection(path);
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
for (String key : section.getKeys()) {
|
||||
map.put(key, section.getString(key));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
+52
-38
@@ -20,22 +20,25 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.core.UuidCache;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.AbstractListener;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.api.event.events.UserFirstLoginEvent;
|
||||
import me.lucko.luckperms.common.constants.Message;
|
||||
import me.lucko.luckperms.common.core.UuidCache;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.utils.AbstractListener;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.*;
|
||||
import net.md_5.bungee.api.event.LoginEvent;
|
||||
import net.md_5.bungee.api.event.PermissionCheckEvent;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -52,22 +55,33 @@ public class BungeeListener extends AbstractListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerPermissionCheck(PermissionCheckEvent e) {
|
||||
if (!(e.getSender() instanceof ProxiedPlayer)) {
|
||||
e.setHasPermission(true);
|
||||
return;
|
||||
}
|
||||
|
||||
final ProxiedPlayer player = ((ProxiedPlayer) e.getSender());
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (user == null) return;
|
||||
|
||||
|
||||
final String server = player.getServer() == null ? null : (player.getServer().getInfo() == null ? null : player.getServer().getInfo().getName());
|
||||
Map<String, Boolean> local = user.getLocalPermissions(plugin.getConfiguration().getServer(), server, null, Collections.singletonList(e.getPermission()));
|
||||
for (Map.Entry<String, Boolean> en : local.entrySet()) {
|
||||
if (en.getKey().equalsIgnoreCase(e.getPermission())) {
|
||||
e.setHasPermission(en.getValue());
|
||||
return;
|
||||
}
|
||||
User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (user.getUserData() == null) {
|
||||
plugin.getLog().warn("Player " + player.getName() + " does not have any user data setup.");
|
||||
return;
|
||||
}
|
||||
|
||||
Contexts contexts = new Contexts(
|
||||
plugin.getContextManager().giveApplicableContext(player, MutableContextSet.empty()),
|
||||
plugin.getConfiguration().isIncludingGlobalPerms(),
|
||||
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
|
||||
true,
|
||||
plugin.getConfiguration().isApplyingGlobalGroups(),
|
||||
plugin.getConfiguration().isApplyingGlobalWorldGroups(),
|
||||
false
|
||||
);
|
||||
|
||||
e.setHasPermission(user.getUserData().getPermissionData(contexts).getPermissionValue(e.getPermission()).asBoolean());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -82,22 +96,35 @@ public class BungeeListener extends AbstractListener implements Listener {
|
||||
final PendingConnection c = e.getConnection();
|
||||
|
||||
if (!cache.isOnlineMode()) {
|
||||
UUID uuid = plugin.getDatastore().getUUID(c.getName());
|
||||
UUID uuid = plugin.getDatastore().getUUID(c.getName()).getUnchecked();
|
||||
if (uuid != null) {
|
||||
cache.addToCache(c.getUniqueId(), uuid);
|
||||
} else {
|
||||
// No previous data for this player
|
||||
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName()));
|
||||
cache.addToCache(c.getUniqueId(), c.getUniqueId());
|
||||
plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId());
|
||||
plugin.getDatastore().force().saveUUIDData(c.getName(), c.getUniqueId()).getUnchecked();
|
||||
}
|
||||
} else {
|
||||
UUID uuid = plugin.getDatastore().getUUID(c.getName()).getUnchecked();
|
||||
if (uuid == null) {
|
||||
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName()));
|
||||
}
|
||||
|
||||
// Online mode, no cache needed. This is just for name -> uuid lookup.
|
||||
plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId());
|
||||
plugin.getDatastore().force().saveUUIDData(c.getName(), c.getUniqueId()).getUnchecked();
|
||||
}
|
||||
|
||||
// We have to make a new user on this thread whilst the connection is being held, or we get concurrency issues as the Bukkit server
|
||||
// and the BungeeCord server try to make a new user at the same time.
|
||||
plugin.getDatastore().loadUser(cache.getUUID(c.getUniqueId()), c.getName());
|
||||
plugin.getDatastore().force().loadUser(cache.getUUID(c.getUniqueId()), c.getName()).getUnchecked();
|
||||
User user = plugin.getUserManager().get(cache.getUUID(c.getUniqueId()));
|
||||
if (user == null) {
|
||||
plugin.getLog().warn("Failed to load user: " + c.getName());
|
||||
} else {
|
||||
user.setupData(false); // Pretty nasty calculation call. Sets up the caching system so data is ready when the user joins.
|
||||
}
|
||||
|
||||
final long time = System.currentTimeMillis() - startTime;
|
||||
if (time >= 1000) {
|
||||
plugin.getLog().warn("Processing login for " + c.getName() + " took " + time + "ms.");
|
||||
@@ -109,18 +136,10 @@ public class BungeeListener extends AbstractListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerPostLogin(PostLoginEvent e) {
|
||||
final ProxiedPlayer player = e.getPlayer();
|
||||
final WeakReference<ProxiedPlayer> p = new WeakReference<>(player);
|
||||
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
|
||||
|
||||
if (user == null) {
|
||||
plugin.getProxy().getScheduler().schedule(plugin, () -> {
|
||||
final ProxiedPlayer pl = p.get();
|
||||
if (pl != null) {
|
||||
pl.sendMessage(WARN_MESSAGE);
|
||||
}
|
||||
}, 3, TimeUnit.SECONDS);
|
||||
} else {
|
||||
user.refreshPermissions();
|
||||
plugin.getProxy().getScheduler().schedule(plugin, () -> player.sendMessage(WARN_MESSAGE), 3, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,9 +147,4 @@ public class BungeeListener extends AbstractListener implements Listener {
|
||||
public void onPlayerQuit(PlayerDisconnectEvent e) {
|
||||
onLeave(e.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerServerSwitch(ServerSwitchEvent e) {
|
||||
refreshPlayer(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
+12
-9
@@ -20,24 +20,27 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import me.lucko.luckperms.commands.SenderFactory;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.commands.SenderFactory;
|
||||
import me.lucko.luckperms.common.constants.Constants;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class BungeeSenderFactory extends SenderFactory<CommandSender> {
|
||||
private static BungeeSenderFactory instance = null;
|
||||
public static BungeeSenderFactory get() {
|
||||
if (instance == null){
|
||||
instance = new BungeeSenderFactory();
|
||||
|
||||
private BungeeSenderFactory(LuckPermsPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
public static synchronized BungeeSenderFactory get(LuckPermsPlugin plugin) {
|
||||
if (instance == null) {
|
||||
instance = new BungeeSenderFactory(plugin);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bungee;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.ApiHandler;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.PlatformType;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.api.ApiProvider;
|
||||
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||
import me.lucko.luckperms.common.commands.CommandManager;
|
||||
import me.lucko.luckperms.common.commands.ConsecutiveExecutor;
|
||||
import me.lucko.luckperms.common.commands.Sender;
|
||||
import me.lucko.luckperms.common.config.LPConfiguration;
|
||||
import me.lucko.luckperms.common.constants.Permission;
|
||||
import me.lucko.luckperms.common.contexts.ContextManager;
|
||||
import me.lucko.luckperms.common.contexts.ServerCalculator;
|
||||
import me.lucko.luckperms.common.core.UuidCache;
|
||||
import me.lucko.luckperms.common.data.Importer;
|
||||
import me.lucko.luckperms.common.groups.GroupManager;
|
||||
import me.lucko.luckperms.common.runnables.ExpireTemporaryTask;
|
||||
import me.lucko.luckperms.common.runnables.UpdateTask;
|
||||
import me.lucko.luckperms.common.storage.Datastore;
|
||||
import me.lucko.luckperms.common.storage.StorageFactory;
|
||||
import me.lucko.luckperms.common.tracks.TrackManager;
|
||||
import me.lucko.luckperms.common.users.UserManager;
|
||||
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||
import me.lucko.luckperms.common.utils.LocaleManager;
|
||||
import me.lucko.luckperms.common.utils.LogFactory;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
|
||||
private LPConfiguration configuration;
|
||||
private UserManager userManager;
|
||||
private GroupManager groupManager;
|
||||
private TrackManager trackManager;
|
||||
private Datastore datastore;
|
||||
private UuidCache uuidCache;
|
||||
private ApiProvider apiProvider;
|
||||
private Logger log;
|
||||
private Importer importer;
|
||||
private ConsecutiveExecutor consecutiveExecutor;
|
||||
private LocaleManager localeManager;
|
||||
private ContextManager<ProxiedPlayer> contextManager;
|
||||
private CalculatorFactory calculatorFactory;
|
||||
private BufferedRequest<Void> updateTaskBuffer;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
log = LogFactory.wrap(getLogger());
|
||||
|
||||
getLog().info("Loading configuration...");
|
||||
configuration = new BungeeConfig(this);
|
||||
|
||||
localeManager = new LocaleManager();
|
||||
File locale = new File(getDataFolder(), "lang.yml");
|
||||
if (locale.exists()) {
|
||||
getLog().info("Found locale file. Attempting to load from it.");
|
||||
try {
|
||||
localeManager.loadFromFile(locale);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// register events
|
||||
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
|
||||
|
||||
// register commands
|
||||
getLog().info("Registering commands...");
|
||||
CommandManager commandManager = new CommandManager(this);
|
||||
getProxy().getPluginManager().registerCommand(this, new BungeeCommand(commandManager));
|
||||
|
||||
// disable the default Bungee /perms command so it gets handled by the Bukkit plugin
|
||||
getProxy().getDisabledCommands().add("perms");
|
||||
|
||||
datastore = StorageFactory.getDatastore(this, "h2");
|
||||
|
||||
getLog().info("Loading internal permission managers...");
|
||||
uuidCache = new UuidCache(getConfiguration().isOnlineMode());
|
||||
userManager = new UserManager(this);
|
||||
groupManager = new GroupManager(this);
|
||||
trackManager = new TrackManager();
|
||||
importer = new Importer(commandManager);
|
||||
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
|
||||
calculatorFactory = new BungeeCalculatorFactory(this);
|
||||
|
||||
contextManager = new ContextManager<>();
|
||||
BackendServerCalculator serverCalculator = new BackendServerCalculator();
|
||||
getProxy().getPluginManager().registerListener(this, serverCalculator);
|
||||
contextManager.registerCalculator(serverCalculator);
|
||||
contextManager.registerCalculator(new ServerCalculator<>(getConfiguration().getServer()));
|
||||
|
||||
final LPBungeePlugin i = this;
|
||||
updateTaskBuffer = new BufferedRequest<Void>(6000L, this::doAsync) {
|
||||
@Override
|
||||
protected Void perform() {
|
||||
doAsync(new UpdateTask(i));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
int mins = getConfiguration().getSyncTime();
|
||||
if (mins > 0) {
|
||||
getProxy().getScheduler().schedule(this, new UpdateTask(this), mins, mins, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
// 20 times per second (once per "tick")
|
||||
getProxy().getScheduler().schedule(this, BungeeSenderFactory.get(this), 50L, 50L, TimeUnit.MILLISECONDS);
|
||||
getProxy().getScheduler().schedule(this, new ExpireTemporaryTask(this), 3L, 3L, TimeUnit.SECONDS);
|
||||
getProxy().getScheduler().schedule(this, consecutiveExecutor, 1L, 1L, TimeUnit.SECONDS);
|
||||
|
||||
getLog().info("Registering API...");
|
||||
apiProvider = new ApiProvider(this);
|
||||
ApiHandler.registerProvider(apiProvider);
|
||||
|
||||
// Run update task to refresh any online users
|
||||
getLog().info("Scheduling Update Task to refresh any online users.");
|
||||
updateTaskBuffer.request();
|
||||
|
||||
getLog().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLog().info("Closing datastore...");
|
||||
datastore.shutdown();
|
||||
|
||||
getLog().info("Unregistering API...");
|
||||
ApiHandler.unregisterProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformType getType() {
|
||||
return PlatformType.BUNGEE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getMainDir() {
|
||||
return getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return getProxy().getOnlineCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPlayerList() {
|
||||
return getProxy().getPlayers().stream().map(ProxiedPlayer::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getOnlinePlayers() {
|
||||
return getProxy().getPlayers().stream().map(ProxiedPlayer::getUniqueId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline(UUID external) {
|
||||
return getProxy().getPlayer(external) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getNotifyListeners() {
|
||||
return getProxy().getPlayers().stream()
|
||||
.map(p -> BungeeSenderFactory.get(this).wrap(p, Collections.singleton(Permission.LOG_NOTIFY)))
|
||||
.filter(Permission.LOG_NOTIFY::isAuthorized)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return BungeeSenderFactory.get(this).wrap(getProxy().getConsole());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Contexts> getPreProcessContexts(boolean op) {
|
||||
Set<ContextSet> c = new HashSet<>();
|
||||
c.add(ContextSet.empty());
|
||||
c.add(ContextSet.singleton("server", getConfiguration().getServer()));
|
||||
c.addAll(getProxy().getServers().values().stream()
|
||||
.map(ServerInfo::getName)
|
||||
.map(s -> {
|
||||
MutableContextSet set = new MutableContextSet();
|
||||
set.add("server", getConfiguration().getServer());
|
||||
set.add("world", s);
|
||||
return set.makeImmutable();
|
||||
})
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
|
||||
return c.stream()
|
||||
.map(set -> new Contexts(
|
||||
set,
|
||||
getConfiguration().isIncludingGlobalPerms(),
|
||||
getConfiguration().isIncludingGlobalWorldPerms(),
|
||||
true,
|
||||
getConfiguration().isApplyingGlobalGroups(),
|
||||
getConfiguration().isApplyingGlobalWorldGroups(),
|
||||
false
|
||||
))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPlugin(String name) {
|
||||
return getProxy().getPluginManager().getPlugin(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getService(Class clazz) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String playerName) {
|
||||
return null; // Not needed on Bungee
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginLoaded(String name) {
|
||||
return getProxy().getPluginManager().getPlugins().stream()
|
||||
.filter(p -> p.getDescription().getName().equalsIgnoreCase(name))
|
||||
.findAny()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
getProxy().getScheduler().runAsync(this, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
r.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsyncRepeating(Runnable r, long interval) {
|
||||
long millis = interval * 50L; // convert from ticks to milliseconds
|
||||
getProxy().getScheduler().schedule(this, r, millis, millis, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.users;
|
||||
|
||||
import me.lucko.luckperms.LPBungeePlugin;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BungeeUserManager extends UserManager {
|
||||
private final LPBungeePlugin plugin;
|
||||
|
||||
public BungeeUserManager(LPBungeePlugin plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(User user) {
|
||||
if (user != null) {
|
||||
// Cannot clear the ProxiedPlayer's permission map, they're leaving so that will get GCed anyway
|
||||
// Calling getPermissions.clear() throws an UnsupportedOperationException
|
||||
getAll().remove(user.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup(User user) {
|
||||
if (plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) {
|
||||
unload(user);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User make(UUID uuid) {
|
||||
return new BungeeUser(uuid, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User make(UUID uuid, String username) {
|
||||
return new BungeeUser(uuid, username, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAllUsers() {
|
||||
plugin.getProxy().getPlayers().stream()
|
||||
.map(p -> plugin.getUuidCache().getUUID(p.getUniqueId()))
|
||||
.forEach(u -> plugin.getDatastore().loadUser(u, "null"));
|
||||
}
|
||||
}
|
||||
@@ -5,51 +5,187 @@
|
||||
# +------------------------------------------------------------------------+ #
|
||||
##############################################################################
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | General | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# The name of the server, used for server specific permissions. Set to 'global' to disable.
|
||||
server: bungee
|
||||
|
||||
# If users on this server should have their global permissions/groups applied.
|
||||
# If users on this server should have their global permissions applied.
|
||||
# If set to false, only server specific permissions will apply for users on this server
|
||||
include-global: false
|
||||
|
||||
# If users on this server should have their global world permissions applied.
|
||||
# If set to false, only world specific permissions will apply for users on this server
|
||||
include-global-world: true
|
||||
|
||||
# If users on this server should have global (non-server specific) groups applied
|
||||
apply-global-groups: true
|
||||
|
||||
# If users on this server should have global (non-world specific) groups applied
|
||||
apply-global-world-groups: true
|
||||
|
||||
# If this server is in offline or online mode.
|
||||
# This setting allows a player to have the same UUID across a network of offline mode/mixed servers.
|
||||
|
||||
#
|
||||
# You should generally reflect the setting in server.properties here. Except when...
|
||||
|
||||
#
|
||||
# 1. You have Spigot servers connected to a BungeeCord proxy, with online-mode set to false, but 'bungeecord' set to true in the spigot.yml
|
||||
# AND 'ip-forward' set to true in the BungeeCord config.yml
|
||||
# In this case, set online-mode in LuckPerms to true, despite the server being in offline mode.
|
||||
|
||||
#
|
||||
# 2. You are only running one server instance using LuckPerms, (not a network)
|
||||
# In this case, set online-mode to true no matter what is set in server.properties. (we can just fallback to the servers uuid cache)
|
||||
#
|
||||
# 3. If your proxy is running in offline mode, and you are using PaperSpigot (https://ci.destroystokyo.com/job/PaperSpigot/),
|
||||
# you should set "bungee-online-mode" to false in the paper.yml, and set "online-mode" to true in all LuckPerms configs.
|
||||
# This approach is thoroughly recommended for offline mode networks.
|
||||
online-mode: true
|
||||
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
log-notify: true
|
||||
|
||||
# If LuckPerms should print to console every time a plugin checks if a player has a permission
|
||||
debug-permission-checks: false
|
||||
|
||||
# Mirrors world names. Whenever LuckPerms checks what world a user is in, if the world name is in this list, the value assigned
|
||||
# will be sent forward for permission calculation instead.
|
||||
world-rewrite:
|
||||
# world_nether: world
|
||||
# world_the_end: world
|
||||
|
||||
# Rewrites group names. The underlying name of the group does not change, just the output in commands / placeholders / Vault.
|
||||
group-name-rewrite:
|
||||
# default: Member
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | Permission Calculation | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
# If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered permissions matching
|
||||
# the wildcard. This will only work for plugins that define all of their permissions to the server.
|
||||
# the wildcard.
|
||||
apply-wildcards: true
|
||||
|
||||
# If the plugin should parse regex permissions.
|
||||
# If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the node, and resolve &
|
||||
# apply all registered permissions matching the regex. This will only work for plugins that define all of their
|
||||
# permissions to the server.
|
||||
# apply all registered permissions matching the regex.
|
||||
apply-regex: true
|
||||
|
||||
# If the plugin should complete and apply shorthand permissions.
|
||||
# If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||
apply-shorthand: true
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | Storage | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
||||
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
|
||||
# Fill out connection info below if you're using MySQL or MongoDB
|
||||
storage-method: h2
|
||||
|
||||
# This block enables support for split datastores.
|
||||
split-storage:
|
||||
enabled: false
|
||||
methods:
|
||||
user: h2
|
||||
group: h2
|
||||
track: h2
|
||||
uuid: h2
|
||||
log: h2
|
||||
|
||||
data:
|
||||
address: localhost:3306
|
||||
database: minecraft
|
||||
username: root
|
||||
password: ''
|
||||
pool-size: 10 # The size of the MySQL connection pool.
|
||||
|
||||
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
|
||||
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
|
||||
sync-minutes: 3
|
||||
sync-minutes: 3
|
||||
|
||||
|
||||
|
||||
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | Default Assignments | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
|
||||
# This section allows you to define defaults to give users whenever they connect to the server.
|
||||
# The default assignments are highly configurable and conditional.
|
||||
#
|
||||
# There is one default assignment built into LuckPerms, which will add all users to the "default" group if they
|
||||
# are not a member of any other group. This setting cannot be disabled. However, you can use this section to add more of
|
||||
# your own.
|
||||
#
|
||||
# IMPORTANT:
|
||||
# In order to save storage space, LuckPerms does not store users who have no permissions defined, and are only a member
|
||||
# of the default group. Adding default assignments to this section will negate this effect. It is HIGHLY RECCOMENDED
|
||||
# that instead of assigning defaults here, you add permissions to the "default" group, or set the "default" group to inherit
|
||||
# other groups, and then use the group-name-rewrite rule above.
|
||||
#
|
||||
# It is also important to note that these rules are considered every time a player logs into the server, and are applied
|
||||
# directly to the user's data. Simply removing a rule here will not reserse the effect of that rule on any users who have
|
||||
# already had it applied to them.
|
||||
#
|
||||
# The "has" and "lacks" conditions below support standard boolean logic, using the 'and' & 'or' characters used in Java.
|
||||
# e.g. "(some.other.permission | some.permission.other) & some.thing.else" == a user has 'some.other.permission', or
|
||||
# 'some.permission.other', and they also have 'some.thing.else'
|
||||
#
|
||||
# Groups are represented by the permission node: group.<group name>
|
||||
# Per server and per world nodes are represented by: "server-world/permission" or "server/permission"
|
||||
#
|
||||
# Within conditions, permission nodes MUST be escaped using "<" and ">". See the example below.
|
||||
#
|
||||
# Explaination of the examples below: (they're just to demonstrate the features & use cases)
|
||||
#
|
||||
# rule1:
|
||||
# If a user is either in the vip or vip+ group, and they have the "titles.titlecollector" permission set to true, and the
|
||||
# "some.random.permission" set to false... if they're not in the group "prison_titlepack" on the "prison" server, then
|
||||
# give add them to the "prison_titlepack" group on the "prison" server, and remove "some.random.permission".
|
||||
#
|
||||
# rule2:
|
||||
# If the user isn't in any of the following groups on the skyblock server: sb_level1, sb_level2, sb_level3, then add
|
||||
# them to sb_level1 on the skyblock server.
|
||||
#
|
||||
# rule3:
|
||||
# If the user is a member of the default group, remove them from default, add them to member, and set their primary group
|
||||
# to member.
|
||||
#
|
||||
# WARNING: Unlike internal commands, this system does not ensure that a group exists before adding a user to it.
|
||||
# It also does not unsure that a user is a member of a group before making that group their primary group.
|
||||
#
|
||||
# Before you use "give: group.<name>" or "set-primary-group", make sure that the group exists, and that the user is
|
||||
# a member of the group.
|
||||
default-assignments:
|
||||
# rule1:
|
||||
# if:
|
||||
# has-true: (<group.vip> | <group.vip+>) & <titles.tilecollector>
|
||||
# has-false: <some.random.permission>
|
||||
# lacks: <prison/group.prison_titlepack>
|
||||
# give:
|
||||
# - prison/group.prison_titlepack
|
||||
# take:
|
||||
# - some.random.permission
|
||||
# rule2:
|
||||
# if:
|
||||
# lacks: <skyblock/group.sb_level1> & <skyblock/group.sb_level2> & <skyblock/group.sb_level3>
|
||||
# give:
|
||||
# - skyblock/group.sb_level1
|
||||
# rule3:
|
||||
# if:
|
||||
# has-true: <group.default>
|
||||
# take:
|
||||
# - group.default
|
||||
# give:
|
||||
# - group.member
|
||||
# set-primary-group: member
|
||||
@@ -1,6 +1,6 @@
|
||||
name: LuckPerms
|
||||
author: Luck
|
||||
version: ${release.version}.${git.closest.tag.commit.count}
|
||||
main: me.lucko.luckperms.LPBungeePlugin
|
||||
softdepend: [PowerfulPerms] # For migration
|
||||
description: A permissions plugin
|
||||
author: Luck
|
||||
main: me.lucko.luckperms.bungee.LPBungeePlugin
|
||||
softdepends: [PowerfulPerms] # For migration
|
||||
+19
-2
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>2.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>2.4.7</version>
|
||||
<version>2.5.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- SQLite -->
|
||||
@@ -67,6 +67,13 @@
|
||||
<version>1.7.9</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- SnakeYAML -->
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.14</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- gson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
@@ -105,6 +112,10 @@
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.gravitydevelopment.updater</groupId>
|
||||
<artifactId>updater</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -125,6 +136,12 @@
|
||||
<version>3.0-dev-52</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.bananaco</groupId>
|
||||
<artifactId>bpermissions-api</artifactId>
|
||||
<version>2.12</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+7
-12
@@ -20,23 +20,18 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.users;
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import me.lucko.luckperms.LPBungeePlugin;
|
||||
import me.lucko.luckperms.api.LuckPermsApi;
|
||||
|
||||
import java.util.UUID;
|
||||
public class ApiHandler {
|
||||
|
||||
public class BungeeUser extends User {
|
||||
BungeeUser(UUID uuid, LPBungeePlugin plugin) {
|
||||
super(uuid, plugin);
|
||||
public static void registerProvider(LuckPermsApi luckPermsApi) {
|
||||
LuckPerms.registerProvider(luckPermsApi);
|
||||
}
|
||||
|
||||
BungeeUser(UUID uuid, String username, LPBungeePlugin plugin) {
|
||||
super(uuid, username, plugin);
|
||||
public static void unregisterProvider() {
|
||||
LuckPerms.unregisterProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPermissions() {
|
||||
// Do nothing. Permissions are applied when needed in a listener.
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Factory class to make a thread-safe sender instance
|
||||
* @param <T> the command sender type
|
||||
*/
|
||||
public abstract class SenderFactory<T> implements Runnable {
|
||||
private final Map<T, List<String>> messages = new HashMap<>();
|
||||
//private final List<Map.Entry<T, String>> messages = new ArrayList<>();
|
||||
private final SenderFactory<T> factory = this;
|
||||
|
||||
protected abstract String getName(T t);
|
||||
protected abstract UUID getUuid(T t);
|
||||
protected abstract void sendMessage(T t, String s);
|
||||
protected abstract boolean hasPermission(T t, String node);
|
||||
|
||||
public final Sender wrap(T t) {
|
||||
return new Sender() {
|
||||
final WeakReference<T> tRef = new WeakReference<>(t);
|
||||
|
||||
// Cache these permissions, so they can be accessed async
|
||||
final Map<Permission, Boolean> perms = Arrays.stream(Permission.values())
|
||||
.map(p -> new AbstractMap.SimpleEntry<>(p, factory.hasPermission(t, p.getNode())))
|
||||
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
|
||||
|
||||
@Getter
|
||||
final String name = factory.getName(t);
|
||||
|
||||
@Getter
|
||||
final UUID uuid = factory.getUuid(t);
|
||||
|
||||
@Override
|
||||
public void sendMessage(String s) {
|
||||
final T t = tRef.get();
|
||||
if (t != null) {
|
||||
synchronized (messages) {
|
||||
if (!messages.containsKey(t)) {
|
||||
messages.put(t, new ArrayList<>());
|
||||
}
|
||||
|
||||
messages.get(t).add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Permission permission) {
|
||||
synchronized (perms) {
|
||||
return perms.get(permission);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
synchronized (messages) {
|
||||
if (!messages.isEmpty()) {
|
||||
messages.entrySet().forEach(e -> e.getValue().forEach(s -> factory.sendMessage(e.getKey(), s)));
|
||||
messages.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.utils.DateUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@UtilityClass
|
||||
public class Util {
|
||||
|
||||
public static void sendPluginMessage(Sender sender, String message) {
|
||||
sender.sendMessage(color(Message.PREFIX + message));
|
||||
}
|
||||
|
||||
public static String color(String s) {
|
||||
return translateAlternateColorCodes('&', s);
|
||||
}
|
||||
|
||||
public static String translateAlternateColorCodes(char altColorChar, String textToTranslate) {
|
||||
// Stolen from Bukkit :>
|
||||
char[] b = textToTranslate.toCharArray();
|
||||
|
||||
for (int i = 0; i < b.length - 1; ++i) {
|
||||
if (b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) {
|
||||
b[i] = 167;
|
||||
b[i + 1] = Character.toLowerCase(b[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
return new String(b);
|
||||
}
|
||||
|
||||
public static String stripColor(String s) {
|
||||
return s == null ? null : Patterns.STRIP_COLOR_PATTERN.matcher(s).replaceAll("");
|
||||
}
|
||||
|
||||
public static String formatBoolean(boolean b) {
|
||||
return b ? "&atrue" : "&cfalse";
|
||||
}
|
||||
|
||||
public static void sendBoolean(Sender sender, String node, boolean b) {
|
||||
sender.sendMessage(Util.color("&b" + node + ": " + formatBoolean(b)));
|
||||
}
|
||||
|
||||
public static String listToCommaSep(List<String> strings) {
|
||||
if (strings.isEmpty()) return "&6None";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
strings.forEach(s -> sb.append("&6").append(s).append("&7, "));
|
||||
return sb.delete(sb.length() - 2, sb.length()).toString();
|
||||
}
|
||||
|
||||
public static String listToArrowSep(List<String> strings, String highlight) {
|
||||
if (strings.isEmpty()) return "&6None";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String s : strings) {
|
||||
if (s.equalsIgnoreCase(highlight)) {
|
||||
sb.append("&e").append(s).append("&7 ---> ");
|
||||
} else {
|
||||
sb.append("&6").append(s).append("&7 ---> ");
|
||||
}
|
||||
}
|
||||
return sb.delete(sb.length() - 6, sb.length()).toString();
|
||||
}
|
||||
|
||||
public static String listToArrowSep(List<String> strings, String highlightFirst, String highlightSecond, boolean reversed) {
|
||||
if (strings.isEmpty()) return "&6None";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String s : strings) {
|
||||
if (s.equalsIgnoreCase(highlightFirst)) {
|
||||
sb.append("&e").append(s).append("&4").append(reversed ? " <--- " : " ---> ");
|
||||
} else if (s.equalsIgnoreCase(highlightSecond)) {
|
||||
sb.append("&e").append(s).append("&7").append(reversed ? " <--- " : " ---> ");
|
||||
} else {
|
||||
sb.append("&6").append(s).append("&7").append(reversed ? " <--- " : " ---> ");
|
||||
}
|
||||
}
|
||||
return sb.delete(sb.length() - 6, sb.length()).toString();
|
||||
}
|
||||
|
||||
public static String listToArrowSep(List<String> strings) {
|
||||
if (strings.isEmpty()) return "&6None";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
strings.forEach(s -> sb.append("&6").append(s).append("&e ---> "));
|
||||
return sb.delete(sb.length() - 6, sb.length()).toString();
|
||||
}
|
||||
|
||||
public static String permNodesToString(Map<String, Boolean> nodes) {
|
||||
if (nodes.isEmpty()) return "&6None";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
|
||||
if (e.getValue()) {
|
||||
sb.append("&a").append(e.getKey()).append("&7, ");
|
||||
} else {
|
||||
sb.append("&c").append(e.getKey()).append("&7, ");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.delete(sb.length() - 2, sb.length()).toString();
|
||||
}
|
||||
|
||||
public static String tempNodesToString(Map<Map.Entry<String, Boolean>, Long> nodes) {
|
||||
if (nodes.isEmpty()) return "&6None";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (Map.Entry<Map.Entry<String, Boolean>, Long> e : nodes.entrySet()) {
|
||||
if (e.getKey().getValue()) {
|
||||
sb.append("&a").append(e.getKey().getKey()).append("&6 - expires in ")
|
||||
.append(DateUtil.formatDateDiff(e.getValue())).append("\n");
|
||||
} else {
|
||||
sb.append("&c").append(e.getKey().getKey()).append("&6 - expires in ")
|
||||
.append(DateUtil.formatDateDiff(e.getValue())).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static UUID parseUuid(String s) {
|
||||
try {
|
||||
return UUID.fromString(s);
|
||||
} catch (IllegalArgumentException e) {
|
||||
try {
|
||||
return UUID.fromString(s.replaceAll(
|
||||
"(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})",
|
||||
"$1-$2-$3-$4-$5"));
|
||||
} catch (IllegalArgumentException e1) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.*;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupInheritsPerm extends SubCommand<Group> {
|
||||
public GroupInheritsPerm() {
|
||||
super("inheritspermission", "Checks to see if a group inherits a certain permission node",
|
||||
"/%s group <group> inheritspermission <node> [server] [world]", Permission.GROUP_INHERITSPERMISSION,
|
||||
Predicate.notInRange(1, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
if (args.size() >= 2) {
|
||||
if (ArgumentChecker.checkServer(args.get(1))) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1)));
|
||||
} else {
|
||||
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1), args.get(2)));
|
||||
}
|
||||
|
||||
} else {
|
||||
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true));
|
||||
}
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupSetInherit extends SubCommand<Group> {
|
||||
public GroupSetInherit() {
|
||||
super("setinherit", "Sets another group for this group to inherit permissions from",
|
||||
"/%s group <group> setinherit <group> [server] [world]", Permission.GROUP_SETINHERIT,
|
||||
Predicate.notInRange(1, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
String groupName = args.get(0).toLowerCase();
|
||||
|
||||
if (ArgumentChecker.checkNode(groupName)) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadGroup(groupName)) {
|
||||
Message.GROUP_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
Group group1 = plugin.getGroupManager().get(groupName);
|
||||
if (group1 == null) {
|
||||
Message.GROUP_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.LOADING_ERROR;
|
||||
}
|
||||
|
||||
try {
|
||||
if (args.size() >= 2) {
|
||||
final String server = args.get(1).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
group.setInheritGroup(group1, server);
|
||||
Message.GROUP_SETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), group1.getName(), server);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("setinherit " + group1.getName() + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(2).toLowerCase();
|
||||
group.setInheritGroup(group1, server, world);
|
||||
Message.GROUP_SETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), group1.getName(), server, world);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("setinherit " + group1.getName() + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.setInheritGroup(group1);
|
||||
Message.GROUP_SETINHERIT_SUCCESS.send(sender, group.getName(), group1.getName());
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("setinherit " + group1.getName())
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.GROUP_ALREADY_INHERITS.send(sender, group.getName(), group1.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
|
||||
return getGroupTabComplete(args, plugin);
|
||||
}
|
||||
}
|
||||
-129
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
import me.lucko.luckperms.utils.DateUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupSetTempInherit extends SubCommand<Group> {
|
||||
public GroupSetTempInherit() {
|
||||
super("settempinherit", "Sets another group for this group to inherit permissions from temporarily",
|
||||
"/%s group <group> settempinherit <group> <duration> [server] [world]",
|
||||
Permission.GROUP_SET_TEMP_INHERIT, Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
String groupName = args.get(0).toLowerCase();
|
||||
|
||||
if (ArgumentChecker.checkNode(groupName)) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
long duration;
|
||||
try {
|
||||
duration = Long.parseLong(args.get(1));
|
||||
} catch (NumberFormatException e) {
|
||||
try {
|
||||
duration = DateUtil.parseDateDiff(args.get(1), true);
|
||||
} catch (DateUtil.IllegalDateException e1) {
|
||||
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(1));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
if (DateUtil.shouldExpire(duration)) {
|
||||
Message.PAST_DATE_ERROR.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadGroup(groupName)) {
|
||||
Message.GROUP_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
Group group1 = plugin.getGroupManager().get(groupName);
|
||||
if (group1 == null) {
|
||||
Message.GROUP_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
group.setInheritGroup(group1, server, duration);
|
||||
Message.GROUP_SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), group1.getName(), server,
|
||||
DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("settempinherit " + group1.getName() + " " + duration + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
group.setInheritGroup(group1, server, world, duration);
|
||||
Message.GROUP_SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), group1.getName(), server,
|
||||
world, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("settempinherit " + group1.getName() + " " + duration + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.setInheritGroup(group1, duration);
|
||||
Message.GROUP_SET_TEMP_INHERIT_SUCCESS.send(sender, group.getName(), group1.getName(), DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("settempinherit " + group1.getName() + " " + duration)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.USER_ALREADY_TEMP_MEMBER_OF.send(sender, group.getName(), group1.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
|
||||
return getGroupTabComplete(args, plugin);
|
||||
}
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupUnsetInherit extends SubCommand<Group> {
|
||||
public GroupUnsetInherit() {
|
||||
super("unsetinherit", "Unsets another group for this group to inherit permissions from",
|
||||
"/%s group <group> unsetinherit <group> [server] [world]", Permission.GROUP_UNSETINHERIT,
|
||||
Predicate.notInRange(1, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
String groupName = args.get(0).toLowerCase();
|
||||
|
||||
if (ArgumentChecker.checkNode(groupName)) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
try {
|
||||
if (args.size() >= 2) {
|
||||
final String server = args.get(1).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
group.unsetPermission("group." + groupName, server);
|
||||
Message.GROUP_UNSETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("unsetinherit " + groupName + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(2).toLowerCase();
|
||||
group.unsetPermission("group." + groupName, server, world);
|
||||
Message.GROUP_UNSETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("unsetinherit " + groupName + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.unsetPermission("group." + groupName);
|
||||
Message.GROUP_UNSETINHERIT_SUCCESS.send(sender, group.getName(), groupName);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("unsetinherit " + groupName)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.GROUP_DOES_NOT_INHERIT.send(sender, group.getName(), groupName);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
|
||||
return getGroupTabComplete(args, plugin);
|
||||
}
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.group.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GroupUnsetTempInherit extends SubCommand<Group> {
|
||||
public GroupUnsetTempInherit() {
|
||||
super("unsettempinherit", "Unsets another group for this group to inherit permissions from",
|
||||
"/%s group <group> unsettempinherit <group> [server] [world]", Permission.GROUP_UNSET_TEMP_INHERIT,
|
||||
Predicate.notInRange(1, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
String groupName = args.get(0).toLowerCase();
|
||||
|
||||
if (ArgumentChecker.checkNode(groupName)) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
try {
|
||||
if (args.size() >= 2) {
|
||||
final String server = args.get(1).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
group.unsetPermission("group." + groupName, server, true);
|
||||
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("unsettempinherit " + groupName + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(2).toLowerCase();
|
||||
group.unsetPermission("group." + groupName, server, world, true);
|
||||
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("unsettempinherit " + groupName + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
group.unsetPermission("group." + groupName, true);
|
||||
Message.GROUP_UNSET_TEMP_INHERIT_SUCCESS.send(sender, group.getName(), groupName);
|
||||
LogEntry.build().actor(sender).acted(group)
|
||||
.action("unsettempinherit " + groupName)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(group, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.GROUP_DOES_NOT_TEMP_INHERIT.send(sender, group.getName(), groupName);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
|
||||
return getGroupTabComplete(args, plugin);
|
||||
}
|
||||
}
|
||||
-529
@@ -1,529 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.migration.subcommands;
|
||||
|
||||
import com.github.cheesesoftware.PowerfulPermsAPI.*;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import static me.lucko.luckperms.constants.Permission.MIGRATION;
|
||||
|
||||
public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
/* <sadness>
|
||||
What kind of API requires reflection to function with multiple versions...
|
||||
Doesn't that just defeat the whole god damn point of having an API in the first place?
|
||||
Whatever happened to the concept of depreciation and responsible API creation?
|
||||
I tried to keep reflection to a minimum, but in some places there's no other option.
|
||||
This class is a complete fucking mess for that reason. I sad now :(
|
||||
</sadness> */
|
||||
private static Method getPlayerGroupsMethod = null;
|
||||
private static Method getGroupMethod = null;
|
||||
private static boolean legacy = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerOwnGroups", UUID.class, ResultRunnable.class);
|
||||
getPlayerGroupsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
try {
|
||||
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerGroups", UUID.class, ResultRunnable.class);
|
||||
getPlayerGroupsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
getGroupMethod = CachedGroup.class.getMethod("getGroup");
|
||||
getGroupMethod.setAccessible(true);
|
||||
legacy = true;
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public MigrationPowerfulPerms() {
|
||||
super("powerfulperms", "Migration from PowerfulPerms",
|
||||
"/%s migration powerfulperms <address> <database> <username> <password> <db table>", MIGRATION, Predicate.not(5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List<String> args, String label) {
|
||||
try {
|
||||
return run(plugin, args);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
private CommandResult run(LuckPermsPlugin plugin, List<String> args) {
|
||||
final Logger log = plugin.getLog();
|
||||
if (!plugin.isPluginLoaded("PowerfulPerms")) {
|
||||
log.severe("PowerfulPerms Migration: Error -> PowerfulPerms is not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
final String address = args.get(0);
|
||||
final String database = args.get(1);
|
||||
final String username = args.get(2);
|
||||
final String password = args.get(3);
|
||||
final String dbTable = args.get(4);
|
||||
|
||||
// Find a list of UUIDs
|
||||
log.info("PowerfulPerms Migration: Getting a list of UUIDs to migrate.");
|
||||
|
||||
@Cleanup HikariDataSource hikari = new HikariDataSource();
|
||||
hikari.setMaximumPoolSize(2);
|
||||
hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
|
||||
hikari.addDataSourceProperty("serverName", address.split(":")[0]);
|
||||
hikari.addDataSourceProperty("port", address.split(":")[1]);
|
||||
hikari.addDataSourceProperty("databaseName", database);
|
||||
hikari.addDataSourceProperty("user", username);
|
||||
hikari.addDataSourceProperty("password", password);
|
||||
|
||||
Set<UUID> uuids = new HashSet<>();
|
||||
|
||||
try {
|
||||
@Cleanup Connection connection = hikari.getConnection();
|
||||
DatabaseMetaData meta = connection.getMetaData();
|
||||
|
||||
@Cleanup ResultSet tables = meta.getTables(null, null, dbTable, null);
|
||||
if (!tables.next()) {
|
||||
log.severe("PowerfulPerms Migration: Error - Couldn't find table.");
|
||||
return CommandResult.FAILURE;
|
||||
|
||||
} else {
|
||||
@Cleanup PreparedStatement columnPs = connection.prepareStatement("SELECT COLUMN_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=?");
|
||||
columnPs.setString(1, dbTable);
|
||||
@Cleanup ResultSet columnRs = columnPs.executeQuery();
|
||||
|
||||
log.info("Found table: " + dbTable);
|
||||
while (columnRs.next()) {
|
||||
log.info("" + columnRs.getString("COLUMN_NAME") + " - " + columnRs.getString("COLUMN_TYPE"));
|
||||
}
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement("SELECT `uuid` FROM " + dbTable);
|
||||
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
|
||||
|
||||
while (resultSet.next()) {
|
||||
uuids.add(UUID.fromString(resultSet.getString("uuid")));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
if (uuids.isEmpty()) {
|
||||
log.severe("PowerfulPerms Migration: Error - Unable to find any UUIDs to migrate.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
log.info("PowerfulPerms Migration: Found " + uuids.size() + " uuids. Starting migration.");
|
||||
|
||||
PowerfulPermsPlugin ppPlugin = (PowerfulPermsPlugin) plugin.getPlugin("PowerfulPerms");
|
||||
PermissionManager pm = ppPlugin.getPermissionManager();
|
||||
|
||||
// Groups first.
|
||||
log.info("PowerfulPerms Migration: Starting group migration.");
|
||||
Map<Integer, Group> groups = pm.getGroups();
|
||||
for (Group g : groups.values()) {
|
||||
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase());
|
||||
final me.lucko.luckperms.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
|
||||
try {
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("create")
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
for (Permission p : g.getOwnPermissions()) {
|
||||
applyPerm(group, p, plugin);
|
||||
}
|
||||
|
||||
for (Group parent : g.getParents()) {
|
||||
try {
|
||||
group.setPermission("group." + parent.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("setinherit " + parent.getName().toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getDatastore().saveGroup(group);
|
||||
}
|
||||
log.info("PowerfulPerms Migration: Group migration complete.");
|
||||
|
||||
// Now users.
|
||||
log.info("PowerfulPerms Migration: Starting user migration.");
|
||||
final Map<UUID, CountDownLatch> progress = new HashMap<>();
|
||||
|
||||
// Migrate all users and their groups
|
||||
for (UUID uuid : uuids) {
|
||||
progress.put(uuid, new CountDownLatch(2));
|
||||
|
||||
// Create a LuckPerms user for the UUID
|
||||
plugin.getDatastore().loadUser(uuid, "null");
|
||||
User user = plugin.getUserManager().get(uuid);
|
||||
|
||||
// Get a list of Permissions held by the user from the PP API.
|
||||
pm.getPlayerOwnPermissions(uuid, new LPResultRunnable<List<Permission>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
List<Permission> perms = this.getResult();
|
||||
perms.forEach(p -> applyPerm(user, p, plugin));
|
||||
|
||||
// Update the progress so the user can be saved and unloaded.
|
||||
synchronized (progress) {
|
||||
progress.get(uuid).countDown();
|
||||
if (progress.get(uuid).getCount() == 0) {
|
||||
plugin.getDatastore().saveUser(user);
|
||||
plugin.getUserManager().cleanup(user);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Migrate the user's groups to LuckPerms from PP.
|
||||
try {
|
||||
getPlayerGroupsMethod.invoke(pm, uuid, new LPResultRunnable<LinkedHashMap<String, List<CachedGroup>>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
Map<String, List<CachedGroup>> groups = getResult();
|
||||
|
||||
for (Map.Entry<String, List<CachedGroup>> e : groups.entrySet()) {
|
||||
final String server;
|
||||
if (e.getKey() != null && (e.getKey().equals("") || e.getKey().equalsIgnoreCase("all"))) {
|
||||
server = null;
|
||||
} else {
|
||||
server = e.getKey();
|
||||
}
|
||||
|
||||
// This is horrible. So many random API changes through versions, no depreciation.
|
||||
if (legacy) {
|
||||
e.getValue().stream()
|
||||
.filter(cg -> !cg.isNegated())
|
||||
.map(cg -> {
|
||||
try {
|
||||
return (Group) getGroupMethod.invoke(cg);
|
||||
} catch (IllegalAccessException | InvocationTargetException e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.forEach(g -> {
|
||||
if (g != null) {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + g.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + g.getName().toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + g.getName().toLowerCase(), true, server);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + g.getName().toLowerCase() + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
e.getValue().stream()
|
||||
.filter(g -> !g.hasExpired() && !g.isNegated())
|
||||
.forEach(g -> {
|
||||
final Group group = pm.getGroup(g.getGroupId());
|
||||
if (g.willExpire()) {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, g.getExpirationDate().getTime() / 1000L);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addtempgroup " + group.getName().toLowerCase() + " " + g.getExpirationDate().getTime() / 1000L)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, server, g.getExpirationDate().getTime() / 1000L);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addtempgroup " + group.getName().toLowerCase() + " " + g.getExpirationDate().getTime() / 1000L + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + group.getName().toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, server);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + group.getName().toLowerCase() + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update the progress so the user can be saved and unloaded.
|
||||
synchronized (progress) {
|
||||
progress.get(uuid).countDown();
|
||||
if (progress.get(uuid).getCount() == 0) {
|
||||
plugin.getDatastore().saveUser(user);
|
||||
plugin.getUserManager().cleanup(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.info("PowerfulPerms Migration: Error");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// All groups are migrated, but there may still be some users being migrated.
|
||||
// This block will wait for all users to be completed.
|
||||
log.info("PowerfulPerms Migration: Waiting for user migration to complete. This may take some time");
|
||||
boolean sleep = true;
|
||||
while (sleep) {
|
||||
sleep = false;
|
||||
|
||||
for (Map.Entry<UUID, CountDownLatch> e : progress.entrySet()) {
|
||||
if (e.getValue().getCount() != 0) {
|
||||
sleep = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sleep) {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We done.
|
||||
log.info("PowerfulPerms Migration: Success! Completed without any errors.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private void applyPerm(PermissionHolder holder, Permission p, LuckPermsPlugin plugin) {
|
||||
String node = p.getPermissionString();
|
||||
boolean value = true;
|
||||
if (node.startsWith("!")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
|
||||
String server = p.getServer();
|
||||
if (server != null && server.equalsIgnoreCase("all")) {
|
||||
server = null;
|
||||
}
|
||||
|
||||
String world = p.getWorld();
|
||||
if (world != null && world.equalsIgnoreCase("all")) {
|
||||
world = null;
|
||||
}
|
||||
|
||||
long expireAt = 0L;
|
||||
if (!legacy) {
|
||||
if (p.willExpire()) {
|
||||
expireAt = p.getExpirationDate().getTime() / 1000L;
|
||||
}
|
||||
}
|
||||
|
||||
if (world != null && server == null) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
if (world != null) {
|
||||
if (expireAt == 0L) {
|
||||
try {
|
||||
holder.setPermission(node, value, server, world);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + node + " " + value + " " + server + " " + world)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
holder.setPermission(node, value, server, world, expireAt);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("settemp " + node + " " + value + " " + expireAt + " " + server + " " + world)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (server != null) {
|
||||
if (expireAt == 0L) {
|
||||
try {
|
||||
holder.setPermission(node, value, server);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + node + " " + value + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
holder.setPermission(node, value, server, expireAt);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("settemp " + node + " " + value + " " + expireAt + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (expireAt == 0L) {
|
||||
try {
|
||||
holder.setPermission(node, value);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("set " + node + " " + value)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
holder.setPermission(node, value, expireAt);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(holder).action("settemp " + node + " " + value + " " + expireAt)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default ResultRunnable, callbacks will always run in the same thread. (an async one, hopefully.)
|
||||
* @param <T> type
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public abstract class LPResultRunnable<T> extends ResultRunnable<T> {
|
||||
|
||||
public LPResultRunnable() {
|
||||
super();
|
||||
super.sameThread = true;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return super.result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserClear extends SubCommand<User> {
|
||||
public UserClear() {
|
||||
super("clear", "Clears a users permissions and groups", "/%s user <user> clear", Permission.USER_CLEAR,
|
||||
Predicate.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
user.clearNodes();
|
||||
Message.CLEAR_SUCCESS.send(sender, user.getName());
|
||||
LogEntry.build().actor(sender).acted(user).action("clear").build().submit(plugin, sender);
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.*;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserInheritsPerm extends SubCommand<User> {
|
||||
public UserInheritsPerm() {
|
||||
super("inheritspermission", "Checks to see if a user inherits a certain permission node",
|
||||
"/%s user <user> inheritspermission <node> [server] [world]", Permission.USER_INHERITSPERMISSION,
|
||||
Predicate.notInRange(1, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
if (args.size() >= 2) {
|
||||
if (ArgumentChecker.checkServer(args.get(1))) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true, args.get(1)));
|
||||
} else {
|
||||
Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true, args.get(1), args.get(2)));
|
||||
}
|
||||
|
||||
} else {
|
||||
Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true));
|
||||
}
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.*;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
public class UserListNodes extends SubCommand<User> {
|
||||
public UserListNodes() {
|
||||
super("listnodes", "Lists the permission nodes the user has", "/%s user <user> listnodes",
|
||||
Permission.USER_LISTNODES, Predicate.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
Message.LISTNODES.send(sender, user.getName(), Util.permNodesToString(exportToLegacy(user.getPermanentNodes())));
|
||||
Message.LISTNODES_TEMP.send(sender, user.getName(), Util.tempNodesToString(user.getTemporaryNodesLegacy()));
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserRemoveGroup extends SubCommand<User> {
|
||||
public UserRemoveGroup() {
|
||||
super("removegroup", "Removes a user from a group", "/%s user <user> removegroup <group> [server] [world]",
|
||||
Permission.USER_REMOVEGROUP, Predicate.notInRange(1, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
String groupName = args.get(0).toLowerCase();
|
||||
|
||||
if (ArgumentChecker.checkNode(groupName)) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if ((args.size() == 1 || (args.size() == 2 && args.get(1).equalsIgnoreCase("global")))
|
||||
&& user.getPrimaryGroup().equalsIgnoreCase(groupName)) {
|
||||
Message.USER_REMOVEGROUP_ERROR_PRIMARY.send(sender);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
try {
|
||||
if (args.size() >= 2) {
|
||||
final String server = args.get(1).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
user.unsetPermission("group." + groupName, server);
|
||||
Message.USER_REMOVEGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removegroup " + groupName + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(2).toLowerCase();
|
||||
user.unsetPermission("group." + groupName, server, world);
|
||||
Message.USER_REMOVEGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removegroup " + groupName + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.unsetPermission("group." + groupName);
|
||||
Message.USER_REMOVEGROUP_SUCCESS.send(sender, user.getName(), groupName);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removegroup " + groupName)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.USER_NOT_MEMBER_OF.send(sender, user.getName(), groupName);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
|
||||
return getGroupTabComplete(args, plugin);
|
||||
}
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserRemoveTempGroup extends SubCommand<User> {
|
||||
public UserRemoveTempGroup() {
|
||||
super("removetempgroup", "Removes a user from a temporary group",
|
||||
"/%s user <user> removetempgroup <group> [server] [world]", Permission.USER_REMOVETEMPGROUP,
|
||||
Predicate.notInRange(1, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
String groupName = args.get(0).toLowerCase();
|
||||
|
||||
if (ArgumentChecker.checkNode(groupName)) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
try {
|
||||
if (args.size() >= 2) {
|
||||
final String server = args.get(1).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
user.unsetPermission("group." + groupName, server, true);
|
||||
Message.USER_REMOVETEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removetempgroup " + groupName + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(2).toLowerCase();
|
||||
user.unsetPermission("group." + groupName, server, world, true);
|
||||
Message.USER_REMOVETEMPGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removetempgroup " + groupName + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.unsetPermission("group." + groupName, true);
|
||||
Message.USER_REMOVETEMPGROUP_SUCCESS.send(sender, user.getName(), groupName);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("removetempgroup " + groupName)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.USER_NOT_TEMP_MEMBER_OF.send(sender, user.getName(), groupName);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
|
||||
return getGroupTabComplete(args, plugin);
|
||||
}
|
||||
}
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserSetPermission extends SubCommand<User> {
|
||||
public UserSetPermission() {
|
||||
super("set", "Sets a permission for a user",
|
||||
"/%s user <user> set <node> <true|false> [server] [world]", Permission.USER_SETPERMISSION,
|
||||
Predicate.notInRange(2, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
String node = args.get(0).replace("{SPACE}", " ");
|
||||
String bool = args.get(1).toLowerCase();
|
||||
|
||||
if (ArgumentChecker.checkNode(node)) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
Message.USER_USE_ADDGROUP.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!bool.equalsIgnoreCase("true") && !bool.equalsIgnoreCase("false")) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
boolean b = Boolean.parseBoolean(bool);
|
||||
|
||||
try {
|
||||
if (args.size() >= 3) {
|
||||
final String server = args.get(2).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 3) {
|
||||
user.setPermission(node, b, server);
|
||||
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("set " + node + " " + b + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(3).toLowerCase();
|
||||
user.setPermission(node, b, server, world);
|
||||
Message.SETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, bool, user.getName(), server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("set " + node + " " + b + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.setPermission(node, b);
|
||||
Message.SETPERMISSION_SUCCESS.send(sender, node, bool, user.getName());
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("set " + node + " " + b)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.ALREADY_HASPERMISSION.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
|
||||
return getBoolTabComplete(args);
|
||||
}
|
||||
}
|
||||
-130
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
import me.lucko.luckperms.utils.DateUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserSetTempPermission extends SubCommand<User> {
|
||||
public UserSetTempPermission() {
|
||||
super("settemp", "Sets a temporary permission for a user",
|
||||
"/%s user <user> settemp <node> <true|false> <duration> [server] [world]",
|
||||
Permission.USER_SET_TEMP_PERMISSION, Predicate.notInRange(3, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
String node = args.get(0).replace("{SPACE}", " ");
|
||||
String bool = args.get(1).toLowerCase();
|
||||
|
||||
if (ArgumentChecker.checkNode(node)) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
Message.USER_USE_ADDGROUP.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!bool.equalsIgnoreCase("true") && !bool.equalsIgnoreCase("false")) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
boolean b = Boolean.parseBoolean(bool);
|
||||
|
||||
long duration;
|
||||
try {
|
||||
duration = Long.parseLong(args.get(2));
|
||||
} catch (NumberFormatException e) {
|
||||
try {
|
||||
duration = DateUtil.parseDateDiff(args.get(2), true);
|
||||
} catch (DateUtil.IllegalDateException e1) {
|
||||
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
if (DateUtil.shouldExpire(duration)) {
|
||||
Message.PAST_DATE_ERROR.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
try {
|
||||
if (args.size() >= 4) {
|
||||
final String server = args.get(3).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 4) {
|
||||
user.setPermission(node, b, server, duration);
|
||||
Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("settemp " + node + " " + b + " " + duration + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(4).toLowerCase();
|
||||
user.setPermission(node, b, server, world, duration);
|
||||
Message.SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS.send(sender, node, bool, user.getName(), server, world, DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("settemp " + node + " " + b + " " + duration + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.setPermission(node, b, duration);
|
||||
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, bool, user.getName(), DateUtil.formatDateDiff(duration));
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("settemp " + node + " " + b + " " + duration)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectAlreadyHasException e) {
|
||||
Message.ALREADY_HAS_TEMP_PERMISSION.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
|
||||
return getBoolTabComplete(args);
|
||||
}
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserUnSetPermission extends SubCommand<User> {
|
||||
public UserUnSetPermission() {
|
||||
super("unset", "Unsets a permission for a user",
|
||||
"/%s user <user> unset <node> [server] [world]", Permission.USER_UNSETPERMISSION, Predicate.notInRange(1, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
String node = args.get(0).replace("{SPACE}", " ");
|
||||
|
||||
if (ArgumentChecker.checkNode(node)) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
Message.USER_USE_REMOVEGROUP.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
try {
|
||||
if (args.size() >= 2) {
|
||||
final String server = args.get(1).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
user.unsetPermission(node, server);
|
||||
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("unset " + node + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(2).toLowerCase();
|
||||
user.unsetPermission(node, server, world);
|
||||
Message.UNSETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, user.getName(), server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("unset " + node + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.unsetPermission(node);
|
||||
Message.UNSETPERMISSION_SUCCESS.send(sender, node, user.getName());
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("unset " + node)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.DOES_NOT_HAVEPERMISSION.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.commands.user.subcommands;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.ArgumentChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserUnsetTempPermission extends SubCommand<User> {
|
||||
public UserUnsetTempPermission() {
|
||||
super("unsettemp", "Unsets a temporary permission for a user",
|
||||
"/%s user <user> unsettemp <node> [server] [world]", Permission.USER_UNSET_TEMP_PERMISSION,
|
||||
Predicate.notInRange(1, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
String node = args.get(0).replace("{SPACE}", " ");
|
||||
|
||||
if (ArgumentChecker.checkNode(node)) {
|
||||
sendUsage(sender, label);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
Message.USER_USE_REMOVEGROUP.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
try {
|
||||
if (args.size() >= 2) {
|
||||
final String server = args.get(1).toLowerCase();
|
||||
if (ArgumentChecker.checkServer(server)) {
|
||||
Message.SERVER_INVALID_ENTRY.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
user.unsetPermission(node, server, true);
|
||||
Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("unsettemp " + node + " " + server)
|
||||
.build().submit(plugin, sender);
|
||||
} else {
|
||||
final String world = args.get(2).toLowerCase();
|
||||
user.unsetPermission(node, server, world, true);
|
||||
Message.UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, user.getName(), server, world);
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("unsettemp " + node + " " + server + " " + world)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
} else {
|
||||
user.unsetPermission(node, true);
|
||||
Message.UNSET_TEMP_PERMISSION_SUCCESS.send(sender, node, user.getName());
|
||||
LogEntry.build().actor(sender).acted(user)
|
||||
.action("unsettemp " + node)
|
||||
.build().submit(plugin, sender);
|
||||
}
|
||||
|
||||
save(user, sender, plugin);
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (ObjectLacksException e) {
|
||||
Message.DOES_NOT_HAVE_TEMP_PERMISSION.send(sender, user.getName());
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
+58
-23
@@ -20,20 +20,26 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms;
|
||||
package me.lucko.luckperms.common;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.implementation.ApiProvider;
|
||||
import me.lucko.luckperms.commands.ConsecutiveExecutor;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import me.lucko.luckperms.core.UuidCache;
|
||||
import me.lucko.luckperms.data.Importer;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.UserManager;
|
||||
import me.lucko.luckperms.api.PlatformType;
|
||||
import me.lucko.luckperms.common.api.ApiProvider;
|
||||
import me.lucko.luckperms.common.calculators.CalculatorFactory;
|
||||
import me.lucko.luckperms.common.commands.ConsecutiveExecutor;
|
||||
import me.lucko.luckperms.common.commands.Sender;
|
||||
import me.lucko.luckperms.common.config.LPConfiguration;
|
||||
import me.lucko.luckperms.common.constants.Message;
|
||||
import me.lucko.luckperms.common.contexts.ContextManager;
|
||||
import me.lucko.luckperms.common.core.UuidCache;
|
||||
import me.lucko.luckperms.common.data.Importer;
|
||||
import me.lucko.luckperms.common.groups.GroupManager;
|
||||
import me.lucko.luckperms.common.storage.Datastore;
|
||||
import me.lucko.luckperms.common.tracks.TrackManager;
|
||||
import me.lucko.luckperms.common.users.UserManager;
|
||||
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||
import me.lucko.luckperms.common.utils.LocaleManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
@@ -59,17 +65,19 @@ public interface LuckPermsPlugin {
|
||||
ApiProvider getApiProvider();
|
||||
Importer getImporter();
|
||||
ConsecutiveExecutor getConsecutiveExecutor();
|
||||
LocaleManager getLocaleManager();
|
||||
ContextManager getContextManager();
|
||||
CalculatorFactory getCalculatorFactory();
|
||||
|
||||
/**
|
||||
* @return the version of the plugin
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
|
||||
/**
|
||||
* @return the platform type
|
||||
*/
|
||||
Type getType();
|
||||
PlatformType getType();
|
||||
|
||||
/**
|
||||
* @return the main plugin directory
|
||||
@@ -86,7 +94,10 @@ public interface LuckPermsPlugin {
|
||||
* @param uuid The player's uuid
|
||||
* @return a formatted status string
|
||||
*/
|
||||
Message getPlayerStatus(UUID uuid);
|
||||
default Message getPlayerStatus(UUID uuid) {
|
||||
UUID external = getUuidCache().getExternalUUID(uuid);
|
||||
return isOnline(external) ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of users online on the platform
|
||||
@@ -100,10 +111,23 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
List<String> getPlayerList();
|
||||
|
||||
/**
|
||||
* Gets the UUIDs of the users online on the platform
|
||||
* @return a {@link Set} of UUIDs
|
||||
*/
|
||||
Set<UUID> getOnlinePlayers();
|
||||
|
||||
/**
|
||||
* Checks if a user is online
|
||||
* @param external the users external uuid
|
||||
* @return true if the user is online
|
||||
*/
|
||||
boolean isOnline(UUID external);
|
||||
|
||||
/**
|
||||
* @return a {@link List} of senders online on the platform
|
||||
*/
|
||||
List<Sender> getSenders();
|
||||
List<Sender> getNotifyListeners();
|
||||
|
||||
/**
|
||||
* @return the console sender of the instance
|
||||
@@ -111,10 +135,11 @@ public interface LuckPermsPlugin {
|
||||
Sender getConsoleSender();
|
||||
|
||||
/**
|
||||
* Gets all possible permission nodes, used for resolving wildcards
|
||||
* @return a {@link List} of permission nodes
|
||||
* Gets a set of Contexts that should be pre-processed in advance
|
||||
* @param op if the user being processed is op
|
||||
* @return a set of contexts
|
||||
*/
|
||||
List<String> getPossiblePermissions();
|
||||
Set<Contexts> getPreProcessContexts(boolean op);
|
||||
|
||||
/**
|
||||
* Gets a set of players ignoring logging output
|
||||
@@ -136,6 +161,13 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
Object getService(Class clazz);
|
||||
|
||||
/**
|
||||
* Used as a backup for migration
|
||||
* @param playerName the players name
|
||||
* @return a uuid if found, or null if not
|
||||
*/
|
||||
UUID getUUID(String playerName);
|
||||
|
||||
/**
|
||||
* Checks if a plugin is loaded on the platform
|
||||
* @param name the name of the plugin
|
||||
@@ -146,7 +178,7 @@ public interface LuckPermsPlugin {
|
||||
/**
|
||||
* Runs an update task
|
||||
*/
|
||||
void runUpdateTask();
|
||||
BufferedRequest<Void> getUpdateTaskBuffer();
|
||||
|
||||
/**
|
||||
* Execute a runnable asynchronously
|
||||
@@ -160,8 +192,11 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
void doSync(Runnable r);
|
||||
|
||||
/**
|
||||
* Execute a runnable asynchronously on a loop
|
||||
* @param r the task to run
|
||||
* @param interval the time between runs in ticks
|
||||
*/
|
||||
void doAsyncRepeating(Runnable r, long interval);
|
||||
|
||||
enum Type {
|
||||
BUKKIT, BUNGEE, SPONGE;
|
||||
}
|
||||
}
|
||||
+44
-25
@@ -20,26 +20,28 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.implementation;
|
||||
package me.lucko.luckperms.common.api;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.*;
|
||||
import me.lucko.luckperms.api.context.ContextListener;
|
||||
import me.lucko.luckperms.api.context.IContextCalculator;
|
||||
import me.lucko.luckperms.api.event.LPEvent;
|
||||
import me.lucko.luckperms.api.event.LPListener;
|
||||
import me.lucko.luckperms.api.implementation.internal.*;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.users.UserIdentifier;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static me.lucko.luckperms.api.implementation.internal.Utils.checkNode;
|
||||
import static me.lucko.luckperms.common.api.internal.Utils.checkNode;
|
||||
|
||||
/**
|
||||
* Provides static access to LuckPerms
|
||||
* Implements the LuckPerms API using the plugin instance
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class ApiProvider implements LuckPermsApi {
|
||||
@@ -62,12 +64,12 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public void runUpdateTask() {
|
||||
plugin.runUpdateTask();
|
||||
plugin.getUpdateTaskBuffer().request();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getApiVersion() {
|
||||
return 1.6;
|
||||
return 2.13;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,6 +77,11 @@ public class ApiProvider implements LuckPermsApi {
|
||||
return plugin.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformType getPlatformType() {
|
||||
return plugin.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerListener(@NonNull LPListener listener) {
|
||||
eventBus.register(listener);
|
||||
@@ -87,17 +94,17 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public LPConfiguration getConfiguration() {
|
||||
return new LPConfigurationLink(plugin.getConfiguration());
|
||||
return new me.lucko.luckperms.common.api.internal.LPConfigurationLink(plugin.getConfiguration());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Datastore getDatastore() {
|
||||
return new DatastoreLink(plugin, plugin.getDatastore());
|
||||
return new me.lucko.luckperms.common.api.internal.DatastoreLink(plugin, plugin.getDatastore());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UuidCache getUuidCache() {
|
||||
return new UuidCacheLink(plugin.getUuidCache());
|
||||
return new me.lucko.luckperms.common.api.internal.UuidCacheLink(plugin.getUuidCache());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,12 +114,12 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public User getUser(@NonNull UUID uuid) {
|
||||
final me.lucko.luckperms.users.User user = plugin.getUserManager().get(uuid);
|
||||
final me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(uuid);
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new UserLink(user);
|
||||
return new me.lucko.luckperms.common.api.internal.UserLink(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,12 +129,12 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public User getUser(@NonNull String name) {
|
||||
final me.lucko.luckperms.users.User user = plugin.getUserManager().get(name);
|
||||
final me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(name);
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new UserLink(user);
|
||||
return new me.lucko.luckperms.common.api.internal.UserLink(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,28 +144,28 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public Set<User> getUsers() {
|
||||
return plugin.getUserManager().getAll().values().stream().map(UserLink::new).collect(Collectors.toSet());
|
||||
return plugin.getUserManager().getAll().values().stream().map(me.lucko.luckperms.common.api.internal.UserLink::new).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserLoaded(@NonNull UUID uuid) {
|
||||
return plugin.getUserManager().isLoaded(uuid);
|
||||
return plugin.getUserManager().isLoaded(UserIdentifier.of(uuid, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanupUser(@NonNull User user) {
|
||||
Utils.checkUser(user);
|
||||
plugin.getUserManager().cleanup(((UserLink) user).getMaster());
|
||||
me.lucko.luckperms.common.api.internal.Utils.checkUser(user);
|
||||
plugin.getUserManager().cleanup(((me.lucko.luckperms.common.api.internal.UserLink) user).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group getGroup(@NonNull String name) {
|
||||
final me.lucko.luckperms.groups.Group group = plugin.getGroupManager().get(name);
|
||||
final me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(name);
|
||||
if (group == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new GroupLink(group);
|
||||
return new me.lucko.luckperms.common.api.internal.GroupLink(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,7 +175,7 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public Set<Group> getGroups() {
|
||||
return plugin.getGroupManager().getAll().values().stream().map(GroupLink::new).collect(Collectors.toSet());
|
||||
return plugin.getGroupManager().getAll().values().stream().map(me.lucko.luckperms.common.api.internal.GroupLink::new).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,12 +185,12 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public Track getTrack(@NonNull String name) {
|
||||
final me.lucko.luckperms.tracks.Track track = plugin.getTrackManager().get(name);
|
||||
final me.lucko.luckperms.common.tracks.Track track = plugin.getTrackManager().get(name);
|
||||
if (track == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TrackLink(track);
|
||||
return new me.lucko.luckperms.common.api.internal.TrackLink(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,7 +200,7 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public Set<Track> getTracks() {
|
||||
return plugin.getTrackManager().getAll().values().stream().map(TrackLink::new).collect(Collectors.toSet());
|
||||
return plugin.getTrackManager().getAll().values().stream().map(me.lucko.luckperms.common.api.internal.TrackLink::new).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -203,6 +210,18 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public Node.Builder buildNode(@NonNull String permission) throws IllegalArgumentException {
|
||||
return new me.lucko.luckperms.utils.Node.Builder(checkNode(permission));
|
||||
return new me.lucko.luckperms.common.core.Node.Builder(checkNode(permission));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void registerContextCalculator(IContextCalculator<?> contextCalculator) {
|
||||
plugin.getContextManager().registerCalculator(contextCalculator);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void registerContextListener(ContextListener<?> contextListener) {
|
||||
plugin.getContextManager().registerListener(contextListener);
|
||||
}
|
||||
}
|
||||
+56
-137
@@ -20,37 +20,33 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.implementation.internal;
|
||||
package me.lucko.luckperms.common.api.internal;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.*;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.utils.AbstractFuture;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static me.lucko.luckperms.api.implementation.internal.Utils.*;
|
||||
import static me.lucko.luckperms.common.api.internal.Utils.*;
|
||||
|
||||
/**
|
||||
* Provides a link between {@link Datastore} and {@link me.lucko.luckperms.storage.Datastore}
|
||||
* Provides a link between {@link Datastore} and {@link me.lucko.luckperms.common.storage.Datastore}
|
||||
*/
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
public class DatastoreLink implements Datastore {
|
||||
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final me.lucko.luckperms.storage.Datastore master;
|
||||
private final me.lucko.luckperms.common.storage.Datastore master;
|
||||
private final Async async;
|
||||
private final Sync sync;
|
||||
private final Future future;
|
||||
|
||||
public DatastoreLink(@NonNull LuckPermsPlugin plugin, @NonNull me.lucko.luckperms.storage.Datastore master) {
|
||||
public DatastoreLink(@NonNull LuckPermsPlugin plugin, @NonNull me.lucko.luckperms.common.storage.Datastore master) {
|
||||
this.plugin = plugin;
|
||||
this.master = master;
|
||||
this.async = new Async(master);
|
||||
@@ -93,7 +89,7 @@ public class DatastoreLink implements Datastore {
|
||||
|
||||
@AllArgsConstructor
|
||||
public class Async implements Datastore.Async {
|
||||
private final me.lucko.luckperms.storage.Datastore master;
|
||||
private final me.lucko.luckperms.common.storage.Datastore master;
|
||||
|
||||
@Override
|
||||
public void logAction(@NonNull LogEntry entry, Callback<Boolean> callback) {
|
||||
@@ -206,68 +202,72 @@ public class DatastoreLink implements Datastore {
|
||||
|
||||
@AllArgsConstructor
|
||||
public class Sync implements Datastore.Sync {
|
||||
private final me.lucko.luckperms.storage.Datastore master;
|
||||
private final me.lucko.luckperms.common.storage.Datastore master;
|
||||
|
||||
@Override
|
||||
public boolean logAction(@NonNull LogEntry entry) {
|
||||
return master.logAction(entry);
|
||||
return master.logAction(entry).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getLog() {
|
||||
return new LogLink(master.getLog());
|
||||
me.lucko.luckperms.common.data.Log log = master.getLog().getUnchecked();
|
||||
if (log == null) {
|
||||
return null;
|
||||
}
|
||||
return new LogLink(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) {
|
||||
return master.loadUser(uuid, checkUsername(username));
|
||||
return master.loadUser(uuid, checkUsername(username)).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(@NonNull UUID uuid) {
|
||||
return master.loadUser(uuid, "null");
|
||||
return master.loadUser(uuid, "null").getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(@NonNull UUID uuid, @NonNull String username) {
|
||||
return master.loadUser(uuid, checkUsername(username));
|
||||
return master.loadUser(uuid, checkUsername(username)).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(@NonNull User user) {
|
||||
checkUser(user);
|
||||
return master.saveUser(((UserLink) user).getMaster());
|
||||
return master.saveUser(((UserLink) user).getMaster()).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cleanupUsers() {
|
||||
return master.cleanupUsers();
|
||||
return master.cleanupUsers().getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueUsers() {
|
||||
return master.getUniqueUsers();
|
||||
return master.getUniqueUsers().getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(@NonNull String name) {
|
||||
return master.createAndLoadGroup(checkName(name));
|
||||
return master.createAndLoadGroup(checkName(name)).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(@NonNull String name) {
|
||||
return master.loadGroup(checkName(name));
|
||||
return master.loadGroup(checkName(name)).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
return master.loadAllGroups();
|
||||
return master.loadAllGroups().getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(@NonNull Group group) {
|
||||
checkGroup(group);
|
||||
return master.saveGroup(((GroupLink) group).getMaster());
|
||||
return master.saveGroup(((GroupLink) group).getMaster()).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -276,240 +276,159 @@ public class DatastoreLink implements Datastore {
|
||||
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
|
||||
throw new IllegalArgumentException("Cannot delete the default group.");
|
||||
}
|
||||
return master.deleteGroup(((GroupLink) group).getMaster());
|
||||
return master.deleteGroup(((GroupLink) group).getMaster()).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(@NonNull String name) {
|
||||
return master.createAndLoadTrack(checkName(name));
|
||||
return master.createAndLoadTrack(checkName(name)).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(@NonNull String name) {
|
||||
return master.loadTrack(checkName(name));
|
||||
return master.loadTrack(checkName(name)).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
return master.loadAllTracks();
|
||||
return master.loadAllTracks().getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(@NonNull Track track) {
|
||||
checkTrack(track);
|
||||
return master.saveTrack(((TrackLink) track).getMaster());
|
||||
return master.saveTrack(((TrackLink) track).getMaster()).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(@NonNull Track track) {
|
||||
checkTrack(track);
|
||||
return master.deleteTrack(((TrackLink) track).getMaster());
|
||||
return master.deleteTrack(((TrackLink) track).getMaster()).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
|
||||
return master.saveUUIDData(checkUsername(username), uuid);
|
||||
return master.saveUUIDData(checkUsername(username), uuid).getUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(@NonNull String username) {
|
||||
return master.getUUID(checkUsername(username));
|
||||
return master.getUUID(checkUsername(username)).getUnchecked();
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
public class Future implements Datastore.Future {
|
||||
private final me.lucko.luckperms.storage.Datastore master;
|
||||
private final me.lucko.luckperms.common.storage.Datastore master;
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> logAction(@NonNull LogEntry entry) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.logAction(entry, lpf);
|
||||
return lpf;
|
||||
return master.logAction(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Log> getLog() {
|
||||
LPFuture<Log> lpf = new LPFuture<>();
|
||||
master.getLog(log -> lpf.onComplete(new LogLink(log)));
|
||||
return lpf;
|
||||
AbstractFuture<Log> fut = new AbstractFuture<>();
|
||||
master.getLog(log -> fut.complete(new LogLink(log)));
|
||||
return fut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadUser(uuid, checkUsername(username), lpf);
|
||||
return lpf;
|
||||
return master.loadUser(uuid, checkUsername(username));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadUser(@NonNull UUID uuid) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadUser(uuid, "null", lpf);
|
||||
return lpf;
|
||||
return master.loadUser(uuid, "null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadUser(@NonNull UUID uuid, @NonNull String username) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadUser(uuid, checkUsername(username), lpf);
|
||||
return lpf;
|
||||
return master.loadUser(uuid, checkUsername(username));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> saveUser(@NonNull User user) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
checkUser(user);
|
||||
master.saveUser(((UserLink) user).getMaster(), lpf);
|
||||
return lpf;
|
||||
return master.saveUser(((UserLink) user).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> cleanupUsers() {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.cleanupUsers(lpf);
|
||||
return lpf;
|
||||
return master.cleanupUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Set<UUID>> getUniqueUsers() {
|
||||
LPFuture<Set<UUID>> lpf = new LPFuture<>();
|
||||
master.getUniqueUsers(lpf);
|
||||
return lpf;
|
||||
return master.getUniqueUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> createAndLoadGroup(@NonNull String name) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.createAndLoadGroup(checkName(name), lpf);
|
||||
return lpf;
|
||||
return master.createAndLoadGroup(checkName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadGroup(@NonNull String name) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadGroup(checkName(name), lpf);
|
||||
return lpf;
|
||||
return master.loadGroup(checkName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadAllGroups() {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadAllGroups(lpf);
|
||||
return lpf;
|
||||
return master.loadAllGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> saveGroup(@NonNull Group group) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
checkGroup(group);
|
||||
master.saveGroup(((GroupLink) group).getMaster(), lpf);
|
||||
return lpf;
|
||||
return master.saveGroup(((GroupLink) group).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> deleteGroup(@NonNull Group group) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
checkGroup(group);
|
||||
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
|
||||
throw new IllegalArgumentException("Cannot delete the default group.");
|
||||
}
|
||||
master.deleteGroup(((GroupLink) group).getMaster(), lpf);
|
||||
return lpf;
|
||||
return master.deleteGroup(((GroupLink) group).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> createAndLoadTrack(@NonNull String name) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.createAndLoadTrack(checkName(name), lpf);
|
||||
return lpf;
|
||||
return master.createAndLoadTrack(checkName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadTrack(@NonNull String name) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadTrack(checkName(name), lpf);
|
||||
return lpf;
|
||||
return master.loadTrack(checkName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadAllTracks() {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadAllTracks(lpf);
|
||||
return lpf;
|
||||
return master.loadAllTracks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> saveTrack(@NonNull Track track) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
checkTrack(track);
|
||||
master.saveTrack(((TrackLink) track).getMaster(), lpf);
|
||||
return lpf;
|
||||
return master.saveTrack(((TrackLink) track).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> deleteTrack(@NonNull Track track) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
checkTrack(track);
|
||||
master.deleteTrack(((TrackLink) track).getMaster(), lpf);
|
||||
return lpf;
|
||||
return master.deleteTrack(((TrackLink) track).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.saveUUIDData(checkUsername(username), uuid, lpf);
|
||||
return lpf;
|
||||
return master.saveUUIDData(checkUsername(username), uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<UUID> getUUID(@NonNull String username) {
|
||||
LPFuture<UUID> lpf = new LPFuture<>();
|
||||
master.getUUID(checkUsername(username), lpf);
|
||||
return lpf;
|
||||
}
|
||||
}
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class LPFuture<T> implements Callback<T>, java.util.concurrent.Future<T> {
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
private T value;
|
||||
|
||||
@Override
|
||||
public void onComplete(T t) {
|
||||
value = t;
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
// Not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return latch.getCount() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() throws InterruptedException {
|
||||
latch.await();
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
|
||||
if (latch.await(timeout, unit)) {
|
||||
return value;
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
return master.getUUID(checkUsername(username));
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -20,7 +20,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.implementation.internal;
|
||||
package me.lucko.luckperms.common.api.internal;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -32,22 +32,22 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static me.lucko.luckperms.api.implementation.internal.Utils.*;
|
||||
import static me.lucko.luckperms.common.api.internal.Utils.*;
|
||||
|
||||
/**
|
||||
* Provides a link between {@link Group} and {@link me.lucko.luckperms.groups.Group}
|
||||
* Provides a link between {@link Group} and {@link me.lucko.luckperms.common.groups.Group}
|
||||
*/
|
||||
@EqualsAndHashCode(of = {"name"}, callSuper = false)
|
||||
@SuppressWarnings("unused")
|
||||
public class GroupLink extends PermissionHolderLink implements Group {
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final me.lucko.luckperms.groups.Group master;
|
||||
private final me.lucko.luckperms.common.groups.Group master;
|
||||
|
||||
@Getter
|
||||
private final String name;
|
||||
|
||||
public GroupLink(@NonNull me.lucko.luckperms.groups.Group master) {
|
||||
public GroupLink(@NonNull me.lucko.luckperms.common.groups.Group master) {
|
||||
super(master);
|
||||
this.master = master;
|
||||
this.name = master.getName();
|
||||
+70
-8
@@ -20,19 +20,21 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.implementation.internal;
|
||||
package me.lucko.luckperms.common.api.internal;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.api.LPConfiguration;
|
||||
import me.lucko.luckperms.api.data.DatastoreConfiguration;
|
||||
import me.lucko.luckperms.api.data.MySQLConfiguration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provides a link between {@link LPConfiguration} and {@link me.lucko.luckperms.core.LPConfiguration}
|
||||
* Provides a link between {@link LPConfiguration} and {@link me.lucko.luckperms.common.config.LPConfiguration}
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class LPConfigurationLink implements LPConfiguration {
|
||||
private final me.lucko.luckperms.core.LPConfiguration master;
|
||||
private final me.lucko.luckperms.common.config.LPConfiguration master;
|
||||
|
||||
@Override
|
||||
public String getServer() {
|
||||
@@ -56,27 +58,77 @@ public class LPConfigurationLink implements LPConfiguration {
|
||||
|
||||
@Override
|
||||
public boolean getIncludeGlobalPerms() {
|
||||
return master.getIncludeGlobalPerms();
|
||||
return master.isIncludingGlobalPerms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIncludeGlobalWorldPerms() {
|
||||
return master.isIncludingGlobalWorldPerms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getApplyGlobalGroups() {
|
||||
return master.isApplyingGlobalGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getApplyGlobalWorldGroups() {
|
||||
return master.isApplyingGlobalWorldGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getOnlineMode() {
|
||||
return master.getOnlineMode();
|
||||
return master.isOnlineMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getApplyWildcards() {
|
||||
return master.getApplyWildcards();
|
||||
return master.isApplyingWildcards();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getApplyRegex() {
|
||||
return master.getApplyRegex();
|
||||
return master.isApplyingRegex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getApplyShorthand() {
|
||||
return master.getApplyShorthand();
|
||||
return master.isApplyingShorthand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getLogNotify() {
|
||||
return master.isLogNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDebugPermissionChecks() {
|
||||
return master.isDebugPermissionChecks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getEnableOps() {
|
||||
return master.isOpsEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCommandsAllowOp() {
|
||||
return master.isCommandsAllowOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAutoOp() {
|
||||
return master.isAutoOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVaultServer() {
|
||||
return master.getVaultServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVaultIncludeGlobal() {
|
||||
return master.isVaultIncludingGlobal();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@@ -94,4 +146,14 @@ public class LPConfigurationLink implements LPConfiguration {
|
||||
public String getStorageMethod() {
|
||||
return master.getStorageMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getSplitStorage() {
|
||||
return master.isSplitStorage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getSplitStorageOptions() {
|
||||
return master.getSplitStorageOptions();
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -20,7 +20,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.implementation.internal;
|
||||
package me.lucko.luckperms.common.api.internal;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
@@ -31,14 +31,14 @@ import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.UUID;
|
||||
|
||||
import static me.lucko.luckperms.api.implementation.internal.Utils.checkName;
|
||||
import static me.lucko.luckperms.common.api.internal.Utils.checkName;
|
||||
|
||||
/**
|
||||
* Provides a link between {@link Log} and {@link me.lucko.luckperms.data.Log}
|
||||
* Provides a link between {@link Log} and {@link me.lucko.luckperms.common.data.Log}
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class LogLink implements Log {
|
||||
private final me.lucko.luckperms.data.Log master;
|
||||
private final me.lucko.luckperms.common.data.Log master;
|
||||
|
||||
@Override
|
||||
public SortedSet<LogEntry> getContent() {
|
||||
+51
-19
@@ -20,30 +20,29 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.implementation.internal;
|
||||
package me.lucko.luckperms.common.api.internal;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.api.PermissionHolder;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.api.*;
|
||||
import me.lucko.luckperms.api.context.ContextSet;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static me.lucko.luckperms.api.implementation.internal.Utils.*;
|
||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||
import static me.lucko.luckperms.common.api.internal.Utils.*;
|
||||
import static me.lucko.luckperms.common.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
/**
|
||||
* Provides a link between {@link PermissionHolder} and {@link me.lucko.luckperms.core.PermissionHolder}
|
||||
* Provides a link between {@link PermissionHolder} and {@link me.lucko.luckperms.common.core.PermissionHolder}
|
||||
*/
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
@SuppressWarnings("unused")
|
||||
@AllArgsConstructor
|
||||
public class PermissionHolderLink implements PermissionHolder {
|
||||
|
||||
@NonNull
|
||||
private final me.lucko.luckperms.core.PermissionHolder master;
|
||||
private final me.lucko.luckperms.common.core.PermissionHolder master;
|
||||
|
||||
@Override
|
||||
public String getObjectName() {
|
||||
@@ -51,23 +50,33 @@ public class PermissionHolderLink implements PermissionHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortedSet<Node> getPermissions() {
|
||||
return Collections.unmodifiableSortedSet(master.getPermissions());
|
||||
public SortedSet<? extends Node> getPermissions() {
|
||||
return master.getPermissions(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Node> getEnduringPermissions() {
|
||||
return Collections.unmodifiableSet(master.getNodes());
|
||||
return master.getNodes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Node> getTransientPermissions() {
|
||||
return Collections.unmodifiableSet(master.getTransientNodes());
|
||||
return master.getTransientNodes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Node> getAllNodes() {
|
||||
return Collections.unmodifiableSet(master.getAllNodes(null));
|
||||
return Collections.unmodifiableSet(master.getAllNodes(null, Contexts.allowAll()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortedSet<LocalizedNode> getAllNodes(@NonNull Contexts contexts) {
|
||||
return master.getAllNodes(null, contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<LocalizedNode> getAllNodesFiltered(@NonNull Contexts contexts) {
|
||||
return master.getAllNodesFiltered(contexts);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -232,27 +241,50 @@ public class PermissionHolderLink implements PermissionHolder {
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups, List<String> possibleNodes) {
|
||||
return master.getLocalPermissions(server, world, excludedGroups, possibleNodes);
|
||||
Map<String, String> context = new HashMap<>();
|
||||
if (server != null && !server.equals("")) {
|
||||
context.put("server", server);
|
||||
}
|
||||
if (world != null && !world.equals("")) {
|
||||
context.put("world", world);
|
||||
}
|
||||
return master.exportNodes(new Contexts(ContextSet.fromMap(context), true, true, true, true, true, false), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups) {
|
||||
return master.getLocalPermissions(server, world, excludedGroups);
|
||||
Map<String, String> context = new HashMap<>();
|
||||
if (server != null && !server.equals("")) {
|
||||
context.put("server", server);
|
||||
}
|
||||
if (world != null && !world.equals("")) {
|
||||
context.put("world", world);
|
||||
}
|
||||
return master.exportNodes(new Contexts(ContextSet.fromMap(context), true, true, true, true, true, false), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups, List<String> possibleNodes) {
|
||||
return master.getLocalPermissions(server, excludedGroups, possibleNodes);
|
||||
return getLocalPermissions(server, null, excludedGroups, possibleNodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups) {
|
||||
return master.getLocalPermissions(server, excludedGroups);
|
||||
return getLocalPermissions(server, null, excludedGroups, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getPermissions(String server, String world, Map<String, String> extraContext, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups) {
|
||||
return master.exportNodes(server, world, extraContext, includeGlobal, applyGroups, possibleNodes);
|
||||
if (extraContext == null) {
|
||||
extraContext = new HashMap<>();
|
||||
}
|
||||
if (server != null && !server.equals("")) {
|
||||
extraContext.put("server", server);
|
||||
}
|
||||
if (world != null && !world.equals("")) {
|
||||
extraContext.put("world", world);
|
||||
}
|
||||
return master.exportNodes(new Contexts(ContextSet.fromMap(extraContext), includeGlobal, includeGlobal, applyGroups, true, true, false), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
Loaded 100 of 313 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user