Compare commits

..
57 Commits
Author SHA1 Message Date
Luck 2429831153 API changes for 2.11 2016-10-05 21:40:54 +01:00
Luck 80d2246634 Fix exporting users not in the default group 2016-10-04 20:48:58 +01:00
Luck 56df2477ca Fix UnsupportedOperationExceptions with #getPermissions 2016-10-04 17:30:27 +01:00
Luck 9b4384dc33 Revert: Merge dummy implementations 2016-10-04 17:15:10 +01:00
Luck bc65857831 Fix CME 2016-10-04 17:13:32 +01:00
Luck de462d2385 Merge dummy implementations 2016-10-04 16:58:54 +01:00
Luck 90150428be Inject a dummy on quit instead of a real PermBase instance 2016-10-04 16:19:41 +01:00
Luck 2a7f951f4f Fix NPE / crash on player quit 2016-10-04 16:10:06 +01:00
Luck 82789328c1 Pre-process permissions and apply immediately on login events 2016-10-04 14:57:00 +01:00
Luck 13bccd1d3f Fix users not receiving permission updates 2016-10-03 21:41:47 +01:00
Luck 43c514132d Cache node deserialization 2016-10-03 21:18:59 +01:00
Luck 9e0fdcbfee Fix memory leak, woops 2016-10-03 20:43:36 +01:00
Luck 008dc3fc52 Move some classes around 2016-10-03 20:42:11 +01:00
Luck 9fde237d9b Swap slow get method 2016-10-03 19:53:43 +01:00
Luck d626c08b4c Small fix for #getAllWithPermission 2016-10-03 16:45:52 +01:00
Luck 58e223e74b Implement bulk prefix/suffix removal 2016-10-02 21:17:59 +01:00
Luck 1da1df156e Fix issues related to Node comparisons 2016-10-02 15:44:46 +01:00
Luck 3442372281 Cleanup random debug messages 2016-10-02 15:43:44 +01:00
Luck 1b3b50c113 Refactor PermissionHolder & Sponge subjects 2016-10-02 15:05:53 +01:00
Luck 18e126b781 Fix issue with permissions sometimes not being removed 2016-10-02 10:33:58 +01:00
Luck c88600adda Make User constructor protected. Closes #18. 2016-10-01 22:56:57 +01:00
Luck 4787361e66 Implement locks to hopefully resolve race conditions with I/O - experimental 2016-10-01 19:03:05 +01:00
Luck b5ece8b5bd Fix exception 2016-09-30 22:26:39 +01:00
Luck 7ee3116f29 Maybe fix broken inheritance 2016-09-30 20:43:08 +01:00
Luck 1fc0d77971 Cache & fix (and maybe break) Vault Chat implementation 2016-09-30 20:08:59 +01:00
Luck a32ab4bf7f Show where a permission was inherited from in the inheritsperm command 2016-09-30 19:21:19 +01:00
Luck 2d8083bf18 Another Vault fix & cleanup User / Group classes 2016-09-30 17:45:29 +01:00
Luck 63b9be9845 Change Vault behavior & cleanup Node class 2016-09-30 17:09:19 +01:00
Luck 85a83d8c71 Add logging output to Vault 2016-09-29 22:04:46 +01:00
Luck 71b33a296c Calculate Sponge defaults using context 2016-09-29 20:38:03 +01:00
Luck becdfd6f03 Silence subject load errors unless debug-permission-checks is true 2016-09-29 20:02:38 +01:00
Luck 41744f9416 Add clone commands 2016-09-29 18:07:41 +01:00
Luck cb89a92ba9 Message colour changes and standardization 2016-09-28 21:16:07 +01:00
Luck 93d54373c6 Add detailed command info system 2016-09-28 20:59:08 +01:00
Luck 385addfe08 cleanup 2016-09-27 20:21:13 +01:00
Luck 4c21957b04 Cache Vault lookups & properly sort listnodes output 2016-09-27 20:18:06 +01:00
Luck ab6b011225 Fix permission lookups being case sensitive 2016-09-26 18:52:01 +01:00
Luck e72d91503c Maybe nicer looking messages 2016-09-26 18:42:46 +01:00
Luck b9ee206908 Add some more bulk edit commands 2016-09-25 21:23:48 +01:00
Luck 4c9abba5fa Maybe fix vault (again) 2016-09-25 19:26:36 +01:00
Luck 3424b0542a Release 2.10 2016-09-25 17:32:58 +01:00
Luck fec90b8958 Add bulkchange commands 2016-09-25 17:29:11 +01:00
Luck 4da7fe4ff9 Small fixes to context system 2016-09-25 16:55:14 +01:00
Luck c53623dd67 Make command usage output easier to read 2016-09-25 14:34:27 +01:00
Luck 6540ffa4dd Refactor storage 2016-09-25 12:47:15 +01:00
Luck 5ee6db02ff Proper context implementation - WIP 2016-09-25 10:19:36 +01:00
Luck d8221f466a Fix messages not being formatted correctly 2016-09-24 17:22:33 +01:00
Luck 462bea2a09 Remove broken repo, maybe fix build 2016-09-24 16:58:45 +01:00
Luck f452a97278 fix typo 2016-09-23 22:19:17 +01:00
Luck eb9d2be587 Add locale file support 2016-09-23 22:14:40 +01:00
Luck df1e747861 Add commands to view inherited groups 2016-09-23 19:23:31 +01:00
Luck f48595b1ff Add world and group name rewriting, refactor configs 2016-09-23 18:58:19 +01:00
Luck 12cd4e19cb Update config comments 2016-09-22 18:25:49 +01:00
Luck a195e94522 Calculate defaults after all plugins have loaded 2016-09-22 17:34:51 +01:00
Luck 02abb39dc2 Change #isPermissionSet to be more like the Bukkit impl 2016-09-21 22:04:18 +01:00
Luck f7a0b1ef78 Refactor default permissions to be less bad 2016-09-21 21:30:42 +01:00
Luck 7678f25879 Fix default permissions not properly applying on Bukkit 2016-09-21 17:40:05 +01:00
210 changed files with 8581 additions and 4147 deletions

No files matched your search

+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.9-SNAPSHOT</version>
<version>2.11-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,155 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api;
import com.google.common.collect.ImmutableMap;
import java.util.Collections;
import java.util.Map;
/**
* Represents the context and options for a permission lookup.
* All values are immutable.
* @since 2.11
*/
public class Contexts {
public static final String SERVER_KEY = "server";
public static final String WORLD_KEY = "world";
/**
* Gets a context that will allow all nodes
* @return a context that will not apply any filters
*/
public static Contexts allowAll() {
return new Contexts(Collections.emptyMap(), 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) {
if (context == null) {
throw new NullPointerException("context");
}
this.context = ImmutableMap.copyOf(context);
this.includeGlobal = includeGlobal;
this.includeGlobalWorld = includeGlobalWorld;
this.applyGroups = applyGroups;
this.applyGlobalGroups = applyGlobalGroups;
this.applyGlobalWorldGroups = applyGlobalWorldGroups;
}
/**
* The contexts that apply for this lookup
*
* The keys for servers and worlds are defined as static values.
*/
private final Map<String, String> context;
/**
* If global or non server specific nodes should be applied
*/
private final boolean includeGlobal;
/**
* If global or non world specific nodes should be applied
*/
private final boolean includeGlobalWorld;
/**
* If parent groups should be applied
*/
private final boolean applyGroups;
/**
* If global or non server specific group memberships should be applied
*/
private final boolean applyGlobalGroups;
/**
* If global or non world specific group memberships should be applied
*/
private final boolean applyGlobalWorldGroups;
/**
* Gets the contexts that apply for this lookup
* @return an immutable map of context key value pairs
*/
public Map<String, String> getContext() {
return this.context;
}
/**
* Gets if global or non server specific nodes should be applied
* @return true if global or non server specific nodes should be applied
*/
public boolean isIncludeGlobal() {
return this.includeGlobal;
}
/**
* Gets if global or non world specific nodes should be applied
* @return true if global or non world specific nodes should be applied
*/
public boolean isIncludeGlobalWorld() {
return this.includeGlobalWorld;
}
/**
* Gets if parent groups should be applied
* @return true if parent groups should be applied
*/
public boolean isApplyGroups() {
return this.applyGroups;
}
/**
* Gets if global or non server specific group memberships should be applied
* @return true if global or non server specific group memberships should be applied
*/
public boolean isApplyGlobalGroups() {
return this.applyGlobalGroups;
}
/**
* Gets if global or non world specific group memberships should be applied
* @return true if global or non world specific group memberships should be applied
*/
public boolean isApplyGlobalWorldGroups() {
return this.applyGlobalWorldGroups;
}
public String toString() {
return "Contexts(" +
"context=" + this.getContext() + ", " +
"includeGlobal=" + this.isIncludeGlobal() + ", " +
"includeGlobalWorld=" + this.isIncludeGlobalWorld() + ", " +
"applyGroups=" + this.isApplyGroups() + ", " +
"applyGlobalGroups=" + this.isApplyGlobalGroups() + ", " +
"applyGlobalWorldGroups=" + this.isApplyGlobalWorldGroups() +
")";
}
}
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api;
/**
* Represents a Node and where it was inherited from.
* @since 2.11
*/
public interface LocalizedNode extends Node {
/**
* Gets the node
* @return the node this instance is representing
*/
Node getNode();
/**
* Gets the location where the {@link Node} is inherited from
* @return where the node was inherited from. Will not return null.
* @see PermissionHolder#getObjectName()
*/
String getLocation();
}
@@ -22,6 +22,8 @@
package me.lucko.luckperms.api;
import me.lucko.luckperms.api.context.ContextListener;
import me.lucko.luckperms.api.context.IContextCalculator;
import me.lucko.luckperms.api.event.LPListener;
import java.util.Optional;
@@ -218,4 +220,18 @@ public interface LuckPermsApi {
*/
Node.Builder buildNode(String permission) throws IllegalArgumentException;
/**
* Register a custom context calculator to the server
* @param contextCalculator the context calculator to register. The type MUST be the player class of the platform.
* @throws ClassCastException if the type is not the player class of the platform.
*/
void registerContextCalculator(IContextCalculator<?> contextCalculator);
/**
* Registers a custom context listener to the server,
* @param contextListener the context listener to register. The type MUST be the player class of the platform.
* @throws ClassCastException if the type is not the player class of the platform.
*/
void registerContextListener(ContextListener<?> contextListener);
}
@@ -105,7 +105,15 @@ public interface Node extends Map.Entry<String, Boolean> {
boolean shouldApplyOnWorld(String world, boolean includeGlobal, boolean applyRegex);
/**
* If this node should apply given the specific context
* If this node should apply in the given context
* @param context the context key value pairs
* @param worldAndServer if world and server contexts should be checked
* @return true if the node should apply
*/
boolean shouldApplyWithContext(Map<String, String> context, boolean worldAndServer);
/**
* If this node should apply in the given context
* @param context the context key value pairs
* @return true if the node should apply
*/
@@ -47,7 +47,7 @@ public interface PermissionHolder {
* @return an immutable set of permissions in priority order
* @since 2.6
*/
SortedSet<Node> getPermissions();
SortedSet<? extends Node> getPermissions();
/**
* Similar to {@link #getPermissions()}, except excluding transient permissions
@@ -68,9 +68,34 @@ public interface PermissionHolder {
* Gets an immutable set of the nodes that this object has and inherits
* @return an immutable set of permissions
* @since 2.6
* @deprecated in favour of {@link #getAllNodes(Contexts)}
*/
@Deprecated
Set<Node> getAllNodes();
/**
* Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context
* Unlike {@link #getAllNodesFiltered(Contexts)}, this method will not filter individual nodes. The context is only
* used to determine which groups should apply.
* Nodes are sorted into priority order.
* @param contexts the context for the lookup,
* @return a mutable sorted set of permissions
* @throws NullPointerException if the context is null
* @since 2.11
*/
SortedSet<LocalizedNode> getAllNodes(Contexts contexts);
/**
* Gets a mutable set of the nodes that is objects has and inherits, filtered by context.
* Unlike {@link #getAllNodes(Contexts)}, this method WILL filter individual nodes, and only return ones that fully
* meet the context provided.
* @param contexts the context for the lookup
* @return a mutable set of permissions
* @throws NullPointerException if the context is null
* @since 2.11
*/
Set<LocalizedNode> getAllNodesFiltered(Contexts contexts);
/**
* Gets an immutable Map of the objects permission nodes
* @return an immutable map of permissions
@@ -499,7 +524,9 @@ public interface PermissionHolder {
* @param applyGroups if inherited group permissions should be included
* @return a map of permissions
* @since 2.6
* @deprecated in favour of {@link #getAllNodesFiltered(Contexts)}
*/
@Deprecated
Map<String, Boolean> getPermissions(String server, String world, Map<String, String> extraContext, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups);
/**
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.context;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* A simple implementation of the listener aspects of {@link IContextCalculator<T>}
* @param <T> the subject type
*/
public abstract class ContextCalculator<T> implements IContextCalculator<T> {
private final List<ContextListener<T>> listeners = new CopyOnWriteArrayList<>();
/**
* Pushes an update to all registered {@link ContextListener}s.
* Make sure any changes are applied internally before this method is called.
* @param subject the subject that changed
* @param before the context state before the change
* @param current the context state after the change (now)
* @throws NullPointerException if any parameters are null
*/
protected void pushUpdate(T subject, Map.Entry<String, String> before, Map.Entry<String, String> current) {
if (subject == null) {
throw new NullPointerException("subject");
}
if (before == null) {
throw new NullPointerException("before");
}
if (current == null) {
throw new NullPointerException("current");
}
for (ContextListener<T> listener : listeners) {
try {
listener.onContextChange(subject, before, current);
} catch (Exception e) {
System.out.println("Exception whilst passing context change to listener: " + listener);
e.printStackTrace();
}
}
}
@Override
public void addListener(ContextListener<T> listener) {
if (listener == null) {
throw new NullPointerException("listener");
}
listeners.add(listener);
}
}
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.context;
import java.util.Map;
/**
* Listens to context changes
* @param <T> the subject type, Is ALWAYS the player class of the platform.
*/
public interface ContextListener<T> {
/**
* Called whenever a context changes on the
* @param subject the subject that had context changed
* @param before the context state before the change
* @param current the context state after the change (now)
*/
void onContextChange(T subject, Map.Entry<String, String> before, Map.Entry<String, String> current) throws Exception;
}
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.context;
import java.util.Map;
/**
* Calculates whether contexts are applicable to {@link T}
*
* <p>Somewhat inspired by the system used on Sponge.
* @param <T> the subject type. Is ALWAYS the player class of the platform.
*/
public interface IContextCalculator<T> {
/**
* Gives the subject all of the applicable contexts they meet
* @param subject the subject to add contexts tp
* @param accumulator a map of contexts to add to
* @return the map
*/
Map<String, String> giveApplicableContext(T subject, Map<String, String> accumulator);
/**
* Checks to see if a context is applicable to a subject
* @param subject the subject to check against
* @param context the context to check for
* @return true if met, or false if not. If this calculator does not calculate the given context, return false.
*/
boolean isContextApplicable(T subject, Map.Entry<String, String> context);
/**
* Adds a listener to be called whenever a context handled by this calculator changes
* @param listener the listener instance
* @throws NullPointerException if listener is null
*/
void addListener(ContextListener<T> listener);
}
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.9-SNAPSHOT</version>
<version>2.11-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.9-SNAPSHOT</version>
<version>2.11-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.9-SNAPSHOT</version>
<version>2.11-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -44,7 +44,7 @@ class BukkitCommand extends CommandManager implements CommandExecutor, TabExecut
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
onCommand(
BukkitSenderFactory.get().wrap(sender),
BukkitSenderFactory.get(getPlugin()).wrap(sender),
label,
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
Callback.empty()
@@ -55,6 +55,6 @@ class BukkitCommand extends CommandManager implements CommandExecutor, TabExecut
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
return onTabComplete(BukkitSenderFactory.get().wrap(sender), Arrays.asList(args));
return onTabComplete(BukkitSenderFactory.get(getPlugin()).wrap(sender), Arrays.asList(args));
}
}
@@ -22,14 +22,17 @@
package me.lucko.luckperms;
import me.lucko.luckperms.core.LPConfiguration;
import me.lucko.luckperms.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;
class BukkitConfig extends LPConfiguration<LPBukkitPlugin> {
class BukkitConfig extends AbstractConfiguration<LPBukkitPlugin> {
private YamlConfiguration configuration;
BukkitConfig(LPBukkitPlugin plugin) {
@@ -55,11 +58,6 @@ class BukkitConfig extends LPConfiguration<LPBukkitPlugin> {
}
}
@Override
protected void set(String path, Object value) {
configuration.set(path, value);
}
@Override
protected String getString(String path, String def) {
return configuration.getString(path, def);
@@ -74,4 +72,20 @@ class BukkitConfig extends LPConfiguration<LPBukkitPlugin> {
protected boolean getBoolean(String path, boolean def) {
return configuration.getBoolean(path, def);
}
@SuppressWarnings("unchecked")
@Override
protected Map<String, String> getMap(String path, Map<String, String> def) {
Map<String, String> map = new HashMap<>();
ConfigurationSection section = configuration.getConfigurationSection(path);
if (section == null) {
return def;
}
for (String key : section.getKeys(false)) {
map.put(key, section.getString(key));
}
return map;
}
}
@@ -22,6 +22,7 @@
package me.lucko.luckperms;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.inject.Injector;
import me.lucko.luckperms.inject.LPPermissible;
@@ -34,6 +35,8 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.*;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
class BukkitListener extends AbstractListener implements Listener {
@@ -52,7 +55,41 @@ class BukkitListener extends AbstractListener implements Listener {
return;
}
// 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);
}
}
}
@EventHandler(priority = EventPriority.LOWEST)
@@ -65,46 +102,62 @@ class BukkitListener extends AbstractListener implements Listener {
return;
}
if (user instanceof BukkitUser) {
BukkitUser u = (BukkitUser) user;
BukkitUser u = (BukkitUser) user;
try {
// Make a new permissible for the user
LPPermissible lpPermissible = new LPPermissible(player, plugin, plugin.getDefaultsProvider());
try {
LPPermissible lpPermissible = new LPPermissible(player, plugin);
Injector.inject(player, lpPermissible);
u.setLpPermissible(lpPermissible);
} catch (Throwable t) {
t.printStackTrace();
}
// Insert the pre-processed permissions into the permissible
lpPermissible.getLuckPermsPermissions().putAll(u.getLoginPreProcess());
u.setLoginPreProcess(null);
// Inject into the player
Injector.inject(player, lpPermissible);
u.setLpPermissible(lpPermissible);
} catch (Throwable t) {
t.printStackTrace();
}
}
plugin.doAsync(user::refreshPermissions);
@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.getUserManager().getWorldCache().put(internal, e.getPlayer().getWorld().getName());
plugin.getWorldCalculator().getWorldCache().put(internal, e.getPlayer().getWorld().getName());
plugin.doAsync(() -> refreshPlayer(internal));
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
plugin.getUserManager().getWorldCache().put(internal, e.getPlayer().getWorld().getName());
plugin.doAsync(() -> refreshPlayer(internal));
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerQuit(PlayerQuitEvent e) {
plugin.getUserManager().getWorldCache().remove(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
final UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
plugin.getWorldCalculator().getWorldCache().remove(internal);
onLeave(e.getPlayer().getUniqueId());
if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) {
plugin.getVaultHook().getPermissionHook().getVaultUserManager().clearUser(internal);
}
}
@EventHandler
public void onPlayerCommand(PlayerCommandPreprocessEvent e) {
if (plugin.getConfiguration().getEnableOps()) {
if (plugin.getConfiguration().isOpsEnabled()) {
return;
}
@@ -22,8 +22,6 @@
package me.lucko.luckperms;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import me.lucko.luckperms.commands.SenderFactory;
import me.lucko.luckperms.constants.Constants;
import org.bukkit.command.CommandSender;
@@ -31,12 +29,16 @@ import org.bukkit.entity.Player;
import java.util.UUID;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BukkitSenderFactory extends SenderFactory<CommandSender> {
private static BukkitSenderFactory instance = null;
public static synchronized BukkitSenderFactory get() {
private BukkitSenderFactory(LuckPermsPlugin plugin) {
super(plugin);
}
public static synchronized BukkitSenderFactory get(LuckPermsPlugin plugin) {
if (instance == null) {
instance = new BukkitSenderFactory();
instance = new BukkitSenderFactory(plugin);
}
return instance;
}
@@ -28,10 +28,14 @@ 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.core.LPConfiguration;
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;
@@ -41,6 +45,7 @@ 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 org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
@@ -57,6 +62,8 @@ import java.util.stream.Collectors;
@Getter
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private VaultHook vaultHook = null;
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
private LPConfiguration configuration;
private BukkitUserManager userManager;
@@ -68,6 +75,10 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private Logger log;
private Importer importer;
private ConsecutiveExecutor consecutiveExecutor;
private DefaultsProvider defaultsProvider;
private LocaleManager localeManager;
private ContextManager<Player> contextManager;
private WorldCalculator worldCalculator;
@Override
public void onEnable() {
@@ -76,6 +87,20 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
getLog().info("Loading configuration...");
configuration = new BukkitConfig(this);
localeManager = new LocaleManager();
File locale = new File(getDataFolder(), "lang.yml");
if (locale.exists()) {
getLog().info("Found locale file. Attempting to load from it.");
try {
localeManager.loadFromFile(locale);
} catch (Exception e) {
e.printStackTrace();
}
}
defaultsProvider = new DefaultsProvider();
getServer().getScheduler().runTaskLater(this, () -> defaultsProvider.refresh(), 1L);
// register events
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new BukkitListener(this), this);
@@ -91,20 +116,27 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
datastore = StorageFactory.getDatastore(this, "h2");
getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
uuidCache = new UuidCache(getConfiguration().isOnlineMode());
userManager = new BukkitUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager();
importer = new Importer(commandManager);
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
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) {
long ticks = mins * 60 * 20;
getServer().getScheduler().runTaskTimerAsynchronously(this, new UpdateTask(this), ticks, ticks);
}
getServer().getScheduler().runTaskTimer(this, BukkitSenderFactory.get(), 1L, 1L);
getServer().getScheduler().runTaskTimer(this, BukkitSenderFactory.get(this), 1L, 1L);
getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpireTemporaryTask(this), 60L, 60L);
getServer().getScheduler().runTaskTimerAsynchronously(this, consecutiveExecutor, 20L, 20L);
@@ -112,7 +144,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
getLog().info("Attempting to hook into Vault...");
try {
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
VaultHook.hook(this);
vaultHook = new VaultHook();
vaultHook.hook(this);
getLog().info("Registered Vault permission & chat hook.");
} else {
getLog().info("Vault not found.");
@@ -135,8 +168,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
e.printStackTrace();
}
registerPermissions(getConfiguration().getCommandsAllowOp() ? PermissionDefault.OP : PermissionDefault.FALSE);
if (!getConfiguration().getEnableOps()) {
registerPermissions(getConfiguration().isCommandsAllowOp() ? PermissionDefault.OP : PermissionDefault.FALSE);
if (!getConfiguration().isOpsEnabled()) {
getServer().getOperators().forEach(o -> o.setOp(false));
}
@@ -151,6 +184,10 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
getLog().info("Unregistering API...");
LuckPerms.unregisterProvider();
getServer().getServicesManager().unregisterAll(this);
if (vaultHook != null) {
vaultHook.unhook(this);
}
}
@Override
@@ -196,14 +233,14 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
@Override
public List<Sender> getNotifyListeners() {
return getServer().getOnlinePlayers().stream()
.map(p -> BukkitSenderFactory.get().wrap(p, Collections.singleton(me.lucko.luckperms.constants.Permission.LOG_NOTIFY)))
.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)
.collect(Collectors.toList());
}
@Override
public Sender getConsoleSender() {
return BukkitSenderFactory.get().wrap(getServer().getConsoleSender());
return BukkitSenderFactory.get(this).wrap(getServer().getConsoleSender());
}
@Override
@@ -23,18 +23,21 @@
package me.lucko.luckperms.api.vault;
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.ChatCache;
import me.lucko.luckperms.api.vault.cache.VaultUser;
import me.lucko.luckperms.core.PermissionHolder;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Contexts;
import net.milkbowl.vault.chat.Chat;
import java.util.Iterator;
import java.util.HashMap;
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;
@@ -54,13 +57,8 @@ import static me.lucko.luckperms.utils.ArgumentChecker.unescapeCharacters;
*
* Node that special characters used within LuckPerms are escaped:
* See {@link me.lucko.luckperms.utils.ArgumentChecker#escapeCharacters(String)}
*
* Registered on normal priority so other plugins can override.
*/
public class VaultChatHook extends Chat {
@Setter
private LPBukkitPlugin plugin;
private final VaultPermissionHook perms;
VaultChatHook(VaultPermissionHook perms) {
@@ -79,38 +77,103 @@ public class VaultChatHook extends Chat {
private void saveMeta(PermissionHolder holder, String world, String node, String value) {
if (holder == null) return;
if (node.equals("")) return;
node = escapeCharacters(node);
value = escapeCharacters(value);
Iterator<Node> nodes = holder.getNodes().iterator();
while (nodes.hasNext()) {
Node n = nodes.next();
if (n.isMeta() && n.getMeta().getKey().equals(node)) {
nodes.remove();
perms.scheduleTask(() -> {
String k = escapeCharacters(node);
String v = escapeCharacters(value);
List<Node> toRemove = holder.getNodes().stream()
.filter(n -> n.isMeta() && n.getMeta().getKey().equals(k))
.collect(Collectors.toList());
toRemove.forEach(n -> {
try {
holder.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
});
Node.Builder metaNode = new me.lucko.luckperms.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);
}
}
Node.Builder metaNode = new me.lucko.luckperms.utils.Node.Builder("meta." + node + "." + value).setValue(true);
if (!perms.getServer().equalsIgnoreCase("global")) {
metaNode.setServer(perms.getServer());
}
if (world != null && !world.equals("")) {
metaNode.setServer(perms.getServer()).setWorld(world);
}
try {
holder.setPermission(metaNode.build());
} catch (ObjectAlreadyHasException ignored) {}
try {
holder.setPermission(metaNode.build());
} catch (ObjectAlreadyHasException ignored) {}
perms.objectSave(holder);
perms.save(holder);
});
}
private String getMeta(PermissionHolder holder, String world, String node, String defaultValue) {
if (holder == null) return defaultValue;
private void setChatMeta(boolean prefix, PermissionHolder holder, String value, String 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));
node.setValue(true);
if (!perms.getServer().equalsIgnoreCase("global")) {
node.setServer(perms.getServer());
}
if (world != null && !world.equals("")) {
node.setServer(perms.getServer()).setWorld(world);
}
try {
holder.setPermission(node.build());
} catch (ObjectAlreadyHasException ignored) {}
perms.save(holder);
});
}
private String getUserMeta(User user, String world, String node, String defaultValue) {
if (user == null) return defaultValue;
node = escapeCharacters(node);
if (!perms.getVaultUserManager().containsUser(user.getUuid())) {
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));
}
private String getUserChatMeta(boolean prefix, User user, String world) {
if (user == null) return "";
if (!perms.getVaultUserManager().containsUser(user.getUuid())) {
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()));
}
private String getGroupMeta(Group group, String world, String node, String defaultValue) {
if (group == null) return defaultValue;
if (node.equals("")) return defaultValue;
node = escapeCharacters(node);
for (Node n : holder.getPermissions(true)) {
for (Node n : group.getPermissions(true)) {
if (!n.getValue()) {
continue;
}
@@ -136,34 +199,19 @@ public class VaultChatHook extends Chat {
return defaultValue;
}
private void setChatMeta(boolean prefix, PermissionHolder holder, String value, String world) {
if (holder == null) return;
if (value.equals("")) return;
Node.Builder node = new me.lucko.luckperms.utils.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);
}
try {
holder.setPermission(node.build());
} catch (ObjectAlreadyHasException ignored) {}
perms.objectSave(holder);
}
private String getChatMeta(boolean prefix, PermissionHolder holder, String world) {
if (holder == null) return "";
private String getGroupChatMeta(boolean prefix, Group group, String world) {
if (group == null) return "";
int priority = Integer.MIN_VALUE;
String meta = null;
for (Node n : holder.getAllNodes(null, Contexts.allowAll())) {
Map<String, String> context = new HashMap<>();
context.put("server", perms.getServer());
if (world != null) {
context.put("world", world);
}
for (Node n : group.getAllNodes(null, new Contexts(context, perms.isIncludeGlobal(), true, true, true, true))) {
if (!n.getValue()) {
continue;
}
@@ -191,104 +239,104 @@ public class VaultChatHook extends Chat {
}
public String getPlayerPrefix(String world, @NonNull String player) {
final User user = plugin.getUserManager().get(player);
return getChatMeta(true, user, world);
final User user = perms.getPlugin().getUserManager().get(player);
return getUserChatMeta(true, user, world);
}
public void setPlayerPrefix(String world, @NonNull String player, @NonNull String prefix) {
final User user = plugin.getUserManager().get(player);
final User user = perms.getPlugin().getUserManager().get(player);
setChatMeta(true, user, prefix, world);
}
public String getPlayerSuffix(String world, @NonNull String player) {
final User user = plugin.getUserManager().get(player);
return getChatMeta(false, user, world);
final User user = perms.getPlugin().getUserManager().get(player);
return getUserChatMeta(false, user, world);
}
public void setPlayerSuffix(String world, @NonNull String player, @NonNull String suffix) {
final User user = plugin.getUserManager().get(player);
final User user = perms.getPlugin().getUserManager().get(player);
setChatMeta(false, user, suffix, world);
}
public String getGroupPrefix(String world, @NonNull String group) {
final Group g = plugin.getGroupManager().get(group);
return getChatMeta(false, g, world);
final Group g = perms.getPlugin().getGroupManager().get(group);
return getGroupChatMeta(false, g, world);
}
public void setGroupPrefix(String world, @NonNull String group, @NonNull String prefix) {
final Group g = plugin.getGroupManager().get(group);
final Group g = perms.getPlugin().getGroupManager().get(group);
setChatMeta(true, g, prefix, world);
}
public String getGroupSuffix(String world, @NonNull String group) {
final Group g = plugin.getGroupManager().get(group);
return getChatMeta(false, g, world);
final Group g = perms.getPlugin().getGroupManager().get(group);
return getGroupChatMeta(false, g, world);
}
public void setGroupSuffix(String world, @NonNull String group, @NonNull String suffix) {
final Group g = plugin.getGroupManager().get(group);
final Group g = perms.getPlugin().getGroupManager().get(group);
setChatMeta(false, g, suffix, world);
}
public int getPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int defaultValue) {
final User user = plugin.getUserManager().get(player);
final User user = perms.getPlugin().getUserManager().get(player);
try {
return Integer.parseInt(getMeta(user, world, node, String.valueOf(defaultValue)));
return Integer.parseInt(getUserMeta(user, world, node, String.valueOf(defaultValue)));
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void setPlayerInfoInteger(String world, @NonNull String player, @NonNull String node, int value) {
final User user = plugin.getUserManager().get(player);
final User user = perms.getPlugin().getUserManager().get(player);
saveMeta(user, world, node, String.valueOf(value));
}
public int getGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int defaultValue) {
final Group g = plugin.getGroupManager().get(group);
final Group g = perms.getPlugin().getGroupManager().get(group);
try {
return Integer.parseInt(getMeta(g, world, node, String.valueOf(defaultValue)));
return Integer.parseInt(getGroupMeta(g, world, node, String.valueOf(defaultValue)));
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void setGroupInfoInteger(String world, @NonNull String group, @NonNull String node, int value) {
final Group g = plugin.getGroupManager().get(group);
final Group g = perms.getPlugin().getGroupManager().get(group);
saveMeta(g, world, node, String.valueOf(value));
}
public double getPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double defaultValue) {
final User user = plugin.getUserManager().get(player);
final User user = perms.getPlugin().getUserManager().get(player);
try {
return Double.parseDouble(getMeta(user, world, node, String.valueOf(defaultValue)));
return Double.parseDouble(getUserMeta(user, world, node, String.valueOf(defaultValue)));
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void setPlayerInfoDouble(String world, @NonNull String player, @NonNull String node, double value) {
final User user = plugin.getUserManager().get(player);
final User user = perms.getPlugin().getUserManager().get(player);
saveMeta(user, world, node, String.valueOf(value));
}
public double getGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double defaultValue) {
final Group g = plugin.getGroupManager().get(group);
final Group g = perms.getPlugin().getGroupManager().get(group);
try {
return Double.parseDouble(getMeta(g, world, node, String.valueOf(defaultValue)));
return Double.parseDouble(getGroupMeta(g, world, node, String.valueOf(defaultValue)));
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void setGroupInfoDouble(String world, @NonNull String group, @NonNull String node, double value) {
final Group g = plugin.getGroupManager().get(group);
final Group g = perms.getPlugin().getGroupManager().get(group);
saveMeta(g, world, node, String.valueOf(value));
}
public boolean getPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean defaultValue) {
final User user = plugin.getUserManager().get(player);
String s = getMeta(user, world, node, String.valueOf(defaultValue));
final User user = perms.getPlugin().getUserManager().get(player);
String s = getUserMeta(user, world, node, String.valueOf(defaultValue));
if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) {
return defaultValue;
}
@@ -296,13 +344,13 @@ public class VaultChatHook extends Chat {
}
public void setPlayerInfoBoolean(String world, @NonNull String player, @NonNull String node, boolean value) {
final User user = plugin.getUserManager().get(player);
final User user = perms.getPlugin().getUserManager().get(player);
saveMeta(user, world, node, String.valueOf(value));
}
public boolean getGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean defaultValue) {
final Group g = plugin.getGroupManager().get(group);
String s = getMeta(g, world, node, String.valueOf(defaultValue));
final Group g = perms.getPlugin().getGroupManager().get(group);
String s = getGroupMeta(g, world, node, String.valueOf(defaultValue));
if (!s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) {
return defaultValue;
}
@@ -310,27 +358,27 @@ public class VaultChatHook extends Chat {
}
public void setGroupInfoBoolean(String world, @NonNull String group, @NonNull String node, boolean value) {
final Group g = plugin.getGroupManager().get(group);
final Group g = perms.getPlugin().getGroupManager().get(group);
saveMeta(g, world, node, String.valueOf(value));
}
public String getPlayerInfoString(String world, @NonNull String player, @NonNull String node, String defaultValue) {
final User user = plugin.getUserManager().get(player);
return getMeta(user, world, node, defaultValue);
final User user = perms.getPlugin().getUserManager().get(player);
return getUserMeta(user, world, node, defaultValue);
}
public void setPlayerInfoString(String world, @NonNull String player, @NonNull String node, String value) {
final User user = plugin.getUserManager().get(player);
final User user = perms.getPlugin().getUserManager().get(player);
saveMeta(user, world, node, value);
}
public String getGroupInfoString(String world, @NonNull String group, @NonNull String node, String defaultValue) {
final Group g = plugin.getGroupManager().get(group);
return getMeta(g, world, node, defaultValue);
final Group g = perms.getPlugin().getGroupManager().get(group);
return getGroupMeta(g, world, node, defaultValue);
}
public void setGroupInfoString(String world, @NonNull String group, @NonNull String node, String value) {
final Group g = plugin.getGroupManager().get(group);
final Group g = perms.getPlugin().getGroupManager().get(group);
saveMeta(g, world, node, value);
}
@@ -22,40 +22,53 @@
package me.lucko.luckperms.api.vault;
import lombok.Getter;
import me.lucko.luckperms.LPBukkitPlugin;
import net.milkbowl.vault.chat.Chat;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.ServicesManager;
@Getter
public class VaultHook {
private VaultChatHook chatHook = null;
private VaultPermissionHook permissionHook = null;
private static VaultChatHook chatHook = null;
private static VaultPermissionHook permissionHook = null;
public static void hook(LPBukkitPlugin plugin) {
public void hook(LPBukkitPlugin plugin) {
try {
if (permissionHook == null) {
permissionHook = new VaultPermissionHook();
}
permissionHook.setPlugin(plugin);
permissionHook.setServer(plugin.getConfiguration().getVaultServer());
permissionHook.setIncludeGlobal(plugin.getConfiguration().getVaultIncludeGlobal());
permissionHook.setIncludeGlobal(plugin.getConfiguration().isVaultIncludingGlobal());
permissionHook.setup();
if (chatHook == null) {
chatHook = new VaultChatHook(permissionHook);
}
chatHook.setPlugin(plugin);
final ServicesManager sm = plugin.getServer().getServicesManager();
sm.unregisterAll(plugin);
sm.register(Permission.class, permissionHook, plugin, ServicePriority.High);
sm.register(Chat.class, chatHook, plugin, ServicePriority.Low);
sm.register(Chat.class, chatHook, plugin, ServicePriority.High);
} catch (Exception e) {
e.printStackTrace();
}
}
public void unhook(LPBukkitPlugin plugin) {
final ServicesManager sm = plugin.getServer().getServicesManager();
if (permissionHook != null) {
sm.unregister(Permission.class, permissionHook);
}
if (chatHook != null) {
sm.unregister(Chat.class, chatHook);
}
}
public boolean isHooked() {
return permissionHook != null && chatHook != null;
}
}
@@ -26,7 +26,10 @@ import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.api.data.Callback;
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.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
@@ -34,11 +37,22 @@ import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import net.milkbowl.vault.permission.Permission;
public class VaultPermissionHook extends Permission {
import java.util.*;
/**
* The LuckPerms Vault Permission implementation
* Most lookups are cached.
*/
public class VaultPermissionHook extends Permission implements Runnable {
private final List<Runnable> tasks = new ArrayList<>();
@Getter
@Setter
private LPBukkitPlugin plugin;
@Getter
private VaultUserManager vaultUserManager;
@Getter
@Setter
private String server = "global";
@@ -47,6 +61,34 @@ public class VaultPermissionHook extends Permission {
@Setter
private boolean includeGlobal = true;
public void setup() {
vaultUserManager = new VaultUserManager(plugin, this);
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, this, 1L, 1L);
}
public void log(String s) {
if (plugin.getConfiguration().isDebugPermissionChecks()) {
plugin.getLog().info("[VAULT] " + s);
}
}
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";
@@ -62,17 +104,24 @@ public class VaultPermissionHook extends Permission {
return true;
}
private boolean objectHas(String world, PermissionHolder object, String permission) {
if (object == null) return false;
private boolean objectHas(String world, Group group, String permission) {
if (group == null) return false;
Map<String, String> context = new HashMap<>();
if (world != null && !world.equals("")) {
return object.hasPermission(permission, true, server, world);
} else {
return object.hasPermission(permission, true, server);
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 objectAdd(String world, PermissionHolder object, String permission) {
private boolean add(String world, PermissionHolder object, String permission) {
if (object == null) return false;
try {
@@ -83,11 +132,11 @@ public class VaultPermissionHook extends Permission {
}
} catch (ObjectAlreadyHasException ignored) {}
objectSave(object);
save(object);
return true;
}
private boolean objectRemove(String world, PermissionHolder object, String permission) {
private boolean remove(String world, PermissionHolder object, String permission) {
if (object == null) return false;
try {
@@ -98,118 +147,156 @@ public class VaultPermissionHook extends Permission {
}
} catch (ObjectLacksException ignored) {}
objectSave(object);
save(object);
return true;
}
void objectSave(PermissionHolder t) {
void save(PermissionHolder t) {
if (t instanceof User) {
((User) t).refreshPermissions();
plugin.getDatastore().saveUser(((User) t), Callback.empty());
plugin.getDatastore().saveUser(((User) t));
}
if (t instanceof Group) {
plugin.getDatastore().saveGroup(((Group) t), c -> plugin.runUpdateTask());
plugin.getDatastore().saveGroup(((Group) t));
plugin.runUpdateTask();
}
}
@Override
public boolean playerHas(String world, @NonNull String player, @NonNull String permission) {
return objectHas(world, plugin.getUserManager().get(player), permission);
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())) {
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);
}
@Override
public boolean playerAdd(String world, @NonNull String player, @NonNull String permission) {
log("Adding permission to player " + player + ": '" + permission + "' on world " + world + ", server " + server);
final User user = plugin.getUserManager().get(player);
return objectAdd(world, user, permission);
scheduleTask(() -> add(world, 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);
final User user = plugin.getUserManager().get(player);
return objectRemove(world, user, permission);
scheduleTask(() -> remove(world, user, permission));
return true;
}
@Override
public boolean groupHas(String world, @NonNull String groupName, @NonNull String permission) {
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);
}
@Override
public boolean groupAdd(String world, @NonNull String groupName, @NonNull String permission) {
log("Adding permission to group " + groupName + ": '" + permission + "' on world " + world + ", server " + server);
final Group group = plugin.getGroupManager().get(groupName);
return objectAdd(world, group, permission);
scheduleTask(() -> add(world, 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);
final Group group = plugin.getGroupManager().get(groupName);
return objectRemove(world, group, permission);
scheduleTask(() -> remove(world, 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);
final User user = plugin.getUserManager().get(player);
if (user == null) return false;
final Group group1 = plugin.getGroupManager().get(group);
if (group1 == null) return false;
if (world != null && !world.equals("")) {
return user.isInGroup(group1, server, world);
} else {
return user.isInGroup(group1);
}
return user.getNodes().stream()
.filter(Node::isGroupNode)
.filter(n -> n.shouldApplyOnServer(server, isIncludeGlobal(), false))
.filter(n -> n.shouldApplyOnWorld(world, true, false))
.map(Node::getGroupName)
.filter(s -> s.equalsIgnoreCase(group))
.findAny().isPresent();
}
@Override
public boolean playerAddGroup(String world, @NonNull String player, @NonNull String groupName) {
log("Adding player " + player + " to group: '" + groupName + "' on world " + world + ", 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;
try {
if (world != null && !world.equals("")) {
user.addGroup(group, server, world);
} else {
user.addGroup(group);
}
} catch (ObjectAlreadyHasException ignored) {}
objectSave(user);
scheduleTask(() -> {
try {
if (world != null && !world.equals("")) {
user.addGroup(group, server, world);
} else {
user.addGroup(group, server);
}
} catch (ObjectAlreadyHasException ignored) {}
save(user);
});
return true;
}
@Override
public boolean playerRemoveGroup(String world, @NonNull String player, @NonNull String groupName) {
log("Removing player " + player + " from group: '" + groupName + "' on world " + world + ", 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;
try {
if (world != null && !world.equals("")) {
user.removeGroup(group, server, world);
} else {
user.removeGroup(group);
}
} catch (ObjectLacksException ignored) {}
objectSave(user);
scheduleTask(() -> {
try {
if (world != null && !world.equals("")) {
user.removeGroup(group, server, world);
} else {
user.removeGroup(group, server);
}
} catch (ObjectLacksException ignored) {}
save(user);
});
return true;
}
@Override
public String[] getPlayerGroups(String world, @NonNull String player) {
final User user = plugin.getUserManager().get(player);
return (user == null) ? new String[0] :
world != null && !world.equals("") ? user.getGroups(server, world, includeGlobal).toArray(new String[0]) :
user.getGroupNames().toArray(new String[0]);
log("Getting groups of player: " + player + ", on world " + world + ", 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))
.map(Node::getGroupName)
.toArray(String[]::new);
}
@Override
public String getPrimaryGroup(String world, @NonNull String player) {
log("Getting primary group of player: " + player);
final User user = plugin.getUserManager().get(player);
return (user == null) ? null : user.getPrimaryGroup();
}
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.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();
}
}
@@ -0,0 +1,72 @@
/*
* 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.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.calculators.*;
import me.lucko.luckperms.users.BukkitUser;
import me.lucko.luckperms.users.User;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ContextCache {
@Getter
private final Map<String, String> context;
@Getter
private final Map<String, Boolean> permissionCache = new ConcurrentHashMap<>();
private final PermissionCalculator calculator;
public ContextCache(User user, Map<String, String> context, LuckPermsPlugin plugin, DefaultsProvider defaultsProvider) {
this.context = context;
List<PermissionProcessor> processors = new ArrayList<>(5);
processors.add(new MapProcessor(permissionCache));
if (plugin.getConfiguration().isApplyingWildcards()) {
processors.add(new WildcardProcessor(permissionCache));
}
if (plugin.getConfiguration().isApplyingRegex()) {
processors.add(new RegexProcessor(permissionCache));
}
processors.add(new DefaultsProcessor(((BukkitUser) user)::isOp, defaultsProvider));
calculator = new PermissionCalculator(plugin, user.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors);
}
public void invalidateCache() {
calculator.invalidateCache();
}
public Tristate getPermissionValue(@NonNull String permission) {
return calculator.getPermissionValue(permission);
}
}
@@ -0,0 +1,181 @@
/*
* 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;
}
}
@@ -0,0 +1,68 @@
/*
* 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,47 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.api.Tristate;
import org.bukkit.permissions.PermissionAttachmentInfo;
import java.util.Map;
@AllArgsConstructor
public class AttachmentProcessor implements PermissionProcessor {
@Getter
private final Map<String, PermissionAttachmentInfo> map;
@Override
public Tristate hasPermission(String permission) {
if (map.containsKey(permission)) {
return Tristate.fromBoolean(map.get(permission).getValue());
}
return Tristate.UNDEFINED;
}
}
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.calculators;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.Tristate;
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 DefaultsProvider defaultsProvider;
@Override
public Tristate hasPermission(String permission) {
Tristate t = defaultsProvider.hasDefault(permission, isOp.get());
if (t != Tristate.UNDEFINED) {
return t;
}
Permission defPerm = Bukkit.getServer().getPluginManager().getPermission(permission);
if (defPerm != null) {
return Tristate.fromBoolean(defPerm.getDefault().getValue(isOp.get()));
} else {
return Tristate.UNDEFINED;
}
}
}
@@ -0,0 +1,177 @@
/*
* 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.calculators;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.Tristate;
import org.bukkit.Bukkit;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class DefaultsProvider {
private final DummyPermissible opDummy = new DummyPermissible(this::refreshOp);
private final DummyPermissible nonOpDummy = new DummyPermissible(this::refreshNonOp);
private final Map<String, Boolean> op = new HashMap<>();
private final Map<String, Boolean> nonOp = new HashMap<>();
public void refresh() {
refreshOp();
refreshNonOp();
}
private void refreshOp() {
calculateDefaults(op, opDummy, true);
}
private void refreshNonOp() {
calculateDefaults(nonOp, nonOpDummy, false);
}
private static void calculateDefaults(Map<String, Boolean> map, DummyPermissible p, boolean op) {
Set<String> perms = map.keySet();
for (String name : perms) {
Bukkit.getServer().getPluginManager().unsubscribeFromPermission(name, p);
}
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(false, p);
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(true, p);
map.clear();
Set<Permission> defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(op);
Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(op, p);
for (Permission perm : defaults) {
String name = perm.getName().toLowerCase();
map.put(name, true);
Bukkit.getServer().getPluginManager().subscribeToPermission(name, p);
calculateChildPermissions(map, p, perm.getChildren(), false);
}
}
private static void calculateChildPermissions(Map<String, Boolean> map, DummyPermissible p, Map<String, Boolean> children, boolean invert) {
for (Map.Entry<String, Boolean> e : children.entrySet()) {
Permission perm = Bukkit.getServer().getPluginManager().getPermission(e.getKey());
boolean value = e.getValue() ^ invert;
String lName = e.getKey().toLowerCase();
map.put(lName, value);
Bukkit.getServer().getPluginManager().subscribeToPermission(e.getKey(), p);
if (perm != null) {
calculateChildPermissions(map, p, perm.getChildren(), !value);
}
}
}
public Tristate hasDefault(String permission, boolean isOp) {
Map<String, Boolean> map = isOp ? op : nonOp;
if (!map.containsKey(permission)) {
return Tristate.UNDEFINED;
}
return Tristate.fromBoolean(map.get(permission));
}
@AllArgsConstructor
private static class DummyPermissible implements Permissible {
private final Runnable onRefresh;
@Override
public void recalculatePermissions() {
onRefresh.run();
}
@Override
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
return Collections.emptySet();
}
@Override
public boolean isPermissionSet(String name) {
return false;
}
@Override
public boolean isPermissionSet(Permission perm) {
return false;
}
@Override
public boolean hasPermission(String name) {
return false;
}
@Override
public boolean hasPermission(Permission perm) {
return false;
}
@Override
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
return null;
}
@Override
public PermissionAttachment addAttachment(Plugin plugin) {
return null;
}
@Override
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
return null;
}
@Override
public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
return null;
}
@Override
public void removeAttachment(PermissionAttachment attachment) {
}
@Override
public boolean isOp() {
return false;
}
@Override
public void setOp(boolean value) {
}
}
}
@@ -0,0 +1,90 @@
/*
* 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.contexts;
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 org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@RequiredArgsConstructor
public class WorldCalculator extends ContextCalculator<Player> implements Listener {
private static final String WORLD_KEY = "world";
private final LuckPermsPlugin plugin;
@Getter
private final Map<UUID, String> worldCache = new ConcurrentHashMap<>();
@Override
public Map<String, String> giveApplicableContext(Player subject, Map<String, String> accumulator) {
String world = getWorld(subject);
if (world != null) {
accumulator.put(WORLD_KEY, world);
}
return accumulator;
}
@Override
public boolean isContextApplicable(Player subject, Map.Entry<String, String> context) {
if (!context.getKey().equals(WORLD_KEY)) {
return false;
}
String world = getWorld(subject);
return world != null && world.equals(context.getValue());
}
private String getWorld(Player player) {
UUID internal = plugin.getUuidCache().getUUID(player.getUniqueId());
if (!worldCache.containsKey(internal)) {
return null;
}
String world = worldCache.get(internal);
return plugin.getConfiguration().getWorldRewrites().getOrDefault(world, world);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
worldCache.put(internal, e.getPlayer().getWorld().getName());
pushUpdate(
e.getPlayer(),
Maps.immutableEntry(WORLD_KEY, e.getFrom().getName()),
Maps.immutableEntry(WORLD_KEY, e.getPlayer().getWorld().getName())
);
}
}
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.inject;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import java.util.Collections;
import java.util.Set;
public class DummyPermissibleBase extends PermissibleBase {
public DummyPermissibleBase() {
super(null);
}
@Override
public boolean isOp() {
return false;
}
@Override
public void setOp(boolean value) {
}
@Override
public boolean isPermissionSet(String name) {
return false;
}
@Override
public boolean isPermissionSet(Permission perm) {
return false;
}
@Override
public boolean hasPermission(String inName) {
return false;
}
@Override
public boolean hasPermission(Permission perm) {
return false;
}
@Override
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
return null;
}
@Override
public PermissionAttachment addAttachment(Plugin plugin) {
return null;
}
@Override
public void removeAttachment(PermissionAttachment attachment) {
}
@Override
public void recalculatePermissions() {
}
@Override
public synchronized void clearPermissions() {
}
@Override
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
return null;
}
@Override
public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
return null;
}
@Override
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
return Collections.emptySet();
}
}
@@ -62,7 +62,10 @@ public class Injector {
try {
Permissible permissible = getPermissible(sender);
if (permissible instanceof LPPermissible) {
getPermField(sender).set(sender, new PermissibleBase(sender));
/* 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());
}
return true;
} catch (Exception e) {
@@ -22,13 +22,11 @@
package me.lucko.luckperms.inject;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.utils.PermissionCalculator;
import me.lucko.luckperms.utils.PermissionProcessor;
import me.lucko.luckperms.calculators.*;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.permissions.*;
@@ -36,7 +34,6 @@ import org.bukkit.plugin.Plugin;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.stream.Collectors;
@@ -55,22 +52,24 @@ public class LPPermissible extends PermissibleBase {
private final List<PermissionAttachment> attachments = new LinkedList<>();
private final Map<String, PermissionAttachmentInfo> attachmentPermissions = new HashMap<>();
public LPPermissible(@NonNull CommandSender sender, LuckPermsPlugin plugin) {
public LPPermissible(@NonNull CommandSender sender, LuckPermsPlugin plugin, DefaultsProvider defaultsProvider) {
super(sender);
this.parent = sender;
List<PermissionProcessor> processors = new ArrayList<>(5);
processors.add(new PermissionCalculator.MapProcessor(luckPermsPermissions));
processors.add(new MapProcessor(luckPermsPermissions));
processors.add(new AttachmentProcessor(attachmentPermissions));
if (plugin.getConfiguration().getApplyWildcards()) {
processors.add(new PermissionCalculator.WildcardProcessor(luckPermsPermissions));
if (plugin.getConfiguration().isApplyingWildcards()) {
processors.add(new WildcardProcessor(luckPermsPermissions));
}
if (plugin.getConfiguration().getApplyRegex()) {
processors.add(new PermissionCalculator.RegexProcessor(luckPermsPermissions));
if (plugin.getConfiguration().isApplyingRegex()) {
processors.add(new RegexProcessor(luckPermsPermissions));
}
processors.add(new BukkitDefaultsProcessor(parent::isOp));
processors.add(new DefaultsProcessor(parent::isOp, defaultsProvider));
calculator = new PermissionCalculator(plugin, parent.getName(), plugin.getConfiguration().getDebugPermissionChecks(), processors);
calculator = new PermissionCalculator(plugin, parent.getName(), plugin.getConfiguration().isDebugPermissionChecks(), processors);
recalculatePermissions();
}
public void invalidateCache() {
@@ -89,7 +88,7 @@ public class LPPermissible extends PermissibleBase {
@Override
public boolean isPermissionSet(@NonNull String name) {
return luckPermsPermissions.containsKey(name.toLowerCase()) || attachmentPermissions.containsKey(name.toLowerCase());
return calculator.getPermissionValue(name) != Tristate.UNDEFINED;
}
@Override
@@ -198,16 +197,6 @@ public class LPPermissible extends PermissibleBase {
}
attachmentPermissions.clear();
Set<Permission> defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(isOp());
Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(isOp(), parent);
for (Permission perm : defaults) {
String name = perm.getName().toLowerCase();
attachmentPermissions.put(name, new PermissionAttachmentInfo(parent, name, null, true));
Bukkit.getServer().getPluginManager().subscribeToPermission(name, parent);
calculateChildPermissions(perm.getChildren(), false, null);
}
for (PermissionAttachment attachment : attachments) {
calculateChildPermissions(attachment.getPermissions(), false, attachment);
@@ -268,36 +257,4 @@ public class LPPermissible extends PermissibleBase {
attachment.remove();
}
}
@AllArgsConstructor
private static class AttachmentProcessor implements PermissionProcessor {
@Getter
private final Map<String, PermissionAttachmentInfo> map;
@Override
public Tristate hasPermission(String permission) {
if (map.containsKey(permission)) {
return Tristate.fromBoolean(map.get(permission).getValue());
}
return Tristate.UNDEFINED;
}
}
@AllArgsConstructor
private static class BukkitDefaultsProcessor implements PermissionProcessor {
private final Supplier<Boolean> isOp;
@Override
public Tristate hasPermission(String permission) {
Permission defPerm = Bukkit.getServer().getPluginManager().getPermission(permission);
if (defPerm != null) {
return Tristate.fromBoolean(defPerm.getDefault().getValue(isOp.get()));
} else {
return Tristate.UNDEFINED;
}
}
}
}
@@ -25,13 +25,15 @@ 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 me.lucko.luckperms.utils.Contexts;
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;
@@ -42,6 +44,10 @@ public class BukkitUser extends User {
@Setter
private LPPermissible lpPermissible = null;
@Getter
@Setter
private Map<String, Boolean> loginPreProcess = null;
BukkitUser(UUID uuid, LPBukkitPlugin plugin) {
super(uuid, plugin);
this.plugin = plugin;
@@ -52,6 +58,10 @@ public class BukkitUser extends User {
this.plugin = plugin;
}
public boolean isOp() {
return lpPermissible != null && lpPermissible.isOp();
}
@SuppressWarnings("unchecked")
@Override
public synchronized void refreshPermissions() {
@@ -62,16 +72,15 @@ public class BukkitUser extends User {
// 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(
getPlugin().getConfiguration().getServer(),
plugin.getUserManager().getWorldCache().get(getUuid()),
null,
getPlugin().getConfiguration().getIncludeGlobalPerms(),
getPlugin().getConfiguration().getIncludeGlobalWorldPerms(),
plugin.getContextManager().giveApplicableContext((Player) lpPermissible.getParent(), new HashMap<>()),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
getPlugin().getConfiguration().getApplyGlobalGroups(),
getPlugin().getConfiguration().getApplyGlobalWorldGroups()
plugin.getConfiguration().isApplyingGlobalGroups(),
plugin.getConfiguration().isApplyingGlobalWorldGroups()
),
Collections.emptyList()
Collections.emptyList(),
true
);
try {
@@ -96,7 +105,7 @@ public class BukkitUser extends User {
lpPermissible.invalidateCache();
existing.putAll(toApply);
if (plugin.getConfiguration().getAutoOp()) {
if (plugin.getConfiguration().isAutoOp()) {
boolean op = false;
for (Map.Entry<String, Boolean> e : toApply.entrySet()) {
@@ -118,5 +127,9 @@ public class BukkitUser extends User {
} catch (Exception e) {
e.printStackTrace();
}
if (plugin.getVaultHook() != null && plugin.getVaultHook().isHooked()) {
plugin.getVaultHook().getPermissionHook().getVaultUserManager().setupUser(this);
}
}
}
@@ -22,23 +22,19 @@
package me.lucko.luckperms.users;
import lombok.Getter;
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.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
public class BukkitUserManager extends UserManager {
public class BukkitUserManager extends UserManager implements ContextListener<Player> {
private final LPBukkitPlugin plugin;
@Getter
private final Map<UUID, String> worldCache = new ConcurrentHashMap<>();
public BukkitUserManager(LPBukkitPlugin plugin) {
super(plugin);
this.plugin = plugin;
@@ -51,11 +47,11 @@ public class BukkitUserManager extends UserManager {
Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid()));
if (player != null) {
if (u.getLpPermissible() != null) {
Injector.unInject(player);
Injector.unInject(player); // TODO is this needed?
u.setLpPermissible(null);
}
if (plugin.getConfiguration().getAutoOp()) {
if (plugin.getConfiguration().isAutoOp()) {
player.setOp(false);
}
}
@@ -70,18 +66,17 @@ public class BukkitUserManager extends UserManager {
}
@Override
public User make(UUID uuid) {
return new BukkitUser(uuid, plugin);
}
@Override
public User make(UUID uuid, String username) {
return new BukkitUser(uuid, username, plugin);
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, so we need to get the players on the Bukkit thread.
// 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()))
@@ -89,4 +84,14 @@ public class BukkitUserManager extends UserManager {
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);
}
}
}
+10 -2
View File
@@ -80,14 +80,22 @@ vault-server: global
# If global permissions should be considered when retrieving meta or player groups
vault-include-global: true
# Mirrors world names. Whenever LuckPerms checks what world a user is in, if the world name is in this list, the value assigned
# will be sent forward for permission calculation instead.
world-rewrite:
#world_nether: world
#world_the_end: world
# Rewrites group names. The underlying name of the group does not change, just the output in commands / placeholders / Vault.
group-name-rewrite:
#default: Member
# Which storage method the plugin should use.
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
# Fill out connection info below if you're using MySQL or MongoDB
storage-method: h2
# This block enables support for split datastores.
# Only touch this if you're sure that you know what you're doing.
# I (the author) do not endorse nor recommend the use of this feature.
split-storage:
enabled: false
methods:
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.9-SNAPSHOT</version>
<version>2.11-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -45,7 +45,7 @@ class BungeeCommand extends Command implements TabExecutor {
@Override
public void execute(CommandSender sender, String[] args) {
manager.onCommand(
BungeeSenderFactory.get().wrap(sender),
BungeeSenderFactory.get(manager.getPlugin()).wrap(sender),
"bperms",
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
Callback.empty()
@@ -54,6 +54,6 @@ class BungeeCommand extends Command implements TabExecutor {
@Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
return manager.onTabComplete(BungeeSenderFactory.get().wrap(sender), Arrays.asList(args));
return manager.onTabComplete(BungeeSenderFactory.get(manager.getPlugin()).wrap(sender), Arrays.asList(args));
}
}
@@ -22,7 +22,7 @@
package me.lucko.luckperms;
import me.lucko.luckperms.core.LPConfiguration;
import me.lucko.luckperms.config.AbstractConfiguration;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
@@ -31,8 +31,10 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
class BungeeConfig extends LPConfiguration<LPBungeePlugin> {
class BungeeConfig extends AbstractConfiguration<LPBungeePlugin> {
private Configuration configuration;
BungeeConfig(LPBungeePlugin plugin) {
@@ -62,11 +64,6 @@ class BungeeConfig extends LPConfiguration<LPBungeePlugin> {
}
}
@Override
protected void set(String path, Object value) {
configuration.set(path, value);
}
@Override
protected String getString(String path, String def) {
return configuration.getString(path, def);
@@ -81,4 +78,19 @@ class BungeeConfig extends LPConfiguration<LPBungeePlugin> {
protected boolean getBoolean(String path, boolean def) {
return configuration.getBoolean(path, def);
}
@Override
protected Map<String, String> getMap(String path, Map<String, String> def) {
Map<String, String> map = new HashMap<>();
Configuration section = configuration.getSection(path);
if (section == null) {
return def;
}
for (String key : section.getKeys()) {
map.put(key, section.getString(key));
}
return map;
}
}
@@ -29,7 +29,10 @@ import me.lucko.luckperms.utils.AbstractListener;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.*;
import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.api.event.PermissionCheckEvent;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
@@ -118,9 +121,4 @@ public class BungeeListener extends AbstractListener implements Listener {
plugin.getPlayerCache().remove(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
onLeave(e.getPlayer().getUniqueId());
}
@EventHandler
public void onPlayerServerSwitch(ServerSwitchEvent e) {
refreshPlayer(e.getPlayer().getUniqueId());
}
}
@@ -23,8 +23,7 @@
package me.lucko.luckperms;
import lombok.Getter;
import me.lucko.luckperms.utils.PermissionCalculator;
import me.lucko.luckperms.utils.PermissionProcessor;
import me.lucko.luckperms.calculators.*;
import java.util.ArrayList;
import java.util.List;
@@ -40,15 +39,15 @@ public class BungeePlayerCache {
public BungeePlayerCache(LuckPermsPlugin plugin, String name) {
List<PermissionProcessor> processors = new ArrayList<>(3);
processors.add(new PermissionCalculator.MapProcessor(permissions));
if (plugin.getConfiguration().getApplyWildcards()) {
processors.add(new PermissionCalculator.WildcardProcessor(permissions));
processors.add(new MapProcessor(permissions));
if (plugin.getConfiguration().isApplyingWildcards()) {
processors.add(new WildcardProcessor(permissions));
}
if (plugin.getConfiguration().getApplyRegex()) {
processors.add(new PermissionCalculator.RegexProcessor(permissions));
if (plugin.getConfiguration().isApplyingRegex()) {
processors.add(new RegexProcessor(permissions));
}
calculator = new PermissionCalculator(plugin, name, plugin.getConfiguration().getDebugPermissionChecks(), processors);
calculator = new PermissionCalculator(plugin, name, plugin.getConfiguration().isDebugPermissionChecks(), processors);
}
public void invalidateCache() {
@@ -22,8 +22,6 @@
package me.lucko.luckperms;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import me.lucko.luckperms.commands.SenderFactory;
import me.lucko.luckperms.constants.Constants;
import net.md_5.bungee.api.CommandSender;
@@ -32,12 +30,16 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.UUID;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BungeeSenderFactory extends SenderFactory<CommandSender> {
private static BungeeSenderFactory instance = null;
public static synchronized BungeeSenderFactory get() {
private BungeeSenderFactory(LuckPermsPlugin plugin) {
super(plugin);
}
public static synchronized BungeeSenderFactory get(LuckPermsPlugin plugin) {
if (instance == null) {
instance = new BungeeSenderFactory();
instance = new BungeeSenderFactory(plugin);
}
return instance;
}
@@ -29,9 +29,12 @@ 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.core.LPConfiguration;
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;
@@ -41,7 +44,7 @@ import me.lucko.luckperms.storage.Datastore;
import me.lucko.luckperms.storage.StorageFactory;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.BungeeUserManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LocaleManager;
import me.lucko.luckperms.utils.LogFactory;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
@@ -57,7 +60,7 @@ 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 UserManager userManager;
private BungeeUserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
@@ -66,6 +69,8 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
private Logger log;
private Importer importer;
private ConsecutiveExecutor consecutiveExecutor;
private LocaleManager localeManager;
private ContextManager<ProxiedPlayer> contextManager;
@Override
public void onEnable() {
@@ -74,6 +79,17 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
getLog().info("Loading configuration...");
configuration = new BungeeConfig(this);
localeManager = new LocaleManager();
File locale = new File(getDataFolder(), "lang.yml");
if (locale.exists()) {
getLog().info("Found locale file. Attempting to load from it.");
try {
localeManager.loadFromFile(locale);
} catch (Exception e) {
e.printStackTrace();
}
}
// register events
getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
@@ -88,20 +104,27 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
datastore = StorageFactory.getDatastore(this, "h2");
getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
uuidCache = new UuidCache(getConfiguration().isOnlineMode());
userManager = new BungeeUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager();
importer = new Importer(commandManager);
consecutiveExecutor = new ConsecutiveExecutor(commandManager);
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) {
getProxy().getScheduler().schedule(this, new UpdateTask(this), mins, mins, TimeUnit.MINUTES);
}
// 20 times per second (once per "tick")
getProxy().getScheduler().schedule(this, BungeeSenderFactory.get(), 50L, 50L, TimeUnit.MILLISECONDS);
getProxy().getScheduler().schedule(this, BungeeSenderFactory.get(this), 50L, 50L, TimeUnit.MILLISECONDS);
getProxy().getScheduler().schedule(this, new ExpireTemporaryTask(this), 3L, 3L, TimeUnit.SECONDS);
getProxy().getScheduler().schedule(this, consecutiveExecutor, 1L, 1L, TimeUnit.SECONDS);
@@ -162,14 +185,14 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
@Override
public List<Sender> getNotifyListeners() {
return getProxy().getPlayers().stream()
.map(p -> BungeeSenderFactory.get().wrap(p, Collections.singleton(Permission.LOG_NOTIFY)))
.map(p -> BungeeSenderFactory.get(this).wrap(p, Collections.singleton(Permission.LOG_NOTIFY)))
.filter(Permission.LOG_NOTIFY::isAuthorized)
.collect(Collectors.toList());
}
@Override
public Sender getConsoleSender() {
return BungeeSenderFactory.get().wrap(getProxy().getConsole());
return BungeeSenderFactory.get(this).wrap(getProxy().getConsole());
}
@Override
@@ -0,0 +1,66 @@
/*
* 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.contexts;
import com.google.common.collect.Maps;
import me.lucko.luckperms.api.context.ContextCalculator;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ServerSwitchEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import java.util.Map;
public class BackendServerCalculator extends ContextCalculator<ProxiedPlayer> implements Listener {
private static final String WORLD_KEY = "world";
@Override
public Map<String, String> giveApplicableContext(ProxiedPlayer subject, Map<String, String> accumulator) {
String server = getServer(subject);
if (server != null) {
accumulator.put(WORLD_KEY, server);
}
return accumulator;
}
@Override
public boolean isContextApplicable(ProxiedPlayer subject, Map.Entry<String, String> context) {
if (!context.getKey().equals(WORLD_KEY)) {
return false;
}
String server = getServer(subject);
return server != null && server.equals(context.getValue());
}
@EventHandler
public void onPlayerServerSwitch(ServerSwitchEvent e) {
pushUpdate(e.getPlayer(), Maps.immutableEntry("null", "null"), Maps.immutableEntry(WORLD_KEY, getServer(e.getPlayer())));
}
private static String getServer(ProxiedPlayer player) {
return player.getServer() == null ? null : (player.getServer().getInfo() == null ? null : player.getServer().getInfo().getName());
}
}
@@ -24,12 +24,13 @@ 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 me.lucko.luckperms.utils.Contexts;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -58,21 +59,18 @@ public class BungeeUser extends User {
return;
}
final String server = player.getServer() == null ? null : (player.getServer().getInfo() == null ? null : player.getServer().getInfo().getName());
// Calculate the permissions that should be applied. This is done async.
Map<String, Boolean> toApply = exportNodes(
new Contexts(
plugin.getConfiguration().getServer(),
server,
null,
plugin.getConfiguration().getIncludeGlobalPerms(),
plugin.getConfiguration().getIncludeGlobalWorldPerms(),
plugin.getContextManager().giveApplicableContext(player, new HashMap<>()),
plugin.getConfiguration().isIncludingGlobalPerms(),
plugin.getConfiguration().isIncludingGlobalWorldPerms(),
true,
plugin.getConfiguration().getApplyGlobalGroups(),
plugin.getConfiguration().getApplyGlobalWorldGroups()
plugin.getConfiguration().isApplyingGlobalGroups(),
plugin.getConfiguration().isApplyingGlobalWorldGroups()
),
Collections.emptyList()
Collections.emptyList(),
true
);
Map<String, Boolean> existing = playerCache.getPermissions();
@@ -23,10 +23,13 @@
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 {
public class BungeeUserManager extends UserManager implements ContextListener<ProxiedPlayer> {
private final LPBungeePlugin plugin;
public BungeeUserManager(LPBungeePlugin plugin) {
@@ -42,13 +45,12 @@ public class BungeeUserManager extends UserManager {
}
@Override
public User make(UUID uuid) {
return new BungeeUser(uuid, plugin);
}
@Override
public User make(UUID uuid, String username) {
return new BungeeUser(uuid, username, plugin);
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
@@ -57,4 +59,14 @@ public class BungeeUserManager extends UserManager {
.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);
}
}
}
+12 -2
View File
@@ -59,14 +59,24 @@ log-notify: true
# If LuckPerms should print to console every time a plugin checks if a player has a permission
debug-permission-checks: false
# Mirrors world names. Whenever LuckPerms checks what world a user is in, if the world name is in this list, the value assigned
# will be sent forward for permission calculation instead.
# Remember world names on BungeeCord relate to the backend server name a user is connected to.
world-rewrite:
#hub2: hub
#hub3: hub
#opfactions: factions
# Rewrites group names. The underlying name of the group does not change, just the output in commands / placeholders / Vault.
group-name-rewrite:
#default: Member
# Which storage method the plugin should use.
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
# Fill out connection info below if you're using MySQL or MongoDB
storage-method: h2
# This block enables support for split datastores.
# Only touch this if you're sure that you know what you're doing.
# I (the author) do not endorse nor recommend the use of this feature.
split-storage:
enabled: false
methods:
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.9-SNAPSHOT</version>
<version>2.11-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -27,14 +27,16 @@ 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.core.LPConfiguration;
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 java.io.File;
import java.util.List;
@@ -60,6 +62,8 @@ public interface LuckPermsPlugin {
ApiProvider getApiProvider();
Importer getImporter();
ConsecutiveExecutor getConsecutiveExecutor();
LocaleManager getLocaleManager();
ContextManager getContextManager();
/**
* @return the version of the plugin
@@ -27,9 +27,12 @@ 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 java.util.Optional;
import java.util.Set;
@@ -67,7 +70,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public double getApiVersion() {
return 2.9;
return 2.11;
}
@Override
@@ -147,7 +150,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public boolean isUserLoaded(@NonNull UUID uuid) {
return plugin.getUserManager().isLoaded(uuid);
return plugin.getUserManager().isLoaded(UserIdentifier.of(uuid, null));
}
@Override
@@ -208,6 +211,18 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Node.Builder buildNode(@NonNull String permission) throws IllegalArgumentException {
return new me.lucko.luckperms.utils.Node.Builder(checkNode(permission));
return new me.lucko.luckperms.core.Node.Builder(checkNode(permission));
}
@SuppressWarnings("unchecked")
@Override
public void registerContextCalculator(IContextCalculator<?> contextCalculator) {
plugin.getContextManager().registerCalculator(contextCalculator);
}
@SuppressWarnings("unchecked")
@Override
public void registerContextListener(ContextListener<?> contextListener) {
plugin.getContextManager().registerListener(contextListener);
}
}
@@ -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.core.LPConfiguration}
* Provides a link between {@link LPConfiguration} and {@link me.lucko.luckperms.config.LPConfiguration}
*/
@AllArgsConstructor
public class LPConfigurationLink implements LPConfiguration {
private final me.lucko.luckperms.core.LPConfiguration master;
private final me.lucko.luckperms.config.LPConfiguration master;
@Override
public String getServer() {
@@ -58,67 +58,67 @@ public class LPConfigurationLink implements LPConfiguration {
@Override
public boolean getIncludeGlobalPerms() {
return master.getIncludeGlobalPerms();
return master.isIncludingGlobalPerms();
}
@Override
public boolean getIncludeGlobalWorldPerms() {
return master.getIncludeGlobalWorldPerms();
return master.isIncludingGlobalWorldPerms();
}
@Override
public boolean getApplyGlobalGroups() {
return master.getApplyGlobalGroups();
return master.isApplyingGlobalGroups();
}
@Override
public boolean getApplyGlobalWorldGroups() {
return master.getApplyGlobalWorldGroups();
return master.isApplyingGlobalWorldGroups();
}
@Override
public boolean getOnlineMode() {
return master.getOnlineMode();
return master.isOnlineMode();
}
@Override
public boolean getApplyWildcards() {
return master.getApplyWildcards();
return master.isApplyingWildcards();
}
@Override
public boolean getApplyRegex() {
return master.getApplyRegex();
return master.isApplyingRegex();
}
@Override
public boolean getApplyShorthand() {
return master.getApplyShorthand();
return master.isApplyingShorthand();
}
@Override
public boolean getLogNotify() {
return master.getLogNotify();
return master.isLogNotify();
}
@Override
public boolean getDebugPermissionChecks() {
return master.getDebugPermissionChecks();
return master.isDebugPermissionChecks();
}
@Override
public boolean getEnableOps() {
return master.getEnableOps();
return master.isOpsEnabled();
}
@Override
public boolean getCommandsAllowOp() {
return master.getCommandsAllowOp();
return master.isCommandsAllowOp();
}
@Override
public boolean getAutoOp() {
return master.getAutoOp();
return master.isAutoOp();
}
@Override
@@ -128,7 +128,7 @@ public class LPConfigurationLink implements LPConfiguration {
@Override
public boolean getVaultIncludeGlobal() {
return master.getVaultIncludeGlobal();
return master.isVaultIncludingGlobal();
}
@SuppressWarnings("deprecation")
@@ -149,10 +149,9 @@ public class LPConfigurationLink implements LPConfiguration {
@Override
public boolean getSplitStorage() {
return master.getSplitStorage();
return master.isSplitStorage();
}
@SuppressWarnings("unchecked")
@Override
public Map<String, String> getSplitStorageOptions() {
return master.getSplitStorageOptions();
@@ -24,12 +24,9 @@ package me.lucko.luckperms.api.implementation.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.utils.Contexts;
import java.util.*;
@@ -39,7 +36,7 @@ import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
/**
* Provides a link between {@link PermissionHolder} and {@link me.lucko.luckperms.core.PermissionHolder}
*/
@SuppressWarnings({"unused", "deprecation"})
@SuppressWarnings("unused")
@AllArgsConstructor
public class PermissionHolderLink implements PermissionHolder {
@@ -52,18 +49,18 @@ public class PermissionHolderLink implements PermissionHolder {
}
@Override
public SortedSet<Node> getPermissions() {
return Collections.unmodifiableSortedSet(master.getPermissions(false));
public SortedSet<? extends Node> getPermissions() {
return master.getPermissions(false);
}
@Override
public Set<Node> getEnduringPermissions() {
return Collections.unmodifiableSet(master.getNodes());
return master.getNodes();
}
@Override
public Set<Node> getTransientPermissions() {
return Collections.unmodifiableSet(master.getTransientNodes());
return master.getTransientNodes();
}
@Override
@@ -71,6 +68,16 @@ public class PermissionHolderLink implements PermissionHolder {
return Collections.unmodifiableSet(master.getAllNodes(Collections.emptyList(), Contexts.allowAll()));
}
@Override
public SortedSet<LocalizedNode> getAllNodes(@NonNull Contexts contexts) {
return master.getAllNodes(Collections.emptyList(), contexts);
}
@Override
public Set<LocalizedNode> getAllNodesFiltered(@NonNull Contexts contexts) {
return master.getAllNodesFiltered(contexts);
}
@Override
public Map<String, Boolean> getNodes() {
return exportToLegacy(master.getNodes());
@@ -233,27 +240,50 @@ public class PermissionHolderLink implements PermissionHolder {
@Override
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups, List<String> possibleNodes) {
return master.getLocalPermissions(server, world, excludedGroups, possibleNodes);
Map<String, String> context = new HashMap<>();
if (server != null && !server.equals("")) {
context.put("server", server);
}
if (world != null && !world.equals("")) {
context.put("world", world);
}
return master.exportNodes(new Contexts(context, true, true, true, true, true), Collections.emptyList(), false);
}
@Override
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups) {
return master.getLocalPermissions(server, world, excludedGroups);
Map<String, String> context = new HashMap<>();
if (server != null && !server.equals("")) {
context.put("server", server);
}
if (world != null && !world.equals("")) {
context.put("world", world);
}
return master.exportNodes(new Contexts(context, true, true, true, true, true), Collections.emptyList(), false);
}
@Override
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups, List<String> possibleNodes) {
return master.getLocalPermissions(server, excludedGroups, possibleNodes);
return getLocalPermissions(server, null, excludedGroups, possibleNodes);
}
@Override
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups) {
return master.getLocalPermissions(server, excludedGroups);
return getLocalPermissions(server, null, excludedGroups, null);
}
@Override
public Map<String, Boolean> getPermissions(String server, String world, Map<String, String> extraContext, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups) {
return master.exportNodes(new Contexts(server, world, extraContext, includeGlobal, includeGlobal, applyGroups, true, true), possibleNodes);
if (extraContext == null) {
extraContext = new HashMap<>();
}
if (server != null && !server.equals("")) {
extraContext.put("server", server);
}
if (world != null && !world.equals("")) {
extraContext.put("world", world);
}
return master.exportNodes(new Contexts(extraContext, includeGlobal, includeGlobal, applyGroups, true, true), possibleNodes, false);
}
@Override
@@ -0,0 +1,45 @@
/*
* 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.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.api.Tristate;
import java.util.Map;
@AllArgsConstructor
public class MapProcessor implements PermissionProcessor {
@Getter
private final Map<String, Boolean> map;
@Override
public Tristate hasPermission(String permission) {
if (map.containsKey(permission)) {
return Tristate.fromBoolean(map.get(permission));
}
return Tristate.UNDEFINED;
}
}
@@ -0,0 +1,71 @@
/*
* 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.calculators;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.Tristate;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Calculates and caches permissions
*/
@RequiredArgsConstructor
public class PermissionCalculator {
private final LuckPermsPlugin plugin;
private final String objectName;
private final boolean debug;
private final List<PermissionProcessor> processors;
private final Map<String, Tristate> cache = new ConcurrentHashMap<>();
public void invalidateCache() {
cache.clear();
}
public Tristate getPermissionValue(String permission) {
permission = permission.toLowerCase();
Tristate t = cache.computeIfAbsent(permission, this::lookupPermissionValue);
if (debug) {
plugin.getLog().info("Checking if " + objectName + " has permission: " + permission + " - (" + t.toString() + ")");
}
return t;
}
private Tristate lookupPermissionValue(String permission) {
for (PermissionProcessor processor : processors) {
Tristate v = processor.hasPermission(permission);
if (v == Tristate.UNDEFINED) {
continue;
}
return v;
}
return Tristate.UNDEFINED;
}
}
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.utils;
package me.lucko.luckperms.calculators;
import me.lucko.luckperms.api.Tristate;
@@ -0,0 +1,56 @@
/*
* 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.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.constants.Patterns;
import java.util.Map;
import java.util.regex.Pattern;
@AllArgsConstructor
public class RegexProcessor implements PermissionProcessor {
@Getter
private final Map<String, Boolean> map;
@Override
public Tristate hasPermission(String permission) {
for (Map.Entry<String, Boolean> e : map.entrySet()) {
if (e.getKey().toLowerCase().startsWith("r=")) {
Pattern p = Patterns.compile(e.getKey().substring(2));
if (p == null) {
continue;
}
if (p.matcher(permission).matches()) {
return Tristate.fromBoolean(e.getValue());
}
}
}
return Tristate.UNDEFINED;
}
}
@@ -0,0 +1,80 @@
/*
* 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.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.api.Tristate;
import java.util.Map;
@AllArgsConstructor
public class WildcardProcessor implements PermissionProcessor {
@Getter
private final Map<String, Boolean> map;
@Override
public Tristate hasPermission(String permission) {
String node = permission;
while (node.contains(".")) {
int endIndex = node.lastIndexOf('.');
if (endIndex == -1) {
break;
}
node = node.substring(0, endIndex);
if (!isEmpty(node)) {
if (map.containsKey(node + ".*")) {
return Tristate.fromBoolean(map.get(node + ".*"));
}
}
}
if (map.containsKey("'*'")) {
return Tristate.fromBoolean(map.get("'*'"));
}
if (map.containsKey("*")) {
return Tristate.fromBoolean(map.get("*"));
}
return Tristate.UNDEFINED;
}
private static boolean isEmpty(String s) {
if (s.equals("")) {
return true;
}
char[] chars = s.toCharArray();
for (char c : chars) {
if (c != '.') {
return false;
}
}
return true;
}
}
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.commands;
import com.google.common.collect.ImmutableList;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Arg {
public static Arg create(String name, boolean required, String description) {
return new Arg(name, required, description);
}
public static ImmutableList<Arg> list(Arg... args) {
return ImmutableList.copyOf(args);
}
private final String name;
private final boolean required;
private final String description;
public String asPrettyString() {
if (required) {
return "&8<&7" + name + "&8>";
} else {
return "&8[&7" + name + "&8]";
}
}
}
@@ -39,7 +39,7 @@ 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.constants.Message;
import me.lucko.luckperms.commands.usersbulkedit.UsersBulkEditMainCommand;
import java.util.ArrayList;
import java.util.Collections;
@@ -49,6 +49,7 @@ import java.util.stream.Collectors;
@AllArgsConstructor
public class CommandManager {
@Getter
private final LuckPermsPlugin plugin;
@Getter
@@ -64,6 +65,7 @@ public class CommandManager {
.add(new ExportCommand())
.add(new QueueCommand())
.add(new MigrationMainCommand())
.add(new UsersBulkEditMainCommand())
.add(new CreateGroup())
.add(new DeleteGroup())
.add(new ListGroups())
@@ -177,10 +179,9 @@ public class CommandManager {
}
private void sendCommandUsage(Sender sender, String label) {
Message.INFO_BRIEF.send(sender, plugin.getVersion());
Util.sendPluginMessage(sender, "&2Running &bLuckPerms v" + plugin.getVersion() + "&2.");
mainCommands.stream()
.filter(c -> c.isAuthorized(sender))
.forEach(c -> Util.sendPluginMessage(sender, "&e-> &d" + String.format(c.getUsage(), label)));
.forEach(c -> Util.sendPluginMessage(sender, "&3> &a" + String.format(c.getUsage(), label)));
}
}
@@ -98,7 +98,7 @@ public abstract class MainCommand<T> {
}
if (sub.getIsArgumentInvalid().test(strippedArgs.size())) {
sub.sendUsage(sender, label);
sub.sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -137,7 +137,7 @@ public abstract class MainCommand<T> {
*/
protected void sendUsage(Sender sender, String label) {
if (getSubCommands().isEmpty()) {
Util.sendPluginMessage(sender, "&e-> &d" + String.format(getUsage(), label));
Util.sendPluginMessage(sender, "&3> &a" + String.format(getUsage(), label));
return;
}
@@ -146,10 +146,10 @@ public abstract class MainCommand<T> {
.collect(Collectors.toList());
if (subs.size() > 0) {
Util.sendPluginMessage(sender, "&e" + getName() + " Sub Commands:");
Util.sendPluginMessage(sender, "&b" + getName() + " Sub Commands: &7(" + String.format(getUsage(), label) + " ...)");
for (SubCommand s : subs) {
s.sendUsage(sender, label);
s.sendUsage(sender);
}
} else {
@@ -22,6 +22,7 @@
package me.lucko.luckperms.commands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Permission;
import java.util.UUID;
@@ -31,6 +32,7 @@ import java.util.UUID;
*/
public interface Sender {
LuckPermsPlugin getPlatform();
String getName();
UUID getUuid();
void sendMessage(String s);
@@ -24,6 +24,8 @@ package me.lucko.luckperms.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;
@@ -36,7 +38,9 @@ import java.util.stream.Collectors;
* Factory class to make a thread-safe sender instance
* @param <T> the command sender type
*/
@RequiredArgsConstructor
public abstract class SenderFactory<T> implements Runnable {
private final LuckPermsPlugin plugin;
private final Map<T, List<String>> messages = new HashMap<>();
private final AtomicBoolean shouldSend = new AtomicBoolean(false);
private final SenderFactory<T> factory = this;
@@ -47,11 +51,11 @@ public abstract class SenderFactory<T> implements Runnable {
protected abstract boolean hasPermission(T t, String node);
public final Sender wrap(T t) {
return new SenderImp(t, null);
return new SenderImp(plugin, t, null);
}
public final Sender wrap(T t, Set<Permission> toCheck) {
return new SenderImp(t, toCheck);
return new SenderImp(plugin, t, toCheck);
}
@Override
@@ -85,7 +89,11 @@ public abstract class SenderFactory<T> implements Runnable {
private final boolean console;
private SenderImp(T t, Set<Permission> toCheck) {
@Getter
private final LuckPermsPlugin platform;
private SenderImp(LuckPermsPlugin platform, T t, Set<Permission> toCheck) {
this.platform = platform;
this.tRef = new WeakReference<>(t);
this.name = factory.getName(t);
this.uuid = factory.getUuid(t);
@@ -22,6 +22,7 @@
package me.lucko.luckperms.commands;
import com.google.common.collect.ImmutableList;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
@@ -55,11 +56,6 @@ public abstract class SubCommand<T> {
*/
private final String description;
/**
* The command usage
*/
private final String usage;
/**
* The permission needed to use this command
*/
@@ -70,6 +66,8 @@ public abstract class SubCommand<T> {
*/
private final Predicate<? super Integer> isArgumentInvalid;
private final ImmutableList<Arg> args;
/**
* Called when this sub command is ran
* @param plugin a link to the main plugin instance
@@ -95,10 +93,28 @@ public abstract class SubCommand<T> {
/**
* Send the command usage to a sender
* @param sender the sender to send the usage to
* @param label the command label used
*/
public void sendUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&e-> &d" + String.format(getUsage(), label));
public void sendUsage(Sender sender) {
String usage = "";
if (args != null) {
usage += "&3 - &7";
for (Arg arg : args) {
usage += arg.asPrettyString() + " ";
}
}
Util.sendPluginMessage(sender, "&3> &a" + getName() + usage);
}
public void sendDetailedUsage(Sender sender) {
Util.sendPluginMessage(sender, "&3&lCommand Usage &3- &b" + getName());
Util.sendPluginMessage(sender, "&b> &7" + getDescription());
if (args != null) {
Util.sendPluginMessage(sender, "&3Arguments:");
for (Arg arg : args) {
Util.sendPluginMessage(sender, "&b- " + arg.asPrettyString() + "&3 -> &7" + arg.getDescription());
}
}
}
/**
@@ -23,7 +23,9 @@
package me.lucko.luckperms.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;
@@ -79,27 +81,38 @@ public class Util {
return b ? "&atrue" : "&cfalse";
}
public static void sendBoolean(Sender sender, String node, boolean b) {
sender.sendMessage(Util.color("&b" + node + ": " + formatBoolean(b)));
public static String formatTristate(Tristate t) {
switch (t) {
case TRUE:
return "&atrue";
case FALSE:
return "&cfalse";
default:
return "&cundefined";
}
}
public static void sendTristate(Sender sender, String node, Tristate t) {
sender.sendMessage(Util.color("&b" + node + ": " + formatTristate(t)));
}
public static String listToCommaSep(List<String> strings) {
if (strings.isEmpty()) return "&6None";
if (strings.isEmpty()) return "&bNone";
StringBuilder sb = new StringBuilder();
strings.forEach(s -> sb.append("&6").append(s).append("&7, "));
strings.forEach(s -> sb.append("&3").append(s).append("&7, "));
return sb.delete(sb.length() - 2, sb.length()).toString();
}
public static String listToArrowSep(List<String> strings, String highlight) {
if (strings.isEmpty()) return "&6None";
if (strings.isEmpty()) return "&bNone";
StringBuilder sb = new StringBuilder();
for (String s : strings) {
if (s.equalsIgnoreCase(highlight)) {
sb.append("&e").append(s).append("&7 ---> ");
sb.append("&b").append(s).append("&7 ---> ");
} else {
sb.append("&6").append(s).append("&7 ---> ");
sb.append("&3").append(s).append("&7 ---> ");
}
}
return sb.delete(sb.length() - 6, sb.length()).toString();
@@ -111,11 +124,11 @@ public class Util {
StringBuilder sb = new StringBuilder();
for (String s : strings) {
if (s.equalsIgnoreCase(highlightFirst)) {
sb.append("&e").append(s).append("&4").append(reversed ? " <--- " : " ---> ");
sb.append("&b").append(s).append("&4").append(reversed ? " <--- " : " ---> ");
} else if (s.equalsIgnoreCase(highlightSecond)) {
sb.append("&e").append(s).append("&7").append(reversed ? " <--- " : " ---> ");
sb.append("&b").append(s).append("&7").append(reversed ? " <--- " : " ---> ");
} else {
sb.append("&6").append(s).append("&7").append(reversed ? " <--- " : " ---> ");
sb.append("&3").append(s).append("&7").append(reversed ? " <--- " : " ---> ");
}
}
return sb.delete(sb.length() - 6, sb.length()).toString();
@@ -125,18 +138,18 @@ public class Util {
if (strings.isEmpty()) return "&6None";
StringBuilder sb = new StringBuilder();
strings.forEach(s -> sb.append("&6").append(s).append("&e ---> "));
strings.forEach(s -> sb.append("&3").append(s).append("&b ---> "));
return sb.delete(sb.length() - 6, sb.length()).toString();
}
public static String permNodesToString(SortedSet<Node> nodes) {
public static String permNodesToString(SortedSet<LocalizedNode> nodes) {
StringBuilder sb = new StringBuilder();
for (Node node : nodes) {
if (node.isTemporary()) {
continue;
}
sb.append("&6-> ").append(node.getValue() ? "&a" : "&c");
sb.append("&3> ").append(node.getValue() ? "&a" : "&c");
sb.append(node.getPermission());
if (node.isServerSpecific()) {
sb.append(" &7(&f").append(node.getServer().get()).append("&7)");
@@ -148,13 +161,13 @@ public class Util {
}
if (sb.length() == 0) {
return "&6None";
return "&3None";
}
return sb.toString();
}
public static String tempNodesToString(SortedSet<Node> nodes) {
public static String tempNodesToString(SortedSet<LocalizedNode> nodes) {
StringBuilder sb = new StringBuilder();
for (Node node : nodes) {
@@ -162,7 +175,7 @@ public class Util {
continue;
}
sb.append("&6-> ").append(node.getValue() ? "&a" : "&c");
sb.append("&3> ").append(node.getValue() ? "&a" : "&c");
sb.append(node.getPermission());
if (node.isServerSpecific()) {
sb.append(" &7(&f").append(node.getServer().get()).append("&7)");
@@ -175,7 +188,65 @@ public class Util {
}
if (sb.length() == 0) {
return "&6None";
return "&3None";
}
return sb.toString();
}
public static String permGroupsToString(SortedSet<LocalizedNode> nodes) {
StringBuilder sb = new StringBuilder();
for (Node node : nodes) {
if (!node.isGroupNode()) {
continue;
}
if (node.isTemporary()) {
continue;
}
sb.append("&3> &f").append(node.getGroupName());
if (node.isServerSpecific()) {
sb.append(" &7(&f").append(node.getServer().get()).append("&7)");
}
if (node.isWorldSpecific()) {
sb.append(" &7(&f").append(node.getWorld().get()).append("&7)");
}
sb.append("\n");
}
if (sb.length() == 0) {
return "&3None";
}
return sb.toString();
}
public static String tempGroupsToString(SortedSet<LocalizedNode> nodes) {
StringBuilder sb = new StringBuilder();
for (Node node : nodes) {
if (!node.isGroupNode()) {
continue;
}
if (!node.isTemporary()) {
continue;
}
sb.append("&3> &f").append(node.getGroupName());
if (node.isServerSpecific()) {
sb.append(" &7(&f").append(node.getServer().get()).append("&7)");
}
if (node.isWorldSpecific()) {
sb.append(" &7(&f").append(node.getWorld().get()).append("&7)");
}
sb.append("&6 - expires in ").append(DateUtil.formatDateDiff(node.getExpiryUnixTime())).append("\n");
}
if (sb.length() == 0) {
return "&3None";
}
return sb.toString();
@@ -71,7 +71,7 @@ public class DeleteGroup extends SingleMainCommand {
return CommandResult.FAILURE;
}
Message.DELETE_SUCCESS.send(sender, groupName);
Message.DELETE_SUCCESS.send(sender, group.getDisplayName());
LogEntry.build().actor(sender).actedName(groupName).type('G').action("delete").build().submit(plugin, sender);
plugin.runUpdateTask();
return CommandResult.SUCCESS;
@@ -39,6 +39,7 @@ public class GroupMainCommand extends MainCommand<Group> {
super("Group", "/%s group <group>", 2, ImmutableList.<SubCommand<Group>>builder()
.add(new GroupInfo())
.add(new GroupListNodes())
.add(new GroupListParents())
.add(new GroupHasPerm())
.add(new GroupInheritsPerm())
.add(new GroupSetPermission())
@@ -59,8 +60,10 @@ public class GroupMainCommand extends MainCommand<Group> {
.add(new GroupAddTempSuffix())
.add(new GroupRemoveTempPrefix())
.add(new GroupRemoveTempSuffix())
.add(new GroupBulkChange())
.add(new GroupClear())
.add(new GroupRename())
.add(new GroupClone())
.build()
);
}
@@ -29,9 +29,11 @@ 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 java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ListGroups extends SingleMainCommand {
public ListGroups() {
@@ -45,7 +47,13 @@ public class ListGroups extends SingleMainCommand {
return CommandResult.LOADING_ERROR;
}
Message.GROUPS_LIST.send(sender, Util.listToCommaSep(new ArrayList<>(plugin.getGroupManager().getAll().keySet())));
Message.GROUPS_LIST.send(
sender,
Util.listToCommaSep(new ArrayList<>(plugin.getGroupManager().getAll().values().stream()
.map(Group::getDisplayName)
.collect(Collectors.toList()))
)
);
return CommandResult.SUCCESS;
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -38,8 +35,14 @@ import java.util.List;
public class GroupAddPrefix extends SubCommand<Group> {
public GroupAddPrefix() {
super("addprefix", "Adds a prefix to the group", "/%s group <group> addprefix <priority> <prefix> [server] [world]",
Permission.GROUP_ADDPREFIX, Predicate.notInRange(2, 4));
super("addprefix", "Adds a prefix to the group", Permission.GROUP_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
@@ -65,14 +68,14 @@ public class GroupAddPrefix extends SubCommand<Group> {
if (args.size() == 3) {
group.setPermission(node, true, server);
Message.ADDPREFIX_SERVER_SUCCESS.send(sender, group.getName(), prefix, priority, server);
Message.ADDPREFIX_SERVER_SUCCESS.send(sender, group.getDisplayName(), prefix, priority, server);
LogEntry.build().actor(sender).acted(group)
.action("addprefix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
group.setPermission(node, true, server, world);
Message.ADDPREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), prefix, priority, server, world);
Message.ADDPREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), prefix, priority, server, world);
LogEntry.build().actor(sender).acted(group)
.action("addprefix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
@@ -80,7 +83,7 @@ public class GroupAddPrefix extends SubCommand<Group> {
} else {
group.setPermission(node, true);
Message.ADDPREFIX_SUCCESS.send(sender, group.getName(), prefix, priority);
Message.ADDPREFIX_SUCCESS.send(sender, group.getDisplayName(), prefix, priority);
LogEntry.build().actor(sender).acted(group)
.action("addprefix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
@@ -89,7 +92,7 @@ public class GroupAddPrefix extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_PREFIX.send(sender, group.getName());
Message.ALREADY_HAS_PREFIX.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -38,8 +35,14 @@ import java.util.List;
public class GroupAddSuffix extends SubCommand<Group> {
public GroupAddSuffix() {
super("addsuffix", "Adds a suffix to the group", "/%s group <group> addsuffix <priority> <suffix> [server] [world]",
Permission.GROUP_ADDSUFFIX, Predicate.notInRange(2, 4));
super("addsuffix", "Adds a suffix to the group", Permission.GROUP_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
@@ -65,14 +68,14 @@ public class GroupAddSuffix extends SubCommand<Group> {
if (args.size() == 3) {
group.setPermission(node, true, server);
Message.ADDSUFFIX_SERVER_SUCCESS.send(sender, group.getName(), suffix, priority, server);
Message.ADDSUFFIX_SERVER_SUCCESS.send(sender, group.getDisplayName(), suffix, priority, server);
LogEntry.build().actor(sender).acted(group)
.action("addsuffix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
group.setPermission(node, true, server, world);
Message.ADDSUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), suffix, priority, server, world);
Message.ADDSUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), suffix, priority, server, world);
LogEntry.build().actor(sender).acted(group)
.action("addsuffix " + priority + " " + args.get(1) + " " + server + " " + world)
.build().submit(plugin, sender);
@@ -80,7 +83,7 @@ public class GroupAddSuffix extends SubCommand<Group> {
} else {
group.setPermission(node, true);
Message.ADDSUFFIX_SUCCESS.send(sender, group.getName(), suffix, priority);
Message.ADDSUFFIX_SUCCESS.send(sender, group.getDisplayName(), suffix, priority);
LogEntry.build().actor(sender).acted(group)
.action("addsuffix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
@@ -89,7 +92,7 @@ public class GroupAddSuffix extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_SUFFIX.send(sender, group.getName());
Message.ALREADY_HAS_SUFFIX.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -39,8 +36,15 @@ import java.util.List;
public class GroupAddTempPrefix extends SubCommand<Group> {
public GroupAddTempPrefix() {
super("addtempprefix", "Adds a prefix to the group temporarily", "/%s group <group> addtempprefix <priority> <prefix> <duration> [server] [world]",
Permission.GROUP_ADD_TEMP_PREFIX, Predicate.notInRange(3, 5));
super("addtempprefix", "Adds a prefix to the group temporarily", Permission.GROUP_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
@@ -83,14 +87,14 @@ public class GroupAddTempPrefix extends SubCommand<Group> {
if (args.size() == 4) {
group.setPermission(node, true, server, duration);
Message.ADD_TEMP_PREFIX_SERVER_SUCCESS.send(sender, group.getName(), prefix, priority, server, DateUtil.formatDateDiff(duration));
Message.ADD_TEMP_PREFIX_SERVER_SUCCESS.send(sender, group.getDisplayName(), prefix, priority, server, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(4).toLowerCase();
group.setPermission(node, true, server, world, duration);
Message.ADD_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), prefix, priority, server, world, DateUtil.formatDateDiff(duration));
Message.ADD_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), prefix, priority, server, world, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration + " " + server + " " + world)
.build().submit(plugin, sender);
@@ -98,7 +102,7 @@ public class GroupAddTempPrefix extends SubCommand<Group> {
} else {
group.setPermission(node, true, duration);
Message.ADD_TEMP_PREFIX_SUCCESS.send(sender, group.getName(), prefix, priority, DateUtil.formatDateDiff(duration));
Message.ADD_TEMP_PREFIX_SUCCESS.send(sender, group.getDisplayName(), prefix, priority, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("addtempprefix " + priority + " " + args.get(1) + " " + duration)
.build().submit(plugin, sender);
@@ -107,7 +111,7 @@ public class GroupAddTempPrefix extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_PREFIX.send(sender, group.getName());
Message.ALREADY_HAS_PREFIX.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -39,8 +36,15 @@ import java.util.List;
public class GroupAddTempSuffix extends SubCommand<Group> {
public GroupAddTempSuffix() {
super("addtempsuffix", "Adds a suffix to the group temporarily", "/%s group <group> addtempsuffix <priority> <suffix> <duration> [server] [world]",
Permission.GROUP_ADD_TEMP_SUFFIX, Predicate.notInRange(3, 5));
super("addtempsuffix", "Adds a suffix to the group temporarily", Permission.GROUP_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
@@ -83,14 +87,14 @@ public class GroupAddTempSuffix extends SubCommand<Group> {
if (args.size() == 4) {
group.setPermission(node, true, server, duration);
Message.ADD_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, group.getName(), suffix, priority, server, DateUtil.formatDateDiff(duration));
Message.ADD_TEMP_SUFFIX_SERVER_SUCCESS.send(sender, group.getDisplayName(), suffix, priority, server, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(4).toLowerCase();
group.setPermission(node, true, server, world, duration);
Message.ADD_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), suffix, priority, server, world, DateUtil.formatDateDiff(duration));
Message.ADD_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), suffix, priority, server, world, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration + " " + server + " " + world)
.build().submit(plugin, sender);
@@ -98,7 +102,7 @@ public class GroupAddTempSuffix extends SubCommand<Group> {
} else {
group.setPermission(node, true, duration);
Message.ADD_TEMP_SUFFIX_SUCCESS.send(sender, group.getName(), suffix, priority, DateUtil.formatDateDiff(duration));
Message.ADD_TEMP_SUFFIX_SUCCESS.send(sender, group.getDisplayName(), suffix, priority, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("addtempsuffix " + priority + " " + args.get(1) + " " + duration)
.build().submit(plugin, sender);
@@ -107,7 +111,7 @@ public class GroupAddTempSuffix extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_SUFFIX.send(sender, group.getName());
Message.ALREADY_HAS_SUFFIX.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.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.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class GroupBulkChange extends SubCommand<Group> {
public GroupBulkChange() {
super("bulkchange", "Applies a bulk permission change to the group's permissions", Permission.GROUP_BULKCHANGE, Predicate.not(3),
Arg.list(
Arg.create("server|world", true, "if the bulk change is modifying a 'server' or a 'world'"),
Arg.create("from", true, "the server/world to be changed from. can be 'global' or 'null' respectively"),
Arg.create("to", true, "the server/world to replace 'from' (can be 'null')")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
String type = args.get(0).toLowerCase();
String from = args.get(1);
String to = args.get(2);
if (to.equals("null")) {
to = null;
}
Set<Node> toAdd = new HashSet<>();
Set<Node> toRemove = new HashSet<>();
if (!type.equals("world") && !type.equals("server")) {
Message.BULK_CHANGE_TYPE_ERROR.send(sender);
return CommandResult.FAILURE;
}
Iterator<Node> iterator = group.getNodes().iterator();
if (type.equals("world")) {
while (iterator.hasNext()) {
Node element = iterator.next();
String world = element.getWorld().orElse("null");
if (!world.equals(from)) {
continue;
}
toRemove.add(element);
toAdd.add(me.lucko.luckperms.core.Node.builderFromExisting(element).setWorld(to).build());
}
} else {
while (iterator.hasNext()) {
Node element = iterator.next();
String server = element.getServer().orElse("global");
if (!server.equals(from)) {
continue;
}
toRemove.add(element);
toAdd.add(me.lucko.luckperms.core.Node.builderFromExisting(element).setServer(to).build());
}
}
toRemove.forEach(n -> {
try {
group.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
});
toAdd.forEach(n -> {
try {
group.setPermission(n);
} catch (ObjectAlreadyHasException ignored) {}
});
save(group, sender, plugin);
Message.BULK_CHANGE_SUCCESS.send(sender, toAdd.size());
return CommandResult.SUCCESS;
}
}
@@ -23,19 +23,18 @@
package me.lucko.luckperms.commands.group.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.groups.Group;
import me.lucko.luckperms.utils.Contexts;
import java.util.*;
public class GroupChatMeta extends SubCommand<Group> {
public GroupChatMeta() {
super("chatmeta", "Displays a groups chat meta", "/%s group <group> chatmeta", Permission.GROUP_CHATMETA,
Predicate.alwaysFalse());
super("chatmeta", "Lists the group's chat meta", Permission.GROUP_CHATMETA, Predicate.alwaysFalse(), null);
}
@Override
@@ -68,18 +67,18 @@ public class GroupChatMeta extends SubCommand<Group> {
}
if (prefixes.isEmpty()) {
Message.CHAT_META_PREFIX_NONE.send(sender, group.getName());
Message.CHAT_META_PREFIX_NONE.send(sender, group.getDisplayName());
} else {
Message.CHAT_META_PREFIX_HEADER.send(sender, group.getName());
Message.CHAT_META_PREFIX_HEADER.send(sender, group.getDisplayName());
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, group.getName());
Message.CHAT_META_SUFFIX_NONE.send(sender, group.getDisplayName());
} else {
Message.CHAT_META_SUFFIX_HEADER.send(sender, group.getName());
Message.CHAT_META_SUFFIX_HEADER.send(sender, group.getDisplayName());
for (Map.Entry<Integer, String> e : suffixes) {
Message.CHAT_META_ENTRY.send(sender, e.getKey(), e.getValue());
}
@@ -36,14 +36,13 @@ import java.util.List;
public class GroupClear extends SubCommand<Group> {
public GroupClear() {
super("clear", "Clears a groups permissions", "/%s group <group> clear", Permission.GROUP_CLEAR,
Predicate.alwaysFalse());
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.getName());
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;
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
import java.util.List;
public class GroupClone extends SubCommand<Group> {
public GroupClone() {
super("clone", "Clone the group", Permission.GROUP_CLONE, Predicate.not(1),
Arg.list(Arg.create("name", true, "the name of the clone"))
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
String newGroupName = args.get(0).toLowerCase();
if (ArgumentChecker.checkName(newGroupName)) {
Message.GROUP_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (plugin.getDatastore().loadGroup(newGroupName)) {
Message.GROUP_ALREADY_EXISTS.send(sender);
return CommandResult.INVALID_ARGS;
}
if (!plugin.getDatastore().createAndLoadGroup(newGroupName)) {
Message.CREATE_GROUP_ERROR.send(sender);
return CommandResult.FAILURE;
}
Group newGroup = plugin.getGroupManager().get(newGroupName);
if (newGroup == null) {
Message.GROUP_LOAD_ERROR.send(sender);
return CommandResult.LOADING_ERROR;
}
newGroup.setNodes(group.getNodes());
Message.CLONE_SUCCESS.send(sender, group.getName(), newGroup.getName());
LogEntry.build().actor(sender).acted(group).action("clone " + newGroup.getName()).build().submit(plugin, sender);
save(newGroup, sender, plugin);
return CommandResult.SUCCESS;
}
}
@@ -26,6 +26,7 @@ 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;
@@ -33,9 +34,14 @@ import java.util.List;
public class GroupHasPerm extends SubCommand<Group> {
public GroupHasPerm() {
super("haspermission", "Checks to see if a group has a certain permission node",
"/%s group <group> haspermission <node> [server] [world]", Permission.GROUP_HASPERMISSION,
Predicate.notInRange(1, 3));
super("haspermission", "Checks to see if the group has a certain permission node", Permission.GROUP_HASPERMISSION,
Predicate.notInRange(1, 3),
Arg.list(
Arg.create("node", true, "the permission node to check for"),
Arg.create("server", false, "the server to check on"),
Arg.create("world", false, "the world to check on")
)
);
}
@Override
@@ -47,13 +53,13 @@ public class GroupHasPerm extends SubCommand<Group> {
}
if (args.size() == 2) {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1)));
Util.sendTristate(sender, args.get(0), group.hasPermission(new Node.Builder(args.get(0)).setServer(args.get(1)).build()));
} else {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1), args.get(2)));
Util.sendTristate(sender, args.get(0), group.hasPermission(new Node.Builder(args.get(0)).setServer(args.get(1)).setWorld(args.get(2)).build()));
}
} else {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, "global"));
Util.sendTristate(sender, args.get(0), group.hasPermission(new Node.Builder(args.get(0)).build()));
}
return CommandResult.SUCCESS;
}
@@ -35,14 +35,13 @@ import java.util.List;
public class GroupInfo extends SubCommand<Group> {
public GroupInfo() {
super("info", "Gives info about the group", "/%s group <group> info", Permission.GROUP_INFO,
Predicate.alwaysFalse());
super("info", "Gives info about the group", Permission.GROUP_INFO, Predicate.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
Message.GROUP_INFO.send(sender,
group.getName(),
group.getDisplayName(),
group.getPermanentNodes().size(),
group.getTemporaryNodes().size(),
label,
@@ -26,6 +26,8 @@ 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;
@@ -33,13 +35,19 @@ import java.util.List;
public class GroupInheritsPerm extends SubCommand<Group> {
public GroupInheritsPerm() {
super("inheritspermission", "Checks to see if a group inherits a certain permission node",
"/%s group <group> inheritspermission <node> [server] [world]", Permission.GROUP_INHERITSPERMISSION,
Predicate.notInRange(1, 3));
super("inheritspermission", "Checks to see if the group inherits a certain permission node",
Permission.GROUP_INHERITSPERMISSION, Predicate.notInRange(1, 3),
Arg.list(
Arg.create("node", true, "the permission node to check for"),
Arg.create("server", false, "the server to check on"),
Arg.create("world", false, "the world to check on")
)
);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
InheritanceInfo result;
if (args.size() >= 2) {
if (ArgumentChecker.checkServer(args.get(1))) {
Message.SERVER_INVALID_ENTRY.send(sender);
@@ -47,14 +55,26 @@ public class GroupInheritsPerm extends SubCommand<Group> {
}
if (args.size() == 2) {
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1)));
result = group.inheritsPermissionInfo(new Node.Builder(args.get(0)).setServer(args.get(1)).build());
} else {
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1), args.get(2)));
result = group.inheritsPermissionInfo(new Node.Builder(args.get(0)).setServer(args.get(1)).setWorld(args.get(2)).build());
}
} else {
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true));
result = group.inheritsPermissionInfo(new Node.Builder(args.get(0)).build());
}
String location = null;
if (result.getLocation().isPresent()) {
if (result.getLocation().get().equals(group.getObjectName())) {
location = "self";
} else {
location = result.getLocation().get();
}
}
Util.sendPluginMessage(sender, "&b" + args.get(0) + ": " + Util.formatTristate(result.getResult()) +
(result.getLocation().isPresent() ? " &7(inherited from &a" + location + "&7)" : ""));
return CommandResult.SUCCESS;
}
}
@@ -32,14 +32,13 @@ import java.util.List;
public class GroupListNodes extends SubCommand<Group> {
public GroupListNodes() {
super("listnodes", "Lists the permission nodes the group has", "/%s group <group> listnodes",
Permission.GROUP_LISTNODES, Predicate.alwaysFalse());
super("listnodes", "Lists the permission nodes the group has", Permission.GROUP_LISTNODES, Predicate.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
Message.LISTNODES.send(sender, group.getName(), Util.permNodesToString(group.getPermissions(false)));
Message.LISTNODES_TEMP.send(sender, group.getName(), Util.tempNodesToString(group.getPermissions(false)));
Message.LISTNODES.send(sender, group.getDisplayName(), Util.permNodesToString(group.getPermissions(false)));
Message.LISTNODES_TEMP.send(sender, group.getDisplayName(), Util.tempNodesToString(group.getPermissions(false)));
return CommandResult.SUCCESS;
}
}
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupListParents extends SubCommand<Group> {
public GroupListParents() {
super("listparents", "Lists the groups that this group inherits from", Permission.GROUP_LISTPARENTS, Predicate.alwaysFalse(), null);
}
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
Message.LISTPARENTS.send(sender, group.getDisplayName(), Util.permGroupsToString(group.getPermissions(false)));
Message.LISTPARENTS_TEMP.send(sender, group.getDisplayName(), Util.tempGroupsToString(group.getPermissions(false)));
return CommandResult.SUCCESS;
}
}
@@ -23,10 +23,8 @@
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.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;
@@ -34,12 +32,19 @@ 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 a group", "/%s group <group> removeprefix <priority> <prefix> [server] [world]",
Permission.GROUP_REMOVEPREFIX, Predicate.notInRange(2, 4));
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
@@ -53,44 +58,96 @@ public class GroupRemovePrefix extends SubCommand<Group> {
return CommandResult.INVALID_ARGS;
}
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
if (prefix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
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.getName(), prefix, priority, server);
LogEntry.build().actor(sender).acted(group)
.action("removeprefix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
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 {
final String world = args.get(3).toLowerCase();
group.unsetPermission(node, server, world);
Message.REMOVEPREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), prefix, priority, server, world);
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) + " " + server + " " + world)
.action("removeprefix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
} else {
group.unsetPermission(node);
Message.REMOVEPREFIX_SUCCESS.send(sender, group.getName(), 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;
}
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_PREFIX.send(sender, group.getName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -23,10 +23,8 @@
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.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;
@@ -34,12 +32,19 @@ 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 a group", "/%s group <group> removesuffix <priority> <suffix> [server] [world]",
Permission.GROUP_REMOVESUFFIX, Predicate.notInRange(2, 4));
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
@@ -53,44 +58,96 @@ public class GroupRemoveSuffix extends SubCommand<Group> {
return CommandResult.INVALID_ARGS;
}
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
if (suffix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
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.getName(), suffix, priority, server);
LogEntry.build().actor(sender).acted(group)
.action("removesuffix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
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 {
final String world = args.get(3).toLowerCase();
group.unsetPermission(node, server, world);
Message.REMOVESUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), suffix, priority, server, world);
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) + " " + server + " " + world)
.action("removesuffix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
} else {
group.unsetPermission(node);
Message.REMOVESUFFIX_SUCCESS.send(sender, group.getName(), 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;
}
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_SUFFIX.send(sender, group.getName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -23,10 +23,8 @@
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.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;
@@ -34,12 +32,20 @@ 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 a group", "/%s group <group> removetempprefix <priority> <prefix> [server] [world]",
Permission.GROUP_REMOVE_TEMP_PREFIX, Predicate.notInRange(2, 4));
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
@@ -53,44 +59,96 @@ public class GroupRemoveTempPrefix extends SubCommand<Group> {
return CommandResult.INVALID_ARGS;
}
final String node = "prefix." + priority + "." + ArgumentChecker.escapeCharacters(prefix);
if (prefix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
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.getName(), prefix, priority, server);
LogEntry.build().actor(sender).acted(group)
.action("removetempprefix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
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 {
final String world = args.get(3).toLowerCase();
group.unsetPermission(node, server, world, true);
Message.REMOVE_TEMP_PREFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), prefix, priority, server, world);
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) + " " + server + " " + world)
.action("removetempprefix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
} else {
group.unsetPermission(node, true);
Message.REMOVE_TEMP_PREFIX_SUCCESS.send(sender, group.getName(), 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;
}
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_PREFIX.send(sender, group.getName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -23,10 +23,8 @@
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.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;
@@ -34,12 +32,20 @@ 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 a group", "/%s group <group> removetempsuffix <priority> <suffix> [server] [world]",
Permission.GROUP_REMOVE_TEMP_SUFFIX, Predicate.notInRange(2, 4));
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
@@ -53,44 +59,96 @@ public class GroupRemoveTempSuffix extends SubCommand<Group> {
return CommandResult.INVALID_ARGS;
}
final String node = "suffix." + priority + "." + ArgumentChecker.escapeCharacters(suffix);
if (suffix.equalsIgnoreCase("null")) {
String server = null;
String world = null;
try {
if (args.size() >= 3) {
final String server = args.get(2).toLowerCase();
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.getName(), suffix, priority, server);
LogEntry.build().actor(sender).acted(group)
.action("removetempsuffix " + priority + " " + args.get(1) + " " + server)
.build().submit(plugin, sender);
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 {
final String world = args.get(3).toLowerCase();
group.unsetPermission(node, server, world, true);
Message.REMOVE_TEMP_SUFFIX_SERVER_WORLD_SUCCESS.send(sender, group.getName(), suffix, priority, server, world);
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) + " " + server + " " + world)
.action("removetempsuffix " + priority + " " + args.get(1))
.build().submit(plugin, sender);
}
} else {
group.unsetPermission(node, true);
Message.REMOVE_TEMP_SUFFIX_SUCCESS.send(sender, group.getName(), 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;
}
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_SUFFIX.send(sender, group.getName());
return CommandResult.STATE_ERROR;
}
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -37,8 +34,9 @@ import java.util.List;
public class GroupRename extends SubCommand<Group> {
public GroupRename() {
super("rename", "Rename this group", "/%s group <group> rename <new name>",
Permission.TRACK_APPEND, Predicate.not(1));
super("rename", "Rename the group", Permission.GROUP_RENAME, Predicate.not(1),
Arg.list(Arg.create("name", true, "the new name"))
);
}
@Override
@@ -70,7 +68,7 @@ public class GroupRename extends SubCommand<Group> {
return CommandResult.FAILURE;
}
plugin.getGroupManager().copy(group, newGroup);
newGroup.setNodes(group.getNodes());
Message.RENAME_SUCCESS.send(sender, group.getName(), newGroup.getName());
LogEntry.build().actor(sender).acted(group).action("rename " + newGroup.getName()).build().submit(plugin, sender);
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -38,9 +35,14 @@ import java.util.List;
public class GroupSetInherit extends SubCommand<Group> {
public GroupSetInherit() {
super("setinherit", "Sets another group for this group to inherit permissions from",
"/%s group <group> setinherit <group> [server] [world]", Permission.GROUP_SETINHERIT,
Predicate.notInRange(1, 3));
super("setinherit", "Sets another group for the group to inherit permissions from",
Permission.GROUP_SETINHERIT, Predicate.notInRange(1, 3),
Arg.list(
Arg.create("group", true, "the group to inherit from"),
Arg.create("server", false, "the server to inherit the group on"),
Arg.create("world", false, "the world to inherit the group on")
)
);
}
@Override
@@ -48,7 +50,7 @@ public class GroupSetInherit extends SubCommand<Group> {
String groupName = args.get(0).toLowerCase();
if (ArgumentChecker.checkNode(groupName)) {
sendUsage(sender, label);
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -73,14 +75,14 @@ public class GroupSetInherit extends SubCommand<Group> {
if (args.size() == 2) {
group.setInheritGroup(group1, server);
Message.GROUP_SETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), group1.getName(), server);
Message.GROUP_SETINHERIT_SERVER_SUCCESS.send(sender, group.getDisplayName(), group1.getDisplayName(), server);
LogEntry.build().actor(sender).acted(group)
.action("setinherit " + group1.getName() + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(2).toLowerCase();
group.setInheritGroup(group1, server, world);
Message.GROUP_SETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), group1.getName(), server, world);
Message.GROUP_SETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), group1.getDisplayName(), server, world);
LogEntry.build().actor(sender).acted(group)
.action("setinherit " + group1.getName() + " " + server + " " + world)
.build().submit(plugin, sender);
@@ -88,7 +90,7 @@ public class GroupSetInherit extends SubCommand<Group> {
} else {
group.setInheritGroup(group1);
Message.GROUP_SETINHERIT_SUCCESS.send(sender, group.getName(), group1.getName());
Message.GROUP_SETINHERIT_SUCCESS.send(sender, group.getDisplayName(), group1.getDisplayName());
LogEntry.build().actor(sender).acted(group)
.action("setinherit " + group1.getName())
.build().submit(plugin, sender);
@@ -97,7 +99,7 @@ public class GroupSetInherit extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.GROUP_ALREADY_INHERITS.send(sender, group.getName(), group1.getName());
Message.GROUP_ALREADY_INHERITS.send(sender, group.getDisplayName(), group1.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -38,8 +35,14 @@ import java.util.List;
public class GroupSetPermission extends SubCommand<Group> {
public GroupSetPermission() {
super("set", "Sets a permission for a group", "/%s group <group> set <node> <true|false> [server] [world]",
Permission.GROUP_SETPERMISSION, Predicate.notInRange(2, 4));
super("set", "Sets a permission for the group", Permission.GROUP_SETPERMISSION, Predicate.notInRange(2, 4),
Arg.list(
Arg.create("node", true, "the permission node to set"),
Arg.create("true|false", true, "the value of the node"),
Arg.create("server", false, "the server to add the permission node on"),
Arg.create("world", false, "the world to add the permission node on")
)
);
}
@Override
@@ -48,7 +51,7 @@ public class GroupSetPermission extends SubCommand<Group> {
String bool = args.get(1).toLowerCase();
if (ArgumentChecker.checkNode(node)) {
sendUsage(sender, label);
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -58,7 +61,7 @@ public class GroupSetPermission extends SubCommand<Group> {
}
if (!bool.equalsIgnoreCase("true") && !bool.equalsIgnoreCase("false")) {
sendUsage(sender, label);
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -74,14 +77,14 @@ public class GroupSetPermission extends SubCommand<Group> {
if (args.size() == 3) {
group.setPermission(node, b, server);
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server);
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, group.getDisplayName(), server);
LogEntry.build().actor(sender).acted(group)
.action("set " + node + " " + b + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(3).toLowerCase();
group.setPermission(node, b, server, world);
Message.SETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, bool, group.getName(), server, world);
Message.SETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, bool, group.getDisplayName(), server, world);
LogEntry.build().actor(sender).acted(group)
.action("set " + node + " " + b + " " + server + " " + world)
.build().submit(plugin, sender);
@@ -89,7 +92,7 @@ public class GroupSetPermission extends SubCommand<Group> {
} else {
group.setPermission(node, b);
Message.SETPERMISSION_SUCCESS.send(sender, node, bool, group.getName());
Message.SETPERMISSION_SUCCESS.send(sender, node, bool, group.getDisplayName());
LogEntry.build().actor(sender).acted(group)
.action("set " + node + " " + b)
.build().submit(plugin, sender);
@@ -98,7 +101,7 @@ public class GroupSetPermission extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HASPERMISSION.send(sender, group.getName());
Message.ALREADY_HASPERMISSION.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -39,9 +36,15 @@ import java.util.List;
public class GroupSetTempInherit extends SubCommand<Group> {
public GroupSetTempInherit() {
super("settempinherit", "Sets another group for this group to inherit permissions from temporarily",
"/%s group <group> settempinherit <group> <duration> [server] [world]",
Permission.GROUP_SET_TEMP_INHERIT, Predicate.notInRange(2, 4));
super("settempinherit", "Sets another group for the group to inherit permissions from temporarily",
Permission.GROUP_SET_TEMP_INHERIT, Predicate.notInRange(2, 4),
Arg.list(
Arg.create("group", true, "the group to inherit from"),
Arg.create("duration", true, "the duration of the group membership"),
Arg.create("server", false, "the server to add the group on"),
Arg.create("world", false, "the world to add the group on")
)
);
}
@Override
@@ -49,7 +52,7 @@ public class GroupSetTempInherit extends SubCommand<Group> {
String groupName = args.get(0).toLowerCase();
if (ArgumentChecker.checkNode(groupName)) {
sendUsage(sender, label);
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -91,7 +94,7 @@ public class GroupSetTempInherit extends SubCommand<Group> {
if (args.size() == 3) {
group.setInheritGroup(group1, server, duration);
Message.GROUP_SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), group1.getName(), server,
Message.GROUP_SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getDisplayName(), group1.getDisplayName(), server,
DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("settempinherit " + group1.getName() + " " + duration + " " + server)
@@ -99,7 +102,7 @@ public class GroupSetTempInherit extends SubCommand<Group> {
} else {
final String world = args.get(3).toLowerCase();
group.setInheritGroup(group1, server, world, duration);
Message.GROUP_SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), group1.getName(), server,
Message.GROUP_SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), group1.getDisplayName(), server,
world, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("settempinherit " + group1.getName() + " " + duration + " " + server + " " + world)
@@ -108,7 +111,7 @@ public class GroupSetTempInherit extends SubCommand<Group> {
} else {
group.setInheritGroup(group1, duration);
Message.GROUP_SET_TEMP_INHERIT_SUCCESS.send(sender, group.getName(), group1.getName(), DateUtil.formatDateDiff(duration));
Message.GROUP_SET_TEMP_INHERIT_SUCCESS.send(sender, group.getDisplayName(), group1.getDisplayName(), DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("settempinherit " + group1.getName() + " " + duration)
.build().submit(plugin, sender);
@@ -117,7 +120,7 @@ public class GroupSetTempInherit extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.USER_ALREADY_TEMP_MEMBER_OF.send(sender, group.getName(), group1.getName());
Message.USER_ALREADY_TEMP_MEMBER_OF.send(sender, group.getDisplayName(), group1.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -39,9 +36,16 @@ import java.util.List;
public class GroupSetTempPermission extends SubCommand<Group> {
public GroupSetTempPermission() {
super("settemp", "Sets a temporary permission for a group",
"/%s group <group> settemp <node> <true|false> <duration> [server] [world]",
Permission.GROUP_SET_TEMP_PERMISSION, Predicate.notInRange(3, 5));
super("settemp", "Sets a permission for the group temporarily", Permission.GROUP_SET_TEMP_PERMISSION,
Predicate.notInRange(3, 5),
Arg.list(
Arg.create("node", true, "the permission node to set"),
Arg.create("true|false", true, "the value of the node"),
Arg.create("duration", true, "the duration until the permission node expires"),
Arg.create("server", false, "the server to add the permission node on"),
Arg.create("world", false, "the world to add the permission node on")
)
);
}
@Override
@@ -50,7 +54,7 @@ public class GroupSetTempPermission extends SubCommand<Group> {
String bool = args.get(1).toLowerCase();
if (ArgumentChecker.checkNode(node)) {
sendUsage(sender, label);
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -60,7 +64,7 @@ public class GroupSetTempPermission extends SubCommand<Group> {
}
if (!bool.equalsIgnoreCase("true") && !bool.equalsIgnoreCase("false")) {
sendUsage(sender, label);
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -93,7 +97,7 @@ public class GroupSetTempPermission extends SubCommand<Group> {
if (args.size() == 4) {
group.setPermission(node, b, server, duration);
Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server,
Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, group.getDisplayName(), server,
DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("settemp " + node + " " + b + " " + duration + " " + server)
@@ -101,7 +105,7 @@ public class GroupSetTempPermission extends SubCommand<Group> {
} else {
final String world = args.get(4).toLowerCase();
group.setPermission(node, b, server, world, duration);
Message.SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS.send(sender, node, bool, group.getName(), server,
Message.SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS.send(sender, node, bool, group.getDisplayName(), server,
world, DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("settemp " + node + " " + b + " " + duration + " " + server + " " + world)
@@ -110,7 +114,7 @@ public class GroupSetTempPermission extends SubCommand<Group> {
} else {
group.setPermission(node, b, duration);
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, bool, group.getName(), DateUtil.formatDateDiff(duration));
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, bool, group.getDisplayName(), DateUtil.formatDateDiff(duration));
LogEntry.build().actor(sender).acted(group)
.action("settemp " + node + " " + b + " " + duration)
.build().submit(plugin, sender);
@@ -119,7 +123,7 @@ public class GroupSetTempPermission extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HAS_TEMP_PERMISSION.send(sender, group.getName());
Message.ALREADY_HAS_TEMP_PERMISSION.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
@@ -34,8 +34,7 @@ import java.util.stream.Collectors;
public class GroupShowTracks extends SubCommand<Group> {
public GroupShowTracks() {
super("showtracks", "Lists the tracks that this group features on", "/%s group <group> showtracks",
Permission.GROUP_SHOWTRACKS, Predicate.alwaysFalse());
super("showtracks", "Lists the tracks that the group features on", Permission.GROUP_SHOWTRACKS, Predicate.alwaysFalse(), null);
}
@Override
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -38,8 +35,13 @@ import java.util.List;
public class GroupUnSetPermission extends SubCommand<Group> {
public GroupUnSetPermission() {
super("unset", "Unsets a permission for a group", "/%s group <group> unset <node> [server] [world]",
Permission.GROUP_UNSETPERMISSION, Predicate.notInRange(1, 3));
super("unset", "Unsets a permission for the group", Permission.GROUP_UNSETPERMISSION, Predicate.notInRange(1, 3),
Arg.list(
Arg.create("node", true, "the permission node to unset"),
Arg.create("server", false, "the server to remove the permission node on"),
Arg.create("world", false, "the world to remove the permission node on")
)
);
}
@Override
@@ -47,7 +49,7 @@ public class GroupUnSetPermission extends SubCommand<Group> {
String node = args.get(0).replace("{SPACE}", " ");
if (ArgumentChecker.checkNode(node)) {
sendUsage(sender, label);
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -66,14 +68,14 @@ public class GroupUnSetPermission extends SubCommand<Group> {
if (args.size() == 2) {
group.unsetPermission(node, server);
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server);
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, group.getDisplayName(), server);
LogEntry.build().actor(sender).acted(group)
.action("unset " + node + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission(node, server, world);
Message.UNSETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, group.getName(), server, world);
Message.UNSETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, group.getDisplayName(), server, world);
LogEntry.build().actor(sender).acted(group)
.action("unset " + node + " " + server + " " + world)
.build().submit(plugin, sender);
@@ -81,7 +83,7 @@ public class GroupUnSetPermission extends SubCommand<Group> {
} else {
group.unsetPermission(node);
Message.UNSETPERMISSION_SUCCESS.send(sender, node, group.getName());
Message.UNSETPERMISSION_SUCCESS.send(sender, node, group.getDisplayName());
LogEntry.build().actor(sender).acted(group)
.action("unset " + node)
.build().submit(plugin, sender);
@@ -90,7 +92,7 @@ public class GroupUnSetPermission extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVEPERMISSION.send(sender, group.getName());
Message.DOES_NOT_HAVEPERMISSION.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -38,9 +35,14 @@ import java.util.List;
public class GroupUnsetInherit extends SubCommand<Group> {
public GroupUnsetInherit() {
super("unsetinherit", "Unsets another group for this group to inherit permissions from",
"/%s group <group> unsetinherit <group> [server] [world]", Permission.GROUP_UNSETINHERIT,
Predicate.notInRange(1, 3));
super("unsetinherit", "Removes a previously set inheritance rule", Permission.GROUP_UNSETINHERIT,
Predicate.notInRange(1, 3),
Arg.list(
Arg.create("group", true, "the group to uninherit"),
Arg.create("server", false, "the server to remove the group on"),
Arg.create("world", false, "the world to remove the group on")
)
);
}
@Override
@@ -48,7 +50,7 @@ public class GroupUnsetInherit extends SubCommand<Group> {
String groupName = args.get(0).toLowerCase();
if (ArgumentChecker.checkNode(groupName)) {
sendUsage(sender, label);
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -62,14 +64,14 @@ public class GroupUnsetInherit extends SubCommand<Group> {
if (args.size() == 2) {
group.unsetPermission("group." + groupName, server);
Message.GROUP_UNSETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
Message.GROUP_UNSETINHERIT_SERVER_SUCCESS.send(sender, group.getDisplayName(), groupName, server);
LogEntry.build().actor(sender).acted(group)
.action("unsetinherit " + groupName + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission("group." + groupName, server, world);
Message.GROUP_UNSETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world);
Message.GROUP_UNSETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), groupName, server, world);
LogEntry.build().actor(sender).acted(group)
.action("unsetinherit " + groupName + " " + server + " " + world)
.build().submit(plugin, sender);
@@ -77,7 +79,7 @@ public class GroupUnsetInherit extends SubCommand<Group> {
} else {
group.unsetPermission("group." + groupName);
Message.GROUP_UNSETINHERIT_SUCCESS.send(sender, group.getName(), groupName);
Message.GROUP_UNSETINHERIT_SUCCESS.send(sender, group.getDisplayName(), groupName);
LogEntry.build().actor(sender).acted(group)
.action("unsetinherit " + groupName)
.build().submit(plugin, sender);
@@ -86,7 +88,7 @@ public class GroupUnsetInherit extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.GROUP_DOES_NOT_INHERIT.send(sender, group.getName(), groupName);
Message.GROUP_DOES_NOT_INHERIT.send(sender, group.getDisplayName(), groupName);
return CommandResult.STATE_ERROR;
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -38,9 +35,14 @@ import java.util.List;
public class GroupUnsetTempInherit extends SubCommand<Group> {
public GroupUnsetTempInherit() {
super("unsettempinherit", "Unsets another group for this group to inherit permissions from",
"/%s group <group> unsettempinherit <group> [server] [world]", Permission.GROUP_UNSET_TEMP_INHERIT,
Predicate.notInRange(1, 3));
super("unsettempinherit", "Removes a previously set temporary inheritance rule",
Permission.GROUP_UNSET_TEMP_INHERIT, Predicate.notInRange(1, 3),
Arg.list(
Arg.create("group", true, "the group to uninherit"),
Arg.create("server", false, "the server to remove the group on"),
Arg.create("world", false, "the world to remove the group on")
)
);
}
@Override
@@ -48,7 +50,7 @@ public class GroupUnsetTempInherit extends SubCommand<Group> {
String groupName = args.get(0).toLowerCase();
if (ArgumentChecker.checkNode(groupName)) {
sendUsage(sender, label);
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -62,14 +64,14 @@ public class GroupUnsetTempInherit extends SubCommand<Group> {
if (args.size() == 2) {
group.unsetPermission("group." + groupName, server, true);
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getDisplayName(), groupName, server);
LogEntry.build().actor(sender).acted(group)
.action("unsettempinherit " + groupName + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission("group." + groupName, server, world, true);
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world);
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getDisplayName(), groupName, server, world);
LogEntry.build().actor(sender).acted(group)
.action("unsettempinherit " + groupName + " " + server + " " + world)
.build().submit(plugin, sender);
@@ -77,7 +79,7 @@ public class GroupUnsetTempInherit extends SubCommand<Group> {
} else {
group.unsetPermission("group." + groupName, true);
Message.GROUP_UNSET_TEMP_INHERIT_SUCCESS.send(sender, group.getName(), groupName);
Message.GROUP_UNSET_TEMP_INHERIT_SUCCESS.send(sender, group.getDisplayName(), groupName);
LogEntry.build().actor(sender).acted(group)
.action("unsettempinherit " + groupName)
.build().submit(plugin, sender);
@@ -86,7 +88,7 @@ public class GroupUnsetTempInherit extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.GROUP_DOES_NOT_TEMP_INHERIT.send(sender, group.getName(), groupName);
Message.GROUP_DOES_NOT_TEMP_INHERIT.send(sender, group.getDisplayName(), groupName);
return CommandResult.STATE_ERROR;
}
}
@@ -23,10 +23,7 @@
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntry;
@@ -38,9 +35,14 @@ import java.util.List;
public class GroupUnsetTempPermission extends SubCommand<Group> {
public GroupUnsetTempPermission() {
super("unsettemp", "Unsets a temporary permission for a group",
"/%s group <group> unsettemp <node> [server] [world]", Permission.GROUP_UNSET_TEMP_PERMISSION,
Predicate.notInRange(1, 3));
super("unsettemp", "Unsets a temporary permission for the group", Permission.GROUP_UNSET_TEMP_PERMISSION,
Predicate.notInRange(1, 3),
Arg.list(
Arg.create("node", true, "the permission node to unset"),
Arg.create("server", false, "the server to remove the permission node on"),
Arg.create("world", false, "the world to remove the permission node on")
)
);
}
@Override
@@ -48,7 +50,7 @@ public class GroupUnsetTempPermission extends SubCommand<Group> {
String node = args.get(0).replace("{SPACE}", " ");
if (ArgumentChecker.checkNode(node)) {
sendUsage(sender, label);
sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
@@ -67,14 +69,14 @@ public class GroupUnsetTempPermission extends SubCommand<Group> {
if (args.size() == 2) {
group.unsetPermission(node, server);
Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server);
Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, group.getDisplayName(), server);
LogEntry.build().actor(sender).acted(group)
.action("unsettemp " + node + " " + server)
.build().submit(plugin, sender);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission(node, server, world);
Message.UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, group.getName(), server, world);
Message.UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, group.getDisplayName(), server, world);
LogEntry.build().actor(sender).acted(group)
.action("unsettemp " + node + " " + server + " " + world)
.build().submit(plugin, sender);
@@ -82,7 +84,7 @@ public class GroupUnsetTempPermission extends SubCommand<Group> {
} else {
group.unsetPermission(node, true);
Message.UNSET_TEMP_PERMISSION_SUCCESS.send(sender, node, group.getName());
Message.UNSET_TEMP_PERMISSION_SUCCESS.send(sender, node, group.getDisplayName());
LogEntry.build().actor(sender).acted(group)
.action("unsettemp " + node)
.build().submit(plugin, sender);
@@ -91,7 +93,7 @@ public class GroupUnsetTempPermission extends SubCommand<Group> {
save(group, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVE_TEMP_PERMISSION.send(sender, group.getName());
Message.DOES_NOT_HAVE_TEMP_PERMISSION.send(sender, group.getDisplayName());
return CommandResult.STATE_ERROR;
}
}
@@ -24,10 +24,7 @@ package me.lucko.luckperms.commands.log.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.LogEntry;
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.Log;
@@ -41,7 +38,9 @@ import java.util.List;
public class LogExport extends SubCommand<Log> {
public LogExport() {
super("export", "Export the log to a file", "/%s log export <file>", Permission.LOG_EXPORT, Predicate.not(1));
super("export", "Export the log to a file", Permission.LOG_EXPORT, Predicate.not(1),
Arg.list(Arg.create("file", true, "the name of the file"))
);
}
@Override
@@ -24,10 +24,7 @@ package me.lucko.luckperms.commands.log.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.LogEntry;
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.Log;
@@ -40,8 +37,12 @@ import java.util.SortedMap;
public class LogGroupHistory extends SubCommand<Log> {
public LogGroupHistory() {
super("grouphistory", "View an objects history", "/%s log grouphistory <group> [page]", Permission.LOG_GROUP_HISTORY,
Predicate.notInRange(1, 2));
super("grouphistory", "View an group's history", Permission.LOG_GROUP_HISTORY, Predicate.notInRange(1, 2),
Arg.list(
Arg.create("group", true, "the name of the group"),
Arg.create("page", false, "the page number to view")
)
);
}
@Override
@@ -23,10 +23,7 @@
package me.lucko.luckperms.commands.log.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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.Log;
@@ -37,8 +34,9 @@ import java.util.UUID;
public class LogNotify extends SubCommand<Log> {
public LogNotify() {
super("notify", "Toggle notifications", "/%s log notify [on|off]", Permission.LOG_NOTIFY,
Predicate.notInRange(0, 1));
super("notify", "Toggle notifications", Permission.LOG_NOTIFY, Predicate.notInRange(0, 1),
Arg.list(Arg.create("on|off", false, "whether to toggle on or off"))
);
}
@Override
@@ -38,8 +38,12 @@ import java.util.UUID;
public class LogRecent extends SubCommand<Log> {
public LogRecent() {
super("recent", "View recent actions", "/%s log recent [user] [page]", Permission.LOG_RECENT,
Predicate.notInRange(0, 2));
super("recent", "View recent actions", Permission.LOG_RECENT, Predicate.notInRange(0, 2),
Arg.list(
Arg.create("user", false, "the name/uuid of the user to filter by"),
Arg.create("page", false, "the page number to view")
)
);
}
@Override
@@ -70,8 +74,6 @@ public class LogRecent extends SubCommand<Log> {
return CommandResult.INVALID_ARGS;
}
Message.USER_ATTEMPTING_LOOKUP.send(sender);
UUID uuid = plugin.getDatastore().getUUID(s);
if (uuid == null) {
@@ -24,10 +24,7 @@ package me.lucko.luckperms.commands.log.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.LogEntry;
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.Log;
@@ -40,8 +37,12 @@ import java.util.stream.Collectors;
public class LogSearch extends SubCommand<Log> {
public LogSearch() {
super("search", "Search the log for an entry", "/%s log search <query> [page]", Permission.LOG_SEARCH,
Predicate.is(0));
super("search", "Search the log for an entry", Permission.LOG_SEARCH, Predicate.is(0),
Arg.list(
Arg.create("query", true, "the query to search by"),
Arg.create("page", false, "the page number to view")
)
);
}
@Override
@@ -24,10 +24,7 @@ package me.lucko.luckperms.commands.log.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.LogEntry;
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.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.Log;
@@ -40,8 +37,12 @@ import java.util.SortedMap;
public class LogTrackHistory extends SubCommand<Log> {
public LogTrackHistory() {
super("trackhistory", "View an objects history", "/%s log trackhistory <track> [page]", Permission.LOG_TRACK_HISTORY,
Predicate.notInRange(1, 2));
super("trackhistory", "View a track's history", Permission.LOG_TRACK_HISTORY, Predicate.notInRange(1, 2),
Arg.list(
Arg.create("track", true, "the name of the track"),
Arg.create("page", false, "the page number to view")
)
);
}
@Override
@@ -38,8 +38,12 @@ import java.util.UUID;
public class LogUserHistory extends SubCommand<Log> {
public LogUserHistory() {
super("userhistory", "View an objects history", "/%s log userhistory <user> [page]", Permission.LOG_USER_HISTORY,
Predicate.notInRange(1, 2));
super("userhistory", "View a user's history", Permission.LOG_USER_HISTORY, Predicate.notInRange(1, 2),
Arg.list(
Arg.create("user", true, "the name/uuid of the user"),
Arg.create("page", false, "the page number to view")
)
);
}
@Override
@@ -72,8 +76,6 @@ public class LogUserHistory extends SubCommand<Log> {
return CommandResult.INVALID_ARGS;
}
Message.USER_ATTEMPTING_LOOKUP.send(sender);
UUID uuid1 = plugin.getDatastore().getUUID(user);
if (uuid1 == null) {
@@ -82,7 +82,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
}
public MigrationBPermissions() {
super("bpermissions", "Migration from bPermissions", "/%s migration bpermissions", MIGRATION, Predicate.alwaysFalse());
super("bpermissions", "Migration from bPermissions", MIGRATION, Predicate.alwaysFalse(), null);
}
@Override
Loaded 100 of 210 files, more files were not shown because too many files have changed in this diff. Show more