Compare commits

..
28 Commits
Author SHA1 Message Date
Luck cd758d7e48 Bump minor version 2016-10-13 20:40:09 +01:00
Luck fcb0fcadeb Fix StackOverflowException 2016-10-13 20:36:08 +01:00
Luck 26fb506560 Reorganize packages 2016-10-13 20:07:10 +01:00
Luck b6c4239322 Fix NPE 2016-10-13 19:43:48 +01:00
Luck 74f9283f18 Silence exception on #giveDefaultIfNeeded. Resolves #26 2016-10-13 19:25:31 +01:00
Luck 60e6ae6e23 Fix Sponge implementation, remove standalone module 2016-10-13 19:13:34 +01:00
Luck 83d9229295 Refactor caching system (WIP) - still working towards #23 2016-10-12 21:57:57 +01:00
Luck e079b0f3ed Fix meta command showing when a user doesn't have permission to use it 2016-10-11 21:17:04 +01:00
Luck d433a5461d Refactor meta commands, working towards #23 2016-10-11 21:12:10 +01:00
Luck 2c43f6bf21 Fix global permissions and groups sometimes not applying 2016-10-11 19:31:55 +01:00
Luck ac57509a29 Fix prefix/suffix priorities being ignored 2016-10-11 19:31:26 +01:00
Luck c5ce655cf6 Add Vault chat debug messages 2016-10-11 19:06:18 +01:00
Luck 9fe05efb4e Don't force the default group 2016-10-11 18:54:42 +01:00
Luck dcf207f5e5 Fix exception, resolves #20 and #22 2016-10-10 22:39:24 +01:00
Luck 11facab71c Fix NPE, resolves #19 2016-10-10 22:26:39 +01:00
Luck 5b4975f34c Implement persisting subjects (+ defaults) 2016-10-10 18:58:43 +01:00
Luck 069e535f1a Avoid odd behavior where Sponge prevents User subjects from being GCed 2016-10-09 21:34:05 +01:00
Luck 1eb053447e Make refresh calls in SpongeListener run async 2016-10-09 20:49:17 +01:00
Luck 93c7c06b2d Cleanup some Sponge subject classes 2016-10-09 13:14:58 +01:00
Luck b0085bc1e1 Update readme 2016-10-09 10:58:14 +01:00
Luck 9133951446 I'm dumb 2016-10-08 16:45:18 +01:00
Luck 7853d4686a Fix NPE with LPPermissibles & refreshing users 2016-10-08 16:43:57 +01:00
Luck ed5892eb56 add option to ignore vault world parameters 2016-10-08 15:01:54 +01:00
Luck 687804de2c small change to BukkitConfig 2016-10-08 09:05:48 +01:00
Luck 9d166041ab Account for inheritance and wildcards in SimpleSubject 2016-10-07 18:11:59 +01:00
Luck 924041bff4 Add server and world args to clear command, and add clearmeta command 2016-10-06 21:23:27 +01:00
Luck e9216d3e0f Allow the prefix to be modified by the lang file 2016-10-06 19:54:52 +01:00
Luck db8f1bca66 Fix API javadoc & fix Bukkit legacy build 2016-10-06 17:21:04 +01:00
260 changed files with 4547 additions and 5130 deletions

No files matched your search

+6 -3
View File
@@ -14,13 +14,16 @@ LuckPerms is an advanced permissions implementation aiming to be a flexible, per
* [Sponge Plugin Page](https://forums.spongepowered.org/t/luckperms-an-advanced-permissions-system/14274 "Sponge Plugin Page")
## LuckPerms vs Other Plugins
### Bukkit
![alt text](https://static.lucko.me/luckperms-compare-copy.png "Feature comparison")
_Features checked on 23rd Aug 2016. If you find any inaccuracies, please do let me know. I tried to be as fair as possible, and copy all major features from the respective plugin pages._
### Sponge
![alt text](https://static.lucko.me/luckperms-compare-sponge.png "Feature comparison")
_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:
[![JProfiler](https://www.ej-technologies.com/images/product_banners/jprofiler_large.png)](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").
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
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.11-SNAPSHOT</version>
<version>2.12-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -41,14 +41,18 @@ public class Contexts {
* @return a context that will not apply any filters
*/
public static Contexts allowAll() {
return new Contexts(Collections.emptyMap(), true, true, true, true, true);
return new Contexts(Collections.emptyMap(), true, true, true, true, true, true);
}
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);
}
public Contexts(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups) {
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);
}
public Contexts(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
if (context == null) {
throw new NullPointerException("context");
}
@@ -59,6 +63,11 @@ public class Contexts {
this.applyGroups = applyGroups;
this.applyGlobalGroups = applyGlobalGroups;
this.applyGlobalWorldGroups = applyGlobalWorldGroups;
this.op = op;
}
public Contexts(Map<String, String> context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups) {
this(context, includeGlobal, includeGlobalWorld, applyGroups, applyGlobalGroups, applyGlobalWorldGroups, false);
}
/**
@@ -68,6 +77,12 @@ public class Contexts {
*/
private final Map<String, String> 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
*/
@@ -101,6 +116,14 @@ public class Contexts {
return this.context;
}
/**
* 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
@@ -144,6 +167,7 @@ public class Contexts {
public String toString() {
return "Contexts(" +
"context=" + this.getContext() + ", " +
"op=" + this.isOp() + ", " +
"includeGlobal=" + this.isIncludeGlobal() + ", " +
"includeGlobalWorld=" + this.isIncludeGlobalWorld() + ", " +
"applyGroups=" + this.isApplyGroups() + ", " +
@@ -152,4 +176,49 @@ public class Contexts {
")";
}
/*
* 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.getContext();
final Object other$context = other.getContext();
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.getContext();
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;
}
}
@@ -27,7 +27,7 @@ import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* A simple implementation of the listener aspects of {@link IContextCalculator<T>}
* A simple implementation of the listener aspects of {@link IContextCalculator}
* @param <T> the subject type
*/
public abstract class ContextCalculator<T> implements IContextCalculator<T> {
+9 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.11-SNAPSHOT</version>
<version>2.12-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -67,6 +67,14 @@
<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>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.11-SNAPSHOT</version>
<version>2.12-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.11-SNAPSHOT</version>
<version>2.12-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -1,51 +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.cache;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Getter
@RequiredArgsConstructor
public class ChatCache {
private final Map<String, String> context;
@Setter
private String prefix = null;
@Setter
private String suffix = null;
private Map<String, String> meta = new ConcurrentHashMap<>();
public void invalidateCache() {
prefix = null;
suffix = null;
meta.clear();
}
}
@@ -1,181 +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.cache;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.vault.VaultPermissionHook;
import me.lucko.luckperms.users.User;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@RequiredArgsConstructor
public class VaultUser {
private final LPBukkitPlugin plugin;
private final VaultPermissionHook vault;
@Getter
private final User user;
@Getter
private final Map<Map<String, String>, ContextCache> contextData = new ConcurrentHashMap<>();
@Getter
private final Map<Map<String, String>, ChatCache> chatData = new ConcurrentHashMap<>();
public boolean hasPermission(Map<String, String> context, String permission) {
ContextCache cd = contextData.computeIfAbsent(context, map -> calculatePermissions(map, false));
return cd.getPermissionValue(permission).asBoolean();
}
public ChatCache processChatData(Map<String, String> context) {
return chatData.computeIfAbsent(context, map -> calculateChat(map, false));
}
public ContextCache calculatePermissions(Map<String, String> context, boolean apply) {
Map<String, Boolean> toApply = user.exportNodes(
new Contexts(context, vault.isIncludeGlobal(), true, true, true, true),
Collections.emptyList(),
true
);
ContextCache existing = contextData.get(context);
if (existing == null) {
existing = new ContextCache(user, context, plugin, plugin.getDefaultsProvider());
if (apply) {
contextData.put(context, existing);
}
}
boolean different = false;
if (toApply.size() != existing.getPermissionCache().size()) {
different = true;
} else {
for (Map.Entry<String, Boolean> e : existing.getPermissionCache().entrySet()) {
if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) {
continue;
}
different = true;
break;
}
}
if (!different) return existing;
existing.getPermissionCache().clear();
existing.invalidateCache();
existing.getPermissionCache().putAll(toApply);
return existing;
}
public ChatCache calculateChat(Map<String, String> context, boolean apply) {
ChatCache existing = chatData.get(context);
if (existing == null) {
existing = new ChatCache(context);
if (apply) {
chatData.put(context, existing);
}
}
Map<String, String> contexts = new HashMap<>(context);
String server = contexts.get("server");
String world = contexts.get("world");
contexts.remove("server");
contexts.remove("world");
existing.invalidateCache();
// Load meta
for (Node n : user.getPermissions(true)) {
if (!n.getValue()) {
continue;
}
if (!n.isMeta()) {
continue;
}
if (!n.shouldApplyOnServer(server, vault.isIncludeGlobal(), false)) {
continue;
}
if (!n.shouldApplyOnWorld(world, true, false)) {
continue;
}
if (!n.shouldApplyWithContext(contexts, false)) {
continue;
}
Map.Entry<String, String> meta = n.getMeta();
existing.getMeta().put(meta.getKey(), meta.getValue());
}
// Load prefixes & suffixes
int prefixPriority = Integer.MIN_VALUE;
int suffixPriority = Integer.MIN_VALUE;
for (Node n : user.getAllNodes(null, new Contexts(context, vault.isIncludeGlobal(), true, true, true, true))) {
if (!n.getValue()) {
continue;
}
if (!n.isPrefix() && !n.isSuffix()) {
continue;
}
if (!n.shouldApplyOnServer(server, vault.isIncludeGlobal(), false)) {
continue;
}
if (!n.shouldApplyOnWorld(world, true, false)) {
continue;
}
if (!n.shouldApplyWithContext(contexts, false)) {
continue;
}
if (n.isPrefix()) {
Map.Entry<Integer, String> value = n.getPrefix();
if (value.getKey() > prefixPriority) {
existing.setPrefix(value.getValue());
}
} else {
Map.Entry<Integer, String> value = n.getSuffix();
if (value.getKey() > suffixPriority) {
existing.setSuffix(value.getValue());
}
}
}
return existing;
}
}
@@ -1,68 +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.cache;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.api.vault.VaultPermissionHook;
import me.lucko.luckperms.users.User;
import org.bukkit.World;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@RequiredArgsConstructor
public class VaultUserManager {
private final LPBukkitPlugin plugin;
private final VaultPermissionHook vault;
private final Map<UUID, VaultUser> userCache = new ConcurrentHashMap<>();
public void setupUser(User user) {
VaultUser vaultUser = userCache.computeIfAbsent(user.getUuid(), uuid -> new VaultUser(plugin, vault, user));
vaultUser.calculatePermissions(Collections.singletonMap("server", vault.getServer()), true);
vaultUser.calculateChat(Collections.singletonMap("server", vault.getServer()), true);
for (World world : plugin.getServer().getWorlds()) {
Map<String, String> context = new HashMap<>();
context.put("server", vault.getServer());
context.put("world", world.getName());
vaultUser.calculatePermissions(context, true);
vaultUser.calculateChat(context, true);
}
}
public void clearUser(UUID uuid) {
userCache.remove(uuid);
}
public boolean containsUser(UUID uuid) {
return userCache.containsKey(uuid);
}
public VaultUser getUser(UUID uuid) {
return userCache.get(uuid);
}
}
@@ -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);
}
}
@@ -20,14 +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.commands.Util;
import me.lucko.luckperms.constants.Patterns;
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;
@@ -20,15 +20,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms;
package me.lucko.luckperms.bukkit;
import me.lucko.luckperms.config.AbstractConfiguration;
import me.lucko.luckperms.common.config.AbstractConfiguration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@@ -49,13 +47,7 @@ class BukkitConfig extends AbstractConfiguration<LPBukkitPlugin> {
getPlugin().saveResource("config.yml", false);
}
configuration = new YamlConfiguration();
try {
configuration.load(configFile);
} catch (InvalidConfigurationException | IOException e) {
e.printStackTrace();
}
configuration = YamlConfiguration.loadConfiguration(configFile);
}
@Override
@@ -20,23 +20,22 @@
* SOFTWARE.
*/
package me.lucko.luckperms;
package me.lucko.luckperms.bukkit;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.inject.Injector;
import me.lucko.luckperms.inject.LPPermissible;
import me.lucko.luckperms.users.BukkitUser;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.AbstractListener;
import 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.*;
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.Collections;
import java.util.Map;
import java.util.UUID;
class BukkitListener extends AbstractListener implements Listener {
@@ -50,6 +49,7 @@ class BukkitListener extends AbstractListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
if (!plugin.getDatastore().isAcceptingLogins()) {
// The datastore is disabled, prevent players from joining the server
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
return;
@@ -57,38 +57,14 @@ class BukkitListener extends AbstractListener implements Listener {
// Process login
onAsyncLogin(e.getUniqueId(), e.getName());
// Pre-process the user's permissions, so they're ready for PLE.
BukkitUser user = (BukkitUser) plugin.getUserManager().get(plugin.getUuidCache().getUUID(e.getUniqueId()));
Map<String, Boolean> toApply = user.exportNodes(
new Contexts(
Collections.singletonMap("server", plugin.getConfiguration().getServer()),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
plugin.getConfiguration().isApplyingGlobalGroups(),
plugin.getConfiguration().isApplyingGlobalWorldGroups()
),
Collections.emptyList(),
true
);
user.setLoginPreProcess(toApply);
// Hook with Vault early
if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) {
plugin.getVaultHook().getPermissionHook().getVaultUserManager().setupUser(user);
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerPreLoginMonitor(AsyncPlayerPreLoginEvent e) {
if (plugin.getDatastore().isAcceptingLogins() && e.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
// Login event was cancelled by another plugin
final UUID internal = plugin.getUuidCache().getUUID(e.getUniqueId());
onLeave(e.getUniqueId());
if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) {
plugin.getVaultHook().getPermissionHook().getVaultUserManager().clearUser(internal);
}
}
}
@@ -98,61 +74,56 @@ class BukkitListener extends AbstractListener implements Listener {
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;
}
BukkitUser u = (BukkitUser) user;
try {
// Make a new permissible for the user
LPPermissible lpPermissible = new LPPermissible(player, plugin, plugin.getDefaultsProvider());
// Insert the pre-processed permissions into the permissible
lpPermissible.getLuckPermsPermissions().putAll(u.getLoginPreProcess());
u.setLoginPreProcess(null);
LPPermissible lpPermissible = new LPPermissible(player, user, plugin);
// Inject into the player
Injector.inject(player, lpPermissible);
u.setLpPermissible(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.
final UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
onLeave(e.getPlayer().getUniqueId());
if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) {
plugin.getVaultHook().getPermissionHook().getVaultUserManager().clearUser(internal);
}
} else {
User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
// Call another update to calculate full context. (incl. per world permissions)
plugin.doAsync(user::refreshPermissions);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerJoin(PlayerJoinEvent e) {
// Refresh permissions again
UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
plugin.getWorldCalculator().getWorldCache().put(internal, e.getPlayer().getWorld().getName());
plugin.doAsync(() -> refreshPlayer(internal));
}
@EventHandler(priority = EventPriority.LOWEST)
@EventHandler(priority = EventPriority.HIGHEST) // Allow other plugins to see data when this event gets called.
public void onPlayerQuit(PlayerQuitEvent e) {
final UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
final Player player = e.getPlayer();
final UUID internal = plugin.getUuidCache().getUUID(player.getUniqueId());
// Remove from World cache
plugin.getWorldCalculator().getWorldCache().remove(internal);
onLeave(e.getPlayer().getUniqueId());
if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) {
plugin.getVaultHook().getPermissionHook().getVaultUserManager().clearUser(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
@@ -20,10 +20,11 @@
* SOFTWARE.
*/
package me.lucko.luckperms;
package me.lucko.luckperms.bukkit;
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;
@@ -20,33 +20,37 @@
* SOFTWARE.
*/
package me.lucko.luckperms;
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.implementation.ApiProvider;
import me.lucko.luckperms.api.vault.VaultHook;
import me.lucko.luckperms.calculators.DefaultsProvider;
import me.lucko.luckperms.commands.ConsecutiveExecutor;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.config.LPConfiguration;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.contexts.ContextManager;
import me.lucko.luckperms.contexts.ServerCalculator;
import me.lucko.luckperms.contexts.WorldCalculator;
import me.lucko.luckperms.core.UuidCache;
import me.lucko.luckperms.data.Importer;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.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.LocaleManager;
import me.lucko.luckperms.utils.LogFactory;
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.Message;
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.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.Permission;
@@ -66,7 +70,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
private LPConfiguration configuration;
private BukkitUserManager userManager;
private UserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
@@ -79,6 +83,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private LocaleManager localeManager;
private ContextManager<Player> contextManager;
private WorldCalculator worldCalculator;
private CalculatorFactory calculatorFactory;
@Override
public void onEnable() {
@@ -117,18 +122,18 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().isOnlineMode());
userManager = new BukkitUserManager(this);
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()));
contextManager.registerListener(userManager);
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
@@ -157,7 +162,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
getLog().info("Registering API...");
apiProvider = new ApiProvider(this);
LuckPerms.registerProvider(apiProvider);
ApiHandler.registerProvider(apiProvider);
getServer().getServicesManager().register(LuckPermsApi.class, apiProvider, this, ServicePriority.Normal);
// Run update task to refresh any online users
@@ -182,7 +187,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
datastore.shutdown();
getLog().info("Unregistering API...");
LuckPerms.unregisterProvider();
ApiHandler.unregisterProvider();
getServer().getServicesManager().unregisterAll(this);
if (vaultHook != null) {
@@ -233,8 +238,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
@Override
public List<Sender> getNotifyListeners() {
return getServer().getOnlinePlayers().stream()
.map(p -> BukkitSenderFactory.get(this).wrap(p, Collections.singleton(me.lucko.luckperms.constants.Permission.LOG_NOTIFY)))
.filter(me.lucko.luckperms.constants.Permission.LOG_NOTIFY::isAuthorized)
.map(p -> BukkitSenderFactory.get(this).wrap(p, Collections.singleton(me.lucko.luckperms.common.constants.Permission.LOG_NOTIFY)))
.filter(me.lucko.luckperms.common.constants.Permission.LOG_NOTIFY::isAuthorized)
.collect(Collectors.toList());
}
@@ -244,15 +249,68 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
}
@Override
public List<String> getPossiblePermissions() {
final List<String> perms = new ArrayList<>();
public Set<Contexts> getPreProcessContexts(boolean op) {
Set<Map<String, String>> c = new HashSet<>();
c.add(Collections.emptyMap());
c.add(Collections.singletonMap("server", getConfiguration().getServer()));
getServer().getPluginManager().getPermissions().forEach(p -> {
perms.add(p.getName());
p.getChildren().keySet().forEach(perms::add);
});
// Pre process all worlds
c.addAll(getServer().getWorlds().stream()
.map(World::getName)
.map(s -> {
Map<String, String> map = new HashMap<>();
map.put("server", getConfiguration().getServer());
map.put("world", s);
return map;
})
.collect(Collectors.toList())
);
return perms;
// Pre process the separate Vault server, if any
if (!getConfiguration().getServer().equals(getConfiguration().getVaultServer())) {
c.add(Collections.singletonMap("server", getConfiguration().getVaultServer()));
c.addAll(getServer().getWorlds().stream()
.map(World::getName)
.map(s -> {
Map<String, String> map = new HashMap<>();
map.put("server", getConfiguration().getVaultServer());
map.put("world", s);
return map;
})
.collect(Collectors.toList())
);
}
Set<Contexts> contexts = new HashSet<>();
// Convert to full Contexts
contexts.addAll(c.stream()
.map(map -> new Contexts(
map,
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
@@ -290,7 +348,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
Map<String, List<String>> wildcards = new HashMap<>();
List<String> all = new ArrayList<>();
for (me.lucko.luckperms.constants.Permission p : me.lucko.luckperms.constants.Permission.values()) {
for (me.lucko.luckperms.common.constants.Permission p : me.lucko.luckperms.common.constants.Permission.values()) {
pm.addPermission(new Permission(p.getNode(), def));
if (p.getGroup() != null) {
if (!wildcards.containsKey(p.getGroup())) {
@@ -20,13 +20,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.contexts;
package me.lucko.luckperms.bukkit;
import com.google.common.collect.Maps;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.context.ContextCalculator;
import me.lucko.luckperms.common.LuckPermsPlugin;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -20,27 +20,33 @@
* SOFTWARE.
*/
package me.lucko.luckperms.calculators;
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 Map<String, PermissionAttachmentInfo> map;
private final Supplier<Map<String, PermissionAttachmentInfo>> map;
@Override
public Tristate hasPermission(String permission) {
if (map.containsKey(permission)) {
return Tristate.fromBoolean(map.get(permission).getValue());
Map<String, PermissionAttachmentInfo> m = map.get();
if (m == null) {
return Tristate.UNDEFINED;
}
if (m.containsKey(permission)) {
return Tristate.fromBoolean(m.get(permission).getValue());
}
return Tristate.UNDEFINED;
}
@@ -20,30 +20,29 @@
* SOFTWARE.
*/
package me.lucko.luckperms.calculators;
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;
import java.util.function.Supplier;
@AllArgsConstructor
public class DefaultsProcessor implements PermissionProcessor {
private final Supplier<Boolean> isOp;
private final boolean isOp;
private final DefaultsProvider defaultsProvider;
@Override
public Tristate hasPermission(String permission) {
Tristate t = defaultsProvider.hasDefault(permission, isOp.get());
Tristate t = defaultsProvider.hasDefault(permission, isOp);
if (t != Tristate.UNDEFINED) {
return t;
}
Permission defPerm = Bukkit.getServer().getPluginManager().getPermission(permission);
if (defPerm != null) {
return Tristate.fromBoolean(defPerm.getDefault().getValue(isOp.get()));
return Tristate.fromBoolean(defPerm.getDefault().getValue(isOp));
} else {
return Tristate.UNDEFINED;
}
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.calculators;
package me.lucko.luckperms.bukkit.calculators;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.Tristate;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.inject;
package me.lucko.luckperms.bukkit.inject;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.Permission;
@@ -20,37 +20,39 @@
* SOFTWARE.
*/
package me.lucko.luckperms.inject;
package me.lucko.luckperms.bukkit.inject;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.PermissibleBase;
import java.lang.reflect.Field;
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(getInternalClassName("entity.CraftHumanEntity")).getDeclaredField("perm");
HUMAN_ENTITY_FIELD = Class.forName(getVersionedClassName("entity.CraftHumanEntity")).getDeclaredField("perm");
HUMAN_ENTITY_FIELD.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean inject(CommandSender sender, PermissibleBase permissible) {
public static boolean inject(Player player, LPPermissible permissible) {
try {
Field f = getPermField(sender);
f.set(sender, permissible);
HUMAN_ENTITY_FIELD.set(player, permissible);
INJECTED_PERMISSIBLES.put(player.getUniqueId(), permissible);
return true;
} catch (Exception e) {
e.printStackTrace();
@@ -58,15 +60,16 @@ public class Injector {
}
}
public static boolean unInject(CommandSender sender) {
public static boolean unInject(Player player) {
try {
Permissible permissible = getPermissible(sender);
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. */
getPermField(sender).set(sender, new DummyPermissibleBase());
HUMAN_ENTITY_FIELD.set(player, new DummyPermissibleBase());
}
INJECTED_PERMISSIBLES.remove(player.getUniqueId());
return true;
} catch (Exception e) {
e.printStackTrace();
@@ -74,23 +77,11 @@ public class Injector {
}
}
private static Permissible getPermissible(CommandSender sender) {
try {
Field f = getPermField(sender);
return (Permissible) f.get(sender);
} catch (Exception e) {
throw new RuntimeException(e);
}
public static LPPermissible getPermissible(UUID uuid) {
return INJECTED_PERMISSIBLES.get(uuid);
}
private static Field getPermField(CommandSender sender) {
if (sender instanceof Player) {
return HUMAN_ENTITY_FIELD;
}
throw new RuntimeException("Couldn't get perm field for sender " + sender.getClass().getName());
}
private static String getInternalClassName(String className) {
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);
@@ -20,65 +20,64 @@
* SOFTWARE.
*/
package me.lucko.luckperms.inject;
package me.lucko.luckperms.bukkit.inject;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.calculators.*;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import me.lucko.luckperms.common.users.User;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.*;
import org.bukkit.plugin.Plugin;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.stream.Collectors;
/**
* Modified PermissibleBase for LuckPerms
*/
public class LPPermissible extends PermissibleBase {
public class LPPermissible extends PermissibleBase { // TODO autoop stuff
@Getter
private final CommandSender parent;
private final PermissionCalculator calculator;
private final User user;
@Getter
private final Map<String, Boolean> luckPermsPermissions = new ConcurrentHashMap<>();
private final List<PermissionAttachment> attachments = new LinkedList<>();
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 CommandSender sender, LuckPermsPlugin plugin, DefaultsProvider defaultsProvider) {
super(sender);
this.parent = sender;
List<PermissionProcessor> processors = new ArrayList<>(5);
processors.add(new MapProcessor(luckPermsPermissions));
processors.add(new AttachmentProcessor(attachmentPermissions));
if (plugin.getConfiguration().isApplyingWildcards()) {
processors.add(new WildcardProcessor(luckPermsPermissions));
}
if (plugin.getConfiguration().isApplyingRegex()) {
processors.add(new RegexProcessor(luckPermsPermissions));
}
processors.add(new DefaultsProcessor(parent::isOp, defaultsProvider));
calculator = new PermissionCalculator(plugin, parent.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors);
public LPPermissible(@NonNull Player parent, User user, LPBukkitPlugin plugin) {
super(parent);
this.user = user;
this.parent = parent;
this.plugin = plugin;
recalculatePermissions();
}
public void invalidateCache() {
calculator.invalidateCache();
private Contexts calculateContexts() {
return new Contexts(
plugin.getContextManager().giveApplicableContext(parent, new HashMap<>()),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
plugin.getConfiguration().isApplyingGlobalGroups(),
plugin.getConfiguration().isApplyingGlobalWorldGroups(),
parent.isOp()
);
}
@Override
public boolean isOp() {
return parent.isOp();
private boolean hasData() {
return user.getUserData() != null;
}
@Override
@@ -88,7 +87,7 @@ public class LPPermissible extends PermissibleBase {
@Override
public boolean isPermissionSet(@NonNull String name) {
return calculator.getPermissionValue(name) != Tristate.UNDEFINED;
return hasData() && user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(name) != Tristate.UNDEFINED;
}
@Override
@@ -98,9 +97,11 @@ public class LPPermissible extends PermissibleBase {
@Override
public boolean hasPermission(@NonNull String name) {
Tristate ts = calculator.getPermissionValue(name);
if (ts != Tristate.UNDEFINED) {
return ts.asBoolean();
if (hasData()) {
Tristate ts = user.getUserData().getPermissionData(calculateContexts()).getPermissionValue(name);
if (ts != Tristate.UNDEFINED) {
return ts.asBoolean();
}
}
return Permission.DEFAULT_PERMISSION.getValue(isOp());
@@ -108,14 +109,32 @@ public class LPPermissible extends PermissibleBase {
@Override
public boolean hasPermission(@NonNull Permission perm) {
Tristate ts = calculator.getPermissionValue(perm.getName());
if (ts != Tristate.UNDEFINED) {
return ts.asBoolean();
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()) {
@@ -202,7 +221,9 @@ public class LPPermissible extends PermissibleBase {
calculateChildPermissions(attachment.getPermissions(), false, attachment);
}
invalidateCache();
if (hasData()) {
user.getUserData().invalidateCache();
}
}
@Override
@@ -234,18 +255,6 @@ public class LPPermissible extends PermissibleBase {
}
}
@Override
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
Set<PermissionAttachmentInfo> perms = new HashSet<>();
perms.addAll(attachmentPermissions.values());
perms.addAll(luckPermsPermissions.entrySet().stream()
.map(e -> new PermissionAttachmentInfo(parent, e.getKey(), null, e.getValue()))
.collect(Collectors.toList()));
return perms;
}
private class RemoveAttachmentRunnable implements Runnable {
private PermissionAttachment attachment;
@@ -20,18 +20,18 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.vault;
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.vault.cache.ChatCache;
import me.lucko.luckperms.api.vault.cache.VaultUser;
import me.lucko.luckperms.core.PermissionHolder;
import me.lucko.luckperms.common.caching.MetaData;
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.common.utils.ArgumentChecker;
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.chat.Chat;
import java.util.HashMap;
@@ -39,8 +39,8 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static me.lucko.luckperms.utils.ArgumentChecker.escapeCharacters;
import static me.lucko.luckperms.utils.ArgumentChecker.unescapeCharacters;
import static me.lucko.luckperms.common.utils.ArgumentChecker.escapeCharacters;
import static me.lucko.luckperms.common.utils.ArgumentChecker.unescapeCharacters;
/**
* Provides the Vault Chat service through the use of normal permission nodes.
@@ -56,7 +56,7 @@ import static me.lucko.luckperms.utils.ArgumentChecker.unescapeCharacters;
* Permission Nodes = meta.node.value
*
* Node that special characters used within LuckPerms are escaped:
* See {@link me.lucko.luckperms.utils.ArgumentChecker#escapeCharacters(String)}
* See {@link ArgumentChecker#escapeCharacters(String)}
*/
public class VaultChatHook extends Chat {
private final VaultPermissionHook perms;
@@ -74,11 +74,14 @@ public class VaultChatHook extends Chat {
return perms.isEnabled();
}
private void saveMeta(PermissionHolder holder, String world, String node, String value) {
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.scheduleTask(() -> {
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);
@@ -92,12 +95,12 @@ public class VaultChatHook extends Chat {
} catch (ObjectLacksException ignored) {}
});
Node.Builder metaNode = new me.lucko.luckperms.core.Node.Builder("meta." + k + "." + v).setValue(true);
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 (world != null && !world.equals("")) {
metaNode.setServer(perms.getServer()).setWorld(world);
if (finalWorld != null && !finalWorld.equals("")) {
metaNode.setServer(perms.getServer()).setWorld(finalWorld);
}
try {
@@ -109,18 +112,21 @@ public class VaultChatHook extends Chat {
}
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.scheduleTask(() -> {
Node.Builder node = new me.lucko.luckperms.core.Node.Builder(prefix ? "prefix" : "suffix" + ".1000." + escapeCharacters(value));
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 (world != null && !world.equals("")) {
node.setServer(perms.getServer()).setWorld(world);
if (finalWorld != null && !finalWorld.equals("")) {
node.setServer(perms.getServer()).setWorld(finalWorld);
}
try {
@@ -133,46 +139,41 @@ public class VaultChatHook extends Chat {
private String getUserMeta(User user, String world, String node, String defaultValue) {
if (user == null) return defaultValue;
world = perms.isIgnoreWorld() ? null : world;
node = escapeCharacters(node);
if (!perms.getVaultUserManager().containsUser(user.getUuid())) {
perms.log("Getting meta: '" + node + "' for user " + user.getName() + " on world " + world + ", server " + perms.getServer());
if (user.getUserData() == null) {
return defaultValue;
}
VaultUser vaultUser = perms.getVaultUserManager().getUser(user.getUuid());
Map<String, String> context = new HashMap<>();
context.put("server", perms.getServer());
if (world != null) {
context.put("world", world);
}
ChatCache cd = vaultUser.processChatData(context);
return unescapeCharacters(cd.getMeta().getOrDefault(node, 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;
if (!perms.getVaultUserManager().containsUser(user.getUuid())) {
perms.log("Getting " + (prefix ? "prefix" : "suffix") + " for user " + user.getName() + " on world " + world + ", server " + perms.getServer());
if (user.getUserData() == null) {
return "";
}
VaultUser vaultUser = perms.getVaultUserManager().getUser(user.getUuid());
Map<String, String> context = new HashMap<>();
context.put("server", perms.getServer());
if (world != null) {
context.put("world", world);
}
ChatCache cd = vaultUser.processChatData(context);
return unescapeCharacters(prefix ? (cd.getPrefix() == null ? "" : cd.getPrefix()) : (cd.getSuffix() == null ? "" : cd.getSuffix()));
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;
@@ -200,8 +201,11 @@ public class VaultChatHook extends Chat {
}
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;
@@ -289,7 +293,7 @@ public class VaultChatHook extends Chat {
public void setPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int value) {
final User user = perms.getPlugin().getUserManager().get(player);
saveMeta(user, world, node, String.valueOf(value));
setMeta(user, world, node, String.valueOf(value));
}
public int getGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int defaultValue) {
@@ -303,7 +307,7 @@ public class VaultChatHook extends Chat {
public void setGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int value) {
final Group g = perms.getPlugin().getGroupManager().get(group);
saveMeta(g, world, node, String.valueOf(value));
setMeta(g, world, node, String.valueOf(value));
}
public double getPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double defaultValue) {
@@ -317,7 +321,7 @@ public class VaultChatHook extends Chat {
public void setPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double value) {
final User user = perms.getPlugin().getUserManager().get(player);
saveMeta(user, world, node, String.valueOf(value));
setMeta(user, world, node, String.valueOf(value));
}
public double getGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double defaultValue) {
@@ -331,7 +335,7 @@ public class VaultChatHook extends Chat {
public void setGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double value) {
final Group g = perms.getPlugin().getGroupManager().get(group);
saveMeta(g, world, node, String.valueOf(value));
setMeta(g, world, node, String.valueOf(value));
}
public boolean getPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean defaultValue) {
@@ -345,7 +349,7 @@ public class VaultChatHook extends Chat {
public void setPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean value) {
final User user = perms.getPlugin().getUserManager().get(player);
saveMeta(user, world, node, String.valueOf(value));
setMeta(user, world, node, String.valueOf(value));
}
public boolean getGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean defaultValue) {
@@ -359,7 +363,7 @@ public class VaultChatHook extends Chat {
public void setGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean value) {
final Group g = perms.getPlugin().getGroupManager().get(group);
saveMeta(g, world, node, String.valueOf(value));
setMeta(g, world, node, String.valueOf(value));
}
public String getPlayerInfoString(String world, @NonNull String player, @NonNull String node, String defaultValue) {
@@ -369,7 +373,7 @@ public class VaultChatHook extends Chat {
public void setPlayerInfoString(String world, @NonNull String player, @NonNull String node, String value) {
final User user = perms.getPlugin().getUserManager().get(player);
saveMeta(user, world, node, value);
setMeta(user, world, node, value);
}
public String getGroupInfoString(String world, @NonNull String group, @NonNull String node, String defaultValue) {
@@ -379,7 +383,7 @@ public class VaultChatHook extends Chat {
public void setGroupInfoString(String world, @NonNull String group, @NonNull String node, String value) {
final Group g = perms.getPlugin().getGroupManager().get(group);
saveMeta(g, world, node, value);
setMeta(g, world, node, value);
}
}
@@ -20,10 +20,10 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.vault;
package me.lucko.luckperms.bukkit.vault;
import lombok.Getter;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import net.milkbowl.vault.chat.Chat;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.plugin.ServicePriority;
@@ -42,6 +42,7 @@ public class VaultHook {
permissionHook.setPlugin(plugin);
permissionHook.setServer(plugin.getConfiguration().getVaultServer());
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIncludingGlobal());
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIgnoreWorld());
permissionHook.setup();
if (chatHook == null) {
@@ -20,38 +20,37 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.vault;
package me.lucko.luckperms.bukkit.vault;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.vault.cache.VaultUser;
import me.lucko.luckperms.api.vault.cache.VaultUserManager;
import me.lucko.luckperms.core.PermissionHolder;
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 me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import net.milkbowl.vault.permission.Permission;
import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* The LuckPerms Vault Permission implementation
* Most lookups are cached.
*/
public class VaultPermissionHook extends Permission implements Runnable {
private final List<Runnable> tasks = new ArrayList<>();
public class VaultPermissionHook extends Permission {
@Getter
@Setter
private LPBukkitPlugin plugin;
@Getter
private VaultUserManager vaultUserManager;
private VaultScheduler scheduler;
@Getter
@Setter
@@ -61,9 +60,12 @@ public class VaultPermissionHook extends Permission implements Runnable {
@Setter
private boolean includeGlobal = true;
@Getter
@Setter
private boolean ignoreWorld = false;
public void setup() {
vaultUserManager = new VaultUserManager(plugin, this);
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, this, 1L, 1L);
scheduler = new VaultScheduler(plugin);
}
public void log(String s) {
@@ -72,23 +74,6 @@ public class VaultPermissionHook extends Permission implements Runnable {
}
}
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);
}
@Override
public String getName() {
return "LuckPerms";
@@ -104,133 +89,156 @@ public class VaultPermissionHook extends Permission implements Runnable {
return true;
}
private boolean objectHas(String world, Group group, String permission) {
if (group == null) return false;
/**
* 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) {
((User) holder).refreshPermissions();
plugin.getDatastore().saveUser(((User) holder));
}
if (holder instanceof Group) {
plugin.getDatastore().saveGroup(((Group) holder));
plugin.runUpdateTask();
}
}
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);
Map<String, Boolean> toApply = group.exportNodes(
new Contexts(context, includeGlobal, includeGlobal, true, true, true),
Collections.emptyList(), true
);
return toApply.containsKey(permission) && toApply.get(permission);
}
private boolean add(String world, PermissionHolder object, String permission) {
if (object == null) return false;
try {
if (world != null && !world.equals("")) {
object.setPermission(permission, true, server, world);
} else {
object.setPermission(permission, true, server);
}
} catch (ObjectAlreadyHasException ignored) {}
save(object);
return true;
}
private boolean remove(String world, PermissionHolder object, String permission) {
if (object == null) return false;
try {
if (world != null && !world.equals("")) {
object.unsetPermission(permission, server, world);
} else {
object.unsetPermission(permission, server);
}
} catch (ObjectLacksException ignored) {}
save(object);
return true;
}
void save(PermissionHolder t) {
if (t instanceof User) {
((User) t).refreshPermissions();
plugin.getDatastore().saveUser(((User) t));
}
if (t instanceof Group) {
plugin.getDatastore().saveGroup(((Group) t));
plugin.runUpdateTask();
}
return new Contexts(context, isIncludeGlobal(), true, true, true, true);
}
@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 (!vaultUserManager.containsUser(user.getUuid())) {
if (user.getUserData() == null) {
return false;
}
VaultUser vaultUser = vaultUserManager.getUser(user.getUuid());
Map<String, String> context = new HashMap<>();
context.put("server", server);
if (world != null) {
context.put("world", world);
}
return vaultUser.hasPermission(context, permission);
// 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) {
log("Adding permission to player " + player + ": '" + permission + "' on world " + world + ", server " + server);
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);
scheduleTask(() -> add(world, user, permission));
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) {
log("Removing permission from player " + player + ": '" + permission + "' on world " + world + ", server " + server);
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);
scheduleTask(() -> remove(world, user, permission));
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);
return objectHas(world, group, permission);
if (group == null) return false;
// This is a nasty call. Groups aren't cached. :(
Map<String, Boolean> permissions = group.exportNodes(createContext(server, world), Collections.emptyList(), true);
return permissions.containsKey(permission) && permissions.get(permission);
}
@Override
public boolean groupAdd(String world, @NonNull String groupName, @NonNull String permission) {
log("Adding permission to group " + groupName + ": '" + permission + "' on world " + world + ", server " + server);
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);
scheduleTask(() -> add(world, group, permission));
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) {
log("Removing permission from group " + groupName + ": '" + permission + "' on world " + world + ", server " + server);
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);
scheduleTask(() -> remove(world, group, permission));
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) {
log("Checking if player " + player + " is in group: " + group + " on world " + world + ", server " + server);
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(world, true, false))
.filter(n -> n.shouldApplyOnWorld(finalWorld, true, false))
.map(Node::getGroupName)
.filter(s -> s.equalsIgnoreCase(group))
.findAny().isPresent();
@@ -238,17 +246,19 @@ public class VaultPermissionHook extends Permission implements Runnable {
@Override
public boolean playerAddGroup(String world, @NonNull String player, @NonNull String groupName) {
log("Adding player " + player + " to group: '" + groupName + "' on world " + world + ", server " + server);
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;
scheduleTask(() -> {
scheduler.scheduleTask(() -> {
try {
if (world != null && !world.equals("")) {
user.addGroup(group, server, world);
if (finalWorld != null && !finalWorld.equals("")) {
user.addGroup(group, server, finalWorld);
} else {
user.addGroup(group, server);
}
@@ -260,17 +270,19 @@ public class VaultPermissionHook extends Permission implements Runnable {
@Override
public boolean playerRemoveGroup(String world, @NonNull String player, @NonNull String groupName) {
log("Removing player " + player + " from group: '" + groupName + "' on world " + world + ", server " + server);
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;
scheduleTask(() -> {
scheduler.scheduleTask(() -> {
try {
if (world != null && !world.equals("")) {
user.removeGroup(group, server, world);
if (finalWorld != null && !finalWorld.equals("")) {
user.removeGroup(group, server, finalWorld);
} else {
user.removeGroup(group, server);
}
@@ -282,14 +294,16 @@ public class VaultPermissionHook extends Permission implements Runnable {
@Override
public String[] getPlayerGroups(String world, @NonNull String player) {
log("Getting groups of player: " + player + ", on world " + world + ", server " + server);
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(world, true, false))
.filter(n -> n.shouldApplyOnWorld(finalWorld, true, false))
.map(Node::getGroupName)
.toArray(String[]::new);
}
@@ -20,26 +20,34 @@
* SOFTWARE.
*/
package me.lucko.luckperms.contexts;
package me.lucko.luckperms.bukkit.vault;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.sponge.LuckPermsUserSubject;
import me.lucko.luckperms.api.sponge.collections.UserCollection;
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;
@AllArgsConstructor
public class ContextUpdateTask implements Runnable {
private final UserCollection userCollection;
public class VaultScheduler implements Runnable {
private final List<Runnable> tasks = new ArrayList<>();
@Override
public void run() {
for (LuckPermsUserSubject subject : userCollection.getUsers().values()) {
Set<Map<String, String>> contexts = new HashSet<>(subject.getContextData().keySet());
contexts.forEach(map -> subject.calculatePermissions(map, true));
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,135 +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.Contexts;
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import me.lucko.luckperms.inject.LPPermissible;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class BukkitUser extends User {
private final LPBukkitPlugin plugin;
@Getter
@Setter
private LPPermissible lpPermissible = null;
@Getter
@Setter
private Map<String, Boolean> loginPreProcess = 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;
}
public boolean isOp() {
return lpPermissible != null && lpPermissible.isOp();
}
@SuppressWarnings("unchecked")
@Override
public synchronized void refreshPermissions() {
if (lpPermissible == 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 = exportNodes(
new Contexts(
plugin.getContextManager().giveApplicableContext((Player) lpPermissible.getParent(), new HashMap<>()),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
plugin.getConfiguration().isApplyingGlobalGroups(),
plugin.getConfiguration().isApplyingGlobalWorldGroups()
),
Collections.emptyList(),
true
);
try {
Map<String, Boolean> existing = lpPermissible.getLuckPermsPermissions();
boolean different = false;
if (toApply.size() != existing.size()) {
different = true;
} else {
for (Map.Entry<String, Boolean> e : existing.entrySet()) {
if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) {
continue;
}
different = true;
break;
}
}
if (!different) return;
existing.clear();
lpPermissible.invalidateCache();
existing.putAll(toApply);
if (plugin.getConfiguration().isAutoOp()) {
boolean op = false;
for (Map.Entry<String, Boolean> e : toApply.entrySet()) {
if (e.getKey().equalsIgnoreCase("luckperms.autoop") && e.getValue()) {
op = true;
break;
}
}
final boolean finalOp = op;
if (lpPermissible.isOp() != op) {
final Permissible parent = lpPermissible.getParent();
plugin.doSync(() -> parent.setOp(finalOp));
}
}
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
} catch (Exception e) {
e.printStackTrace();
}
if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) {
plugin.getVaultHook().getPermissionHook().getVaultUserManager().setupUser(this);
}
}
}
@@ -1,97 +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.LPBukkitPlugin;
import me.lucko.luckperms.api.context.ContextListener;
import me.lucko.luckperms.inject.Injector;
import org.bukkit.entity.Player;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class BukkitUserManager extends UserManager implements ContextListener<Player> {
private final LPBukkitPlugin plugin;
public BukkitUserManager(LPBukkitPlugin plugin) {
super(plugin);
this.plugin = plugin;
}
@Override
public void preUnload(User user) {
if (user instanceof BukkitUser) {
BukkitUser u = (BukkitUser) user;
Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid()));
if (player != null) {
if (u.getLpPermissible() != null) {
Injector.unInject(player); // TODO is this needed?
u.setLpPermissible(null);
}
if (plugin.getConfiguration().isAutoOp()) {
player.setOp(false);
}
}
}
}
@Override
public void cleanup(User user) {
if (plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) {
unload(user);
}
}
@Override
public User apply(UserIdentifier id) {
BukkitUser user = id.getUsername() == null ?
new BukkitUser(id.getUuid(), plugin) :
new BukkitUser(id.getUuid(), id.getUsername(), plugin);
giveDefaultIfNeeded(user, false);
return user;
}
@Override
public void updateAllUsers() {
// Sometimes called async, as we need to get the players on the Bukkit thread.
plugin.doSync(() -> {
Set<UUID> players = plugin.getServer().getOnlinePlayers().stream()
.map(p -> plugin.getUuidCache().getUUID(p.getUniqueId()))
.collect(Collectors.toSet());
plugin.doAsync(() -> players.forEach(u -> plugin.getDatastore().loadUser(u, "null")));
});
}
@Override
public void onContextChange(Player subject, Map.Entry<String, String> before, Map.Entry<String, String> current) throws Exception {
UUID internal = plugin.getUuidCache().getUUID(subject.getUniqueId());
User user = get(internal);
if (user != null) {
plugin.doAsync(user::refreshPermissions);
}
}
}
+3
View File
@@ -80,6 +80,9 @@ 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:
+1 -1
View File
@@ -4,7 +4,7 @@ description: A permissions plugin
author: Luck
website: https://github.com/lucko/LuckPerms
main: me.lucko.luckperms.LPBukkitPlugin
main: me.lucko.luckperms.bukkit.LPBukkitPlugin
softdepend: [Vault, PermissionsEx, GroupManager, PowerfulPerms, zPermissions, bPermissions] # For migration
commands:
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.11-SNAPSHOT</version>
<version>2.12-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.contexts;
package me.lucko.luckperms.bungee;
import com.google.common.collect.Maps;
import me.lucko.luckperms.api.context.ContextCalculator;
@@ -20,41 +20,32 @@
* SOFTWARE.
*/
package me.lucko.luckperms;
package me.lucko.luckperms.bungee;
import lombok.Getter;
import me.lucko.luckperms.calculators.*;
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;
import java.util.concurrent.ConcurrentHashMap;
public class BungeePlayerCache {
@AllArgsConstructor
public class BungeeCalculatorFactory implements CalculatorFactory {
private final LPBungeePlugin plugin;
private final PermissionCalculator calculator;
@Getter
private final Map<String, Boolean> permissions = new ConcurrentHashMap<>();
public BungeePlayerCache(LuckPermsPlugin plugin, String name) {
@Override
public PermissionCalculator build(Contexts contexts, User user, Map<String, Boolean> map) {
List<PermissionProcessor> processors = new ArrayList<>(3);
processors.add(new MapProcessor(permissions));
processors.add(new MapProcessor(map));
if (plugin.getConfiguration().isApplyingWildcards()) {
processors.add(new WildcardProcessor(permissions));
processors.add(new WildcardProcessor(map));
}
if (plugin.getConfiguration().isApplyingRegex()) {
processors.add(new RegexProcessor(permissions));
processors.add(new RegexProcessor(map));
}
calculator = new PermissionCalculator(plugin, name, plugin.getConfiguration().isDebugPermissionChecks(), processors);
}
public void invalidateCache() {
calculator.invalidateCache();
}
public boolean getPermissionValue(String permission) {
return calculator.getPermissionValue(permission).asBoolean();
return new PermissionCalculator(plugin, user.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors);
}
}
@@ -20,14 +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.commands.Util;
import me.lucko.luckperms.constants.Patterns;
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;
@@ -20,9 +20,9 @@
* SOFTWARE.
*/
package me.lucko.luckperms;
package me.lucko.luckperms.bungee;
import me.lucko.luckperms.config.AbstractConfiguration;
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;
@@ -20,12 +20,14 @@
* 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.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;
@@ -36,6 +38,7 @@ import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@@ -58,12 +61,26 @@ public class BungeeListener extends AbstractListener implements Listener {
final ProxiedPlayer player = ((ProxiedPlayer) e.getSender());
BungeePlayerCache playerCache = plugin.getPlayerCache().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
if (playerCache == null) {
User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
if (user == null) {
return;
}
e.setHasPermission(playerCache.getPermissionValue(e.getPermission()));
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, new HashMap<>()),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
plugin.getConfiguration().isApplyingGlobalGroups(),
plugin.getConfiguration().isApplyingGlobalWorldGroups()
);
e.setHasPermission(user.getUserData().getPermissionData(contexts).getPermissionValue(e.getPermission()).asBoolean());
}
@EventHandler
@@ -83,10 +100,16 @@ public class BungeeListener extends AbstractListener implements Listener {
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());
}
} else {
UUID uuid = plugin.getDatastore().getUUID(c.getName());
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());
}
@@ -94,6 +117,13 @@ public class BungeeListener extends AbstractListener implements Listener {
// 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());
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.");
@@ -105,20 +135,15 @@ public class BungeeListener extends AbstractListener implements Listener {
@EventHandler
public void onPlayerPostLogin(PostLoginEvent e) {
final ProxiedPlayer player = e.getPlayer();
final UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
final User user = plugin.getUserManager().get(internal);
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
if (user == null) {
plugin.getProxy().getScheduler().schedule(plugin, () -> player.sendMessage(WARN_MESSAGE), 3, TimeUnit.SECONDS);
} else {
plugin.getPlayerCache().put(internal, new BungeePlayerCache(plugin, e.getPlayer().getName()));
user.refreshPermissions();
}
}
@EventHandler
public void onPlayerQuit(PlayerDisconnectEvent e) {
plugin.getPlayerCache().remove(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
onLeave(e.getPlayer().getUniqueId());
}
}
@@ -20,10 +20,11 @@
* SOFTWARE.
*/
package me.lucko.luckperms;
package me.lucko.luckperms.bungee;
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;
@@ -20,32 +20,36 @@
* SOFTWARE.
*/
package me.lucko.luckperms;
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.implementation.ApiProvider;
import me.lucko.luckperms.commands.CommandManager;
import me.lucko.luckperms.commands.ConsecutiveExecutor;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.config.LPConfiguration;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.contexts.BackendServerCalculator;
import me.lucko.luckperms.contexts.ContextManager;
import me.lucko.luckperms.contexts.ServerCalculator;
import me.lucko.luckperms.core.UuidCache;
import me.lucko.luckperms.data.Importer;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.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.utils.LocaleManager;
import me.lucko.luckperms.utils.LogFactory;
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.Message;
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.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;
@@ -57,10 +61,9 @@ import java.util.stream.Collectors;
@Getter
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
private final Map<UUID, BungeePlayerCache> playerCache = new ConcurrentHashMap<>();
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
private LPConfiguration configuration;
private BungeeUserManager userManager;
private UserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
@@ -71,6 +74,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
private ConsecutiveExecutor consecutiveExecutor;
private LocaleManager localeManager;
private ContextManager<ProxiedPlayer> contextManager;
private CalculatorFactory calculatorFactory;
@Override
public void onEnable() {
@@ -105,18 +109,18 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().isOnlineMode());
userManager = new BungeeUserManager(this);
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()));
contextManager.registerListener(userManager);
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
@@ -130,7 +134,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
getLog().info("Registering API...");
apiProvider = new ApiProvider(this);
LuckPerms.registerProvider(apiProvider);
ApiHandler.registerProvider(apiProvider);
// Run update task to refresh any online users
getLog().info("Scheduling Update Task to refresh any online users.");
@@ -149,7 +153,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
datastore.shutdown();
getLog().info("Unregistering API...");
LuckPerms.unregisterProvider();
ApiHandler.unregisterProvider();
}
@Override
@@ -196,9 +200,31 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
}
@Override
public List<String> getPossiblePermissions() {
// No such thing on Bungee. Wildcards are processed in the listener instead.
return Collections.emptyList();
public Set<Contexts> getPreProcessContexts(boolean op) {
Set<Map<String, String>> c = new HashSet<>();
c.add(Collections.emptyMap());
c.add(Collections.singletonMap("server", getConfiguration().getServer()));
c.addAll(getProxy().getServers().values().stream()
.map(ServerInfo::getName)
.map(s -> {
Map<String, String> map = new HashMap<>();
map.put("server", getConfiguration().getServer());
map.put("world", s);
return map;
})
.collect(Collectors.toList())
);
return c.stream()
.map(map -> new Contexts(
map,
getConfiguration().isIncludingGlobalPerms(),
getConfiguration().isIncludingGlobalWorldPerms(),
true,
getConfiguration().isApplyingGlobalGroups(),
getConfiguration().isApplyingGlobalWorldGroups()
))
.collect(Collectors.toSet());
}
@Override
@@ -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.users;
import me.lucko.luckperms.BungeePlayerCache;
import me.lucko.luckperms.LPBungeePlugin;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class BungeeUser extends User {
private final LPBungeePlugin plugin;
BungeeUser(UUID uuid, LPBungeePlugin plugin) {
super(uuid, plugin);
this.plugin = plugin;
}
BungeeUser(UUID uuid, String username, LPBungeePlugin plugin) {
super(uuid, username, plugin);
this.plugin = plugin;
}
@Override
public synchronized void refreshPermissions() {
ProxiedPlayer player = plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid()));
if (player == null) {
return;
}
BungeePlayerCache playerCache = plugin.getPlayerCache().get(getUuid());
if (playerCache == null) {
return;
}
// Calculate the permissions that should be applied. This is done async.
Map<String, Boolean> toApply = exportNodes(
new Contexts(
plugin.getContextManager().giveApplicableContext(player, new HashMap<>()),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
plugin.getConfiguration().isApplyingGlobalGroups(),
plugin.getConfiguration().isApplyingGlobalWorldGroups()
),
Collections.emptyList(),
true
);
Map<String, Boolean> existing = playerCache.getPermissions();
boolean different = false;
if (toApply.size() != existing.size()) {
different = true;
} else {
for (Map.Entry<String, Boolean> e : existing.entrySet()) {
if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) {
continue;
}
different = true;
break;
}
}
if (!different) return;
existing.clear();
playerCache.invalidateCache();
existing.putAll(toApply);
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
}
}
@@ -1,72 +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 me.lucko.luckperms.api.context.ContextListener;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.Map;
import java.util.UUID;
public class BungeeUserManager extends UserManager implements ContextListener<ProxiedPlayer> {
private final LPBungeePlugin plugin;
public BungeeUserManager(LPBungeePlugin plugin) {
super(plugin);
this.plugin = plugin;
}
@Override
public void cleanup(User user) {
if (plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) {
unload(user);
}
}
@Override
public User apply(UserIdentifier id) {
BungeeUser user = id.getUsername() == null ?
new BungeeUser(id.getUuid(), plugin) :
new BungeeUser(id.getUuid(), id.getUsername(), plugin);
giveDefaultIfNeeded(user, false);
return user;
}
@Override
public void updateAllUsers() {
plugin.getProxy().getPlayers().stream()
.map(p -> plugin.getUuidCache().getUUID(p.getUniqueId()))
.forEach(u -> plugin.getDatastore().loadUser(u, "null"));
}
@Override
public void onContextChange(ProxiedPlayer subject, Map.Entry<String, String> before, Map.Entry<String, String> current) throws Exception {
UUID internal = plugin.getUuidCache().getUUID(subject.getUniqueId());
User user = get(internal);
if (user != null) {
plugin.doAsync(user::refreshPermissions);
}
}
}
+1 -1
View File
@@ -2,5 +2,5 @@ name: LuckPerms
version: ${release.version}.${git.closest.tag.commit.count}
description: A permissions plugin
author: Luck
main: me.lucko.luckperms.LPBungeePlugin
main: me.lucko.luckperms.bungee.LPBungeePlugin
softdepends: [PowerfulPerms] # For migration
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.11-SNAPSHOT</version>
<version>2.12-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -20,8 +20,18 @@
* SOFTWARE.
*/
package me.lucko.luckperms.gui;
package me.lucko.luckperms;
import me.lucko.luckperms.api.LuckPermsApi;
public class ApiHandler {
public static void registerProvider(LuckPermsApi luckPermsApi) {
LuckPerms.registerProvider(luckPermsApi);
}
public static void unregisterProvider() {
LuckPerms.unregisterProvider();
}
public class InterfaceManager {
// TODO
}
@@ -1,50 +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.groups.Group;
import java.util.List;
public class GroupClear extends SubCommand<Group> {
public GroupClear() {
super("clear", "Clears the group's permissions", Permission.GROUP_CLEAR, Predicate.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
group.clearNodes();
Message.CLEAR_SUCCESS.send(sender, group.getDisplayName());
LogEntry.build().actor(sender).acted(group).action("clear").build().submit(plugin, sender);
save(group, sender, plugin);
return CommandResult.SUCCESS;
}
}
@@ -1,153 +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.api.Node;
import me.lucko.luckperms.commands.*;
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.ArrayList;
import java.util.List;
public class GroupRemovePrefix extends SubCommand<Group> {
public GroupRemovePrefix() {
super("removeprefix", "Removes a prefix from the group", Permission.GROUP_REMOVEPREFIX, Predicate.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to remove the prefix at"),
Arg.create("prefix", true, "the prefix string to remove"),
Arg.create("server", false, "the server to remove the prefix on"),
Arg.create("world", false, "the world to remove the prefix on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
final String prefix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
if (prefix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
if (args.size() >= 3) {
server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 3) {
world = args.get(3).toLowerCase();
}
}
List<Node> toRemove = new ArrayList<>();
for (Node node : group.getNodes()) {
if (!node.isPrefix()) continue;
if (node.getPrefix().getKey() != priority) continue;
if (node.isTemporary()) continue;
if (node.getServer().isPresent()) {
if (server == null) continue;
if (!node.getServer().get().equalsIgnoreCase(server)) continue;
} else {
if (server != null) continue;
}
if (node.getWorld().isPresent()) {
if (world == null) continue;
if (!node.getWorld().get().equalsIgnoreCase(world)) continue;
} else {
if (world != null) continue;
}
toRemove.add(node);
}
toRemove.forEach(n -> {
try {
group.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
});
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
save(group, sender, plugin);
return CommandResult.SUCCESS;
} else {
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
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.unsetPermission(node, server);
Message.REMOVEPREFIX_SERVER_SUCCESS.send(sender, group.getDisplayName(), prefix, priority, server);
LogEntry.build().actor(sender).acted(group)
.action("removeprefix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
group.unsetPermission(node, server, world);
Message.REMOVEPREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), prefix, priority, server, world);
LogEntry.build().actor(sender).acted(group)
.action("removeprefix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
group.unsetPermission(node);
Message.REMOVEPREFIX_SUCCESS.send(sender, group.getDisplayName(), prefix, priority);
LogEntry.build().actor(sender).acted(group)
.action("removeprefix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_PREFIX.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
}
}
@@ -1,153 +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.api.Node;
import me.lucko.luckperms.commands.*;
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.ArrayList;
import java.util.List;
public class GroupRemoveSuffix extends SubCommand<Group> {
public GroupRemoveSuffix() {
super("removesuffix", "Removes a suffix from the group", Permission.GROUP_REMOVESUFFIX, Predicate.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to remove the suffix at"),
Arg.create("suffix", true, "the suffix string to remove"),
Arg.create("server", false, "the server to remove the suffix on"),
Arg.create("world", false, "the world to remove the suffix on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
final String suffix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
if (suffix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
if (args.size() >= 3) {
server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 3) {
world = args.get(3).toLowerCase();
}
}
List<Node> toRemove = new ArrayList<>();
for (Node node : group.getNodes()) {
if (!node.isSuffix()) continue;
if (node.getSuffix().getKey() != priority) continue;
if (node.isTemporary()) continue;
if (node.getServer().isPresent()) {
if (server == null) continue;
if (!node.getServer().get().equalsIgnoreCase(server)) continue;
} else {
if (server != null) continue;
}
if (node.getWorld().isPresent()) {
if (world == null) continue;
if (!node.getWorld().get().equalsIgnoreCase(world)) continue;
} else {
if (world != null) continue;
}
toRemove.add(node);
}
toRemove.forEach(n -> {
try {
group.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
});
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
save(group, sender, plugin);
return CommandResult.SUCCESS;
} else {
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
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.unsetPermission(node, server);
Message.REMOVESUFFIX_SERVER_SUCCESS.send(sender, group.getDisplayName(), suffix, priority, server);
LogEntry.build().actor(sender).acted(group)
.action("removesuffix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
group.unsetPermission(node, server, world);
Message.REMOVESUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), suffix, priority, server, world);
LogEntry.build().actor(sender).acted(group)
.action("removesuffix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
group.unsetPermission(node);
Message.REMOVESUFFIX_SUCCESS.send(sender, group.getDisplayName(), suffix, priority);
LogEntry.build().actor(sender).acted(group)
.action("removesuffix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_SUFFIX.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
}
}
@@ -1,154 +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.api.Node;
import me.lucko.luckperms.commands.*;
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.ArrayList;
import java.util.List;
public class GroupRemoveTempPrefix extends SubCommand<Group> {
public GroupRemoveTempPrefix() {
super("removetempprefix", "Removes a temporary prefix from the group", Permission.GROUP_REMOVE_TEMP_PREFIX,
Predicate.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to remove the prefix at"),
Arg.create("prefix", true, "the prefix string to remove"),
Arg.create("server", false, "the server to remove the prefix on"),
Arg.create("world", false, "the world to remove the prefix on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
final String prefix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
if (prefix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
if (args.size() >= 3) {
server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 3) {
world = args.get(3).toLowerCase();
}
}
List<Node> toRemove = new ArrayList<>();
for (Node node : group.getNodes()) {
if (!node.isPrefix()) continue;
if (node.getPrefix().getKey() != priority) continue;
if (node.isPermanent()) continue;
if (node.getServer().isPresent()) {
if (server == null) continue;
if (!node.getServer().get().equalsIgnoreCase(server)) continue;
} else {
if (server != null) continue;
}
if (node.getWorld().isPresent()) {
if (world == null) continue;
if (!node.getWorld().get().equalsIgnoreCase(world)) continue;
} else {
if (world != null) continue;
}
toRemove.add(node);
}
toRemove.forEach(n -> {
try {
group.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
});
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
save(group, sender, plugin);
return CommandResult.SUCCESS;
} else {
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
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.unsetPermission(node, server, true);
Message.REMOVE_TEMP_PREFIX_SERVER_SUCCESS.send(sender, group.getDisplayName(), prefix, priority, server);
LogEntry.build().actor(sender).acted(group)
.action("removetempprefix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
group.unsetPermission(node, server, world, true);
Message.REMOVE_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), prefix, priority, server, world);
LogEntry.build().actor(sender).acted(group)
.action("removetempprefix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
group.unsetPermission(node, true);
Message.REMOVE_TEMP_PREFIX_SUCCESS.send(sender, group.getDisplayName(), prefix, priority);
LogEntry.build().actor(sender).acted(group)
.action("removetempprefix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_PREFIX.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
}
}
@@ -1,154 +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.api.Node;
import me.lucko.luckperms.commands.*;
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.ArrayList;
import java.util.List;
public class GroupRemoveTempSuffix extends SubCommand<Group> {
public GroupRemoveTempSuffix() {
super("removetempsuffix", "Removes a temporary suffix from the group", Permission.GROUP_REMOVE_TEMP_SUFFIX,
Predicate.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to remove the suffix at"),
Arg.create("suffix", true, "the suffix string to remove"),
Arg.create("server", false, "the server to remove the suffix on"),
Arg.create("world", false, "the world to remove the suffix on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
final String suffix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
if (suffix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
if (args.size() >= 3) {
server = args.get(2).toLowerCase();
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() != 3) {
world = args.get(3).toLowerCase();
}
}
List<Node> toRemove = new ArrayList<>();
for (Node node : group.getNodes()) {
if (!node.isSuffix()) continue;
if (node.getSuffix().getKey() != priority) continue;
if (node.isPermanent()) continue;
if (node.getServer().isPresent()) {
if (server == null) continue;
if (!node.getServer().get().equalsIgnoreCase(server)) continue;
} else {
if (server != null) continue;
}
if (node.getWorld().isPresent()) {
if (world == null) continue;
if (!node.getWorld().get().equalsIgnoreCase(world)) continue;
} else {
if (world != null) continue;
}
toRemove.add(node);
}
toRemove.forEach(n -> {
try {
group.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
});
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
save(group, sender, plugin);
return CommandResult.SUCCESS;
} else {
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
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.unsetPermission(node, server, true);
Message.REMOVE_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, group.getDisplayName(), suffix, priority, server);
LogEntry.build().actor(sender).acted(group)
.action("removetempsuffix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
group.unsetPermission(node, server, world, true);
Message.REMOVE_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), suffix, priority, server, world);
LogEntry.build().actor(sender).acted(group)
.action("removetempsuffix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
group.unsetPermission(node, true);
Message.REMOVE_TEMP_SUFFIX_SUCCESS.send(sender, group.getDisplayName(), suffix, priority);
LogEntry.build().actor(sender).acted(group)
.action("removetempsuffix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_SUFFIX.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
}
}
@@ -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.*;
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.users.User;
import me.lucko.luckperms.utils.ArgumentChecker;
import java.util.List;
public class UserAddPrefix extends SubCommand<User> {
public UserAddPrefix() {
super("addprefix", "Adds a prefix to the user", Permission.USER_ADDPREFIX, Predicate.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
Arg.create("prefix", true, "the prefix string"),
Arg.create("server", false, "the server to add the prefix on"),
Arg.create("world", false, "the world to add the prefix on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
final String prefix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
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, true, server);
Message.ADDPREFIX_SERVER_SUCCESS.send(sender, user.getName(), prefix, priority, server);
LogEntry.build().actor(sender).acted(user)
.action("addprefix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
user.setPermission(node, true, server, world);
Message.ADDPREFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), prefix, priority, server, world);
LogEntry.build().actor(sender).acted(user)
.action("addprefix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
user.setPermission(node, true);
Message.ADDPREFIX_SUCCESS.send(sender, user.getName(), prefix, priority);
LogEntry.build().actor(sender).acted(user)
.action("addprefix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
save(user, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_PREFIX.send(sender, user.getName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -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.*;
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.users.User;
import me.lucko.luckperms.utils.ArgumentChecker;
import java.util.List;
public class UserAddSuffix extends SubCommand<User> {
public UserAddSuffix() {
super("addsuffix", "Adds a suffix to the user", Permission.USER_ADDSUFFIX, Predicate.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
Arg.create("suffix", true, "the suffix string"),
Arg.create("server", false, "the server to add the suffix on"),
Arg.create("world", false, "the world to add the suffix on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
final String suffix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
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, true, server);
Message.ADDSUFFIX_SERVER_SUCCESS.send(sender, user.getName(), suffix, priority, server);
LogEntry.build().actor(sender).acted(user)
.action("addsuffix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
user.setPermission(node, true, server, world);
Message.ADDSUFFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), suffix, priority, server, world);
LogEntry.build().actor(sender).acted(user)
.action("addsuffix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
user.setPermission(node, true);
Message.ADDSUFFIX_SUCCESS.send(sender, user.getName(), suffix, priority);
LogEntry.build().actor(sender).acted(user)
.action("addsuffix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
save(user, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_SUFFIX.send(sender, user.getName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -1,118 +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.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 UserAddTempPrefix extends SubCommand<User> {
public UserAddTempPrefix() {
super("addtempprefix", "Adds a prefix to the user temporarily", Permission.USER_ADD_TEMP_PREFIX, Predicate.notInRange(3, 5),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
Arg.create("prefix", true, "the prefix string"),
Arg.create("duration", true, "the duration until the prefix expires"),
Arg.create("server", false, "the server to add the prefix on"),
Arg.create("world", false, "the world to add the prefix on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
final String prefix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
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;
}
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
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, true, server, duration);
Message.ADD_TEMP_PREFIX_SERVER_SUCCESS.send(sender, user.getName(), prefix, priority, server, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(user)
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(4).toLowerCase();
user.setPermission(node, true, server, world, duration);
Message.ADD_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), prefix, priority, server, world, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(user)
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
user.setPermission(node, true, duration);
Message.ADD_TEMP_PREFIX_SUCCESS.send(sender, user.getName(), prefix, priority, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(user)
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration)
.build().submit(plugin, sender);
}
save(user, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_PREFIX.send(sender, user.getName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -1,118 +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.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 UserAddTempSuffix extends SubCommand<User> {
public UserAddTempSuffix() {
super("addtempsuffix", "Adds a suffix to the user temporarily", Permission.USER_ADD_TEMP_SUFFIX, Predicate.notInRange(3, 5),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
Arg.create("suffix", true, "the suffix string"),
Arg.create("duration", true, "the duration until the suffix expires"),
Arg.create("server", false, "the server to add the suffix on"),
Arg.create("world", false, "the world to add the suffix on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
final String suffix = args.get(1).replace("{SPACE}", " ");
int priority;
try {
priority = Integer.parseInt(args.get(0));
} catch (NumberFormatException e) {
Message.META_INVALID_PRIORITY.send(sender, args.get(0));
return CommandResult.INVALID_ARGS;
}
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;
}
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
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, true, server, duration);
Message.ADD_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, user.getName(), suffix, priority, server, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(user)
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(4).toLowerCase();
user.setPermission(node, true, server, world, duration);
Message.ADD_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, user.getName(), suffix, priority, server, world, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(user)
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration + " " + server + " " + world)
.build().submit(plugin, sender);
}
} else {
user.setPermission(node, true, duration);
Message.ADD_TEMP_SUFFIX_SUCCESS.send(sender, user.getName(), suffix, priority, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(user)
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration)
.build().submit(plugin, sender);
}
save(user, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_SUFFIX.send(sender, user.getName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -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.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Node;
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.AbstractMap.SimpleEntry;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
public class UserChatMeta extends SubCommand<User> {
public UserChatMeta() {
super("chatmeta", "Lists the user's chat meta", Permission.USER_CHATMETA, Predicate.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
SortedSet<Map.Entry<Integer, String>> prefixes = new TreeSet<>(Util.getMetaComparator().reversed());
SortedSet<Map.Entry<Integer, String>> suffixes = new TreeSet<>(Util.getMetaComparator().reversed());
for (Node node : user.getAllNodes(null, Contexts.allowAll())) {
if (!node.isSuffix() && !node.isPrefix()) {
continue;
}
StringBuilder sb = new StringBuilder();
if (node.isServerSpecific()) {
if (node.isWorldSpecific()) {
sb.append("&6W=").append(node.getWorld().get()).append(" ");
}
sb.append("&6S=").append(node.getServer().get()).append(" ");
}
if (node.isPrefix()) {
sb.append(node.getPrefix().getValue());
prefixes.add(new SimpleEntry<>(node.getPrefix().getKey(), sb.toString()));
}
if (node.isSuffix()) {
sb.append(node.getSuffix().getValue());
suffixes.add(new SimpleEntry<>(node.getSuffix().getKey(), sb.toString()));
}
}
if (prefixes.isEmpty()) {
Message.CHAT_META_PREFIX_NONE.send(sender, user.getName());
} else {
Message.CHAT_META_PREFIX_HEADER.send(sender, user.getName());
for (Map.Entry<Integer, String> e : prefixes) {
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue());
}
}
if (suffixes.isEmpty()) {
Message.CHAT_META_SUFFIX_NONE.send(sender, user.getName());
} else {
Message.CHAT_META_SUFFIX_HEADER.send(sender, user.getName());
for (Map.Entry<Integer, String> e : suffixes) {
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue());
}
}
return CommandResult.SUCCESS;
}
}
@@ -1,51 +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 the user's permissions and groups", Permission.USER_CLEAR, Predicate.alwaysFalse(), null);
}
@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;
}
}
@@ -20,23 +20,25 @@
* 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.PlatformType;
import me.lucko.luckperms.api.implementation.ApiProvider;
import me.lucko.luckperms.commands.ConsecutiveExecutor;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.config.LPConfiguration;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.contexts.ContextManager;
import me.lucko.luckperms.core.UuidCache;
import me.lucko.luckperms.data.Importer;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.storage.Datastore;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LocaleManager;
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.LocaleManager;
import java.io.File;
import java.util.List;
@@ -64,6 +66,7 @@ public interface LuckPermsPlugin {
ConsecutiveExecutor getConsecutiveExecutor();
LocaleManager getLocaleManager();
ContextManager getContextManager();
CalculatorFactory getCalculatorFactory();
/**
* @return the version of the plugin
@@ -114,11 +117,8 @@ public interface LuckPermsPlugin {
*/
Sender getConsoleSender();
/**
* Gets all possible permission nodes, used for resolving wildcards
* @return a {@link List} of permission nodes
*/
List<String> getPossiblePermissions();
// TODO javadoc
Set<Contexts> getPreProcessContexts(boolean op);
/**
* Gets a set of players ignoring logging output
@@ -20,26 +20,25 @@
* 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.users.UserIdentifier;
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;
/**
* Implements the LuckPerms API using the plugin instance
@@ -70,7 +69,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public double getApiVersion() {
return 2.11;
return 2.12;
}
@Override
@@ -95,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
@@ -115,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
@@ -130,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
@@ -145,7 +144,7 @@ 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
@@ -155,18 +154,18 @@ public class ApiProvider implements LuckPermsApi {
@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
@@ -176,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
@@ -186,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
@@ -201,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
@@ -211,7 +210,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Node.Builder buildNode(@NonNull String permission) throws IllegalArgumentException {
return new me.lucko.luckperms.core.Node.Builder(checkNode(permission));
return new me.lucko.luckperms.common.core.Node.Builder(checkNode(permission));
}
@SuppressWarnings("unchecked")
@@ -20,15 +20,15 @@
* 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 java.util.Set;
import java.util.UUID;
@@ -36,21 +36,21 @@ 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 +93,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,7 +206,7 @@ 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) {
@@ -319,7 +319,7 @@ public class DatastoreLink implements Datastore {
@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) {
@@ -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();
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.implementation.internal;
package me.lucko.luckperms.common.api.internal;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.LPConfiguration;
@@ -30,11 +30,11 @@ import me.lucko.luckperms.api.data.MySQLConfiguration;
import java.util.Map;
/**
* Provides a link between {@link LPConfiguration} and {@link me.lucko.luckperms.config.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.config.LPConfiguration master;
private final me.lucko.luckperms.common.config.LPConfiguration master;
@Override
public String getServer() {
@@ -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() {
@@ -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;
@@ -30,18 +30,18 @@ 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")
@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() {
@@ -65,12 +65,12 @@ public class PermissionHolderLink implements PermissionHolder {
@Override
public Set<Node> getAllNodes() {
return Collections.unmodifiableSet(master.getAllNodes(Collections.emptyList(), Contexts.allowAll()));
return Collections.unmodifiableSet(master.getAllNodes(null, Contexts.allowAll()));
}
@Override
public SortedSet<LocalizedNode> getAllNodes(@NonNull Contexts contexts) {
return master.getAllNodes(Collections.emptyList(), contexts);
return master.getAllNodes(null, contexts);
}
@Override
@@ -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;
@@ -33,22 +33,22 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import static me.lucko.luckperms.api.implementation.internal.Utils.checkGroup;
import static me.lucko.luckperms.common.api.internal.Utils.checkGroup;
/**
* Provides a link between {@link Track} and {@link me.lucko.luckperms.tracks.Track}
* Provides a link between {@link Track} and {@link me.lucko.luckperms.common.tracks.Track}
*/
@EqualsAndHashCode(of = {"name"})
@SuppressWarnings("unused")
public class TrackLink implements Track {
@Getter(AccessLevel.PACKAGE)
private final me.lucko.luckperms.tracks.Track master;
private final me.lucko.luckperms.common.tracks.Track master;
@Getter
private final String name;
public TrackLink(@NonNull me.lucko.luckperms.tracks.Track master) {
public TrackLink(@NonNull me.lucko.luckperms.common.tracks.Track master) {
this.master = master;
this.name = master.getName();
}
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.implementation.internal;
package me.lucko.luckperms.common.api.internal;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -33,22 +33,22 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.UUID;
import static me.lucko.luckperms.api.implementation.internal.Utils.*;
import static me.lucko.luckperms.common.api.internal.Utils.*;
/**
* Provides a link between {@link User} and {@link me.lucko.luckperms.users.User}
* Provides a link between {@link User} and {@link me.lucko.luckperms.common.users.User}
*/
@EqualsAndHashCode(of = {"uuid"}, callSuper = false)
@SuppressWarnings("unused")
public class UserLink extends PermissionHolderLink implements User {
@Getter
private final me.lucko.luckperms.users.User master;
private final me.lucko.luckperms.common.users.User master;
@Getter
private final UUID uuid;
public UserLink(@NonNull me.lucko.luckperms.users.User master) {
public UserLink(@NonNull me.lucko.luckperms.common.users.User master) {
super(master);
this.master = master;
this.uuid = master.getUuid();
@@ -20,13 +20,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.implementation.internal;
package me.lucko.luckperms.common.api.internal;
import lombok.experimental.UtilityClass;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.utils.ArgumentChecker;
import me.lucko.luckperms.common.utils.ArgumentChecker;
@UtilityClass
public class Utils {
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.api.implementation.internal;
package me.lucko.luckperms.common.api.internal;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.UuidCache;
@@ -28,11 +28,11 @@ import me.lucko.luckperms.api.UuidCache;
import java.util.UUID;
/**
* Provides a link between {@link UuidCache} and {@link me.lucko.luckperms.core.UuidCache}
* Provides a link between {@link UuidCache} and {@link me.lucko.luckperms.common.core.UuidCache}
*/
@AllArgsConstructor
public class UuidCacheLink implements UuidCache {
private final me.lucko.luckperms.core.UuidCache master;
private final me.lucko.luckperms.common.core.UuidCache master;
@Override
public UUID getUUID(UUID external) {
@@ -0,0 +1,116 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.caching;
import com.google.common.collect.ImmutableMap;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;
@RequiredArgsConstructor
public class MetaData {
private final Contexts contexts;
@Getter
private String prefix = null;
@Getter
private String suffix = null;
private Map<String, String> meta = new ConcurrentHashMap<>();
public void loadMeta(SortedSet<LocalizedNode> nodes) {
invalidateCache();
Map<String, String> contexts = new HashMap<>(this.contexts.getContext());
String server = contexts.remove("server");
String world = contexts.remove("world");
int prefixPriority = Integer.MIN_VALUE;
int suffixPriority = Integer.MIN_VALUE;
for (LocalizedNode ln : nodes) {
Node n = ln.getNode();
if (!n.getValue()) {
continue;
}
if (!n.isMeta() || !n.isPrefix() || n.isSuffix()) {
continue;
}
if (!n.shouldApplyOnServer(server, this.contexts.isIncludeGlobal(), false)) {
continue;
}
if (!n.shouldApplyOnWorld(world, this.contexts.isIncludeGlobalWorld(), false)) {
continue;
}
if (!n.shouldApplyWithContext(contexts, false)) {
continue;
}
if (n.isPrefix()) {
Map.Entry<Integer, String> value = n.getPrefix();
if (value.getKey() > prefixPriority) {
this.prefix = value.getValue();
prefixPriority = value.getKey();
}
continue;
}
if (n.isSuffix()) {
Map.Entry<Integer, String> value = n.getSuffix();
if (value.getKey() > suffixPriority) {
this.suffix = value.getValue();
suffixPriority = value.getKey();
}
continue;
}
if (n.isMeta()) {
Map.Entry<String, String> meta = n.getMeta();
this.meta.put(meta.getKey(), meta.getValue());
}
}
}
public void invalidateCache() {
meta.clear();
prefix = null;
suffix = null;
}
public Map<String, String> getMeta() {
return ImmutableMap.copyOf(meta);
}
}
@@ -0,0 +1,89 @@
/*
* 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.common.caching;
import com.google.common.collect.ImmutableMap;
import lombok.NonNull;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.calculators.PermissionCalculator;
import me.lucko.luckperms.common.users.User;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class PermissionData {
private final Contexts contexts;
private final Map<String, Boolean> permissions;
private final PermissionCalculator calculator;
public PermissionData(Contexts contexts, User user, CalculatorFactory calculatorFactory) {
this.contexts = contexts;
permissions = new ConcurrentHashMap<>();
calculator = calculatorFactory.build(contexts, user, permissions);
}
public void invalidateCache() {
calculator.invalidateCache();
}
public void setPermissions(Map<String, Boolean> permissions) {
this.permissions.clear();
this.permissions.putAll(permissions);
invalidateCache();
}
public void comparePermissions(Map<String, Boolean> toApply) {
boolean different = false;
if (toApply.size() != permissions.size()) {
different = true;
} else {
for (Map.Entry<String, Boolean> e : permissions.entrySet()) {
if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) {
continue;
}
different = true;
break;
}
}
if (different) {
setPermissions(toApply);
}
}
public Map<String, Boolean> getImmutableBacking() {
return ImmutableMap.copyOf(permissions);
}
public Tristate getPermissionValue(@NonNull String permission) {
Tristate t = calculator.getPermissionValue(permission);
if (t != Tristate.UNDEFINED) {
return Tristate.fromBoolean(t.asBoolean());
} else {
return Tristate.UNDEFINED;
}
}
}
@@ -0,0 +1,107 @@
/*
* 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.common.caching;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.common.calculators.CalculatorFactory;
import me.lucko.luckperms.common.users.User;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@RequiredArgsConstructor
public class UserData {
private final User user;
private final CalculatorFactory calculatorFactory;
private final Map<Contexts, PermissionData> permission = new ConcurrentHashMap<>();
private final Map<Contexts, MetaData> meta = new ConcurrentHashMap<>();
public PermissionData getPermissionData(Contexts contexts) {
return permission.computeIfAbsent(contexts, this::calculatePermissions);
}
public MetaData getMetaData(Contexts contexts) {
return meta.computeIfAbsent(contexts, this::calculateMeta);
}
public PermissionData calculatePermissions(Contexts contexts) {
PermissionData data = new PermissionData(contexts, user, calculatorFactory);
data.setPermissions(user.exportNodes(contexts, Collections.emptyList(), true));
return data;
}
public void recalculatePermissions(Contexts contexts) {
permission.compute(contexts, (c, data) -> {
if (data == null) {
data = new PermissionData(c, user, calculatorFactory);
}
data.comparePermissions(user.exportNodes(c, Collections.emptyList(), true));
return data;
});
}
public void recalculatePermissions() {
permission.keySet().forEach(this::recalculatePermissions);
}
public MetaData calculateMeta(Contexts contexts) {
MetaData data = new MetaData(contexts);
data.loadMeta(user.getAllNodes(null, contexts));
return data;
}
public void recalculateMeta(Contexts contexts) {
meta.compute(contexts, (c, data) -> {
if (data == null) {
data = new MetaData(c);
}
data.loadMeta(user.getAllNodes(null, c));
return data;
});
}
public void recalculateMeta() {
meta.keySet().forEach(this::recalculateMeta);
}
public void preCalculate(Set<Contexts> contexts) {
contexts.forEach(this::preCalculate);
}
public void preCalculate(Contexts contexts) {
getPermissionData(contexts);
getMetaData(contexts);
}
public void invalidateCache() {
permission.clear();
meta.clear();
}
}
@@ -20,24 +20,18 @@
* SOFTWARE.
*/
package me.lucko.luckperms.users;
package me.lucko.luckperms.common.calculators;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.common.users.User;
import java.util.UUID;
import java.util.Map;
public class StandaloneUser extends User {
/**
* Creates a calculator instance given a set of contexts
*/
public interface CalculatorFactory {
StandaloneUser(UUID uuid, LuckPermsPlugin plugin) {
super(uuid, plugin);
}
PermissionCalculator build(Contexts contexts, User user, Map<String, Boolean> map);
StandaloneUser(UUID uuid, String username, LuckPermsPlugin plugin) {
super(uuid, username, plugin);
}
@Override
public void refreshPermissions() {
// Do nothing.
}
}
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.calculators;
package me.lucko.luckperms.common.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -20,11 +20,11 @@
* SOFTWARE.
*/
package me.lucko.luckperms.calculators;
package me.lucko.luckperms.common.calculators;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.LuckPermsPlugin;
import java.util.List;
import java.util.Map;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.calculators;
package me.lucko.luckperms.common.calculators;
import me.lucko.luckperms.api.Tristate;
@@ -20,12 +20,12 @@
* SOFTWARE.
*/
package me.lucko.luckperms.calculators;
package me.lucko.luckperms.common.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.common.constants.Patterns;
import java.util.Map;
import java.util.regex.Pattern;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.calculators;
package me.lucko.luckperms.common.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import com.google.common.collect.ImmutableList;
import lombok.AccessLevel;
@@ -20,26 +20,26 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import com.google.common.collect.ImmutableList;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.commands.group.CreateGroup;
import me.lucko.luckperms.commands.group.DeleteGroup;
import me.lucko.luckperms.commands.group.GroupMainCommand;
import me.lucko.luckperms.commands.group.ListGroups;
import me.lucko.luckperms.commands.log.LogMainCommand;
import me.lucko.luckperms.commands.migration.MigrationMainCommand;
import me.lucko.luckperms.commands.misc.*;
import me.lucko.luckperms.commands.track.CreateTrack;
import me.lucko.luckperms.commands.track.DeleteTrack;
import me.lucko.luckperms.commands.track.ListTracks;
import me.lucko.luckperms.commands.track.TrackMainCommand;
import me.lucko.luckperms.commands.user.UserMainCommand;
import me.lucko.luckperms.commands.usersbulkedit.UsersBulkEditMainCommand;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.group.CreateGroup;
import me.lucko.luckperms.common.commands.group.DeleteGroup;
import me.lucko.luckperms.common.commands.group.GroupMainCommand;
import me.lucko.luckperms.common.commands.group.ListGroups;
import me.lucko.luckperms.common.commands.log.LogMainCommand;
import me.lucko.luckperms.common.commands.migration.MigrationMainCommand;
import me.lucko.luckperms.common.commands.misc.*;
import me.lucko.luckperms.common.commands.track.CreateTrack;
import me.lucko.luckperms.common.commands.track.DeleteTrack;
import me.lucko.luckperms.common.commands.track.ListTracks;
import me.lucko.luckperms.common.commands.track.TrackMainCommand;
import me.lucko.luckperms.common.commands.user.UserMainCommand;
import me.lucko.luckperms.common.commands.usersbulkedit.UsersBulkEditMainCommand;
import java.util.ArrayList;
import java.util.Collections;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import lombok.AllArgsConstructor;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -20,13 +20,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import com.google.common.collect.ImmutableList;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.constants.Message;
import java.util.ArrayList;
import java.util.Collections;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import lombok.experimental.UtilityClass;
@@ -20,10 +20,10 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.constants.Permission;
import java.util.UUID;
@@ -20,14 +20,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import com.google.common.collect.ImmutableMap;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Constants;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.constants.Permission;
import java.lang.ref.WeakReference;
import java.util.*;
@@ -20,10 +20,10 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.constants.Permission;
import java.util.Collections;
import java.util.List;
@@ -20,17 +20,17 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import com.google.common.collect.ImmutableList;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.tracks.Track;
import me.lucko.luckperms.common.users.User;
import java.util.ArrayList;
import java.util.Arrays;
@@ -20,15 +20,15 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
package me.lucko.luckperms.common.commands;
import lombok.experimental.UtilityClass;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.utils.DateUtil;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Patterns;
import me.lucko.luckperms.common.utils.DateUtil;
import java.util.*;
@@ -36,7 +36,11 @@ import java.util.*;
public class Util {
public static void sendPluginMessage(Sender sender, String message) {
sender.sendMessage(color(Message.PREFIX + message));
String prefix = sender.getPlatform().getLocaleManager().getTranslation(Message.PREFIX);
if (prefix == null) {
prefix = Message.PREFIX.getMessage();
}
sender.sendMessage(color(prefix + message));
}
public static List<String> stripQuotes(List<String> input) {
@@ -20,16 +20,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group;
package me.lucko.luckperms.common.commands.group;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SingleMainCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.utils.ArgumentChecker;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.SingleMainCommand;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import java.util.List;
@@ -20,16 +20,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group;
package me.lucko.luckperms.common.commands.group;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SingleMainCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.SingleMainCommand;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import java.util.ArrayList;
import java.util.Collections;
@@ -20,16 +20,17 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group;
package me.lucko.luckperms.common.commands.group;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.group.subcommands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.MainCommand;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.group.subcommands.*;
import me.lucko.luckperms.common.commands.meta.MetaCommands;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.groups.Group;
import java.util.ArrayList;
import java.util.List;
@@ -51,15 +52,7 @@ public class GroupMainCommand extends MainCommand<Group> {
.add(new GroupSetTempInherit())
.add(new GroupUnsetTempInherit())
.add(new GroupShowTracks())
.add(new GroupChatMeta())
.add(new GroupAddPrefix())
.add(new GroupAddSuffix())
.add(new GroupRemovePrefix())
.add(new GroupRemoveSuffix())
.add(new GroupAddTempPrefix())
.add(new GroupAddTempSuffix())
.add(new GroupRemoveTempPrefix())
.add(new GroupRemoveTempSuffix())
.add(new MetaCommands<>(false))
.add(new GroupBulkChange())
.add(new GroupClear())
.add(new GroupRename())
@@ -20,16 +20,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group;
package me.lucko.luckperms.common.commands.group;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SingleMainCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.SingleMainCommand;
import me.lucko.luckperms.common.commands.Util;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.groups.Group;
import java.util.ArrayList;
import java.util.List;
@@ -20,16 +20,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
package me.lucko.luckperms.common.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import java.util.HashSet;
import java.util.Iterator;
@@ -74,7 +74,7 @@ public class GroupBulkChange extends SubCommand<Group> {
}
toRemove.add(element);
toAdd.add(me.lucko.luckperms.core.Node.builderFromExisting(element).setWorld(to).build());
toAdd.add(me.lucko.luckperms.common.core.Node.builderFromExisting(element).setWorld(to).build());
}
} else {
while (iterator.hasNext()) {
@@ -85,7 +85,7 @@ public class GroupBulkChange extends SubCommand<Group> {
}
toRemove.add(element);
toAdd.add(me.lucko.luckperms.core.Node.builderFromExisting(element).setServer(to).build());
toAdd.add(me.lucko.luckperms.common.core.Node.builderFromExisting(element).setServer(to).build());
}
}
@@ -0,0 +1,79 @@
/*
* 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.common.commands.group.subcommands;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import java.util.List;
import java.util.stream.Collectors;
public class GroupClear extends SubCommand<Group> {
public GroupClear() {
super("clear", "Clears the group's permissions and parent groups", Permission.GROUP_CLEAR, Predicate.notInRange(0, 2),
Arg.list(
Arg.create("server", false, "the server name to filter by"),
Arg.create("world", false, "the world name to filter by")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
int before = group.getNodes().size();
if (args.size() == 0) {
group.clearNodes();
} else {
final String server = args.get(0);
if (ArgumentChecker.checkServer(server)) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (args.size() == 2) {
final String world = args.get(1);
group.clearNodes(server, world);
} else {
group.clearNodes(server);
}
}
int changed = before - group.getNodes().size();
if (changed == 1) {
Message.CLEAR_SUCCESS_SINGULAR.send(sender, group.getName(), changed);
} else {
Message.CLEAR_SUCCESS.send(sender, group.getName(), changed);
}
LogEntry.build().actor(sender).acted(group).action("clear " + args.stream().collect(Collectors.joining(" "))).build().submit(plugin, sender);
save(group, sender, plugin);
return CommandResult.SUCCESS;
}
}
@@ -20,15 +20,15 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
package me.lucko.luckperms.common.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.data.LogEntry;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import java.util.List;
@@ -20,15 +20,15 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
package me.lucko.luckperms.common.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.core.Node;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.Node;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import java.util.List;
@@ -20,16 +20,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
package me.lucko.luckperms.common.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.groups.Group;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.Predicate;
import me.lucko.luckperms.common.commands.Sender;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.groups.Group;
import java.util.List;
@@ -20,16 +20,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
package me.lucko.luckperms.common.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.core.InheritanceInfo;
import me.lucko.luckperms.core.Node;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.InheritanceInfo;
import me.lucko.luckperms.common.core.Node;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import java.util.List;
@@ -20,13 +20,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
package me.lucko.luckperms.common.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.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.groups.Group;
import java.util.List;
@@ -20,13 +20,13 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
package me.lucko.luckperms.common.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.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.groups.Group;
import java.util.List;
@@ -20,15 +20,15 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
package me.lucko.luckperms.common.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.data.LogEntry;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import java.util.List;
@@ -20,16 +20,16 @@
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
package me.lucko.luckperms.common.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.data.LogEntry;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.data.LogEntry;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.utils.ArgumentChecker;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
import java.util.List;
Loaded 100 of 260 files, more files were not shown because too many files have changed in this diff. Show more