Changes for version 2.16

This commit is contained in:
Luck
2016-12-02 20:20:24 +00:00
Unverified
parent a063f7664d
commit 307e2b889c
264 changed files with 3450 additions and 2063 deletions
@@ -47,7 +47,11 @@ import me.lucko.luckperms.common.utils.LocaleManager;
import me.lucko.luckperms.common.utils.PermissionCache;
import java.io.File;
import java.util.*;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
/**
@@ -59,72 +63,84 @@ public interface LuckPermsPlugin {
/**
* Gets the user manager instance for the platform
*
* @return the user manager
*/
UserManager getUserManager();
/**
* Gets the group manager instance for the platform
*
* @return the group manager
*/
GroupManager getGroupManager();
/**
* Gets the track manager instance for the platform
*
* @return the track manager
*/
TrackManager getTrackManager();
/**
* Gets the plugin's configuration
*
* @return the plugin config
*/
LPConfiguration getConfiguration();
/**
* Gets the primary data storage instance. This is likely to be wrapped with extra layers for caching, etc.
*
* @return the storage handler instance
*/
Storage getStorage();
/**
* Gets the redis messaging instance if present. Could return null if redis is not enabled.
*
* @return the redis messaging service
*/
RedisMessaging getRedisMessaging();
/**
* Gets a wrapped logger instance for the platform.
*
* @return the plugin's logger
*/
Logger getLog();
/**
* Gets the UUID caching store for the platform
*
* @return the uuid cache
*/
UuidCache getUuidCache();
/**
* Returns the class implementing the LuckPermsAPI on this platform.
*
* @return the api
*/
ApiProvider getApiProvider();
/**
* Gets the importer instance
*
* @return the importer
*/
Importer getImporter();
/**
* Gets the consecutive command executor instance
*
* @return the consecutive executor
*/
ConsecutiveExecutor getConsecutiveExecutor();
/**
* Gets the instance providing locale translations for the plugin
*
* @return the locale manager
*/
LocaleManager getLocaleManager();
@@ -132,76 +148,89 @@ public interface LuckPermsPlugin {
/**
* Gets the context manager.
* This object handles context accumulation for all players on the platform.
*
* @return the context manager
*/
ContextManager getContextManager();
/**
* Gets the class responsible for constructing PermissionCalculators on this platform.
*
* @return the permission calculator factory
*/
CalculatorFactory getCalculatorFactory();
/**
* Gets the verbose debug handler instance.
*
* @return the debug handler instance
*/
DebugHandler getDebugHandler();
/**
* Gets the permission caching instance for the platform.
*
* @return the permission cache instance
*/
PermissionCache getPermissionCache();
/**
* Execute a runnable asynchronously
*
* @param r the task to run
*/
void doAsync(Runnable r);
/**
* Execute a runnable synchronously
*
* @param r the task to run
*/
void doSync(Runnable r);
Executor getSyncExecutor();
Executor getAsyncExecutor();
/**
* Execute a runnable asynchronously on a loop
* @param r the task to run
*
* @param r the task to run
* @param interval the time between runs in ticks
*/
void doAsyncRepeating(Runnable r, long interval);
/**
* Gets a string of the plugin's version
*
* @return the version of the plugin
*/
String getVersion();
/**
* Gets the platform type this instance of LuckPerms is running on.
*
* @return the platform type
*/
PlatformType getType();
/**
* Gets the plugins main directory
*
* @return the main plugin directory
*/
File getMainDir();
/**
* Gets the plugins main data storage directory
*
* @return the platforms data folder
*/
File getDataFolder();
/**
* Returns a colored string indicating the status of a player
*
* @param uuid The player's uuid
* @return a formatted status string
*/
@@ -213,6 +242,7 @@ public interface LuckPermsPlugin {
/**
* Gets a player object linked to this User. The returned object must be the same type
* as the instance used in the platforms {@link ContextManager}
*
* @param user the user instance
* @return a player object, or null, if one couldn't be found.
*/
@@ -220,6 +250,7 @@ public interface LuckPermsPlugin {
/**
* Gets a calculated context instance for the user using the rules of the platform.
*
* @param user the user instance
* @return a contexts object, or null if one couldn't be generated
*/
@@ -227,24 +258,28 @@ public interface LuckPermsPlugin {
/**
* Gets the number of users online on the platform
*
* @return the number of users
*/
int getPlayerCount();
/**
* Gets the usernames of the users online on the platform
*
* @return a {@link List} of usernames
*/
List<String> getPlayerList();
/**
* Gets the UUIDs of the users online on the platform
*
* @return a {@link Set} of UUIDs
*/
Set<UUID> getOnlinePlayers();
/**
* Checks if a user is online
*
* @param external the users external uuid
* @return true if the user is online
*/
@@ -252,18 +287,21 @@ public interface LuckPermsPlugin {
/**
* Gets a list of online Senders on the platform
*
* @return a {@link List} of senders online on the platform
*/
List<Sender> getSenders();
/**
* Gets the console.
*
* @return the console sender of the instance
*/
Sender getConsoleSender();
/**
* Gets a set of Contexts that should be pre-processed in advance
*
* @param op if the user being processed is op
* @return a set of contexts
*/
@@ -275,6 +313,7 @@ public interface LuckPermsPlugin {
/**
* Gets a map of extra information to be shown in the info command
*
* @return a map of options, or null
*/
default LinkedHashMap<String, Object> getExtraInfo() {
@@ -283,12 +322,14 @@ public interface LuckPermsPlugin {
/**
* Gets a set of players ignoring logging output
*
* @return a {@link Set} of {@link UUID}s
*/
Set<UUID> getIgnoringLogs();
/**
* Gets a loaded plugins instance from the platform
*
* @param name the name of the plugin
* @return a plugin instance
*/
@@ -296,6 +337,7 @@ public interface LuckPermsPlugin {
/**
* Gets a provided service from the platform.
*
* @param clazz the class of the service
* @return the service instance, if it is provided for
*/
@@ -303,6 +345,7 @@ public interface LuckPermsPlugin {
/**
* Gets the UUID of a player. Used as a backup for migration
*
* @param playerName the players name
* @return a uuid if found, or null if not
*/
@@ -310,6 +353,7 @@ public interface LuckPermsPlugin {
/**
* Checks if a plugin is loaded on the platform
*
* @param name the name of the plugin
* @return true if the plugin is loaded
*/
@@ -317,6 +361,7 @@ public interface LuckPermsPlugin {
/**
* Gets the update task buffer of the platform, used for scheduling and running update tasks.
*
* @return the update task buffer instance
*/
BufferedRequest<Void> getUpdateTaskBuffer();
@@ -22,16 +22,37 @@
package me.lucko.luckperms.common.api;
import com.google.common.eventbus.EventBus;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.*;
import com.google.common.eventbus.EventBus;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Datastore;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.LPConfiguration;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.LuckPermsApi;
import me.lucko.luckperms.api.MessagingService;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.api.Storage;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.UuidCache;
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.common.LuckPermsPlugin;
import me.lucko.luckperms.common.api.internal.*;
import me.lucko.luckperms.common.api.internal.DatastoreLink;
import me.lucko.luckperms.common.api.internal.GroupLink;
import me.lucko.luckperms.common.api.internal.LPConfigurationLink;
import me.lucko.luckperms.common.api.internal.StorageLink;
import me.lucko.luckperms.common.api.internal.TrackLink;
import me.lucko.luckperms.common.api.internal.UserLink;
import me.lucko.luckperms.common.api.internal.Utils;
import me.lucko.luckperms.common.api.internal.UuidCacheLink;
import me.lucko.luckperms.common.core.NodeBuilder;
import me.lucko.luckperms.common.core.UserIdentifier;
@@ -71,7 +92,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public double getApiVersion() {
return 2.15;
return 2.16;
}
@Override
@@ -24,7 +24,13 @@ package me.lucko.luckperms.common.api.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.Datastore;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Log;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.storage.Storage;
@@ -33,7 +39,11 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import static me.lucko.luckperms.common.api.internal.Utils.*;
import static me.lucko.luckperms.common.api.internal.Utils.checkGroup;
import static me.lucko.luckperms.common.api.internal.Utils.checkName;
import static me.lucko.luckperms.common.api.internal.Utils.checkTrack;
import static me.lucko.luckperms.common.api.internal.Utils.checkUser;
import static me.lucko.luckperms.common.api.internal.Utils.checkUsername;
/**
* Provides a link between {@link Datastore} and {@link Storage}
@@ -104,7 +114,7 @@ public class DatastoreLink implements Datastore {
@Override
public void loadOrCreateUser(@NonNull UUID uuid, @NonNull String username, Callback<Boolean> callback) {
registerCallback(master.force().loadUser(uuid, checkUsername(username)) , callback);
registerCallback(master.force().loadUser(uuid, checkUsername(username)), callback);
}
@Override
@@ -26,13 +26,16 @@ import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import static me.lucko.luckperms.common.api.internal.Utils.*;
import static me.lucko.luckperms.common.api.internal.Utils.checkGroup;
import static me.lucko.luckperms.common.api.internal.Utils.checkServer;
import static me.lucko.luckperms.common.api.internal.Utils.checkTime;
/**
* Provides a link between {@link Group} and {@link me.lucko.luckperms.common.core.model.Group}
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.api.internal;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.LPConfiguration;
import me.lucko.luckperms.api.data.DatastoreConfiguration;
import me.lucko.luckperms.api.data.MySQLConfiguration;
@@ -24,6 +24,7 @@ package me.lucko.luckperms.common.api.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.Log;
import me.lucko.luckperms.api.LogEntry;
@@ -39,7 +40,7 @@ import static me.lucko.luckperms.common.api.internal.Utils.checkName;
@AllArgsConstructor
public class LogLink implements Log {
private final me.lucko.luckperms.common.data.Log master;
@Override
public SortedSet<LogEntry> getContent() {
return master.getContent();
@@ -24,15 +24,28 @@ package me.lucko.luckperms.common.api.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.utils.ExtractedContexts;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.*;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import static me.lucko.luckperms.common.api.internal.Utils.*;
import static me.lucko.luckperms.common.api.internal.Utils.checkNode;
import static me.lucko.luckperms.common.api.internal.Utils.checkServer;
import static me.lucko.luckperms.common.api.internal.Utils.checkTime;
import static me.lucko.luckperms.common.core.model.PermissionHolder.exportToLegacy;
/**
@@ -24,7 +24,13 @@ package me.lucko.luckperms.common.api.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Log;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.Storage;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.common.LuckPermsPlugin;
import java.util.Set;
@@ -32,7 +38,11 @@ import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import static me.lucko.luckperms.common.api.internal.Utils.*;
import static me.lucko.luckperms.common.api.internal.Utils.checkGroup;
import static me.lucko.luckperms.common.api.internal.Utils.checkName;
import static me.lucko.luckperms.common.api.internal.Utils.checkTrack;
import static me.lucko.luckperms.common.api.internal.Utils.checkUser;
import static me.lucko.luckperms.common.api.internal.Utils.checkUsername;
/**
* Provides a link between {@link Storage} and {@link me.lucko.luckperms.common.storage.Storage}
@@ -26,6 +26,7 @@ import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
@@ -25,6 +25,7 @@ package me.lucko.luckperms.common.api.internal;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.caching.UserData;
@@ -35,7 +36,9 @@ import java.util.List;
import java.util.Optional;
import java.util.UUID;
import static me.lucko.luckperms.common.api.internal.Utils.*;
import static me.lucko.luckperms.common.api.internal.Utils.checkGroup;
import static me.lucko.luckperms.common.api.internal.Utils.checkServer;
import static me.lucko.luckperms.common.api.internal.Utils.checkTime;
/**
* Provides a link between {@link User} and {@link me.lucko.luckperms.common.core.model.User}
@@ -22,8 +22,10 @@
package me.lucko.luckperms.common.api.internal;
import com.google.common.base.Preconditions;
import lombok.experimental.UtilityClass;
import com.google.common.base.Preconditions;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
@@ -24,6 +24,7 @@ package me.lucko.luckperms.common.api.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.UuidCache;
import java.util.UUID;
@@ -22,10 +22,12 @@
package me.lucko.luckperms.common.caching;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import lombok.Getter;
import lombok.NoArgsConstructor;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import me.lucko.luckperms.api.caching.MetaData;
import java.util.Map;
@@ -24,9 +24,14 @@ package me.lucko.luckperms.common.caching;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.api.Node;
import java.util.*;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* Holds temporary mutable meta whilst this object is passed up the inheritance tree to accumulate meta from parents
@@ -22,8 +22,10 @@
package me.lucko.luckperms.common.caching;
import com.google.common.collect.ImmutableMap;
import lombok.NonNull;
import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.caching.PermissionData;
@@ -22,14 +22,16 @@
package me.lucko.luckperms.common.caching;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.caching.MetaData;
import me.lucko.luckperms.api.caching.PermissionData;
@@ -32,8 +32,9 @@ public interface CalculatorFactory {
/**
* Builds a PermissionCalculator for the user in the given context
*
* @param contexts the contexts to build the calculator in
* @param user the user to build for
* @param user the user to build for
* @return a permission calculator instance
*/
PermissionCalculator build(Contexts contexts, User user);
@@ -22,10 +22,12 @@
package me.lucko.luckperms.common.calculators;
import lombok.RequiredArgsConstructor;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.LuckPermsPlugin;
@@ -55,7 +57,7 @@ public class PermissionCalculator {
public Tristate getPermissionValue(String permission) {
permission = permission.toLowerCase();
Tristate t = cache.getUnchecked(permission);
Tristate t = cache.getUnchecked(permission);
plugin.getDebugHandler().offer(objectName, permission, t);
plugin.getPermissionCache().offer(permission);
return t;
@@ -29,6 +29,7 @@ import java.util.Map;
public interface PermissionProcessor {
Tristate hasPermission(String permission);
void updateBacking(Map<String, Boolean> map);
}
@@ -22,11 +22,12 @@
package me.lucko.luckperms.common.commands;
import com.google.common.collect.ImmutableList;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import com.google.common.collect.ImmutableList;
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Arg {
@@ -22,8 +22,10 @@
package me.lucko.luckperms.common.commands;
import com.google.common.collect.ImmutableList;
import lombok.Getter;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Permission;
@@ -77,6 +79,7 @@ public abstract class Command<T, S> {
}
public abstract void sendUsage(Sender sender, String label);
public abstract void sendDetailedUsage(Sender sender, String label);
public boolean isAuthorized(Sender sender) {
@@ -22,8 +22,10 @@
package me.lucko.luckperms.common.commands;
import com.google.common.collect.ImmutableList;
import lombok.Getter;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.group.CreateGroup;
import me.lucko.luckperms.common.commands.group.DeleteGroup;
@@ -31,7 +33,13 @@ import me.lucko.luckperms.common.commands.group.GroupMainCommand;
import me.lucko.luckperms.common.commands.group.ListGroups;
import me.lucko.luckperms.common.commands.log.LogMainCommand;
import me.lucko.luckperms.common.commands.migration.MigrationMainCommand;
import me.lucko.luckperms.common.commands.misc.*;
import me.lucko.luckperms.common.commands.misc.ExportCommand;
import me.lucko.luckperms.common.commands.misc.ImportCommand;
import me.lucko.luckperms.common.commands.misc.InfoCommand;
import me.lucko.luckperms.common.commands.misc.NetworkSyncCommand;
import me.lucko.luckperms.common.commands.misc.QueueCommand;
import me.lucko.luckperms.common.commands.misc.SyncCommand;
import me.lucko.luckperms.common.commands.misc.VerboseCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.track.CreateTrack;
import me.lucko.luckperms.common.commands.track.DeleteTrack;
@@ -51,115 +59,6 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
public class CommandManager {
@Getter
private final LuckPermsPlugin plugin;
@Getter
private final List<BaseCommand> mainCommands;
public CommandManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
ImmutableList.Builder<BaseCommand> l = ImmutableList.builder();
l.add(new UserMainCommand())
.add(new GroupMainCommand())
.add(new TrackMainCommand())
.addAll(plugin.getExtraCommands())
.add(new LogMainCommand())
.add(new SyncCommand())
.add(new NetworkSyncCommand())
.add(new InfoCommand())
.add(new VerboseCommand())
.add(new ImportCommand())
.add(new ExportCommand())
.add(new QueueCommand())
.add(new MigrationMainCommand())
.add(new UsersBulkEditMainCommand())
.add(new CreateGroup())
.add(new DeleteGroup())
.add(new ListGroups())
.add(new CreateTrack())
.add(new DeleteTrack())
.add(new ListTracks());
mainCommands = l.build();
}
/**
* Generic on command method to be called from the command executor object of the platform
* Unlike {@link #onCommand(Sender, String, List)}, this method is called in a new thread
* @param sender who sent the command
* @param label the command label used
* @param args the arguments provided
* @param result the callback to be called when the command has fully executed
*/
public void onCommand(Sender sender, String label, List<String> args, Consumer<CommandResult> result) {
plugin.doAsync(() -> {
CommandResult r = onCommand(sender, label, args);
if (result != null) {
plugin.doSync(() -> result.accept(r));
}
});
}
/**
* Generic on command method to be called from the command executor object of the platform
* @param sender who sent the command
* @param label the command label used
* @param args the arguments provided
* @return if the command was successful
*/
@SuppressWarnings("unchecked")
public CommandResult onCommand(Sender sender, String label, List<String> args) {
// Handle no arguments
if (args.size() == 0) {
sendCommandUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Look for the main command.
Optional<BaseCommand> o = mainCommands.stream()
.filter(m -> m.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
// Main command not found
if (!o.isPresent()) {
sendCommandUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Check the Sender has permission to use the main command.
final Command main = o.get();
if (!main.isAuthorized(sender)) {
sendCommandUsage(sender, label);
return CommandResult.NO_PERMISSION;
}
List<String> arguments = new ArrayList<>(args);
handleRewrites(arguments);
arguments.remove(0); // remove the main command arg.
// Check the correct number of args were given for the main command
if (main.getArgumentCheck().test(arguments.size())) {
main.sendUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Try to execute the command.
CommandResult result;
try {
result = main.execute(plugin, sender, null, arguments, label);
} catch (CommandException e) {
result = handleException(e, sender, label, main);
} catch (Exception e) {
e.printStackTrace();
result = CommandResult.FAILURE;
}
return result;
}
public static CommandResult handleException(CommandException e, Sender sender, String label, Command command) {
if (e instanceof ArgumentUtils.ArgumentException) {
if (e instanceof ArgumentUtils.DetailedUsageException) {
@@ -198,56 +97,6 @@ public class CommandManager {
return CommandResult.FAILURE;
}
/**
* Generic tab complete method to be called from the command executor object of the platform
* @param sender who is tab completing
* @param args the arguments provided so far
* @return a list of suggestions
*/
@SuppressWarnings("unchecked")
public List<String> onTabComplete(Sender sender, List<String> args) {
final List<Command> mains = mainCommands.stream()
.filter(m -> m.isAuthorized(sender))
.collect(Collectors.toList());
// Not yet past the point of entering a main command
if (args.size() <= 1) {
// Nothing yet entered
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return mains.stream()
.map(m -> m.getName().toLowerCase())
.collect(Collectors.toList());
}
// Started typing a main command
return mains.stream()
.map(m -> m.getName().toLowerCase())
.filter(s -> s.startsWith(args.get(0).toLowerCase()))
.collect(Collectors.toList());
}
// Find a main command matching the first arg
Optional<Command> o = mains.stream()
.filter(m -> m.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
if (!o.isPresent()) {
return Collections.emptyList();
}
// Pass the processing onto the main command
return o.get().tabComplete(plugin, sender, args.subList(1, args.size()));
}
private void sendCommandUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&2Running &bLuckPerms v" + plugin.getVersion() + "&2.");
mainCommands.stream()
.filter(c -> c.isAuthorized(sender))
.forEach(c -> Util.sendPluginMessage(sender, "&3> &a" + String.format(c.getUsage(), label)));
}
private static void handleRewrites(List<String> args) {
if (args.size() >= 3) {
if (!args.get(0).equalsIgnoreCase("user") && !args.get(0).equalsIgnoreCase("group")) {
@@ -362,9 +211,9 @@ public class CommandManager {
// Provide lazy set rewrite
boolean lazySet = (
args.size() >= 6 &&
args.get(2).equalsIgnoreCase("permission") &&
args.get(3).toLowerCase().startsWith("set") &&
(args.get(5).equalsIgnoreCase("none") || args.get(5).equalsIgnoreCase("0"))
args.get(2).equalsIgnoreCase("permission") &&
args.get(3).toLowerCase().startsWith("set") &&
(args.get(5).equalsIgnoreCase("none") || args.get(5).equalsIgnoreCase("0"))
);
if (lazySet) {
@@ -374,4 +223,165 @@ public class CommandManager {
}
}
}
@Getter
private final LuckPermsPlugin plugin;
@Getter
private final List<BaseCommand> mainCommands;
public CommandManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
ImmutableList.Builder<BaseCommand> l = ImmutableList.builder();
l.add(new UserMainCommand())
.add(new GroupMainCommand())
.add(new TrackMainCommand())
.addAll(plugin.getExtraCommands())
.add(new LogMainCommand())
.add(new SyncCommand())
.add(new NetworkSyncCommand())
.add(new InfoCommand())
.add(new VerboseCommand())
.add(new ImportCommand())
.add(new ExportCommand())
.add(new QueueCommand())
.add(new MigrationMainCommand())
.add(new UsersBulkEditMainCommand())
.add(new CreateGroup())
.add(new DeleteGroup())
.add(new ListGroups())
.add(new CreateTrack())
.add(new DeleteTrack())
.add(new ListTracks());
mainCommands = l.build();
}
/**
* Generic on command method to be called from the command executor object of the platform
* Unlike {@link #onCommand(Sender, String, List)}, this method is called in a new thread
*
* @param sender who sent the command
* @param label the command label used
* @param args the arguments provided
* @param result the callback to be called when the command has fully executed
*/
public void onCommand(Sender sender, String label, List<String> args, Consumer<CommandResult> result) {
plugin.doAsync(() -> {
CommandResult r = onCommand(sender, label, args);
if (result != null) {
plugin.doSync(() -> result.accept(r));
}
});
}
/**
* Generic on command method to be called from the command executor object of the platform
*
* @param sender who sent the command
* @param label the command label used
* @param args the arguments provided
* @return if the command was successful
*/
@SuppressWarnings("unchecked")
public CommandResult onCommand(Sender sender, String label, List<String> args) {
// Handle no arguments
if (args.size() == 0) {
sendCommandUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Look for the main command.
Optional<BaseCommand> o = mainCommands.stream()
.filter(m -> m.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
// Main command not found
if (!o.isPresent()) {
sendCommandUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Check the Sender has permission to use the main command.
final Command main = o.get();
if (!main.isAuthorized(sender)) {
sendCommandUsage(sender, label);
return CommandResult.NO_PERMISSION;
}
List<String> arguments = new ArrayList<>(args);
handleRewrites(arguments);
arguments.remove(0); // remove the main command arg.
// Check the correct number of args were given for the main command
if (main.getArgumentCheck().test(arguments.size())) {
main.sendUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
// Try to execute the command.
CommandResult result;
try {
result = main.execute(plugin, sender, null, arguments, label);
} catch (CommandException e) {
result = handleException(e, sender, label, main);
} catch (Exception e) {
e.printStackTrace();
result = CommandResult.FAILURE;
}
return result;
}
/**
* Generic tab complete method to be called from the command executor object of the platform
*
* @param sender who is tab completing
* @param args the arguments provided so far
* @return a list of suggestions
*/
@SuppressWarnings("unchecked")
public List<String> onTabComplete(Sender sender, List<String> args) {
final List<Command> mains = mainCommands.stream()
.filter(m -> m.isAuthorized(sender))
.collect(Collectors.toList());
// Not yet past the point of entering a main command
if (args.size() <= 1) {
// Nothing yet entered
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return mains.stream()
.map(m -> m.getName().toLowerCase())
.collect(Collectors.toList());
}
// Started typing a main command
return mains.stream()
.map(m -> m.getName().toLowerCase())
.filter(s -> s.startsWith(args.get(0).toLowerCase()))
.collect(Collectors.toList());
}
// Find a main command matching the first arg
Optional<Command> o = mains.stream()
.filter(m -> m.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
if (!o.isPresent()) {
return Collections.emptyList();
}
// Pass the processing onto the main command
return o.get().tabComplete(plugin, sender, args.subList(1, args.size()));
}
private void sendCommandUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&2Running &bLuckPerms v" + plugin.getVersion() + "&2.");
mainCommands.stream()
.filter(c -> c.isAuthorized(sender))
.forEach(c -> Util.sendPluginMessage(sender, "&3> &a" + String.format(c.getUsage(), label)));
}
}
@@ -34,14 +34,14 @@ public enum CommandResult {
INVALID_ARGS(false),
NO_PERMISSION(false);
public static CommandResult of(boolean b) {
return b ? SUCCESS : FAILURE;
}
private boolean value;
public boolean asBoolean() {
return value;
}
public static CommandResult of(boolean b) {
return b ? SUCCESS : FAILURE;
}
}
@@ -25,6 +25,7 @@ package me.lucko.luckperms.common.commands;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.common.commands.sender.Sender;
import java.util.ArrayList;
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands;
import lombok.Getter;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
@@ -141,7 +142,9 @@ public abstract class MainCommand<T> extends BaseCommand<Void, T> {
}
protected abstract List<String> getTargets(LuckPermsPlugin plugin);
protected abstract T getTarget(String target, LuckPermsPlugin plugin, Sender sender);
protected abstract void cleanup(T t, LuckPermsPlugin plugin);
@Override
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands;
import lombok.Getter;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
@@ -22,8 +22,10 @@
package me.lucko.luckperms.common.commands;
import com.google.common.base.Splitter;
import lombok.Getter;
import com.google.common.base.Splitter;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
@@ -34,7 +36,11 @@ import me.lucko.luckperms.common.core.model.Track;
import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.utils.PermissionCache;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -44,46 +50,6 @@ import java.util.stream.Collectors;
@Getter
public abstract class SubCommand<T> extends Command<T, Void> {
public SubCommand(String name, String description, Permission permission, Predicate<Integer> argumentCheck, List<Arg> args) {
super(name, description, permission, argumentCheck, args);
}
/**
* Send the command usage to a sender
* @param sender the sender to send the usage to
*/
@Override
public void sendUsage(Sender sender, String label) {
StringBuilder sb = new StringBuilder();
if (getArgs().isPresent()) {
sb.append("&3 - &7");
for (Arg arg : getArgs().get()) {
sb.append(arg.asPrettyString()).append(" ");
}
}
Util.sendPluginMessage(sender, "&3> &a" + getName().toLowerCase() + sb.toString());
}
@Override
public void sendDetailedUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&3&lCommand Usage &3- &b" + getName());
Util.sendPluginMessage(sender, "&b> &7" + getDescription());
if (getArgs().isPresent()) {
Util.sendPluginMessage(sender, "&3Arguments:");
for (Arg arg : getArgs().get()) {
Util.sendPluginMessage(sender, "&b- " + arg.asPrettyString() + "&3 -> &7" + arg.getDescription());
}
}
}
/*
* ----------------------------------------------------------------------------------
* Utility methods used by #tabComplete and #execute implementations in sub classes
* ----------------------------------------------------------------------------------
*/
public static List<String> getGroupTabComplete(List<String> args, LuckPermsPlugin plugin) {
return getTabComplete(new ArrayList<>(plugin.getGroupManager().getAll().keySet()), args);
}
@@ -100,6 +66,13 @@ public abstract class SubCommand<T> extends Command<T, Void> {
}
}
/*
* ----------------------------------------------------------------------------------
* Utility methods used by #tabComplete and #execute implementations in sub classes
* ----------------------------------------------------------------------------------
*/
public static List<String> getPermissionTabComplete(List<String> args, PermissionCache cache) {
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equals("")) {
@@ -193,4 +166,38 @@ public abstract class SubCommand<T> extends Command<T, Void> {
Message.TRACK_SAVE_ERROR.send(sender);
}
}
public SubCommand(String name, String description, Permission permission, Predicate<Integer> argumentCheck, List<Arg> args) {
super(name, description, permission, argumentCheck, args);
}
/**
* Send the command usage to a sender
*
* @param sender the sender to send the usage to
*/
@Override
public void sendUsage(Sender sender, String label) {
StringBuilder sb = new StringBuilder();
if (getArgs().isPresent()) {
sb.append("&3 - &7");
for (Arg arg : getArgs().get()) {
sb.append(arg.asPrettyString()).append(" ");
}
}
Util.sendPluginMessage(sender, "&3> &a" + getName().toLowerCase() + sb.toString());
}
@Override
public void sendDetailedUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&3&lCommand Usage &3- &b" + getName());
Util.sendPluginMessage(sender, "&b> &7" + getDescription());
if (getArgs().isPresent()) {
Util.sendPluginMessage(sender, "&3Arguments:");
for (Arg arg : getArgs().get()) {
Util.sendPluginMessage(sender, "&b- " + arg.asPrettyString() + "&3 -> &7" + arg.getDescription());
}
}
}
}
@@ -40,8 +40,46 @@ import java.util.Optional;
import java.util.stream.Collectors;
public class SharedMainCommand<T extends PermissionHolder> extends SubCommand<T> {
private boolean user;
private static CommandResult handleException(CommandException e, Sender sender, SharedSubCommand command) {
if (e instanceof ArgumentUtils.ArgumentException) {
if (e instanceof ArgumentUtils.DetailedUsageException) {
command.sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.UseInheritException) {
Message.USE_INHERIT_COMMAND.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidServerException) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.PastDateException) {
Message.PAST_DATE_ERROR.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidDateException) {
Message.ILLEGAL_DATE_ERROR.send(sender, ((ArgumentUtils.InvalidDateException) e).getInvalidDate());
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidPriorityException) {
Message.META_INVALID_PRIORITY.send(sender, ((ArgumentUtils.InvalidPriorityException) e).getInvalidPriority());
return CommandResult.INVALID_ARGS;
}
}
// Not something we can catch.
e.printStackTrace();
return CommandResult.FAILURE;
}
private final List<SharedSubCommand> secondaryCommands;
private boolean user;
public SharedMainCommand(String name, String description, boolean user, List<SharedSubCommand> secondaryCommands) {
super(name, description, null, Predicates.alwaysFalse(), null);
@@ -91,44 +129,6 @@ public class SharedMainCommand<T extends PermissionHolder> extends SubCommand<T>
return result;
}
private static CommandResult handleException(CommandException e, Sender sender, SharedSubCommand command) {
if (e instanceof ArgumentUtils.ArgumentException) {
if (e instanceof ArgumentUtils.DetailedUsageException) {
command.sendDetailedUsage(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.UseInheritException) {
Message.USE_INHERIT_COMMAND.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidServerException) {
Message.SERVER_INVALID_ENTRY.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.PastDateException) {
Message.PAST_DATE_ERROR.send(sender);
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidDateException) {
Message.ILLEGAL_DATE_ERROR.send(sender, ((ArgumentUtils.InvalidDateException) e).getInvalidDate());
return CommandResult.INVALID_ARGS;
}
if (e instanceof ArgumentUtils.InvalidPriorityException) {
Message.META_INVALID_PRIORITY.send(sender, ((ArgumentUtils.InvalidPriorityException) e).getInvalidPriority());
return CommandResult.INVALID_ARGS;
}
}
// Not something we can catch.
e.printStackTrace();
return CommandResult.FAILURE;
}
@Override
public List<String> tabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
final List<SharedSubCommand> subs = secondaryCommands.stream()
@@ -22,9 +22,11 @@
package me.lucko.luckperms.common.commands.generic;
import com.google.common.collect.ImmutableList;
import lombok.AllArgsConstructor;
import lombok.Getter;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Arg;
import me.lucko.luckperms.common.commands.CommandException;
@@ -45,27 +47,39 @@ import java.util.function.Predicate;
@AllArgsConstructor
public abstract class SharedSubCommand {
protected static void save(PermissionHolder holder, Sender sender, LuckPermsPlugin plugin) {
if (holder instanceof User) {
User user = ((User) holder);
SubCommand.save(user, sender, plugin);
return;
}
if (holder instanceof Group) {
Group group = ((Group) holder);
SubCommand.save(group, sender, plugin);
return;
}
throw new IllegalArgumentException();
}
/**
* The name of the sub command
*/
private final String name;
/**
* A brief description of what the sub command does
*/
private final String description;
/**
* The permission needed to use this command
*/
private final Permission userPermission;
private final Permission groupPermission;
/**
* Predicate to test if the argument length given is invalid
*/
private final Predicate<? super Integer> isArgumentInvalid;
private final ImmutableList<Arg> args;
public abstract CommandResult execute(LuckPermsPlugin plugin, Sender sender, PermissionHolder holder, List<String> args) throws CommandException;
@@ -101,20 +115,4 @@ public abstract class SharedSubCommand {
return user ? userPermission.isAuthorized(sender) : groupPermission.isAuthorized(sender);
}
protected static void save(PermissionHolder holder, Sender sender, LuckPermsPlugin plugin) {
if (holder instanceof User) {
User user = ((User) holder);
SubCommand.save(user, sender, plugin);
return;
}
if (holder instanceof Group) {
Group group = ((Group) holder);
SubCommand.save(group, sender, plugin);
return;
}
throw new IllegalArgumentException();
}
}
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.generic.meta;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.commands.generic.SharedMainCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.core.model.PermissionHolder;
@@ -30,20 +31,20 @@ import me.lucko.luckperms.common.core.model.PermissionHolder;
public class CommandMeta<T extends PermissionHolder> extends SharedMainCommand<T> {
public CommandMeta(boolean user) {
super("Meta", "Edit metadata values", user, ImmutableList.<SharedSubCommand>builder()
.add(new MetaInfo())
.add(new MetaSet())
.add(new MetaUnset())
.add(new MetaSetTemp())
.add(new MetaUnsetTemp())
.add(new MetaAddPrefix())
.add(new MetaAddSuffix())
.add(new MetaRemovePrefix())
.add(new MetaRemoveSuffix())
.add(new MetaAddTempPrefix())
.add(new MetaAddTempSuffix())
.add(new MetaRemoveTempPrefix())
.add(new MetaRemoveTempSuffix())
.add(new MetaClear())
.build());
.add(new MetaInfo())
.add(new MetaSet())
.add(new MetaUnset())
.add(new MetaSetTemp())
.add(new MetaUnsetTemp())
.add(new MetaAddPrefix())
.add(new MetaAddSuffix())
.add(new MetaRemovePrefix())
.add(new MetaRemoveSuffix())
.add(new MetaAddTempPrefix())
.add(new MetaAddTempSuffix())
.add(new MetaRemoveTempPrefix())
.add(new MetaRemoveTempSuffix())
.add(new MetaClear())
.build());
}
}
@@ -43,7 +43,7 @@ import java.util.stream.Collectors;
public class MetaAddPrefix extends SharedSubCommand {
public MetaAddPrefix() {
super("addprefix", "Adds a prefix", Permission.USER_META_ADDPREFIX, Permission.GROUP_META_ADDPREFIX,
super("addprefix", "Adds a prefix", Permission.USER_META_ADDPREFIX, Permission.GROUP_META_ADDPREFIX,
Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
@@ -43,7 +43,7 @@ import java.util.stream.Collectors;
public class MetaAddSuffix extends SharedSubCommand {
public MetaAddSuffix() {
super("addsuffix", "Adds a suffix", Permission.USER_META_ADDSUFFIX, Permission.GROUP_META_ADDSUFFIX,
super("addsuffix", "Adds a suffix", Permission.USER_META_ADDSUFFIX, Permission.GROUP_META_ADDSUFFIX,
Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
@@ -44,7 +44,7 @@ import java.util.stream.Collectors;
public class MetaAddTempPrefix extends SharedSubCommand {
public MetaAddTempPrefix() {
super("addtempprefix", "Adds a prefix temporarily", Permission.USER_META_ADDTEMP_PREFIX,
super("addtempprefix", "Adds a prefix temporarily", Permission.USER_META_ADDTEMP_PREFIX,
Permission.GROUP_META_ADDTEMP_PREFIX, Predicates.notInRange(3, 5),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
@@ -44,7 +44,7 @@ import java.util.stream.Collectors;
public class MetaAddTempSuffix extends SharedSubCommand {
public MetaAddTempSuffix() {
super("addtempsuffix", "Adds a suffix temporarily", Permission.USER_META_ADDTEMP_SUFFIX,
super("addtempsuffix", "Adds a suffix temporarily", Permission.USER_META_ADDTEMP_SUFFIX,
Permission.GROUP_META_ADDTEMP_SUFFIX, Predicates.notInRange(3, 5),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
@@ -41,7 +41,7 @@ import java.util.stream.Collectors;
public class MetaClear extends SharedSubCommand {
public MetaClear() {
super("clear", "Clears all chat meta", Permission.USER_META_CLEAR, Permission.GROUP_META_CLEAR, Predicates.notInRange(0, 2),
super("clear", "Clears all chat meta", Permission.USER_META_CLEAR, Permission.GROUP_META_CLEAR, Predicates.notInRange(0, 2),
Arg.list(
Arg.create("server", false, "the server name to filter by"),
Arg.create("world", false, "the world name to filter by")
@@ -36,11 +36,21 @@ import me.lucko.luckperms.common.core.model.PermissionHolder;
import me.lucko.luckperms.common.utils.ExtractedContexts;
import me.lucko.luckperms.common.utils.Predicates;
import java.util.*;
import java.util.AbstractMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
public class MetaInfo extends SharedSubCommand {
private static String processLocation(LocalizedNode node, PermissionHolder holder) {
return node.getLocation().equalsIgnoreCase(holder.getObjectName()) ? "self" : node.getLocation();
}
public MetaInfo() {
super("info", "Shows all chat meta", Permission.USER_META_INFO, Permission.GROUP_META_INFO, Predicates.alwaysFalse(), null);
super("info", "Shows all chat meta", Permission.USER_META_INFO, Permission.GROUP_META_INFO, Predicates.alwaysFalse(), null);
}
@Override
@@ -111,8 +121,4 @@ public class MetaInfo extends SharedSubCommand {
return CommandResult.SUCCESS;
}
private static String processLocation(LocalizedNode node, PermissionHolder holder) {
return node.getLocation().equalsIgnoreCase(holder.getObjectName()) ? "self" : node.getLocation();
}
}
@@ -45,7 +45,7 @@ import java.util.stream.Collectors;
public class MetaRemovePrefix extends SharedSubCommand {
public MetaRemovePrefix() {
super("removeprefix", "Removes a prefix", Permission.USER_META_REMOVEPREFIX, Permission.GROUP_META_REMOVEPREFIX,
super("removeprefix", "Removes a prefix", Permission.USER_META_REMOVEPREFIX, Permission.GROUP_META_REMOVEPREFIX,
Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
@@ -91,7 +91,8 @@ public class MetaRemovePrefix extends SharedSubCommand {
toRemove.forEach(n -> {
try {
holder.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
});
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
@@ -45,7 +45,7 @@ import java.util.stream.Collectors;
public class MetaRemoveSuffix extends SharedSubCommand {
public MetaRemoveSuffix() {
super("removesuffix", "Removes a suffix", Permission.USER_META_REMOVESUFFIX, Permission.GROUP_META_REMOVESUFFIX,
super("removesuffix", "Removes a suffix", Permission.USER_META_REMOVESUFFIX, Permission.GROUP_META_REMOVESUFFIX,
Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
@@ -91,7 +91,8 @@ public class MetaRemoveSuffix extends SharedSubCommand {
toRemove.forEach(n -> {
try {
holder.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
});
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
@@ -45,7 +45,7 @@ import java.util.stream.Collectors;
public class MetaRemoveTempPrefix extends SharedSubCommand {
public MetaRemoveTempPrefix() {
super("removetempprefix", "Removes a temporary prefix", Permission.USER_META_REMOVETEMP_PREFIX, Permission.GROUP_META_REMOVETEMP_PREFIX, Predicates.notInRange(2, 4),
super("removetempprefix", "Removes a temporary prefix", Permission.USER_META_REMOVETEMP_PREFIX, Permission.GROUP_META_REMOVETEMP_PREFIX, Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the prefix at"),
Arg.create("prefix", true, "the prefix string"),
@@ -90,7 +90,8 @@ public class MetaRemoveTempPrefix extends SharedSubCommand {
toRemove.forEach(n -> {
try {
holder.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
});
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
@@ -45,7 +45,7 @@ import java.util.stream.Collectors;
public class MetaRemoveTempSuffix extends SharedSubCommand {
public MetaRemoveTempSuffix() {
super("removetempsuffix", "Removes a temporary suffix", Permission.USER_META_REMOVETEMP_SUFFIX, Permission.GROUP_META_REMOVETEMP_SUFFIX, Predicates.notInRange(2, 4),
super("removetempsuffix", "Removes a temporary suffix", Permission.USER_META_REMOVETEMP_SUFFIX, Permission.GROUP_META_REMOVETEMP_SUFFIX, Predicates.notInRange(2, 4),
Arg.list(
Arg.create("priority", true, "the priority to add the suffix at"),
Arg.create("suffix", true, "the suffix string"),
@@ -90,7 +90,8 @@ public class MetaRemoveTempSuffix extends SharedSubCommand {
toRemove.forEach(n -> {
try {
holder.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
});
Message.BULK_CHANGE_SUCCESS.send(sender, toRemove.size());
@@ -44,7 +44,7 @@ import java.util.stream.Collectors;
public class MetaSet extends SharedSubCommand {
public MetaSet() {
super("set", "Sets a meta value", Permission.USER_META_SET, Permission.GROUP_META_SET, Predicates.notInRange(2, 4),
super("set", "Sets a meta value", Permission.USER_META_SET, Permission.GROUP_META_SET, Predicates.notInRange(2, 4),
Arg.list(
Arg.create("key", true, "the key to set"),
Arg.create("value", true, "the value to set"),
@@ -73,7 +73,8 @@ public class MetaSet extends SharedSubCommand {
try {
holder.setPermission(n);
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
switch (ContextHelper.determine(server, world)) {
case NONE:
@@ -45,7 +45,7 @@ import java.util.stream.Collectors;
public class MetaSetTemp extends SharedSubCommand {
public MetaSetTemp() {
super("settemp", "Sets a meta value temporarily", Permission.USER_META_SETTEMP, Permission.GROUP_META_SETTEMP, Predicates.notInRange(3, 5),
super("settemp", "Sets a meta value temporarily", Permission.USER_META_SETTEMP, Permission.GROUP_META_SETTEMP, Predicates.notInRange(3, 5),
Arg.list(
Arg.create("key", true, "the key to set"),
Arg.create("value", true, "the value to set"),
@@ -75,7 +75,8 @@ public class MetaSetTemp extends SharedSubCommand {
try {
holder.setPermission(n);
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
switch (ContextHelper.determine(server, world)) {
case NONE:
@@ -41,7 +41,7 @@ import java.util.stream.Collectors;
public class MetaUnset extends SharedSubCommand {
public MetaUnset() {
super("unset", "Unsets a meta value", Permission.USER_META_UNSET, Permission.GROUP_META_UNSET,
super("unset", "Unsets a meta value", Permission.USER_META_UNSET, Permission.GROUP_META_UNSET,
Predicates.notInRange(1, 3),
Arg.list(
Arg.create("key", true, "the key to unset"),
@@ -41,7 +41,7 @@ import java.util.stream.Collectors;
public class MetaUnsetTemp extends SharedSubCommand {
public MetaUnsetTemp() {
super("unsettemp", "Unsets a temporary meta value", Permission.USER_META_UNSETTEMP, Permission.GROUP_META_UNSETTEMP,
super("unsettemp", "Unsets a temporary meta value", Permission.USER_META_UNSETTEMP, Permission.GROUP_META_UNSETTEMP,
Predicates.notInRange(1, 3),
Arg.list(
Arg.create("key", true, "the key to unset"),
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.generic.parent;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.commands.generic.SharedMainCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.core.model.PermissionHolder;
@@ -30,12 +31,12 @@ import me.lucko.luckperms.common.core.model.PermissionHolder;
public class CommandParent<T extends PermissionHolder> extends SharedMainCommand<T> {
public CommandParent(boolean user) {
super("Parent", "Edit inheritances", user, ImmutableList.<SharedSubCommand>builder()
.add(new ParentInfo())
.add(new ParentSet())
.add(new ParentAdd())
.add(new ParentRemove())
.add(new ParentAddTemp())
.add(new ParentRemoveTemp())
.build());
.add(new ParentInfo())
.add(new ParentSet())
.add(new ParentAdd())
.add(new ParentRemove())
.add(new ParentAddTemp())
.add(new ParentRemoveTemp())
.build());
}
}
@@ -79,7 +79,8 @@ public class ParentSet extends SharedSubCommand {
try {
holder.setInheritGroup(group);
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
if (holder instanceof User) {
((User) holder).setPrimaryGroup(group.getName());
@@ -92,7 +93,8 @@ public class ParentSet extends SharedSubCommand {
try {
holder.setInheritGroup(group, server);
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
if (server.equalsIgnoreCase("global") && holder instanceof User) {
((User) holder).setPrimaryGroup(group.getName());
@@ -105,7 +107,8 @@ public class ParentSet extends SharedSubCommand {
try {
holder.setInheritGroup(group, server, world);
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
Message.SET_PARENT_SERVER_WORLD_SUCCESS.send(sender, holder.getFriendlyName(), group.getDisplayName(), server, world);
break;
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.generic.permission;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.commands.generic.SharedMainCommand;
import me.lucko.luckperms.common.commands.generic.SharedSubCommand;
import me.lucko.luckperms.common.core.model.PermissionHolder;
@@ -30,13 +31,13 @@ import me.lucko.luckperms.common.core.model.PermissionHolder;
public class CommandPermission<T extends PermissionHolder> extends SharedMainCommand<T> {
public CommandPermission(boolean user) {
super("Permission", "Edit permissions", user, ImmutableList.<SharedSubCommand>builder()
.add(new PermissionInfo())
.add(new PermissionSet())
.add(new PermissionUnset())
.add(new PermissionSetTemp())
.add(new PermissionUnsetTemp())
.add(new PermissionCheck())
.add(new PermissionCheckInherits())
.build());
.add(new PermissionInfo())
.add(new PermissionSet())
.add(new PermissionUnset())
.add(new PermissionSetTemp())
.add(new PermissionUnsetTemp())
.add(new PermissionCheck())
.add(new PermissionCheckInherits())
.build());
}
}
@@ -98,13 +98,15 @@ public class GroupBulkChange extends SubCommand<Group> {
toRemove.forEach(n -> {
try {
group.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
});
toAdd.forEach(n -> {
try {
group.setPermission(n);
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
});
save(group, sender, plugin);
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.group;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Command;
import me.lucko.luckperms.common.commands.MainCommand;
@@ -23,10 +23,17 @@
package me.lucko.luckperms.common.commands.log;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Command;
import me.lucko.luckperms.common.commands.MainCommand;
import me.lucko.luckperms.common.commands.log.subcommands.*;
import me.lucko.luckperms.common.commands.log.subcommands.LogExport;
import me.lucko.luckperms.common.commands.log.subcommands.LogGroupHistory;
import me.lucko.luckperms.common.commands.log.subcommands.LogNotify;
import me.lucko.luckperms.common.commands.log.subcommands.LogRecent;
import me.lucko.luckperms.common.commands.log.subcommands.LogSearch;
import me.lucko.luckperms.common.commands.log.subcommands.LogTrackHistory;
import me.lucko.luckperms.common.commands.log.subcommands.LogUserHistory;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.data.Log;
@@ -43,6 +43,32 @@ import java.util.SortedMap;
import java.util.UUID;
public class LogRecent extends SubCommand<Log> {
private static CommandResult showLog(int page, UUID filter, Sender sender, Log log) {
int maxPage = (filter != null) ? log.getRecentMaxPages(filter) : log.getRecentMaxPages();
if (maxPage == 0) {
Message.LOG_NO_ENTRIES.send(sender);
return CommandResult.STATE_ERROR;
}
if (page < 1 || page > maxPage) {
Message.LOG_INVALID_PAGE_RANGE.send(sender, maxPage);
return CommandResult.INVALID_ARGS;
}
SortedMap<Integer, LogEntry> entries = (filter != null) ? log.getRecent(page, filter) : log.getRecent(page);
if (filter != null) {
String name = entries.values().stream().findAny().get().getActorName();
Message.LOG_RECENT_BY_HEADER.send(sender, name, page, maxPage);
} else {
Message.LOG_RECENT_HEADER.send(sender, page, maxPage);
}
for (Map.Entry<Integer, LogEntry> e : entries.entrySet()) {
Message.LOG_ENTRY.send(sender, e.getKey(), DateUtil.formatDateDiff(e.getValue().getTimestamp()), e.getValue().getFormatted());
}
return CommandResult.SUCCESS;
}
public LogRecent() {
super("recent", "View recent actions", Permission.LOG_RECENT, Predicates.notInRange(0, 2),
Arg.list(
@@ -65,7 +91,8 @@ public class LogRecent extends SubCommand<Log> {
int p = Integer.parseInt(args.get(0));
// page
return showLog(p, null, sender, log);
} catch (NumberFormatException ignored) {}
} catch (NumberFormatException ignored) {
}
}
// User and possibly page
@@ -120,30 +147,4 @@ public class LogRecent extends SubCommand<Log> {
}
}
}
private static CommandResult showLog(int page, UUID filter, Sender sender, Log log) {
int maxPage = (filter != null) ? log.getRecentMaxPages(filter) : log.getRecentMaxPages();
if (maxPage == 0) {
Message.LOG_NO_ENTRIES.send(sender);
return CommandResult.STATE_ERROR;
}
if (page < 1 || page > maxPage) {
Message.LOG_INVALID_PAGE_RANGE.send(sender, maxPage);
return CommandResult.INVALID_ARGS;
}
SortedMap<Integer, LogEntry> entries = (filter != null) ? log.getRecent(page, filter) : log.getRecent(page);
if (filter != null) {
String name = entries.values().stream().findAny().get().getActorName();
Message.LOG_RECENT_BY_HEADER.send(sender, name, page, maxPage);
} else {
Message.LOG_RECENT_HEADER.send(sender, page, maxPage);
}
for (Map.Entry<Integer, LogEntry> e : entries.entrySet()) {
Message.LOG_ENTRY.send(sender, e.getKey(), DateUtil.formatDateDiff(e.getValue().getTimestamp()), e.getValue().getFormatted());
}
return CommandResult.SUCCESS;
}
}
@@ -57,7 +57,8 @@ public class LogSearch extends SubCommand<Log> {
try {
page = Integer.parseInt(args.get(args.size() - 1));
args.remove(args.size() - 1);
} catch (NumberFormatException ignored) {}
} catch (NumberFormatException ignored) {
}
}
final String query = args.stream().collect(Collectors.joining(" "));
@@ -43,6 +43,29 @@ import java.util.SortedMap;
import java.util.UUID;
public class LogUserHistory extends SubCommand<Log> {
private static CommandResult showLog(int page, UUID user, Sender sender, Log log) {
int maxPage = log.getUserHistoryMaxPages(user);
if (maxPage == 0) {
Message.LOG_NO_ENTRIES.send(sender);
return CommandResult.STATE_ERROR;
}
if (page < 1 || page > maxPage) {
Message.LOG_INVALID_PAGE_RANGE.send(sender, maxPage);
return CommandResult.INVALID_ARGS;
}
SortedMap<Integer, LogEntry> entries = log.getUserHistory(page, user);
String name = entries.values().stream().findAny().get().getActedName();
Message.LOG_HISTORY_USER_HEADER.send(sender, name, page, maxPage);
for (Map.Entry<Integer, LogEntry> e : entries.entrySet()) {
Message.LOG_ENTRY.send(sender, e.getKey(), DateUtil.formatDateDiff(e.getValue().getTimestamp()), e.getValue().getFormatted());
}
return CommandResult.SUCCESS;
}
public LogUserHistory() {
super("userhistory", "View a user's history", Permission.LOG_USER_HISTORY, Predicates.notInRange(1, 2),
Arg.list(
@@ -99,27 +122,4 @@ public class LogUserHistory extends SubCommand<Log> {
Message.USER_INVALID_ENTRY.send(sender, user);
return CommandResult.INVALID_ARGS;
}
private static CommandResult showLog(int page, UUID user, Sender sender, Log log) {
int maxPage = log.getUserHistoryMaxPages(user);
if (maxPage == 0) {
Message.LOG_NO_ENTRIES.send(sender);
return CommandResult.STATE_ERROR;
}
if (page < 1 || page > maxPage) {
Message.LOG_INVALID_PAGE_RANGE.send(sender, maxPage);
return CommandResult.INVALID_ARGS;
}
SortedMap<Integer, LogEntry> entries = log.getUserHistory(page, user);
String name = entries.values().stream().findAny().get().getActedName();
Message.LOG_HISTORY_USER_HEADER.send(sender, name, page, maxPage);
for (Map.Entry<Integer, LogEntry> e : entries.entrySet()) {
Message.LOG_ENTRY.send(sender, e.getKey(), DateUtil.formatDateDiff(e.getValue().getTimestamp()), e.getValue().getFormatted());
}
return CommandResult.SUCCESS;
}
}
@@ -23,7 +23,11 @@
package me.lucko.luckperms.common.commands.migration;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.*;
import me.lucko.luckperms.common.commands.Command;
import me.lucko.luckperms.common.commands.CommandException;
import me.lucko.luckperms.common.commands.CommandResult;
import me.lucko.luckperms.common.commands.MainCommand;
import me.lucko.luckperms.common.commands.SubCommand;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.constants.Message;
@@ -35,12 +39,6 @@ import java.util.Optional;
import java.util.stream.Collectors;
public class MigrationMainCommand extends MainCommand<Object> {
private List<Command<Object, ?>> commands = null;
public MigrationMainCommand() {
super("Migration", "Migration commands", "/%s migration", 1, null);
}
@SuppressWarnings("unchecked")
private static List<Command<Object, ?>> getAvailableCommands() {
List<SubCommand<Object>> l = new ArrayList<>();
@@ -48,46 +46,60 @@ public class MigrationMainCommand extends MainCommand<Object> {
try {
Class.forName("org.anjocaido.groupmanager.GroupManager");
l.add((SubCommand<Object>) Class.forName("me.lucko.luckperms.bukkit.migration.MigrationGroupManager").newInstance());
} catch (Throwable ignored) {}
} catch (Throwable ignored) {
}
try {
Class.forName("ru.tehkode.permissions.bukkit.PermissionsEx");
l.add((SubCommand<Object>) Class.forName("me.lucko.luckperms.bukkit.migration.MigrationPermissionsEx").newInstance());
} catch (Throwable ignored) {}
} catch (Throwable ignored) {
}
try {
Class.forName("com.github.cheesesoftware.PowerfulPermsAPI.PowerfulPermsPlugin");
l.add((SubCommand<Object>) Class.forName("me.lucko.luckperms.bukkit.migration.MigrationPowerfulPerms").newInstance());
} catch (Throwable ignored) {}
} catch (Throwable ignored) {
}
try {
Class.forName("org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService");
l.add((SubCommand<Object>) Class.forName("me.lucko.luckperms.bukkit.migration.MigrationZPermissions").newInstance());
} catch (Throwable ignored) {}
} catch (Throwable ignored) {
}
try {
Class.forName("net.alpenblock.bungeeperms.BungeePerms");
l.add((SubCommand<Object>) Class.forName("me.lucko.luckperms.bungee.migration.MigrationBungeePerms").newInstance());
} catch (Throwable ignored) {}
} catch (Throwable ignored) {
}
try {
Class.forName("de.bananaco.bpermissions.api.WorldManager");
l.add((SubCommand<Object>) Class.forName("me.lucko.luckperms.bukkit.migration.MigrationBPermissions").newInstance());
} catch (Throwable ignored) {}
} catch (Throwable ignored) {
}
try {
Class.forName("ninja.leaping.permissionsex.sponge.PermissionsExPlugin");
l.add((SubCommand<Object>) Class.forName("me.lucko.luckperms.sponge.migration.MigrationPermissionsEx").newInstance());
} catch (Throwable ignored) {}
} catch (Throwable ignored) {
}
try {
Class.forName("io.github.djxy.permissionmanager.PermissionManager");
l.add((SubCommand<Object>) Class.forName("me.lucko.luckperms.sponge.migration.MigrationPermissionManager").newInstance());
} catch (Throwable ignored) {}
} catch (Throwable ignored) {
}
return l.stream().collect(Collectors.toList());
}
private List<Command<Object, ?>> commands = null;
public MigrationMainCommand() {
super("Migration", "Migration commands", "/%s migration", 1, null);
}
@SuppressWarnings("deprecation")
@Deprecated
@Override
@@ -48,6 +48,59 @@ import java.util.Set;
import java.util.UUID;
public class ExportCommand extends SingleCommand {
private static void write(BufferedWriter writer, String s) {
try {
writer.write(s);
writer.newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
private static String nodeToString(Node node, String id, boolean group) {
StringBuilder sb = new StringBuilder();
sb.append("/luckperms ").append(group ? "group " : "user ").append(id).append(" ");
if (node.isGroupNode()) {
if (node.isTemporary()) {
sb.append("parent addtemp ");
sb.append(node.getGroupName());
sb.append(" ").append(node.getExpiryUnixTime());
} else {
sb.append("parent add ");
sb.append(node.getGroupName());
}
if (node.isWorldSpecific()) {
sb.append(" ").append(node.getServer().get()).append(" ").append(node.getWorld().get());
} else if (node.isServerSpecific()) {
sb.append(" ").append(node.getServer().get());
}
return sb.toString();
}
sb.append(node.isTemporary() ? "permission settemp " : "permission set ");
if (node.getPermission().contains(" ")) {
sb.append("\"").append(node.getPermission()).append("\"");
} else {
sb.append(node.getPermission());
}
sb.append(" ").append(node.getValue());
if (node.isTemporary()) {
sb.append(" ").append(node.getExpiryUnixTime());
}
if (node.isWorldSpecific()) {
sb.append(" ").append(node.getServer().get()).append(" ").append(node.getWorld().get());
} else if (node.isServerSpecific()) {
sb.append(" ").append(node.getServer().get());
}
return sb.toString();
}
public ExportCommand() {
super("Export", "Export data to a file", "/%s export <file>", Permission.MIGRATION, Predicates.not(1),
Arg.list(
@@ -174,57 +227,4 @@ public class ExportCommand extends SingleCommand {
return sender.getUuid().equals(Constants.getConsoleUUID());
}
private static void write(BufferedWriter writer, String s) {
try {
writer.write(s);
writer.newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
private static String nodeToString(Node node, String id, boolean group) {
StringBuilder sb = new StringBuilder();
sb.append("/luckperms ").append(group ? "group " : "user ").append(id).append(" ");
if (node.isGroupNode()) {
if (node.isTemporary()) {
sb.append("parent addtemp ");
sb.append(node.getGroupName());
sb.append(" ").append(node.getExpiryUnixTime());
} else {
sb.append("parent add ");
sb.append(node.getGroupName());
}
if (node.isWorldSpecific()) {
sb.append(" ").append(node.getServer().get()).append(" ").append(node.getWorld().get());
} else if (node.isServerSpecific()) {
sb.append(" ").append(node.getServer().get());
}
return sb.toString();
}
sb.append(node.isTemporary() ? "permission settemp " : "permission set ");
if (node.getPermission().contains(" ")) {
sb.append("\"").append(node.getPermission()).append("\"");
} else {
sb.append(node.getPermission());
}
sb.append(" ").append(node.getValue());
if (node.isTemporary()) {
sb.append(" ").append(node.getExpiryUnixTime());
}
if (node.isWorldSpecific()) {
sb.append(" ").append(node.getServer().get()).append(" ").append(node.getWorld().get());
} else if (node.isServerSpecific()) {
sb.append(" ").append(node.getServer().get());
}
return sb.toString();
}
}
@@ -39,6 +39,20 @@ import java.util.Map;
import static me.lucko.luckperms.common.commands.utils.Util.formatBoolean;
public class InfoCommand extends SingleCommand {
private static String formatValue(String value) {
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
return Util.formatBoolean(Boolean.parseBoolean(value));
}
try {
int i = Integer.parseInt(value);
return "&a" + i;
} catch (NumberFormatException ignored) {
}
return "&f" + value;
}
public InfoCommand() {
super("Info", "Print general plugin info", "/%s info", Permission.INFO, Predicates.alwaysFalse(), null);
}
@@ -84,17 +98,4 @@ public class InfoCommand extends SingleCommand {
return CommandResult.SUCCESS;
}
private static String formatValue(String value) {
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
return Util.formatBoolean(Boolean.parseBoolean(value));
}
try {
int i = Integer.parseInt(value);
return "&a" + i;
} catch (NumberFormatException ignored) {}
return "&f" + value;
}
}
@@ -36,7 +36,7 @@ import java.util.List;
public class QueueCommand extends SingleCommand {
public QueueCommand() {
super("QueueCommand", "Queue a command for execution", "/%s queuecommand <command args...>", Permission.MIGRATION, Predicates.not(1),
super("QueueCommand", "Queue a command for execution", "/%s queuecommand <command args...>", Permission.MIGRATION, Predicates.not(1),
Arg.list(
Arg.create("command args...", true, "the command's arguments")
)
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.sender;
import lombok.Getter;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.constants.Permission;
@@ -32,6 +33,7 @@ import java.util.UUID;
/**
* Simple implementation of {@link Sender} using a {@link SenderFactory}
*
* @param <T> the command sender type
*/
@Getter
@@ -35,30 +35,35 @@ public interface Sender {
/**
* Gets the platform where the sender is from.
*
* @return the plugin
*/
LuckPermsPlugin getPlatform();
/**
* Gets the sender's username
*
* @return a friendly username for the sender
*/
String getName();
/**
* Gets the sender's unique id. See {@link Constants#getConsoleUUID()} for the console's UUID representation.
*
* @return the sender's uuid
*/
UUID getUuid();
/**
* Send a message back to the Sender
*
* @param s the message to send. Supports '§' for message formatting.
*/
void sendMessage(String s);
/**
* Check if the Sender has a permission.
*
* @param permission the permission to check for
* @return true if the sender has the permission
*/
@@ -23,12 +23,14 @@
package me.lucko.luckperms.common.commands.sender;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.common.LuckPermsPlugin;
import java.util.UUID;
/**
* Factory class to make a thread-safe sender instance
*
* @param <T> the command sender type
*/
@RequiredArgsConstructor
@@ -36,8 +38,11 @@ public abstract class SenderFactory<T> {
private final LuckPermsPlugin plugin;
protected abstract String getName(T t);
protected abstract UUID getUuid(T t);
protected abstract void sendMessage(T t, String s);
protected abstract boolean hasPermission(T t, String node);
public final Sender wrap(T t) {
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.track;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Command;
import me.lucko.luckperms.common.commands.MainCommand;
@@ -108,13 +108,15 @@ public class UserBulkChange extends SubCommand<User> {
toRemove.forEach(n -> {
try {
user.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
});
toAdd.forEach(n -> {
try {
user.setPermission(n);
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
});
save(user, sender, plugin);
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.user;
import com.google.common.base.Objects;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.events.UserDemoteEvent;
import me.lucko.luckperms.common.LuckPermsPlugin;
@@ -160,10 +161,12 @@ public class UserDemote extends SubCommand<User> {
try {
user.unsetPermission(nodes.stream().findAny().get());
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
try {
user.setPermission(NodeFactory.newBuilder("group." + previousGroup.getName()).setServer(server).setWorld(world).build());
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
if (server == null && world == null) {
user.setPrimaryGroup(previousGroup.getName());
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.user;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Command;
import me.lucko.luckperms.common.commands.MainCommand;
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.user;
import com.google.common.base.Objects;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.event.events.UserPromoteEvent;
import me.lucko.luckperms.common.LuckPermsPlugin;
@@ -160,10 +161,12 @@ public class UserPromote extends SubCommand<User> {
try {
user.unsetPermission(nodes.stream().findAny().get());
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
try {
user.setPermission(NodeFactory.newBuilder("group." + nextGroup.getName()).setServer(server).setWorld(world).build());
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
if (server == null && world == null) {
user.setPrimaryGroup(nextGroup.getName());
@@ -62,7 +62,8 @@ public class UserSwitchPrimaryGroup extends SubCommand<User> {
Message.USER_PRIMARYGROUP_ERROR_NOTMEMBER.send(sender, user.getName(), group.getName());
try {
user.setInheritGroup(group);
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
}
user.setPrimaryGroup(group.getName());
@@ -38,7 +38,11 @@ import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.*;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public class BulkEditGroup extends SubCommand<Storage> {
public BulkEditGroup() {
@@ -134,13 +138,15 @@ public class BulkEditGroup extends SubCommand<Storage> {
toRemove.forEach(n -> {
try {
user.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
});
toAdd.forEach(n -> {
try {
user.setPermission(n);
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
});
plugin.getStorage().saveUser(user);
@@ -38,7 +38,11 @@ import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.*;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public class BulkEditPermission extends SubCommand<Storage> {
public BulkEditPermission() {
@@ -124,13 +128,15 @@ public class BulkEditPermission extends SubCommand<Storage> {
toRemove.forEach(n -> {
try {
user.unsetPermission(n);
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
});
toAdd.forEach(n -> {
try {
user.setPermission(n);
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
});
plugin.getStorage().saveUser(user);
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.usersbulkedit;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Command;
import me.lucko.luckperms.common.commands.MainCommand;
@@ -24,6 +24,7 @@ package me.lucko.luckperms.common.commands.utils;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.commands.CommandException;
@@ -119,7 +120,7 @@ public class ArgumentUtils {
return ContextSet.empty();
}
MutableContextSet contextSet = new MutableContextSet();
MutableContextSet contextSet = MutableContextSet.create();
List<String> toQuery = args.subList(fromIndex, args.size());
for (String s : toQuery) {
int index = s.indexOf('=');
@@ -141,11 +142,20 @@ public class ArgumentUtils {
return contextSet.makeImmutable();
}
public static abstract class ArgumentException extends CommandException {}
public static class DetailedUsageException extends ArgumentException {}
public static class UseInheritException extends ArgumentException {}
public static class InvalidServerException extends ArgumentException {}
public static class PastDateException extends ArgumentException {}
public static abstract class ArgumentException extends CommandException {
}
public static class DetailedUsageException extends ArgumentException {
}
public static class UseInheritException extends ArgumentException {
}
public static class InvalidServerException extends ArgumentException {
}
public static class PastDateException extends ArgumentException {
}
@Getter
@AllArgsConstructor
@@ -27,12 +27,12 @@ package me.lucko.luckperms.common.commands.utils;
*/
public class ContextHelper {
public enum CommandContext {
NONE, SERVER, SERVER_AND_WORLD
}
public static CommandContext determine(String server, String world) {
return server == null ? CommandContext.NONE : (world == null ? CommandContext.SERVER : CommandContext.SERVER_AND_WORLD);
}
public enum CommandContext {
NONE, SERVER, SERVER_AND_WORLD
}
}
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.commands.utils;
import lombok.experimental.UtilityClass;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.Tristate;
@@ -31,11 +32,19 @@ import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Patterns;
import me.lucko.luckperms.common.utils.DateUtil;
import java.util.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.SortedSet;
import java.util.UUID;
@UtilityClass
public class Util {
public static final MetaComparator META_COMPARATOR = new MetaComparator();
public static void sendPluginMessage(Sender sender, String message) {
String prefix = sender.getPlatform().getLocaleManager().getTranslation(Message.PREFIX);
if (prefix == null) {
@@ -239,7 +248,6 @@ public class Util {
return sb.delete(sb.length() - 6, sb.length()).toString();
}
public static final MetaComparator META_COMPARATOR = new MetaComparator();
public class MetaComparator implements Comparator<Map.Entry<Integer, ? extends Node>> {
@Override
@@ -22,10 +22,12 @@
package me.lucko.luckperms.common.config;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import lombok.AccessLevel;
import lombok.Getter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.constants.Patterns;
import me.lucko.luckperms.common.defaults.Rule;
@@ -38,6 +40,7 @@ import java.util.Map;
/**
* A thread-safe config abstraction
*
* @param <T> the plugin type
*/
@Getter
@@ -90,13 +93,19 @@ public abstract class AbstractConfiguration<T extends LuckPermsPlugin> implement
}
protected abstract void init();
protected abstract String getString(String path, String def);
protected abstract int getInt(String path, int def);
protected abstract boolean getBoolean(String path, boolean def);
protected abstract List<String> getList(String path, List<String> def);
protected abstract List<String> getObjectList(String path, List<String> def);
protected abstract Map<String, String> getMap(String path, Map<String, String> def);
public void load(String defaultServerName, boolean defaultIncludeGlobal, String defaultStorage) {
server = getString("server", defaultServerName);
syncTime = getInt("data.sync-minutes", 3);
@@ -115,7 +124,8 @@ public abstract class AbstractConfiguration<T extends LuckPermsPlugin> implement
for (Map.Entry<String, String> e : weights.entrySet()) {
try {
mb.put(e.getKey().toLowerCase(), Integer.parseInt(e.getValue()));
} catch (NumberFormatException ignored) {}
} catch (NumberFormatException ignored) {
}
}
groupWeights = mb.build();
logNotify = getBoolean("log-notify", true);
@@ -166,7 +176,7 @@ public abstract class AbstractConfiguration<T extends LuckPermsPlugin> implement
redisEnabled = getBoolean("redis.enabled", false);
redisAddress = getString("redis.address", null);
redisPassword = getString("redis.password", "");
if (Patterns.NON_ALPHA_NUMERIC.matcher(getServer()).find()) {
plugin.getLog().severe("Server name defined in config.yml contains invalid characters. Server names can " +
"only contain alphanumeric characters.\nDefined server name '" + getServer() + "' will be replaced with '" +
@@ -36,12 +36,14 @@ public interface LPConfiguration {
/**
* As of 2.6, this value is a constant
*
* @return the default group node
*/
String getDefaultGroupNode();
/**
* As of 2.6, this value is a constant
*
* @return the name of the default group
*/
String getDefaultGroupName();
@@ -24,6 +24,7 @@ package me.lucko.luckperms.common.constants;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
@@ -51,7 +52,6 @@ public enum Message {
DOES_NOT_HAVE_TEMP_PERMISSION("{0} does not have this permission set temporarily.", true),
/*
* Loading / Saving
*/
@@ -69,7 +69,6 @@ public enum Message {
TRACK_SAVE_ERROR("There was an error whilst saving the track.", true),
/*
* Command Syntax
*/
@@ -86,7 +85,7 @@ public enum Message {
VERBOSE_ON("&bVerbose checking output set to &aTRUE &bfor all permissions.", true),
VERBOSE_ON_QUERY("&bVerbose checking output set to &aTRUE &bfor permissions matching the following filters: &f{0}", true),
VERBOSE_OFF("&bVerbose checking output set to &cFALSE&b.", true),
CREATE_SUCCESS("&b{0}&a was successfully created.", true),
DELETE_SUCCESS("&b{0}&a was successfully deleted.", true),
RENAME_SUCCESS("&b{0}&a was successfully renamed to &b{1}&a.", true),
@@ -119,31 +118,31 @@ public enum Message {
UPDATE_TASK_PUSH_FAILURE("&cError whilst pushing changes to other servers. Is Redis enabled?", true),
INFO(
"{PREFIX}&2Running &bLuckPerms v{0}&2 by &bLuck&2." + "\n" +
"{PREFIX}&f- &3Platform: &f{1}" + "\n" +
"{PREFIX}&f- &3Storage Method: &f{2}" + "\n" +
"{PREFIX}&f- &3Server Name: &f{3}" + "\n" +
"{PREFIX}&f- &3Sync Interval: &a{4} &fminutes" + "\n" +
"{PREFIX}&f- &bCounts:" + "\n" +
"{PREFIX}&f- &3Online Players: &a{5}" + "\n" +
"{PREFIX}&f- &3Loaded Users: &a{6}" + "\n" +
"{PREFIX}&f- &3Loaded Groups: &a{7}" + "\n" +
"{PREFIX}&f- &3Loaded Tracks: &a{8}" + "\n" +
"{PREFIX}&f- &3Log size: &a{9}" + "\n" +
"{PREFIX}&f- &3UUID Cache size: &a{10}" + "\n" +
"{PREFIX}&f- &3Translations loaded: &a{11}" + "\n" +
"{PREFIX}&f- &3Pre-process contexts: &a{12}" + "\n" +
"{PREFIX}&f- &3Context Calculators: &a{13}" + "\n" +
"{PREFIX}&f- &bConfiguration:" + "\n" +
"{PREFIX}&f- &3Online Mode: {14}" + "\n" +
"{PREFIX}&f- &3Redis Enabled: {15}" + "\n" +
"{PREFIX}&f- &bPermission Calculation:" + "\n" +
"{PREFIX}&f- &3Including Global: {16}" + "\n" +
"{PREFIX}&f- &3Including Global World: {17}" + "\n" +
"{PREFIX}&f- &3Applying Global Groups: {18}" + "\n" +
"{PREFIX}&f- &3Applying Global World Groups: {19}" + "\n" +
"{PREFIX}&f- &3Applying Wildcards: {20}" + "\n" +
"{PREFIX}&f- &3Applying Regex: {21}" + "\n" +
"{PREFIX}&f- &3Applying Shorthand: {22}",
"{PREFIX}&f- &3Platform: &f{1}" + "\n" +
"{PREFIX}&f- &3Storage Method: &f{2}" + "\n" +
"{PREFIX}&f- &3Server Name: &f{3}" + "\n" +
"{PREFIX}&f- &3Sync Interval: &a{4} &fminutes" + "\n" +
"{PREFIX}&f- &bCounts:" + "\n" +
"{PREFIX}&f- &3Online Players: &a{5}" + "\n" +
"{PREFIX}&f- &3Loaded Users: &a{6}" + "\n" +
"{PREFIX}&f- &3Loaded Groups: &a{7}" + "\n" +
"{PREFIX}&f- &3Loaded Tracks: &a{8}" + "\n" +
"{PREFIX}&f- &3Log size: &a{9}" + "\n" +
"{PREFIX}&f- &3UUID Cache size: &a{10}" + "\n" +
"{PREFIX}&f- &3Translations loaded: &a{11}" + "\n" +
"{PREFIX}&f- &3Pre-process contexts: &a{12}" + "\n" +
"{PREFIX}&f- &3Context Calculators: &a{13}" + "\n" +
"{PREFIX}&f- &bConfiguration:" + "\n" +
"{PREFIX}&f- &3Online Mode: {14}" + "\n" +
"{PREFIX}&f- &3Redis Enabled: {15}" + "\n" +
"{PREFIX}&f- &bPermission Calculation:" + "\n" +
"{PREFIX}&f- &3Including Global: {16}" + "\n" +
"{PREFIX}&f- &3Including Global World: {17}" + "\n" +
"{PREFIX}&f- &3Applying Global Groups: {18}" + "\n" +
"{PREFIX}&f- &3Applying Global World Groups: {19}" + "\n" +
"{PREFIX}&f- &3Applying Wildcards: {20}" + "\n" +
"{PREFIX}&f- &3Applying Regex: {21}" + "\n" +
"{PREFIX}&f- &3Applying Shorthand: {22}",
false
),
CREATE_GROUP_ERROR("There was an error whilst creating the group.", true),
@@ -260,30 +259,30 @@ public enum Message {
UNSET_META_TEMP_SUCCESS("&aUnset temporary meta value with key &f\"{0}&f\"&a for &b{1}&a.", true),
UNSET_META_TEMP_SERVER_SUCCESS("&aUnset temporary meta value with key &f\"{0}&f\"&a for &b{1}&a on server &b{2}&a.", true),
UNSET_META_TEMP_SERVER_WORLD_SUCCESS("&aUnset temporary meta value with key &f\"{0}&f\"&a for &b{1}&a on server &b{2}&a, world &b{3}&a.", true),
BULK_CHANGE_TYPE_ERROR("Invalid type. Was expecting 'server' or 'world'.", true),
BULK_CHANGE_SUCCESS("&aApplied bulk change successfully. {0} records were changed.", true),
USER_INFO_GENERAL(
"{PREFIX}&b&l> &bUser Info: &f{0}" + "\n" +
"{PREFIX}&f- &3UUID: &f{1}" + "\n" +
"{PREFIX}&f- &3Status: {2}" + "\n" +
"{PREFIX}&f- &3Primary Group: &f{3}" + "\n" +
"{PREFIX}&f- &aCounts:" + "\n" +
"{PREFIX}&f- &3Permissions: &a{4}" + "\n" +
"{PREFIX}&f- &3Temporary Permissions: &a{5}" + "\n" +
"{PREFIX}&f- &3Prefixes: &a{6}" + "\n" +
"{PREFIX}&f- &3Suffixes: &a{7}" + "\n" +
"{PREFIX}&f- &3Meta: &a{8}",
"{PREFIX}&f- &3UUID: &f{1}" + "\n" +
"{PREFIX}&f- &3Status: {2}" + "\n" +
"{PREFIX}&f- &3Primary Group: &f{3}" + "\n" +
"{PREFIX}&f- &aCounts:" + "\n" +
"{PREFIX}&f- &3Permissions: &a{4}" + "\n" +
"{PREFIX}&f- &3Temporary Permissions: &a{5}" + "\n" +
"{PREFIX}&f- &3Prefixes: &a{6}" + "\n" +
"{PREFIX}&f- &3Suffixes: &a{7}" + "\n" +
"{PREFIX}&f- &3Meta: &a{8}",
false
),
USER_INFO_DATA(
"{PREFIX}&f- &aCached Data:" + "\n" +
"{PREFIX}&f- &3Is Loaded: {0}" + "\n" +
"{PREFIX}&f- &3Current Contexts: {1}" + "\n" +
"{PREFIX}&f- &3Current Prefix: {2}" + "\n" +
"{PREFIX}&f- &3Current Suffix: {3}",
"{PREFIX}&f- &3Is Loaded: {0}" + "\n" +
"{PREFIX}&f- &3Current Contexts: {1}" + "\n" +
"{PREFIX}&f- &3Current Prefix: {2}" + "\n" +
"{PREFIX}&f- &3Current Suffix: {3}",
false
),
@@ -301,7 +300,7 @@ public enum Message {
USER_PROMOTE_ERROR_ENDOFTRACK("The end of track &4{0}&c was reached. Unable to promote user.", true),
USER_PROMOTE_ERROR_MALFORMED(
"{PREFIX}The next group on the track, {0}, no longer exists. Unable to promote user." + "\n" +
"{PREFIX}Either create the group, or remove it from the track and try again.",
"{PREFIX}Either create the group, or remove it from the track and try again.",
false
),
USER_DEMOTE_SUCCESS("&aDemoting user along track &b{0}&a from &b{1}&a to &b{2}&a.", true),
@@ -310,22 +309,22 @@ public enum Message {
USER_DEMOTE_ERROR_ENDOFTRACK("The end of track &4{0}&c was reached. Unable to demote user.", true),
USER_DEMOTE_ERROR_MALFORMED(
"{PREFIX}The previous group on the track, {0}, no longer exists. Unable to demote user." + "\n" +
"{PREFIX}Either create the group, or remove it from the track and try again.",
"{PREFIX}Either create the group, or remove it from the track and try again.",
false
),
USER_SHOWPOS("&aShowing &b{0}&a's position on track &b{1}&a.\n{2}", true),
GROUP_INFO(
"{PREFIX}&b&l> &bGroup Info: &f{0}" + "\n" +
"{PREFIX}&f- &3Permissions: &f{1}" + "\n" +
"{PREFIX}&f- &3Temporary Permissions: &f{2}" + "\n" +
"{PREFIX}&f- &3Use &b/{3} group {4} permission info &3to see all permissions.",
"{PREFIX}&f- &3Permissions: &f{1}" + "\n" +
"{PREFIX}&f- &3Temporary Permissions: &f{2}" + "\n" +
"{PREFIX}&f- &3Use &b/{3} group {4} permission info &3to see all permissions.",
false
),
TRACK_INFO(
"{PREFIX}&b&l> &bShowing Track: &f{0}" + "\n" +
"{PREFIX}&f- &7Path: &f{1}",
"{PREFIX}&f- &7Path: &f{1}",
false
),
TRACK_CLEAR("&b{0}&a's groups track was cleared.", true),
@@ -376,10 +375,10 @@ public enum Message {
IMPORT_END_COMPLETE_ERR_SIN("&b(Import) &a&lCOMPLETED &7- took &b{0} &7seconds - &c{1} error.", true),
IMPORT_END_ERROR_HEADER(
"{PREFIX}&b(Import) &7------------> &fShowing Error #&b{0} &7<------------" + "\n" +
"{PREFIX}&b(Import) &fWhilst executing: &3Command #{1}" + "\n" +
"{PREFIX}&b(Import) &fCommand: &7{2}" + "\n" +
"{PREFIX}&b(Import) &fType: &3{3}" + "\n" +
"{PREFIX}&b(Import) &fOutput:",
"{PREFIX}&b(Import) &fWhilst executing: &3Command #{1}" + "\n" +
"{PREFIX}&b(Import) &fCommand: &7{2}" + "\n" +
"{PREFIX}&b(Import) &fType: &3{3}" + "\n" +
"{PREFIX}&b(Import) &fOutput:",
false
),
@@ -388,6 +387,14 @@ public enum Message {
MIGRATION_NOT_CONSOLE("Migration must be performed from the Console.", true);
private static String format(String s, Object... objects) {
for (int i = 0, objsLength = objects.length; i < objsLength; i++) {
Object o = objects[i];
s = s.replace("{" + i + "}", o.toString());
}
return s;
}
@Getter
private String message;
private boolean showPrefix;
@@ -416,12 +423,4 @@ public enum Message {
sender.sendMessage(Util.color(format(s, objects)));
}
}
private static String format(String s, Object... objects) {
for (int i = 0, objsLength = objects.length; i < objsLength; i++) {
Object o = objects[i];
s = s.replace("{" + i + "}", o.toString());
}
return s;
}
}
@@ -22,19 +22,26 @@
package me.lucko.luckperms.common.constants;
import lombok.experimental.UtilityClass;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.UncheckedExecutionException;
import lombok.experimental.UtilityClass;
import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;
@UtilityClass
public class Patterns {
public static final Pattern COMMAND_SEPARATOR = Pattern.compile(" (?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)");
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[\\/\\$\\.\\- ]");
public static final Pattern NON_USERNAME = Pattern.compile("[^A-Za-z0-9_ ]");
public static final Pattern SHORTHAND_NODE = Pattern.compile("\\.\\([^.]+\\)");
public static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf('§') + "[0-9A-FK-OR]");
public static final Pattern NODE_CONTEXTS = Pattern.compile("\\(.+\\).*");
private static final LoadingCache<String, Pattern> CACHE = CacheBuilder.newBuilder()
.build(new CacheLoader<String, Pattern>() {
@Override
@@ -48,13 +55,6 @@ public class Patterns {
}
});
public static final Pattern COMMAND_SEPARATOR = Pattern.compile(" (?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)");
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[\\/\\$\\.\\- ]");
public static final Pattern NON_USERNAME = Pattern.compile("[^A-Za-z0-9_ ]");
public static final Pattern SHORTHAND_NODE = Pattern.compile("\\.\\([^.]+\\)");
public static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf('§') + "[0-9A-FK-OR]");
public static final Pattern NODE_CONTEXTS = Pattern.compile("\\(.+\\).*");
public static Pattern compile(String regex) {
try {
return CACHE.get(regex);
@@ -22,9 +22,11 @@
package me.lucko.luckperms.common.constants;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Getter;
import com.google.common.collect.Sets;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.utils.ImmutableCollectors;
@@ -149,6 +151,10 @@ public enum Permission {
private static final String IDENTIFIER = "luckperms.";
private static Set<String> set(String... args) {
return Sets.newHashSet(args);
}
private Set<String> nodes;
private Type type;
@@ -166,21 +172,17 @@ public enum Permission {
return sender.hasPermission(this);
}
private static Set<String> set(String... args) {
return Sets.newHashSet(args);
}
@Getter
@AllArgsConstructor
public enum Type {
NONE(null),
USER("user"),
GROUP("group"),
TRACK("track"),
LOG("log"),
SPONGE("sponge");
private final String tag;
}
@@ -25,6 +25,7 @@ package me.lucko.luckperms.common.contexts;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import me.lucko.luckperms.api.context.ContextListener;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.IContextCalculator;
@@ -45,7 +46,7 @@ public class ContextManager<T> {
.build(new CacheLoader<T, ContextSet>() {
@Override
public ContextSet load(T t) {
return calculateApplicableContext(t, MutableContextSet.empty()).makeImmutable();
return calculateApplicableContext(t, MutableContextSet.create()).makeImmutable();
}
});
@@ -22,8 +22,10 @@
package me.lucko.luckperms.common.contexts;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import com.google.common.collect.Maps;
import me.lucko.luckperms.api.context.ContextCalculator;
import me.lucko.luckperms.api.context.MutableContextSet;
@@ -22,7 +22,13 @@
package me.lucko.luckperms.common.core;
import lombok.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Tristate;
@@ -22,9 +22,11 @@
package me.lucko.luckperms.common.core;
import com.google.common.base.Splitter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import com.google.common.base.Splitter;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.MutableContextSet;
@@ -42,12 +44,12 @@ import java.util.Set;
@RequiredArgsConstructor
public class NodeBuilder implements Node.Builder {
private final String permission;
private final MutableContextSet extraContexts = MutableContextSet.create();
private Boolean value = true;
private boolean override = false;
private String server = null;
private String world = null;
private long expireAt = 0L;
private final MutableContextSet extraContexts = new MutableContextSet();
NodeBuilder(String permission, boolean shouldConvertContexts) {
if (!shouldConvertContexts) {
@@ -22,12 +22,14 @@
package me.lucko.luckperms.common.core;
import lombok.experimental.UtilityClass;
import com.google.common.base.Splitter;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
import lombok.experimental.UtilityClass;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.Node;
@@ -24,6 +24,7 @@ package me.lucko.luckperms.common.core;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node;
@@ -22,7 +22,12 @@
package me.lucko.luckperms.common.core;
import lombok.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.common.utils.Identifiable;
import java.util.UUID;
@@ -22,10 +22,11 @@
package me.lucko.luckperms.common.core;
import lombok.Getter;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps;
import lombok.Getter;
import java.util.UUID;
@@ -34,11 +35,10 @@ import java.util.UUID;
*/
public class UuidCache {
// External UUID --> Internal UUID
private BiMap<UUID, UUID> cache;
@Getter
private final boolean onlineMode;
// External UUID --> Internal UUID
private BiMap<UUID, UUID> cache;
public UuidCache(boolean onlineMode) {
this.onlineMode = onlineMode;
@@ -25,6 +25,7 @@ package me.lucko.luckperms.common.core.model;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.Identifiable;
@@ -22,13 +22,15 @@
package me.lucko.luckperms.common.core.model;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.api.MetaUtils;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.Tristate;
@@ -36,7 +38,13 @@ import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.common.constants.Patterns;
import me.lucko.luckperms.common.utils.ShorthandParser;
import java.util.*;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -51,6 +59,54 @@ public class ImmutableNode implements Node {
private static final Pattern SUFFIX_PATTERN = Pattern.compile("(?i)suffix\\.-?\\d+\\..*");
private static final Pattern META_PATTERN = Pattern.compile("meta\\..*\\..*");
private static boolean shouldApply(String str, boolean applyRegex, String thisStr) {
if (str.toLowerCase().startsWith("r=") && applyRegex) {
Pattern p = Patterns.compile(str.substring(2));
if (p == null) {
return false;
}
return p.matcher(thisStr).matches();
}
if (str.startsWith("(") && str.endsWith(")") && str.contains("|")) {
final String bits = str.substring(1, str.length() - 1);
Iterable<String> parts = Splitter.on('|').split(bits);
for (String s : parts) {
if (s.equalsIgnoreCase(thisStr)) {
return true;
}
}
return false;
}
return thisStr.equalsIgnoreCase(str);
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private static boolean isInt(String a, String b) {
try {
Integer.parseInt(a);
Integer.parseInt(b);
return true;
} catch (NumberFormatException e) {
return false;
}
}
private static boolean isChar(String a, String b) {
return a.length() == 1 && b.length() == 1;
}
private static Set<String> getCharRange(char a, char b) {
Set<String> s = new HashSet<>();
for (char c = a; c <= b; c++) {
s.add(Character.toString(c));
}
return s;
}
@Getter
private final String permission;
@@ -90,12 +146,13 @@ public class ImmutableNode implements Node {
/**
* Make an immutable node instance
*
* @param permission the actual permission node
* @param value the value (if it's *not* negated)
* @param expireAt the time when the node will expire
* @param server the server this node applies on
* @param world the world this node applies on
* @param contexts any additional contexts applying to this node
* @param value the value (if it's *not* negated)
* @param expireAt the time when the node will expire
* @param server the server this node applies on
* @param world the world this node applies on
* @param contexts any additional contexts applying to this node
*/
public ImmutableNode(String permission, boolean value, boolean override, long expireAt, String server, String world, ContextSet contexts) {
if (permission == null || permission.equals("")) {
@@ -196,7 +253,7 @@ public class ImmutableNode implements Node {
}
@Override
public long getExpiryUnixTime(){
public long getExpiryUnixTime() {
Preconditions.checkState(isTemporary(), "Node does not have an expiry time.");
return expireAt;
}
@@ -290,31 +347,6 @@ public class ImmutableNode implements Node {
return isWorldSpecific() ? shouldApply(world, applyRegex, this.world) : includeGlobal;
}
private static boolean shouldApply(String str, boolean applyRegex, String thisStr) {
if (str.toLowerCase().startsWith("r=") && applyRegex) {
Pattern p = Patterns.compile(str.substring(2));
if (p == null) {
return false;
}
return p.matcher(thisStr).matches();
}
if (str.startsWith("(") && str.endsWith(")") && str.contains("|")) {
final String bits = str.substring(1, str.length() - 1);
Iterable<String> parts = Splitter.on('|').split(bits);
for (String s : parts) {
if (s.equalsIgnoreCase(thisStr)) {
return true;
}
}
return false;
}
return thisStr.equalsIgnoreCase(str);
}
@Override
public boolean shouldApplyWithContext(ContextSet context, boolean worldAndServer) {
if (contexts.isEmpty() && !isServerSpecific() && !isWorldSpecific()) {
@@ -381,29 +413,6 @@ public class ImmutableNode implements Node {
return possibleNodes.stream().filter(pn -> pn.startsWith(match)).collect(Collectors.toList());
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private static boolean isInt(String a, String b) {
try {
Integer.parseInt(a);
Integer.parseInt(b);
return true;
} catch (NumberFormatException e) {
return false;
}
}
private static boolean isChar(String a, String b) {
return a.length() == 1 && b.length() == 1;
}
private static Set<String> getCharRange(char a, char b) {
Set<String> s = new HashSet<>();
for (char c = a; c <= b; c++) {
s.add(Character.toString(c));
}
return s;
}
@Override
public List<String> resolveShorthand() {
return resolvedShorthand;
@@ -22,18 +22,24 @@
package me.lucko.luckperms.common.core.model;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Maps;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.Contexts;
import me.lucko.luckperms.api.LocalizedNode;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.event.events.*;
import me.lucko.luckperms.api.event.events.GroupAddEvent;
import me.lucko.luckperms.api.event.events.GroupRemoveEvent;
import me.lucko.luckperms.api.event.events.PermissionNodeExpireEvent;
import me.lucko.luckperms.api.event.events.PermissionNodeSetEvent;
import me.lucko.luckperms.api.event.events.PermissionNodeUnsetEvent;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.api.internal.GroupLink;
import me.lucko.luckperms.common.api.internal.PermissionHolderLink;
@@ -49,7 +55,16 @@ import me.lucko.luckperms.common.utils.ImmutableLocalizedNode;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -62,6 +77,26 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public abstract class PermissionHolder {
public static Map<String, Boolean> exportToLegacy(Set<Node> nodes) {
Map<String, Boolean> m = new HashMap<>();
for (Node node : nodes) {
m.put(node.toSerializedNode(), node.getValue());
}
return m;
}
private static Node.Builder buildNode(String permission) {
return new NodeBuilder(permission);
}
private static ImmutableLocalizedNode makeLocal(Node node, String location) {
return ImmutableLocalizedNode.of(node, location);
}
private static Node makeNode(String s, Boolean b) {
return NodeFactory.fromSerialisedNode(s, b);
}
/**
* The UUID of the user / name of the group.
* Used to prevent circular inheritance issues
@@ -78,6 +113,9 @@ public abstract class PermissionHolder {
private final Set<Node> nodes = new HashSet<>();
private final Set<Node> transientNodes = new HashSet<>();
@Getter
private final Lock ioLock = new ReentrantLock();
private Cache<ImmutableSet<Node>> enduringCache = new Cache<>(() -> {
synchronized (nodes) {
return ImmutableSet.copyOf(nodes);
@@ -158,19 +196,48 @@ public abstract class PermissionHolder {
return ImmutableSortedSet.copyOfSorted(combined);
});
@Getter
private final Lock ioLock = new ReentrantLock();
public abstract String getFriendlyName();
public Set<Node> getNodes() {
return enduringCache.get();
}
public void setNodes(Map<String, Boolean> nodes) {
Set<Node> set = nodes.entrySet().stream()
.map(e -> makeNode(e.getKey(), e.getValue()))
.collect(Collectors.toSet());
setNodes(set);
}
public void setNodes(Set<Node> set) {
synchronized (nodes) {
if (nodes.equals(set)) {
return;
}
nodes.clear();
nodes.addAll(set);
}
invalidateCache(true);
}
public Set<Node> getTransientNodes() {
return transientCache.get();
}
public void setTransientNodes(Set<Node> set) {
synchronized (transientNodes) {
if (transientNodes.equals(set)) {
return;
}
transientNodes.clear();
transientNodes.addAll(set);
}
invalidateCache(false);
}
private void invalidateCache(boolean enduring) {
if (enduring) {
enduringCache.invalidate();
@@ -183,6 +250,7 @@ public abstract class PermissionHolder {
/**
* Combines and returns this holders nodes in a priority order.
*
* @return the holders transient and permanent nodes
*/
public SortedSet<LocalizedNode> getPermissions(boolean mergeTemp) {
@@ -191,6 +259,7 @@ public abstract class PermissionHolder {
/**
* Removes temporary permissions that have expired
*
* @return true if permissions had expired and were removed
*/
public boolean auditTemporaryPermissions() {
@@ -244,8 +313,9 @@ public abstract class PermissionHolder {
/**
* Resolves inherited nodes and returns them
*
* @param excludedGroups a list of groups to exclude
* @param contexts context to decide if groups should be applied
* @param contexts context to decide if groups should be applied
* @return a set of nodes
*/
public SortedSet<LocalizedNode> getAllNodes(List<String> excludedGroups, ExtractedContexts contexts) {
@@ -269,8 +339,8 @@ public abstract class PermissionHolder {
parents.removeIf(node ->
!node.shouldApplyOnServer(server, context.isApplyGlobalGroups(), plugin.getConfiguration().isApplyingRegex()) ||
!node.shouldApplyOnWorld(world, context.isApplyGlobalWorldGroups(), plugin.getConfiguration().isApplyingRegex()) ||
!node.shouldApplyWithContext(contexts.getContextSet(), false)
!node.shouldApplyOnWorld(world, context.isApplyGlobalWorldGroups(), plugin.getConfiguration().isApplyingRegex()) ||
!node.shouldApplyWithContext(contexts.getContextSet(), false)
);
TreeSet<Map.Entry<Integer, Node>> sortedParents = new TreeSet<>(Util.META_COMPARATOR.reversed());
@@ -345,8 +415,8 @@ public abstract class PermissionHolder {
parents.removeIf(node ->
!node.shouldApplyOnServer(server, context.isApplyGlobalGroups(), plugin.getConfiguration().isApplyingRegex()) ||
!node.shouldApplyOnWorld(world, context.isApplyGlobalWorldGroups(), plugin.getConfiguration().isApplyingRegex()) ||
!node.shouldApplyWithContext(contexts.getContextSet(), false)
!node.shouldApplyOnWorld(world, context.isApplyGlobalWorldGroups(), plugin.getConfiguration().isApplyingRegex()) ||
!node.shouldApplyWithContext(contexts.getContextSet(), false)
);
TreeSet<Map.Entry<Integer, Node>> sortedParents = new TreeSet<>(Util.META_COMPARATOR.reversed());
@@ -378,6 +448,7 @@ public abstract class PermissionHolder {
/**
* Gets all of the nodes that this holder has (and inherits), given the context
*
* @param contexts the context for this request
* @return a map of permissions
*/
@@ -396,8 +467,8 @@ public abstract class PermissionHolder {
allNodes.removeIf(node ->
!node.shouldApplyOnServer(server, context.isIncludeGlobal(), plugin.getConfiguration().isApplyingRegex()) ||
!node.shouldApplyOnWorld(world, context.isIncludeGlobalWorld(), plugin.getConfiguration().isApplyingRegex()) ||
!node.shouldApplyWithContext(contexts.getContextSet(), false)
!node.shouldApplyOnWorld(world, context.isIncludeGlobalWorld(), plugin.getConfiguration().isApplyingRegex()) ||
!node.shouldApplyWithContext(contexts.getContextSet(), false)
);
Set<LocalizedNode> perms = ConcurrentHashMap.newKeySet();
@@ -419,6 +490,7 @@ public abstract class PermissionHolder {
/**
* Converts the output of {@link #getAllNodesFiltered(ExtractedContexts)}, and expands shorthand perms
*
* @param context the context for this request
* @return a map of permissions
*/
@@ -443,42 +515,11 @@ public abstract class PermissionHolder {
return ImmutableMap.copyOf(perms);
}
public void setNodes(Set<Node> set) {
synchronized (nodes) {
if (nodes.equals(set)) {
return;
}
nodes.clear();
nodes.addAll(set);
}
invalidateCache(true);
}
public void setTransientNodes(Set<Node> set) {
synchronized (transientNodes) {
if (transientNodes.equals(set)) {
return;
}
transientNodes.clear();
transientNodes.addAll(set);
}
invalidateCache(false);
}
public void setNodes(Map<String, Boolean> nodes) {
Set<Node> set = nodes.entrySet().stream()
.map(e -> makeNode(e.getKey(), e.getValue()))
.collect(Collectors.toSet());
setNodes(set);
}
/**
* Check if the holder has a permission node
*
* @param node the node to check
* @param t whether to check transient nodes
* @param t whether to check transient nodes
* @return a tristate
*/
public Tristate hasPermission(Node node, boolean t) {
@@ -521,6 +562,7 @@ public abstract class PermissionHolder {
/**
* Check if the holder inherits a node
*
* @param node the node to check
* @return the result of the lookup
*/
@@ -536,6 +578,7 @@ public abstract class PermissionHolder {
/**
* Check if the holder inherits a node
*
* @param node the node to check
* @return the Tristate result
*/
@@ -569,6 +612,7 @@ public abstract class PermissionHolder {
/**
* Sets a permission node
*
* @param node the node to set
* @throws ObjectAlreadyHasException if the holder has this permission already
*/
@@ -587,6 +631,7 @@ public abstract class PermissionHolder {
/**
* Sets a transient permission node
*
* @param node the node to set
* @throws ObjectAlreadyHasException if the holder has this permission already
*/
@@ -629,6 +674,7 @@ public abstract class PermissionHolder {
/**
* Unsets a permission node
*
* @param node the node to unset
* @throws ObjectLacksException if the holder doesn't have this node already
*/
@@ -652,6 +698,7 @@ public abstract class PermissionHolder {
/**
* Unsets a transient permission node
*
* @param node the node to unset
* @throws ObjectLacksException if the holder doesn't have this node already
*/
@@ -829,7 +876,7 @@ public abstract class PermissionHolder {
synchronized (nodes) {
boolean b = nodes.removeIf(n ->
n.isGroupNode() &&
n.isGroupNode() &&
n.getServer().orElse("global").equalsIgnoreCase(finalServer) &&
n.getWorld().orElse("null").equalsIgnoreCase(finalWorld)
);
@@ -934,6 +981,7 @@ public abstract class PermissionHolder {
/**
* Get a {@link List} of all of the groups the holder inherits, on all servers
*
* @return a {@link List} of group names
*/
public List<String> getGroupNames() {
@@ -945,8 +993,9 @@ public abstract class PermissionHolder {
/**
* Get a {@link List} of the groups the holder inherits on a specific server and world
*
* @param server the server to check
* @param world the world to check
* @param world the world to check
* @return a {@link List} of group names
*/
public List<String> getLocalGroups(String server, String world) {
@@ -969,6 +1018,7 @@ public abstract class PermissionHolder {
/**
* Get a {@link List} of the groups the holder inherits on a specific server
*
* @param server the server to check
* @return a {@link List} of group names
*/
@@ -979,24 +1029,4 @@ public abstract class PermissionHolder {
.map(Node::getGroupName)
.collect(Collectors.toList());
}
public static Map<String, Boolean> exportToLegacy(Set<Node> nodes) {
Map<String, Boolean> m = new HashMap<>();
for (Node node : nodes) {
m.put(node.toSerializedNode(), node.getValue());
}
return m;
}
private static Node.Builder buildNode(String permission) {
return new NodeBuilder(permission);
}
private static ImmutableLocalizedNode makeLocal(Node node, String location) {
return ImmutableLocalizedNode.of(node, location);
}
private static Node makeNode(String s, Boolean b) {
return NodeFactory.fromSerialisedNode(s, b);
}
}
@@ -22,11 +22,13 @@
package me.lucko.luckperms.common.core.model;
import com.google.common.collect.ImmutableList;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.common.utils.Identifiable;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
@@ -47,15 +49,13 @@ public class Track implements Identifiable<String> {
*/
@Getter
private final String name;
@Getter
private final Lock ioLock = new ReentrantLock();
/**
* The groups within this track
*/
private List<String> groups = Collections.synchronizedList(new ArrayList<>());
@Getter
private final Lock ioLock = new ReentrantLock();
@Override
public String getId() {
return name.toLowerCase();
@@ -63,6 +63,7 @@ public class Track implements Identifiable<String> {
/**
* Gets an ordered list of the groups on this track
*
* @return am ordered {@link List} of the groups on this track
*/
public List<String> getGroups() {
@@ -76,6 +77,7 @@ public class Track implements Identifiable<String> {
/**
* Gets the number of groups on this track
*
* @return the number of groups on this track
*/
public int getSize() {
@@ -84,6 +86,7 @@ public class Track implements Identifiable<String> {
/**
* Gets the next group on the track, after the one provided
*
* @param current the group before the group being requested
* @return the group name, or null if the end of the track has been reached
* @throws ObjectLacksException if the track does not contain the group given
@@ -94,6 +97,7 @@ public class Track implements Identifiable<String> {
/**
* Gets the group before the group provided
*
* @param current the group after the group being requested
* @return the group name, or null if the start of the track has been reached
* @throws ObjectLacksException if the track does not contain the group given
@@ -104,6 +108,7 @@ public class Track implements Identifiable<String> {
/**
* Gets the next group on the track, after the one provided
*
* @param current the group before the group being requested
* @return the group name, or null if the end of the track has been reached
* @throws ObjectLacksException if the track does not contain the group given
@@ -120,6 +125,7 @@ public class Track implements Identifiable<String> {
/**
* Gets the group before the group provided
*
* @param current the group after the group being requested
* @return the group name, or null if the start of the track has been reached
* @throws ObjectLacksException if the track does not contain the group given
@@ -136,6 +142,7 @@ public class Track implements Identifiable<String> {
/**
* Appends a group to the end of this track
*
* @param group the group to append
* @throws ObjectAlreadyHasException if the group is already on this track somewhere
*/
@@ -146,7 +153,8 @@ public class Track implements Identifiable<String> {
/**
* Inserts a group at a certain position on this track
* @param group the group to be inserted
*
* @param group the group to be inserted
* @param position the index position (a value of 0 inserts at the start)
* @throws ObjectAlreadyHasException if the group is already on this track somewhere
* @throws IndexOutOfBoundsException if the position is less than 0 or greater than the size of the track
@@ -158,6 +166,7 @@ public class Track implements Identifiable<String> {
/**
* Removes a group from this track
*
* @param group the group to remove
* @throws ObjectLacksException if the group is not on this track
*/
@@ -167,6 +176,7 @@ public class Track implements Identifiable<String> {
/**
* Removes a group from this track
*
* @param group the group to remove
* @throws ObjectLacksException if the group is not on this track
*/
@@ -177,6 +187,7 @@ public class Track implements Identifiable<String> {
/**
* Checks if a group features on this track
*
* @param group the group to check
* @return true if the group is on this track
*/
@@ -186,6 +197,7 @@ public class Track implements Identifiable<String> {
/**
* Checks if a group features on this track
*
* @param group the group to check
* @return true if the group is on this track
*/
@@ -26,6 +26,7 @@ import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
import me.lucko.luckperms.common.LuckPermsPlugin;
@@ -22,10 +22,12 @@
package me.lucko.luckperms.common.data;
import com.google.common.base.Splitter;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import com.google.common.base.Splitter;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.CommandManager;
import me.lucko.luckperms.common.commands.CommandResult;
@@ -35,7 +37,11 @@ import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
/**
@@ -213,13 +219,11 @@ public class Importer {
}
private static class Result {
@Getter
private final List<String> output = new ArrayList<>();
@Getter
@Setter
private String command;
@Getter
private final List<String> output = new ArrayList<>();
@Getter
@Setter
private CommandResult result = CommandResult.FAILURE;
@@ -22,19 +22,62 @@
package me.lucko.luckperms.common.data;
import com.google.common.collect.ImmutableSortedSet;
import lombok.Getter;
import com.google.common.collect.ImmutableSortedSet;
import me.lucko.luckperms.api.LogEntry;
import java.util.*;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.UUID;
import java.util.stream.Collectors;
public class Log {
private static final int PAGE_ENTRIES = 5;
public static Builder builder() {
return new Builder();
}
private static final int PAGE_ENTRIES = 5;
private static SortedMap<Integer, LogEntry> getPage(Set<LogEntry> set, int pageNo, int entries) {
if (pageNo < 1) {
throw new IllegalArgumentException("pageNo cannot be less than 1: " + pageNo);
}
int minimumEntries = ((pageNo * 5) - entries) + 1;
if (set.size() < minimumEntries) {
throw new IllegalStateException("Log does not contain that many entries. " +
"Requested: " + minimumEntries + ", Log Count: " + set.size());
}
final SortedMap<Integer, LogEntry> out = new TreeMap<>();
final int max = minimumEntries + entries - 1;
int index = 0;
for (LogEntry e : set) {
index++;
if (index >= minimumEntries) {
out.put(index, e);
}
if (index == max) {
break;
}
}
return out;
}
private static int getMaxPages(int size, int entries) {
return (int) Math.ceil((double) size / entries);
}
private static int getMaxPages(long size, int entries) {
return (int) Math.ceil((double) size / entries);
}
@Getter
private final SortedSet<LogEntry> content;
@@ -141,42 +184,6 @@ public class Log {
.count(), PAGE_ENTRIES);
}
private static SortedMap<Integer, LogEntry> getPage(Set<LogEntry> set, int pageNo, int entries) {
if (pageNo < 1) {
throw new IllegalArgumentException("pageNo cannot be less than 1: " + pageNo);
}
int minimumEntries = ((pageNo * 5) - entries) + 1;
if (set.size() < minimumEntries) {
throw new IllegalStateException("Log does not contain that many entries. " +
"Requested: " + minimumEntries + ", Log Count: " + set.size());
}
final SortedMap<Integer, LogEntry> out = new TreeMap<>();
final int max = minimumEntries + entries - 1;
int index = 0;
for (LogEntry e : set) {
index++;
if (index >= minimumEntries) {
out.put(index, e);
}
if (index == max) {
break;
}
}
return out;
}
private static int getMaxPages(int size, int entries) {
return (int) Math.ceil((double) size / entries);
}
private static int getMaxPages(long size, int entries) {
return (int) Math.ceil((double) size / entries);
}
@SuppressWarnings("WeakerAccess")
public static class Builder {
private final SortedSet<LogEntry> content = new TreeSet<>();
@@ -73,7 +73,7 @@ public class LogEntry extends me.lucko.luckperms.api.LogEntry {
.forEach(s -> Message.LOG.send(s, msg));
}
}
public static class LogEntryBuilder extends AbstractLogEntryBuilder<LogEntry, LogEntry.LogEntryBuilder> {
@Override
@@ -26,11 +26,12 @@ import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.model.PermissionHolder;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.util.function.Function;
import java.util.regex.Pattern;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class LogicParser {
private static final ScriptEngine SCRIPT_ENGINE = new ScriptEngineManager().getEngineByName("nashorn");
@@ -25,6 +25,7 @@ package me.lucko.luckperms.common.defaults;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.model.User;
@@ -92,13 +93,15 @@ public class Rule {
for (String s : toTake) {
try {
user.unsetPermission(NodeFactory.fromSerialisedNode(s, true));
} catch (ObjectLacksException ignored) {}
} catch (ObjectLacksException ignored) {
}
}
for (String s : toGive) {
try {
user.setPermission(NodeFactory.fromSerialisedNode(s, true));
} catch (ObjectAlreadyHasException ignored) {}
} catch (ObjectAlreadyHasException ignored) {
}
}
if (setPrimaryGroup != null) {
@@ -28,12 +28,14 @@ import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import me.lucko.luckperms.common.utils.Identifiable;
import java.util.Map;
/**
* An abstract manager class
*
* @param <I> the class used to identify each object held in this manager
* @param <T> the class this manager is "managing"
*/
@@ -29,6 +29,7 @@ import java.util.function.Function;
/**
* A class which manages instances of a class
*
* @param <I> the class used to identify each object held in this manager
* @param <T> the class this manager is "managing"
*/
@@ -36,12 +37,14 @@ public interface Manager<I, T extends Identifiable<I>> extends Function<I, T> {
/**
* Gets a map containing all cached instances held by this manager.
*
* @return all instances held in this manager
*/
Map<I, ? extends T> getAll();
/**
* Gets or creates an object by id
*
* @param id The id to search by
* @return a {@link T} object if the object is loaded or makes and returns a new object
*/
@@ -49,6 +52,7 @@ public interface Manager<I, T extends Identifiable<I>> extends Function<I, T> {
/**
* Get an object by id
*
* @param id The id to search by
* @return a {@link T} object if the object is loaded, returns null if the object is not loaded
*/
@@ -56,6 +60,7 @@ public interface Manager<I, T extends Identifiable<I>> extends Function<I, T> {
/**
* Check to see if a object is loaded or not
*
* @param id The id of the object
* @return true if the object is loaded
*/
@@ -63,6 +68,7 @@ public interface Manager<I, T extends Identifiable<I>> extends Function<I, T> {
/**
* Removes and unloads the object from the manager
*
* @param t The object to unload
*/
void unload(T t);
@@ -32,6 +32,7 @@ public interface UserManager extends Manager<UserIdentifier, User> {
/**
* Get a user object by name
*
* @param name The name to search by
* @return a {@link User} object if the user is loaded, returns null if the user is not loaded
*/
@@ -39,6 +40,7 @@ public interface UserManager extends Manager<UserIdentifier, User> {
/**
* Get a user object by uuid
*
* @param uuid The uuid to search by
* @return a {@link User} object if the user is loaded, returns null if the user is not loaded
*/
@@ -46,12 +48,14 @@ public interface UserManager extends Manager<UserIdentifier, User> {
/**
* Gives the user the default group if necessary.
*
* @param user the user to give to
*/
boolean giveDefaultIfNeeded(User user, boolean save);
/**
* Checks to see if the user is online, and if they are not, runs {@link #unload(Identifiable)}
*
* @param user The user to be cleaned up
*/
void cleanup(User user);
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.managers.impl;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.managers.AbstractManager;
@@ -23,6 +23,7 @@
package me.lucko.luckperms.common.managers.impl;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.core.UserIdentifier;
@@ -36,6 +37,69 @@ import java.util.UUID;
@RequiredArgsConstructor
public class GenericUserManager extends AbstractManager<UserIdentifier, User> implements UserManager {
public static boolean giveDefaultIfNeeded(User user, boolean save, LuckPermsPlugin plugin) {
boolean hasGroup = false;
if (user.getPrimaryGroup() != null && !user.getPrimaryGroup().isEmpty()) {
for (Node node : user.getPermissions(false)) {
if (node.isGroupNode()) {
hasGroup = true;
break;
}
}
}
if (hasGroup) {
return false;
}
user.setPrimaryGroup("default");
try {
user.setPermission("group.default", true);
} catch (ObjectAlreadyHasException ignored) {
}
if (save) {
plugin.getStorage().saveUser(user);
}
return true;
}
/**
* Check whether the user's state indicates that they should be persisted to storage.
*
* @param user the user to check
* @return true if the user should be saved
*/
public static boolean shouldSave(User user) {
if (user.getNodes().size() != 1) {
return true;
}
for (Node node : user.getNodes()) {
// There's only one.
if (!node.isGroupNode()) {
return true;
}
if (node.isTemporary() || node.isServerSpecific() || node.isWorldSpecific()) {
return true;
}
if (!node.getGroupName().equalsIgnoreCase("default")) {
// The user's only node is not the default group one.
return true;
}
}
if (!user.getPrimaryGroup().equalsIgnoreCase("default")) {
return true; // Not in the default primary group
}
return false;
}
private final LuckPermsPlugin plugin;
@Override
@@ -84,65 +148,4 @@ public class GenericUserManager extends AbstractManager<UserIdentifier, User> im
});
});
}
public static boolean giveDefaultIfNeeded(User user, boolean save, LuckPermsPlugin plugin) {
boolean hasGroup = false;
if (user.getPrimaryGroup() != null && !user.getPrimaryGroup().isEmpty()) {
for (Node node : user.getPermissions(false)) {
if (node.isGroupNode()) {
hasGroup = true;
break;
}
}
}
if (hasGroup) {
return false;
}
user.setPrimaryGroup("default");
try {
user.setPermission("group.default", true);
} catch (ObjectAlreadyHasException ignored) {}
if (save) {
plugin.getStorage().saveUser(user);
}
return true;
}
/**
* Check whether the user's state indicates that they should be persisted to storage.
* @param user the user to check
* @return true if the user should be saved
*/
public static boolean shouldSave(User user) {
if (user.getNodes().size() != 1) {
return true;
}
for (Node node : user.getNodes()) {
// There's only one.
if (!node.isGroupNode()) {
return true;
}
if (node.isTemporary() || node.isServerSpecific() || node.isWorldSpecific()) {
return true;
}
if (!node.getGroupName().equalsIgnoreCase("default")) {
// The user's only node is not the default group one.
return true;
}
}
if (!user.getPrimaryGroup().equalsIgnoreCase("default")) {
return true; // Not in the default primary group
}
return false;
}
}

Some files were not shown because too many files have changed in this diff Show More