Compare commits

...
41 Commits
Author SHA1 Message Date
Luck 24ff465679 Make command usage send with the correct label & bump version 2016-07-17 14:44:52 +01:00
Luck d33a3ffcea Add tab completion 2016-07-17 13:18:43 +01:00
Luck 874a90253b Add support for tracks 2016-07-15 22:44:25 +01:00
Luck 90b6f41f13 Don't shade gson 2016-07-15 16:11:31 +01:00
Luck 33fc4f537a General cleanup 2016-07-15 15:53:13 +01:00
Luck 42322ef932 Pre-compile patterns, add two new commands, check args before doing DB lookup, and limit group names slightly 2016-07-15 15:03:21 +01:00
Luck d5a6a4261d Update project dependencies 2016-07-15 11:56:28 +01:00
Luck 69ab488c47 Only store prefix in one place 2016-07-12 23:15:47 +01:00
Luck ad9b190a7c small cleanup 2016-07-12 11:50:49 +01:00
Luck f35cb95001 enum names should be singular 2016-07-12 11:32:04 +01:00
Luck f803082b15 Move all messages to one class 2016-07-11 20:56:01 +01:00
Luck 2413f0f379 Merge branch 'master' of https://github.com/lucko/LuckPerms 2016-07-05 20:54:09 +01:00
Luck 7ca7fdd472 javaassist is not a dependency of hikari 2016-07-05 20:53:13 +01:00
Luck f6e3f1ca0b Fix NPE and plugin not loading when Vault missing 2016-06-29 20:09:34 +01:00
Luck 84335afacd Huge cleanup 2016-06-29 15:35:57 +01:00
Luck 0e449cdd7a Fix save user query 2016-06-29 11:59:16 +01:00
Luck 3c83c31e9f Use group.<name> instead of luckperms.group.<name> to indicate group membership 2016-06-29 11:57:55 +01:00
Luck 776ec45701 Multiple fixes/improvements to command system 2016-06-28 18:07:55 +01:00
Luck ebbc0511bf don't clear proxiedplayer permission map 2016-06-28 17:28:08 +01:00
Luck d4c335e33e Fix clear command not resetting primary group 2016-06-28 17:21:41 +01:00
Luck e5e1333769 woops 2016-06-28 17:13:14 +01:00
Luck d855be1c65 Fix concurrency issue, remove sqlite from Bungee version and fix join message 2016-06-28 17:10:01 +01:00
Luck d35774b401 Fix primary group not loading and Vault support with EssentialsChat 2016-06-24 21:02:56 +01:00
Luck 1b09488859 Update readme 2016-06-24 18:42:03 +01:00
Luck 697b349167 Add primary groups 2016-06-24 18:38:05 +01:00
Luck 34ca3b3c25 Refactor sql datastore 2016-06-24 11:53:33 +01:00
Luck e07a346e16 fix group deletion not syncing across multiple instances 2016-06-23 21:48:25 +01:00
Luck 4610b3db7e Correct some messages 2016-06-23 18:05:02 +01:00
Luck 0781637617 Add flatfile storage support 2016-06-23 16:37:29 +01:00
Luck 85989aeb7c small cleanup 2016-06-23 13:29:51 +01:00
Luck 0380b7017d Update readme 2016-06-22 21:58:25 +01:00
Luck 91e24ccba1 Fix uuid data not saving 2016-06-22 17:34:48 +01:00
Luck 10a58e372c Fix user group issues 2016-06-22 17:24:30 +01:00
Luck 60f6bac903 Add sqlite support 2016-06-22 16:47:54 +01:00
Luck f6d8fb5286 Use gson instead of internal serialization method 2016-06-22 12:51:37 +01:00
Luck 484bc44288 Change users being updated async and refactor update task 2016-06-17 23:23:28 +01:00
Luck 00c3a8b415 Don't include global groups when global permissions are requested 2016-06-17 20:40:28 +01:00
Luck 20f34d9b45 Slight cleanup and better support for server reloads 2016-06-17 20:06:45 +01:00
Luck 50f4a84d04 Add priority system to permission handling 2016-06-17 19:38:16 +01:00
Luck 96476a2796 cleanup 2016-05-22 18:04:39 +01:00
Luck 17883f21d6 Fix encapsulation & make group inheritance work properly 2016-05-22 11:16:15 +01:00
98 changed files with 4311 additions and 1205 deletions

No files matched your search

+111
View File
@@ -0,0 +1,111 @@
= LuckPerms
A (fairly bad) permissions implementation for Bukkit/BungeeCord.
=== Features
* **Group inheritance** - users can be members of multiple groups, groups can inherit other groups
* **Multi-server support** - data is synced across all servers/platforms
* **Per-server permissions/groups** - define user/group permissions that only apply on certain servers
* **Server-specific groups** - define groups that only apply on certain servers
* **Tracks / paths** - users can be promoted/demoted along multiple group tracks
* **Vault Support** - hooks into Vault to integrate with other plugins
* **Easy and simple setup and configuration using commands** - no editing yml files, yuck
* **Efficient/lightweight** - maybe? Who knows, it might be.
* **BungeeCord compatible** - permissions, users and groups are synced across Bukkit/BungeeCord instances
* **Support for MySQL, SQLite & Flatfile (JSON)** - other storage methods coming soon (maybe)
===== Possible Caveats
* Currently only supports MySQL, SQLite & Flatfile (JSON) (support for more methods might come in the future)
* Not at all tested and could produce unexpected/buggy results and errors
=== Setup
All configuration options are in the **config.yml** file, which is generated automagically when the plugin first starts.
You can define the settings for per-server permissions, the storage method and credentials within this file.
=== Commands
Command usage is printed to the console/chat whenever invalid arguments are provided. Simply typing /perms will list all commands a user has permission to use.
==== Aliases
| Bukkit | /luckperms |
| | /perms |
| | /permissions |
| | /lp |
| | /perm |
| Bungee | /luckpermsbungee |
| | /bperms |
| | /bpermissions |
| | /lpb |
| | /bperm |
Arguments: <required> [optional]
Users with OP have access to all commands.
Additionally, you can use wildcards to grant users access to a selection of commands.
* **All commands** - luckperms.*
* **All user commands** - luckperms.user.*
* **All group commands** - luckperms.group.*
* **All track commands** - luckperms.track.*
| **Command** | **Description** | **Permission** |
| /perms | Sends plugin info and usage | N/A |
| /perms sync | Runs an update task and reloads the data of all online users | luckperms.sync |
| /perms info | Shows information about the plugin | luckperms.info |
| /perms debug | Shows some very brief debug info about the number of users/groups loaded | luckperms.debug |
| | | |
| | | |
| | | |
| /perms creategroup <group> | Creates a new group with the given name | luckperms.creategroup |
| /perms deletegroup <group> | Deletes an existing group | luckperms.deletegroup |
| /perms listgroups | Shows a list of the groups registered within the system | luckperms.listgroups |
| | | |
| | | |
| | | |
| /perms createtrack <track> | Creates a new track with the given name | luckperms.createtrack |
| /perms deletetrack <track> | Deletes an existing track | luckperms.deletetrack |
| /perms listtracks | Shows a list of the tracks registered within the system | luckperms.listtracks |
| | | |
| | | |
| | | |
| /perms user <user> info | Shows info about the user | luckperms.user.info |
| /perms user <user> getuuid | Shows the users Mojang UUID | luckperms.user.getuuid |
| /perms user <user> listnodes | Lists all of the permission nodes the user has | luckperms.user.listnodes |
| /perms user <user> haspermission <node> [server] | Checks if the user has a permission on a certain server | luckperms.user.haspermission |
| /perms user <user> inheritspermission <node> [server] | Checks if the user inherits a permission on a certain server. (This checks all parent groups unlike haspermission) | luckperms.user.inheritspermission |
| /perms user <user> set <node> <true/false> [server]| Sets a permission for the user | luckperms.user.setpermission |
| /perms user <user> unset <node> [server] | Unsets a permission for the user | luckperms.user.unsetpermission |
| /perms user <user> addgroup <group> [server] | Adds the user to a group | luckperms.user.addgroup |
| /perms user <user> removegroup <group> [server] | Removes the user from a group | luckperms.user.removegroup |
| /perms user <user> setprimarygroup <group> | Sets the users primary group | luckperms.user.setprimarygroup |
| /perms user <user> showtracks | Shows a list of the tracks the user can be promoted/demoted on | luckperms.user.showtracks |
| /perms user <user> promote <track> | Promotes the user along a given track | luckperms.user.promote |
| /perms user <user> demote <track> | Demotes the user along a given track | luckperms.user.demote |
| /perms user <user> showpos <track> | Shows the users position on a given track | luckperms.user.showpos |
| /perms user <user> clear | Clears all permissions the user has | luckperms.user.clear |
| | | |
| | | |
| | | |
| /perms group <group> info | Shows info about the group | luckperms.group.info |
| /perms group <group> listnodes | Lists all of the permission nodes the group has | luckperms.group.listnodes |
| /perms group <group> haspermission <node> [server] | Checks if the group has a permission on a certain server | luckperms.group.haspermission |
| /perms group <group> inheritspermission <node> [server] | Checks if the group inherits a permission on a certain server. (This checks all parent groups unlike haspermission) | luckperms.group.inheritspermission |
| /perms group <group> set <node> <true/false> [server]| Sets a permission for the group | luckperms.group.setpermission |
| /perms group <group> unset <node> [server] | Unsets a permission for the group | luckperms.group.unsetpermission |
| /perms group <group> setinherit <group> [server]| Sets the group to inherit all permissions from another group | luckperms.group.setinherit |
| /perms group <group> unsetinherit <group> [server] | Unsets a perviously defined inheritance rule | luckperms.group.unsetinherit |
| /perms group <group> showtracks | Shows a list of the tracks that the users in the group can be promoted/demoted on | luckperms.group.showtracks |
| /perms group <group> clear | Clears all permissions the group has | luckperms.group.clear |
| | | |
| | | |
| | | |
| /perms track <track> info | Shows info about the track | luckperms.track.info |
| /perms track <track> append <group> | Appends a group to the end of the track | luckperms.track.append |
| /perms track <track> insert <group> <position> | Inserts a group at the given position on the track | luckperms.track.insert |
| /perms track <track> remove <group> | Removes a group from the track | luckperms.track.remove |
| /perms track <track> clear | Clears all groups on the track | luckperms.track.clear |
=== License
See LICENSE.md.
-28
View File
@@ -1,28 +0,0 @@
# LuckPerms
A quite possibly shit™ permissions implementation for Bukkit/BungeeCord.
### Why?
Yeah, I don't know. There are other more advanced, optimized, better programmed and thoroughly tested alternative plugins around, you should probably use those instead. I just wanted some specific features, and something that was compatible with BungeeCord.
### Features
- **Group inheritance** - users can be members of multiple groups, groups can inherit other groups
- **Multi-server support** - data is synced across all servers/platforms
- **Per-server permissions/groups** - define permissions that only apply on certain servers
- **Vault Support** - hooks into Vault to integrate with other plugins
- **Everything is configured using commands** - no editing yml files, yuck
- **Efficient** - maybe? Who knows, it might be.
- **BungeeCord compatible** - my main motive for making this was that all other Bungee/Bukkit compatible perms plugins are utter aids. (At least, I couldn't find any decent ones)
### Caveats
- Only supports MySQL
- Not at all tested and could be super unreliable
- It's quite possibly shit™
So, not anything major, really ¯\ _(ツ)_ /¯
### Commands
Command usage is printed when you supply too little arguments.
Bukkit: `/luckperms` `/perms` `/permissions` `/lp` `/perm`
Bungee: `/luckpermsbungee` `/bperms` `/bpermissions` `/lpb` `/bperm`
+3 -3
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko</groupId>
<version>1.0-SNAPSHOT</version>
<version>1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -28,7 +28,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
@@ -37,7 +37,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
@@ -16,6 +16,7 @@ public class BukkitConfig implements LPConfiguration {
create();
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private void create() {
File configFile = new File(plugin.getDataFolder(), "config.yml");
@@ -36,36 +37,36 @@ public class BukkitConfig implements LPConfiguration {
@Override
public String getServer() {
return configuration.getString("server");
}
@Override
public String getPrefix() {
return configuration.getString("prefix");
return configuration.getString("server", "global");
}
@Override
public int getSyncTime() {
return configuration.getInt("sql.sync-minutes");
return configuration.getInt("sql.sync-minutes", 3);
}
@Override
public String getDefaultGroupNode() {
return "luckperms.group." + configuration.getString("default-group");
return "group." + configuration.getString("default-group", "default");
}
@Override
public String getDefaultGroupName() {
return configuration.getString("default-group");
return configuration.getString("default-group", "default");
}
@Override
public boolean getIncludeGlobalPerms() {
return configuration.getBoolean("include-global");
return configuration.getBoolean("include-global", true);
}
@Override
public String getDatabaseValue(String value) {
return configuration.getString("sql." + value);
}
@Override
public String getStorageMethod() {
return configuration.getString("storage-method", "sqlite");
}
}
@@ -5,26 +5,45 @@ import me.lucko.luckperms.commands.Sender;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.List;
class CommandManagerBukkit extends CommandManager implements CommandExecutor {
class CommandManagerBukkit extends CommandManager implements CommandExecutor, TabExecutor {
CommandManagerBukkit(LuckPermsPlugin plugin) {
super(plugin);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
return onCommand(new Sender() {
return onCommand(makeSender(sender), label, Arrays.asList(args));
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
return onTabComplete(makeSender(sender), Arrays.asList(args));
}
private static Sender makeSender(CommandSender sender) {
return new Sender() {
final WeakReference<CommandSender> cs = new WeakReference<>(sender);
@Override
public void sendMessage(String s) {
sender.sendMessage(s);
final CommandSender c = cs.get();
if (c != null) {
c.sendMessage(s);
}
}
@Override
public boolean hasPermission(String node) {
return sender.hasPermission(node);
final CommandSender c = cs.get();
return c != null && c.hasPermission(node);
}
}, Arrays.asList(args));
};
}
}
@@ -2,32 +2,38 @@ package me.lucko.luckperms;
import lombok.Getter;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.data.DatastoreConfiguration;
import me.lucko.luckperms.data.HikariDatastore;
import me.lucko.luckperms.data.MySQLConfiguration;
import me.lucko.luckperms.data.methods.FlatfileDatastore;
import me.lucko.luckperms.data.methods.MySQLDatastore;
import me.lucko.luckperms.data.methods.SQLiteDatastore;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.listeners.PlayerListener;
import me.lucko.luckperms.runnables.UpdateTask;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.BukkitUserManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import net.milkbowl.vault.permission.Permission;
import me.lucko.luckperms.vaulthooks.VaultHook;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Getter
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
public static final String VERSION = "v1.0";
public static final String VERSION = "v1.1";
private LPConfiguration configuration;
private UserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
@Override
@@ -42,40 +48,60 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
CommandManagerBukkit commandManager = new CommandManagerBukkit(this);
PluginCommand main = getServer().getPluginCommand("luckperms");
main.setExecutor(commandManager);
main.setTabCompleter(commandManager);
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
datastore = new HikariDatastore(this);
datastore.init(new DatastoreConfiguration(
configuration.getDatabaseValue("address"),
configuration.getDatabaseValue("database"),
configuration.getDatabaseValue("username"),
configuration.getDatabaseValue("password")
));
final String storageMethod = configuration.getStorageMethod();
if (storageMethod.equalsIgnoreCase("mysql")) {
getLogger().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(this, new MySQLConfiguration(
configuration.getDatabaseValue("address"),
configuration.getDatabaseValue("database"),
configuration.getDatabaseValue("username"),
configuration.getDatabaseValue("password")
));
} else if (storageMethod.equalsIgnoreCase("sqlite")) {
getLogger().info("Using SQLite as storage method.");
datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite"));
} else if (storageMethod.equalsIgnoreCase("flatfile")) {
getLogger().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(this, getDataFolder());
} else {
getLogger().warning("Storage method '" + storageMethod + "' was not recognised. Using SQLite as fallback.");
datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite"));
}
datastore.init();
userManager = new BukkitUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager(this);
// Run update task to refresh any online users
runUpdateTask();
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
long ticks = mins * 60 * 20;
new UpdateTask(this).runTaskTimer(this, ticks, ticks);
getServer().getScheduler().runTaskTimerAsynchronously(this, new UpdateTask(this), ticks, ticks);
}
// Provide vault support
try {
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
getServer().getServicesManager().register(Permission.class, new VaultHook(this), this, ServicePriority.High);
getLogger().info("Registered Vault permission hook.");
} else {
getLogger().info("Vault not found.");
}
} catch (Exception e) {
getLogger().warning("Error whilst hooking into Vault.");
e.printStackTrace();
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
VaultHook.hook(this);
getLogger().info("Registered Vault permission & chat hook.");
} else {
getLogger().info("Vault not found.");
}
}
@Override
public void onDisable() {
datastore.shutdown();
}
@Override
public void doAsync(Runnable r) {
Bukkit.getScheduler().runTaskAsynchronously(this, r);
@@ -93,8 +119,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
@Override
public String getPlayerStatus(UUID uuid) {
if (getServer().getPlayer(uuid) != null) return "&aOnline";
return "&cOffline";
return getServer().getPlayer(uuid) != null ? "&aOnline" : "&cOffline";
}
@Override
@@ -102,8 +127,13 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return getServer().getOnlinePlayers().size();
}
@Override
public List<String> getPlayerList() {
return getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
}
@Override
public void runUpdateTask() {
new UpdateTask(this).runTask(this);
getServer().getScheduler().runTaskAsynchronously(this, new UpdateTask(this));
}
}
@@ -2,9 +2,10 @@ package me.lucko.luckperms.listeners;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.users.BukkitUser;
import me.lucko.luckperms.users.User;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -20,8 +21,8 @@ public class PlayerListener implements Listener {
@EventHandler
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
if (!plugin.getDatastore().isAcceptingLogins()) {
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, color(plugin.getConfiguration().getPrefix() +
"&cError whilst validating login with the network. \nPlease contact an administrator."));
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER,
Util.color(Message.PREFIX + "Error whilst validating login with the network. \nPlease contact an administrator."));
return;
}
plugin.getDatastore().loadOrCreateUser(e.getUniqueId(), e.getName());
@@ -33,8 +34,8 @@ public class PlayerListener implements Listener {
User user = plugin.getUserManager().getUser(player.getUniqueId());
if (user == null) {
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, color(plugin.getConfiguration().getPrefix() +
"&cUser data could not be loaded. Please contact an administrator."));
e.disallow(PlayerLoginEvent.Result.KICK_OTHER,
Util.color(Message.PREFIX + "User data could not be loaded. Please contact an administrator."));
return;
}
@@ -68,8 +69,4 @@ public class PlayerListener implements Listener {
plugin.getUserManager().unloadUser(user);
}
public static String color(String string) {
return ChatColor.translateAlternateColorCodes('&', string);
}
}
@@ -1,25 +0,0 @@
package me.lucko.luckperms.runnables;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBukkitPlugin;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
@AllArgsConstructor
public class UpdateTask extends BukkitRunnable {
private final LPBukkitPlugin plugin;
@Override
public void run() {
plugin.getLogger().info("Running update task.");
// Re-load all of the groups
plugin.getGroupManager().loadAllGroups();
// Refresh all online users.
for (Player p : Bukkit.getOnlinePlayers()) {
plugin.getDatastore().loadUser(p.getUniqueId(), success -> {});
}
}
}
@@ -18,35 +18,33 @@ public class BukkitUser extends User {
@Setter
private PermissionAttachment attachment = null;
public BukkitUser(UUID uuid, LPBukkitPlugin plugin) {
BukkitUser(UUID uuid, LPBukkitPlugin plugin) {
super(uuid, plugin);
this.plugin = plugin;
}
public BukkitUser(UUID uuid, String username, LPBukkitPlugin plugin) {
BukkitUser(UUID uuid, String username, LPBukkitPlugin plugin) {
super(uuid, username, plugin);
this.plugin = plugin;
}
@Override
public void refreshPermissions() {
Player player = Bukkit.getPlayer(getUuid());
if (player == null) return;
plugin.doSync(() -> {
Player player = Bukkit.getPlayer(getUuid());
if (player == null) return;
if (attachment == null) {
getPlugin().getLogger().warning("User " + getName() + " does not have a permissions attachment defined.");
setAttachment(player.addAttachment(plugin));
}
if (attachment == null) {
getPlugin().getLogger().warning("User " + getName() + " does not have a permissions attachment defined.");
setAttachment(player.addAttachment(plugin));
}
// Clear existing permissions
for (String p : attachment.getPermissions().keySet()) {
attachment.setPermission(p, false);
}
// Clear existing permissions
attachment.getPermissions().keySet().forEach(p -> attachment.setPermission(p, false));
// Re-add all defined permissions for the user
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null);
for (String node : local.keySet()) {
attachment.setPermission(node, local.get(node));
}
// Re-add all defined permissions for the user
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null);
local.entrySet().forEach(e -> attachment.setPermission(e.getKey(), e.getValue()));
});
}
}
@@ -10,6 +10,7 @@ public class BukkitUserManager extends UserManager {
private final LPBukkitPlugin plugin;
public BukkitUserManager(LPBukkitPlugin plugin) {
super(plugin);
this.plugin = plugin;
}
@@ -50,4 +51,9 @@ public class BukkitUserManager extends UserManager {
public User makeUser(UUID uuid, String username) {
return new BukkitUser(uuid, username, plugin);
}
@Override
public void updateAllUsers() {
plugin.getServer().getOnlinePlayers().stream().map(Player::getUniqueId).forEach(u -> plugin.getDatastore().loadUser(u));
}
}
@@ -0,0 +1,127 @@
package me.lucko.luckperms.vaulthooks;
import net.milkbowl.vault.chat.Chat;
import net.milkbowl.vault.permission.Permission;
/**
* Dummy class for hooking with Vault plugins that need both Chat + Perms
* This doesn't return anything useful, or change anything internally
*
* Registered on the lowest priority so other plugins can override
*/
class VaultChatHook extends Chat {
VaultChatHook(Permission perms) {
super(perms);
}
private void throwNotSupported() {
// throw new UnsupportedOperationException("LuckPerms cannot perform this operation.");
}
public String getName() {
return "LuckPerms";
}
public boolean isEnabled() {
return true;
}
public String getPlayerPrefix(String world, String player) {
return "";
}
public void setPlayerPrefix(String world, String player, String prefix) {
throwNotSupported();
}
public String getPlayerSuffix(String world, String player) {
return "";
}
public void setPlayerSuffix(String world, String player, String suffix) {
throwNotSupported();
}
public String getGroupPrefix(String world, String group) {
return "";
}
public void setGroupPrefix(String world, String group, String prefix) {
throwNotSupported();
}
public String getGroupSuffix(String world, String group) {
return "";
}
public void setGroupSuffix(String world, String group, String suffix) {
throwNotSupported();
}
public int getPlayerInfoInteger(String world, String player, String node, int defaultValue) {
return defaultValue;
}
public void setPlayerInfoInteger(String world, String player, String node, int value) {
throwNotSupported();
}
public int getGroupInfoInteger(String world, String group, String node, int defaultValue) {
return defaultValue;
}
public void setGroupInfoInteger(String world, String group, String node, int value) {
throwNotSupported();
}
public double getPlayerInfoDouble(String world, String player, String node, double defaultValue) {
return defaultValue;
}
public void setPlayerInfoDouble(String world, String player, String node, double value) {
throwNotSupported();
}
public double getGroupInfoDouble(String world, String group, String node, double defaultValue) {
return defaultValue;
}
public void setGroupInfoDouble(String world, String group, String node, double value) {
throwNotSupported();
}
public boolean getPlayerInfoBoolean(String world, String player, String node, boolean defaultValue) {
return defaultValue;
}
public void setPlayerInfoBoolean(String world, String player, String node, boolean value) {
throwNotSupported();
}
public boolean getGroupInfoBoolean(String world, String group, String node, boolean defaultValue) {
return defaultValue;
}
public void setGroupInfoBoolean(String world, String group, String node, boolean value) {
throwNotSupported();
}
public String getPlayerInfoString(String world, String player, String node, String defaultValue) {
return defaultValue;
}
public void setPlayerInfoString(String world, String player, String node, String value) {
throwNotSupported();
}
public String getGroupInfoString(String world, String group, String node, String defaultValue) {
return defaultValue;
}
public void setGroupInfoString(String world, String group, String node, String value) {
throwNotSupported();
}
}
@@ -0,0 +1,36 @@
package me.lucko.luckperms.vaulthooks;
import me.lucko.luckperms.LPBukkitPlugin;
import net.milkbowl.vault.chat.Chat;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.ServicesManager;
public class VaultHook {
private static VaultChatHook chatHook = null;
private static VaultPermissionHook permissionHook = null;
public static void hook(LPBukkitPlugin plugin) {
try {
if (permissionHook == null) {
permissionHook = new VaultPermissionHook();
}
permissionHook.setPlugin(plugin);
if (chatHook == null) {
chatHook = new VaultChatHook(permissionHook);
}
final ServicesManager sm = plugin.getServer().getServicesManager();
sm.unregisterAll(plugin);
sm.register(Permission.class, permissionHook, plugin, ServicePriority.High);
sm.register(Chat.class, chatHook, plugin, ServicePriority.Lowest);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,15 +1,17 @@
package me.lucko.luckperms;
package me.lucko.luckperms.vaulthooks;
import lombok.AllArgsConstructor;
import lombok.Setter;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import net.milkbowl.vault.permission.Permission;
@AllArgsConstructor
public class VaultHook extends Permission {
private final LPBukkitPlugin plugin;
class VaultPermissionHook extends Permission {
@Setter
private LPBukkitPlugin plugin;
@Override
public String getName() {
@@ -52,7 +54,7 @@ public class VaultHook extends Permission {
try {
user.unsetPermission(permission);
} catch (ObjectLacksPermissionException ignored) {}
} catch (ObjectLacksException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@@ -82,7 +84,7 @@ public class VaultHook extends Permission {
try {
group.unsetPermission(permission);
} catch (ObjectLacksPermissionException ignored) {}
} catch (ObjectLacksException ignored) {}
plugin.runUpdateTask();
return true;
}
@@ -92,7 +94,8 @@ public class VaultHook extends Permission {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
return user.getGroupNames().contains(group);
final Group group1 = plugin.getGroupManager().getGroup(group);
return group1 != null && user.isInGroup(group1);
}
@Override
@@ -120,7 +123,7 @@ public class VaultHook extends Permission {
try {
user.removeGroup(group);
} catch (ObjectLacksPermissionException ignored) {}
} catch (ObjectLacksException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@@ -128,14 +131,13 @@ public class VaultHook extends Permission {
@Override
public String[] getPlayerGroups(String world, String player) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return new String[0];
return user.getGroupNames().toArray(new String[0]);
return (user == null) ? new String[0] : user.getGroupNames().toArray(new String[0]);
}
@Override
public String getPrimaryGroup(String world, String player) {
throw new UnsupportedOperationException();
final User user = plugin.getUserManager().getUser(player);
return (user == null) ? null : user.getPrimaryGroup();
}
@Override
+5 -2
View File
@@ -3,13 +3,16 @@
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server: global
# The default group assigned to all user on join. e.g. a value of "default" = luckperms.group.default
# The default group assigned to all users on their first join.
default-group: default
# If users on this server should have their global permissions/groups applied.
include-global: true
prefix: '&7&l[&b&lL&a&lP&7&l] &c'
# Which storage method the plugin should use.
# Currently supported: mysql, sqlite, flatfile
# Fill out connection info below if you're using MySQL
storage-method: sqlite
sql:
address: localhost:3306
+1 -1
View File
@@ -1,6 +1,6 @@
name: LuckPerms
author: Luck
version: 1.0
version: 1.1
main: me.lucko.luckperms.LPBukkitPlugin
softdepend: [Vault]
description: A permissions plugin
+3 -4
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko</groupId>
<version>1.0-SNAPSHOT</version>
<version>1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -28,7 +28,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
@@ -37,7 +37,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
@@ -59,7 +59,6 @@
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.9-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<!-- LuckPerms Common -->
@@ -27,6 +27,7 @@ public class BungeeConfig implements LPConfiguration {
}
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private File makeFile(String file) throws IOException {
File cfg = new File(plugin.getDataFolder(), file);
@@ -40,39 +41,38 @@ public class BungeeConfig implements LPConfiguration {
return cfg;
}
@Override
public String getServer() {
return configuration.getString("server");
}
@Override
public String getPrefix() {
return configuration.getString("prefix");
return configuration.getString("server", "bungee");
}
@Override
public int getSyncTime() {
return configuration.getInt("sql.sync-minutes");
return configuration.getInt("sql.sync-minutes", 3);
}
@Override
public String getDefaultGroupNode() {
return "luckperms.group." + configuration.getString("default-group");
return "group." + configuration.getString("default-group", "default");
}
@Override
public String getDefaultGroupName() {
return configuration.getString("default-group");
return configuration.getString("default-group", "default");
}
@Override
public boolean getIncludeGlobalPerms() {
return configuration.getBoolean("include-global");
return configuration.getBoolean("include-global", false);
}
@Override
public String getDatabaseValue(String value) {
return configuration.getString("sql." + value);
}
@Override
public String getStorageMethod() {
return configuration.getString("storage-method", "sqlite");
}
}
@@ -3,33 +3,33 @@ package me.lucko.luckperms;
import lombok.Getter;
import me.lucko.luckperms.commands.CommandManager;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.data.DatastoreConfiguration;
import me.lucko.luckperms.data.HikariDatastore;
import me.lucko.luckperms.data.MySQLConfiguration;
import me.lucko.luckperms.data.methods.FlatfileDatastore;
import me.lucko.luckperms.data.methods.MySQLDatastore;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.listeners.PlayerListener;
import me.lucko.luckperms.runnables.UpdateTask;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.BungeeUserManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Getter
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
public static final String VERSION = "v1.0";
public static final String VERSION = "v1.1";
@Getter
LPConfiguration configuration;
@Getter
UserManager userManager;
@Getter
GroupManager groupManager;
@Getter
Datastore datastore;
private LPConfiguration configuration;
private UserManager userManager;
private GroupManager groupManager;
private TrackManager trackManager;
private Datastore datastore;
@Override
public void onEnable() {
@@ -41,16 +41,32 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
// register commands
getProxy().getPluginManager().registerCommand(this, new MainCommand(new CommandManager(this)));
datastore = new HikariDatastore(this);
datastore.init(new DatastoreConfiguration(
configuration.getDatabaseValue("address"),
configuration.getDatabaseValue("database"),
configuration.getDatabaseValue("username"),
configuration.getDatabaseValue("password")
));
// disable the default Bungee /perms command so it gets handled by the Bukkit plugin
getProxy().getDisabledCommands().add("perms");
final String storageMethod = configuration.getStorageMethod();
if (storageMethod.equalsIgnoreCase("mysql")) {
getLogger().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(this, new MySQLConfiguration(
configuration.getDatabaseValue("address"),
configuration.getDatabaseValue("database"),
configuration.getDatabaseValue("username"),
configuration.getDatabaseValue("password")
));
} else if (storageMethod.equalsIgnoreCase("flatfile")) {
getLogger().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(this, getDataFolder());
} else {
getLogger().warning("Storage method '" + storageMethod + "' was not recognised. Using Flatfile as fallback.");
datastore = new FlatfileDatastore(this, getDataFolder());
}
datastore.init();
userManager = new BungeeUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager(this);
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
@@ -58,15 +74,9 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
}
}
@Override
public UserManager getUserManager() {
return userManager;
}
@Override
public GroupManager getGroupManager() {
return groupManager;
public void onDisable() {
datastore.shutdown();
}
@Override
@@ -76,8 +86,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
@Override
public String getPlayerStatus(UUID uuid) {
if (getProxy().getPlayer(uuid) != null) return "&aOnline";
return "&cOffline";
return getProxy().getPlayer(uuid) != null ? "&aOnline" : "&cOffline";
}
@Override
@@ -86,18 +95,13 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
}
@Override
public LPConfiguration getConfiguration() {
return configuration;
}
@Override
public Datastore getDatastore() {
return datastore;
public List<String> getPlayerList() {
return getProxy().getPlayers().stream().map(ProxiedPlayer::getName).collect(Collectors.toList());
}
@Override
public void runUpdateTask() {
new UpdateTask(this).run();
doAsync(new UpdateTask(this));
}
@Override
@@ -5,30 +5,47 @@ import me.lucko.luckperms.commands.Sender;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
import java.lang.ref.WeakReference;
import java.util.Arrays;
public class MainCommand extends Command {
class MainCommand extends Command implements TabExecutor {
private final CommandManager manager;
public MainCommand(CommandManager manager) {
super("luckpermsbungee", "luckperms.use", "bperms", "lpb", "bpermissions", "bp", "bperm");
super("luckpermsbungee", null, "bperms", "lpb", "bpermissions", "bp", "bperm");
this.manager = manager;
}
@Override
public void execute(CommandSender sender, String[] args) {
manager.onCommand(new Sender() {
manager.onCommand(makeSender(sender), "bperms", Arrays.asList(args));
}
@Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
return manager.onTabComplete(makeSender(sender), Arrays.asList(args));
}
private static Sender makeSender(CommandSender sender) {
return new Sender() {
final WeakReference<CommandSender> cs = new WeakReference<>(sender);
@Override
public void sendMessage(String s) {
sender.sendMessage(new TextComponent(s));
final CommandSender c = cs.get();
if (c != null) {
c.sendMessage(new TextComponent(s));
}
}
@Override
public boolean hasPermission(String node) {
return sender.hasPermission(node);
final CommandSender c = cs.get();
return c != null && c.hasPermission(node);
}
}, Arrays.asList(args));
};
}
}
@@ -3,7 +3,7 @@ package me.lucko.luckperms.listeners;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBungeePlugin;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.users.User;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@@ -12,6 +12,9 @@ import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;
@AllArgsConstructor
public class PlayerListener implements Listener {
@@ -20,17 +23,27 @@ public class PlayerListener implements Listener {
@EventHandler
public void onPlayerPostLogin(PostLoginEvent e) {
final ProxiedPlayer player = e.getPlayer();
final WeakReference<ProxiedPlayer> p = new WeakReference<>(player);
plugin.getDatastore().loadOrCreateUser(player.getUniqueId(), player.getName(), success -> {
if (!success) {
e.getPlayer().sendMessage(new TextComponent(Util.color("&e&l[LP] &cPermissions data could not be loaded. Please contact an administrator.")));
plugin.getProxy().getScheduler().schedule(plugin, () -> {
final ProxiedPlayer pl = p.get();
if (pl != null) {
pl.sendMessage(new TextComponent(Util.color(Message.PREFIX + "Permissions data could not be loaded. Please contact an administrator.")));
}
}, 3, TimeUnit.SECONDS);
} else {
User user = plugin.getUserManager().getUser(player.getUniqueId());
user.refreshPermissions();
final ProxiedPlayer pl = p.get();
if (pl != null) {
final User user = plugin.getUserManager().getUser(pl.getUniqueId());
user.refreshPermissions();
}
}
});
plugin.getDatastore().saveUUIDData(e.getPlayer().getName(), e.getPlayer().getUniqueId(), success -> {});
plugin.getDatastore().saveUUIDData(player.getName(), player.getUniqueId(), success -> {});
}
@EventHandler
@@ -1,23 +0,0 @@
package me.lucko.luckperms.runnables;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBungeePlugin;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@AllArgsConstructor
public class UpdateTask implements Runnable {
private final LPBungeePlugin plugin;
@Override
public void run() {
plugin.getLogger().info("Running update task.");
// Re-load all of the groups
plugin.getGroupManager().loadAllGroups();
// Refresh all online users.
for (ProxiedPlayer p : plugin.getProxy().getPlayers()) {
plugin.getDatastore().loadUser(p.getUniqueId(), success -> {});
}
}
}
@@ -12,12 +12,12 @@ public class BungeeUser extends User {
private final LPBungeePlugin plugin;
public BungeeUser(UUID uuid, LPBungeePlugin plugin) {
BungeeUser(UUID uuid, LPBungeePlugin plugin) {
super(uuid, plugin);
this.plugin = plugin;
}
public BungeeUser(UUID uuid, String username, LPBungeePlugin plugin) {
BungeeUser(UUID uuid, String username, LPBungeePlugin plugin) {
super(uuid, username, plugin);
this.plugin = plugin;
}
@@ -29,14 +29,10 @@ public class BungeeUser extends User {
// Clear existing permissions
Collection<String> perms = new ArrayList<>(player.getPermissions());
for (String p : perms) {
player.setPermission(p, false);
}
perms.forEach(p -> player.setPermission(p, false));
// Re-add all defined permissions for the user
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null);
for (String node : local.keySet()) {
player.setPermission(node, local.get(node));
}
local.entrySet().forEach(e -> player.setPermission(e.getKey(), e.getValue()));
}
}
@@ -9,18 +9,15 @@ public class BungeeUserManager extends UserManager {
private final LPBungeePlugin plugin;
public BungeeUserManager(LPBungeePlugin plugin) {
super(plugin);
this.plugin = plugin;
}
@Override
public void unloadUser(User user) {
if (user != null) {
ProxiedPlayer player = plugin.getProxy().getPlayer(user.getUuid());
if (player != null) {
player.getPermissions().clear();
}
// Cannot clear the ProxiedPlayer's permission map, they're leaving so that will get GCed anyway
// Calling getPermissions.clear() throws an UnsupportedOperationException
getUsers().remove(user.getUuid());
}
}
@@ -41,4 +38,9 @@ public class BungeeUserManager extends UserManager {
public User makeUser(UUID uuid, String username) {
return new BungeeUser(uuid, username, plugin);
}
@Override
public void updateAllUsers() {
plugin.getProxy().getPlayers().stream().map(ProxiedPlayer::getUniqueId).forEach(u -> plugin.getDatastore().loadUser(u));
}
}
+5 -2
View File
@@ -3,13 +3,16 @@
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server: bungee
# The default group assigned to all user on join. e.g. a value of "default" = luckperms.group.default
# The default group assigned to all users on their first join.
default-group: default
# If users on this server should have their global permissions/groups applied.
include-global: false
prefix: '&7&l[&b&lL&a&lP&7&l] &c'
# Which storage method the plugin should use.
# Currently supported: mysql & flatfile
# Fill out connection info below if you're using MySQL
storage-method: flatfile
sql:
address: localhost:3306
+3 -1
View File
@@ -1,3 +1,5 @@
name: LuckPerms
author: Luck
version: 1.1
main: me.lucko.luckperms.LPBungeePlugin
author: Luck
description: A permissions plugin
+2 -2
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko</groupId>
<version>1.0-SNAPSHOT</version>
<version>1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -15,7 +15,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
@@ -2,9 +2,11 @@ package me.lucko.luckperms;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;
@@ -12,16 +14,22 @@ public interface LuckPermsPlugin {
/**
* Retrieves the {@link UserManager} used to manage users and their permissions/groups
* @return the {@link UserManager} object
* @return the {@link UserManager} instance
*/
UserManager getUserManager();
/**
* Retrieves the {@link GroupManager} used to manage the loaded groups and modify their permissions
* @return the {@link GroupManager} object
* @return the {@link GroupManager} instance
*/
GroupManager getGroupManager();
/**
* Retrieves the {@link TrackManager} used to manage the loaded tracks
* @return the {@link TrackManager} instance
*/
TrackManager getTrackManager();
/**
* Retrieves the {@link LPConfiguration} for getting values from the config
* @return the {@link LPConfiguration} implementation for the platform
@@ -58,6 +66,12 @@ public interface LuckPermsPlugin {
*/
int getPlayerCount();
/**
* Gets the usernames of the users online on the platform
* @return a {@link List} of usernames
*/
List<String> getPlayerList();
/**
* Runs an update task
*/
@@ -10,12 +10,21 @@ import me.lucko.luckperms.commands.group.subcommands.*;
import me.lucko.luckperms.commands.misc.DebugCommand;
import me.lucko.luckperms.commands.misc.InfoCommand;
import me.lucko.luckperms.commands.misc.SyncCommand;
import me.lucko.luckperms.commands.track.CreateTrackCommand;
import me.lucko.luckperms.commands.track.DeleteTrackCommand;
import me.lucko.luckperms.commands.track.ListTracksCommand;
import me.lucko.luckperms.commands.track.TrackMainCommand;
import me.lucko.luckperms.commands.track.subcommands.*;
import me.lucko.luckperms.commands.user.UserMainCommand;
import me.lucko.luckperms.commands.user.subcommands.*;
import me.lucko.luckperms.constants.Message;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import java.util.stream.Collectors;
public class CommandManager {
private final LuckPermsPlugin plugin;
@@ -30,12 +39,18 @@ public class CommandManager {
this.registerMainCommand(userCommand);
userCommand.registerSubCommand(new UserAddGroupCommand());
userCommand.registerSubCommand(new UserClearCommand());
userCommand.registerSubCommand(new UserDemoteCommand());
userCommand.registerSubCommand(new UserGetUUIDCommand());
userCommand.registerSubCommand(new UserHasPermCommand());
userCommand.registerSubCommand(new UserInfoCommand());
userCommand.registerSubCommand(new UserInheritsPermCommand());
userCommand.registerSubCommand(new UserListNodesCommand());
userCommand.registerSubCommand(new UserPromoteCommand());
userCommand.registerSubCommand(new UserRemoveGroupCommand());
userCommand.registerSubCommand(new UserSetPermissionCommand());
userCommand.registerSubCommand(new UserSetPrimaryGroupCommand());
userCommand.registerSubCommand(new UserShowPosCommand());
userCommand.registerSubCommand(new UserShowTracksCommand());
userCommand.registerSubCommand(new UserUnSetPermissionCommand());
GroupMainCommand groupCommand = new GroupMainCommand();
@@ -43,15 +58,28 @@ public class CommandManager {
groupCommand.registerSubCommand(new GroupClearCommand());
groupCommand.registerSubCommand(new GroupHasPermCommand());
groupCommand.registerSubCommand(new GroupInfoCommand());
groupCommand.registerSubCommand(new GroupInheritsPermCommand());
groupCommand.registerSubCommand(new GroupListNodesCommand());
groupCommand.registerSubCommand(new GroupSetInheritCommand());
groupCommand.registerSubCommand(new GroupSetPermissionCommand());
groupCommand.registerSubCommand(new GroupShowTracksCommand());
groupCommand.registerSubCommand(new GroupUnsetInheritCommand());
groupCommand.registerSubCommand(new GroupUnSetPermissionCommand());
TrackMainCommand trackCommand = new TrackMainCommand();
this.registerMainCommand(trackCommand);
trackCommand.registerSubCommand(new TrackAppendCommand());
trackCommand.registerSubCommand(new TrackClearCommand());
trackCommand.registerSubCommand(new TrackInfoCommand());
trackCommand.registerSubCommand(new TrackInsertCommand());
trackCommand.registerSubCommand(new TrackRemoveCommand());
this.registerMainCommand(new CreateGroupCommand());
this.registerMainCommand(new DeleteGroupCommand());
this.registerMainCommand(new ListGroupsCommand());
this.registerMainCommand(new CreateTrackCommand());
this.registerMainCommand(new DeleteTrackCommand());
this.registerMainCommand(new ListTracksCommand());
this.registerMainCommand(new DebugCommand());
this.registerMainCommand(new InfoCommand());
this.registerMainCommand(new SyncCommand());
@@ -63,51 +91,75 @@ public class CommandManager {
* @param args the arguments provided
* @return if the command was successful (hint: it always is :> )
*/
public boolean onCommand(Sender sender, List<String> args) {
public boolean onCommand(Sender sender, String label, List<String> args) {
if (args.size() == 0) {
Util.sendPluginMessage(sender, "&6Running &bLuckPerms " + plugin.getVersion() + "&6.");
if (sender.hasPermission("luckperms.info")) {
for (MainCommand c : mainCommands) {
Util.sendPluginMessage(sender, "&e-> &d" + c.getUsage());
}
}
} else {
String c = args.get(0);
MainCommand main = null;
for (MainCommand mainCommand : mainCommands) {
if (mainCommand.getName().equalsIgnoreCase(c)) {
main = mainCommand;
break;
}
}
if (main == null) {
Util.sendPluginMessage(sender, "Command not recognised.");
return true;
}
if (main.getRequiredArgsLength() == 0) {
main.execute(plugin, sender, null);
return true;
}
if (args.size() == 1) {
main.sendUsage(sender);
return true;
}
main.execute(plugin, sender, new ArrayList<>(args.subList(1, args.size())));
sendCommandUsage(sender, label);
return true;
}
Optional<MainCommand> o = mainCommands.stream().filter(m -> m.getName().equalsIgnoreCase(args.get(0))).limit(1).findAny();
if (!o.isPresent()) {
sendCommandUsage(sender, label);
return true;
}
final MainCommand main = o.get();
if (!main.canUse(sender)) {
sendCommandUsage(sender, label);
return true;
}
if (main.getRequiredArgsLength() == 0) {
main.execute(plugin, sender, null, label);
return true;
}
if (args.size() == 1) {
main.sendUsage(sender, label);
return true;
}
main.execute(plugin, sender, new ArrayList<>(args.subList(1, args.size())), label);
return true;
}
public void registerMainCommand(MainCommand command) {
/**
* 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
*/
public List<String> onTabComplete(Sender sender, List<String> args) {
final List<MainCommand> mains = mainCommands.stream().filter(m -> m.canUse(sender)).collect(Collectors.toList());
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return mains.stream().map(MainCommand::getName).map(String::toLowerCase).collect(Collectors.toList());
}
return mains.stream().map(MainCommand::getName).map(String::toLowerCase).filter(s -> s.startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
}
Optional<MainCommand> o = mains.stream().filter(m -> m.getName().equalsIgnoreCase(args.get(0))).limit(1).findAny();
if (!o.isPresent()) {
return Collections.emptyList();
}
return o.get().onTabComplete(sender, args.subList(1, args.size()), plugin);
}
private void registerMainCommand(MainCommand command) {
plugin.getLogger().log(Level.INFO, "[CommandManager] Registered main command '" + command.getName() + "'");
mainCommands.add(command);
}
private void sendCommandUsage(Sender sender, String label) {
Message.INFO_BRIEF.send(sender, plugin.getVersion());
mainCommands.stream()
.filter(c -> c.canUse(sender))
.forEach(c -> Util.sendPluginMessage(sender, "&e-> &d" + String.format(c.getUsage(), label)));
}
}
@@ -1,42 +1,66 @@
package me.lucko.luckperms.commands;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Message;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Getter
@AllArgsConstructor
public abstract class MainCommand {
@Getter
private final String name;
@Getter
private final String usage;
@Getter
private final int requiredArgsLength;
public MainCommand(String name, String usage, int requiredArgsLength) {
this.name = name;
this.usage = usage;
this.requiredArgsLength = requiredArgsLength;
}
protected abstract void execute(LuckPermsPlugin plugin, Sender sender, List<String> args);
protected abstract void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label);
protected abstract List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin);
public abstract List<? extends SubCommand> getSubCommands();
protected void sendUsage(Sender sender) {
protected void sendUsage(Sender sender, String label) {
if (getSubCommands().isEmpty()) {
Util.sendPluginMessage(sender, "&e-> &d" + String.format(getUsage(), label));
return;
}
List<SubCommand> subs = getSubCommands().stream().filter(s -> s.isAuthorized(sender)).collect(Collectors.toList());
if (subs.size() > 0) {
Util.sendPluginMessage(sender, "&e" + getName() + " Sub Commands:");
for (SubCommand s : subs) {
s.sendUsage(sender);
s.sendUsage(sender, label);
}
} else {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
Message.COMMAND_NO_PERMISSION.send(sender);
}
}
protected boolean canUse(Sender sender) {
return getSubCommands().stream().filter(sc -> sc.isAuthorized(sender)).count() != 0;
}
protected List<String> onAbstractTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
final List<SubCommand> subs = getSubCommands().stream().filter(s -> s.isAuthorized(sender)).collect(Collectors.toList());
if (args.size() == 2) {
if (args.get(1).equalsIgnoreCase("")) {
return subs.stream().map(SubCommand::getName).map(String::toLowerCase).collect(Collectors.toList());
}
return subs.stream().map(SubCommand::getName).map(String::toLowerCase)
.filter(s -> s.toLowerCase().startsWith(args.get(1).toLowerCase())).collect(Collectors.toList());
}
Optional<SubCommand> o = subs.stream().filter(s -> s.getName().equalsIgnoreCase(args.get(1))).limit(1).findAny();
if (!o.isPresent()) {
return Collections.emptyList();
}
return o.get().onTabComplete(sender, args.subList(2, args.size()), plugin);
}
}
@@ -1,34 +1,62 @@
package me.lucko.luckperms.commands;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Permission;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@Getter
@AllArgsConstructor
public abstract class SubCommand {
@Getter
private final String name;
@Getter
private final String description;
@Getter
private final String usage;
private final Permission permission;
@Getter
private final String permission;
protected static List<String> getGroupTabComplete(List<String> args, LuckPermsPlugin plugin) {
return getTabComplete(new ArrayList<>(plugin.getGroupManager().getGroups().keySet()), args);
}
public SubCommand(String name, String description, String usage, String permission) {
this.name = name;
this.description = description;
this.usage = usage;
this.permission = permission;
protected static List<String> getTrackTabComplete(List<String> args, LuckPermsPlugin plugin) {
return getTabComplete(new ArrayList<>(plugin.getTrackManager().getTracks().keySet()), args);
}
private static List<String> getTabComplete(List<String> options, List<String> args) {
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return options;
}
return options.stream().filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
}
return Collections.emptyList();
}
protected static List<String> getBoolTabComplete(List<String> args) {
if (args.size() == 2) {
return Arrays.asList("true", "false");
} else {
return Collections.emptyList();
}
}
public boolean isAuthorized(Sender sender) {
return sender.hasPermission(permission);
return permission.isAuthorized(sender);
}
public void sendUsage(Sender sender) {
Util.sendPluginMessage(sender, "&e-> &d" + getUsage());
public void sendUsage(Sender sender, String label) {
Util.sendPluginMessage(sender, "&e-> &d" + String.format(getUsage(), label));
}
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
public abstract boolean isArgLengthInvalid(int argLength);
@@ -1,14 +1,17 @@
package me.lucko.luckperms.commands;
import me.lucko.luckperms.constants.Message;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class Util {
private Util() {}
public static void sendPluginMessage(Sender sender, String message) {
// TODO: Pull the prefix from the config somehow
sender.sendMessage(color("&7&l[&b&lL&a&lP&7&l] &c" + message));
sender.sendMessage(color(Message.PREFIX + message));
}
public static String color(String s) {
@@ -19,8 +22,8 @@ public class Util {
// Stolen from Bukkit :>
char[] b = textToTranslate.toCharArray();
for(int i = 0; i < b.length - 1; ++i) {
if(b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) {
for (int i = 0; i < b.length - 1; ++i) {
if (b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) {
b[i] = 167;
b[i + 1] = Character.toLowerCase(b[i + 1]);
}
@@ -41,24 +44,58 @@ public class Util {
if (strings.isEmpty()) return "&6None";
StringBuilder sb = new StringBuilder();
for (String s : strings) {
sb.append("&6").append(s).append("&7, ");
}
strings.forEach(s -> sb.append("&6").append(s).append("&7, "));
return sb.delete(sb.length() - 2, sb.length()).toString();
}
public static String listToArrowSep(List<String> strings, String highlight) {
if (strings.isEmpty()) return "&6None";
StringBuilder sb = new StringBuilder();
for (String s : strings) {
if (s.equalsIgnoreCase(highlight)) {
sb.append("&e").append(s).append("&7 ---> ");
} else {
sb.append("&6").append(s).append("&7 ---> ");
}
}
return sb.delete(sb.length() - 6, sb.length()).toString();
}
public static String listToArrowSep(List<String> strings, String highlightFirst, String highlightSecond, boolean reversed) {
if (strings.isEmpty()) return "&6None";
StringBuilder sb = new StringBuilder();
for (String s : strings) {
if (s.equalsIgnoreCase(highlightFirst)) {
sb.append("&e").append(s).append("&4").append(reversed ? " <--- " : " ---> ");
} else if (s.equalsIgnoreCase(highlightSecond)) {
sb.append("&e").append(s).append("&7").append(reversed ? " <--- " : " ---> ");
} else {
sb.append("&6").append(s).append("&7").append(reversed ? " <--- " : " ---> ");
}
}
return sb.delete(sb.length() - 6, sb.length()).toString();
}
public static String listToArrowSep(List<String> strings) {
if (strings.isEmpty()) return "&6None";
StringBuilder sb = new StringBuilder();
strings.forEach(s -> sb.append("&6").append(s).append("&e ---> "));
return sb.delete(sb.length() - 6, sb.length()).toString();
}
public static String nodesToString(Map<String, Boolean> nodes) {
if (nodes.isEmpty()) return "&6None";
StringBuilder sb = new StringBuilder();
for (String node : nodes.keySet()) {
if (nodes.get(node)) {
sb.append("&a").append(node).append("&7, ");
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
if (e.getValue()) {
sb.append("&a").append(e.getKey()).append("&7, ");
} else {
sb.append("&c").append(node).append("&7, ");
sb.append("&c").append(e.getKey()).append("&7, ");
}
}
@@ -4,39 +4,46 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.utils.Patterns;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CreateGroupCommand extends MainCommand {
public CreateGroupCommand() {
super("CreateGroup", "/perms creategroup <group>", 1);
super("CreateGroup", "/%s creategroup <group>", 1);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.creategroup")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (args.size() == 0) {
sendUsage(sender);
sendUsage(sender, label);
return;
}
String groupName = args.get(0).toLowerCase();
if (groupName.length() > 36) {
Message.GROUP_NAME_TOO_LONG.send(sender, groupName);
return;
}
if (Patterns.NON_ALPHA_NUMERIC.matcher(groupName).find()) {
Message.GROUP_INVALID_ENTRY.send(sender);
return;
}
plugin.getDatastore().loadGroup(groupName, success -> {
if (success) {
Util.sendPluginMessage(sender, "That group already exists!");
Message.GROUP_ALREADY_EXISTS.send(sender);
} else {
plugin.getDatastore().createAndLoadGroup(groupName, success1 -> {
if (!success1) {
Util.sendPluginMessage(sender, "There was an error whilst creating the group.");
Message.CREATE_GROUP_ERROR.send(sender);
} else {
Util.sendPluginMessage(sender, "&b" + groupName + "&a was successfully created.");
Message.CREATE_SUCCESS.send(sender, groupName);
plugin.runUpdateTask();
}
});
@@ -44,8 +51,18 @@ public class CreateGroupCommand extends MainCommand {
});
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
@Override
public List<SubCommand> getSubCommands() {
return new ArrayList<>();
return Collections.emptyList();
}
@Override
protected boolean canUse(Sender sender) {
return Permission.CREATE_GROUP.isAuthorized(sender);
}
}
@@ -4,50 +4,48 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class DeleteGroupCommand extends MainCommand {
public DeleteGroupCommand() {
super("DeleteGroup", "/perms deletegroup <group>", 1);
super("DeleteGroup", "/%s deletegroup <group>", 1);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.deletegroup")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (args.size() == 0) {
sendUsage(sender);
sendUsage(sender, label);
return;
}
String groupName = args.get(0).toLowerCase();
if (groupName.equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
Util.sendPluginMessage(sender, "You cannot delete the default group.");
Message.DELETE_GROUP_ERROR_DEFAULT.send(sender);
return;
}
plugin.getDatastore().loadGroup(groupName, success -> {
if (!success) {
Util.sendPluginMessage(sender, "That group does not exist!");
Message.GROUP_DOES_NOT_EXIST.send(sender);
} else {
Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) {
Util.sendPluginMessage(sender, "An unexpected error occurred.");
Message.GROUP_LOAD_ERROR.send(sender);
} else {
plugin.getDatastore().deleteGroup(group, success1 -> {
if (!success1) {
Util.sendPluginMessage(sender, "There was an error whilst creating the group.");
Message.DELETE_GROUP_ERROR.send(sender);
} else {
Util.sendPluginMessage(sender, "&b" + groupName + "&a was successfully deleted.");
Message.DELETE_SUCCESS.send(sender, groupName);
plugin.runUpdateTask();
}
});
@@ -56,8 +54,28 @@ public class DeleteGroupCommand extends MainCommand {
});
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
final List<String> groups = new ArrayList<>(plugin.getGroupManager().getGroups().keySet());
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return groups;
}
return groups.stream().filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
}
return Collections.emptyList();
}
@Override
public List<SubCommand> getSubCommands() {
return new ArrayList<>();
return Collections.emptyList();
}
@Override
protected boolean canUse(Sender sender) {
return Permission.DELETE_GROUP.isAuthorized(sender);
}
}
@@ -4,11 +4,12 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.groups.Group;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class GroupMainCommand extends MainCommand {
@@ -16,13 +17,26 @@ public class GroupMainCommand extends MainCommand {
private final List<GroupSubCommand> subCommands = new ArrayList<>();
public GroupMainCommand() {
super("Group", "/perms group <group>", 2);
super("Group", "/%s group <group>", 2);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (args.size() <= 1) {
sendUsage(sender);
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (args.size() < 2) {
sendUsage(sender, label);
return;
}
Optional<GroupSubCommand> o = subCommands.stream().filter(s -> s.getName().equalsIgnoreCase(args.get(1))).limit(1).findAny();
if (!o.isPresent()) {
Message.COMMAND_NOT_RECOGNISED.send(sender);
return;
}
final GroupSubCommand sub = o.get();
if (!sub.isAuthorized(sender)) {
Message.COMMAND_NO_PERMISSION.send(sender);
return;
}
@@ -31,52 +45,43 @@ public class GroupMainCommand extends MainCommand {
strippedArgs.addAll(args.subList(2, args.size()));
}
String c = args.get(1);
GroupSubCommand tempSub = null;
for (GroupSubCommand s : subCommands) {
if (s.getName().equalsIgnoreCase(c)) {
tempSub = s;
break;
}
}
final GroupSubCommand sub = tempSub;
if (sub == null) {
Util.sendPluginMessage(sender, "Command not recognised.");
if (sub.isArgLengthInvalid(strippedArgs.size())) {
sub.sendUsage(sender, label);
return;
}
if (!sub.isAuthorized(sender)) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
String g = args.get(0).toLowerCase();
plugin.getDatastore().loadGroup(g, success -> {
final String groupName = args.get(0).toLowerCase();
plugin.getDatastore().loadGroup(groupName, success -> {
if (!success) {
Util.sendPluginMessage(sender, "&eGroup could not be found.");
Message.GROUP_NOT_FOUND.send(sender);
return;
}
Group group = plugin.getGroupManager().getGroup(g);
Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) {
Util.sendPluginMessage(sender, "&eGroup could not be found.");
Message.GROUP_NOT_FOUND.send(sender);
return;
}
if (sub.isArgLengthInvalid(strippedArgs.size())) {
sub.sendUsage(sender);
return;
}
sub.execute(plugin, sender, group, strippedArgs);
sub.execute(plugin, sender, group, strippedArgs, label);
});
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
final List<String> groups = new ArrayList<>(plugin.getGroupManager().getGroups().keySet());
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return groups;
}
return groups.stream().filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
}
return onAbstractTabComplete(sender, args, plugin);
}
@Override
public List<? extends SubCommand> getSubCommands() {
return subCommands;
@@ -86,18 +91,4 @@ public class GroupMainCommand extends MainCommand {
subCommands.add(subCommand);
}
@Override
protected void sendUsage(Sender sender) {
List<SubCommand> subs = getSubCommands().stream().filter(s -> s.isAuthorized(sender)).collect(Collectors.toList());
if (subs.size() > 0) {
Util.sendPluginMessage(sender, "&e" + getName() + " Sub Commands:");
for (SubCommand s : subs) {
s.sendUsage(sender);
}
} else {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
}
}
}
@@ -3,24 +3,25 @@ package me.lucko.luckperms.commands.group;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public abstract class GroupSubCommand extends SubCommand {
public GroupSubCommand(String name, String description, String usage, String permission) {
protected GroupSubCommand(String name, String description, String usage, Permission permission) {
super(name, description, usage, permission);
}
protected abstract void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args);
protected abstract void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label);
protected void saveGroup(Group group, Sender sender, LuckPermsPlugin plugin) {
plugin.getDatastore().saveGroup(group, success -> {
if (success) {
Util.sendPluginMessage(sender, "&7(Group data was saved to the datastore)");
Message.GROUP_SAVE_SUCCESS.send(sender);
} else {
Util.sendPluginMessage(sender, "There was an error whilst saving the group.");
Message.GROUP_SAVE_ERROR.send(sender);
}
plugin.runUpdateTask();
@@ -5,33 +5,41 @@ import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ListGroupsCommand extends MainCommand {
public ListGroupsCommand() {
super("ListGroups", "/perms listgroups", 0);
super("ListGroups", "/%s listgroups", 0);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.listgroups")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
plugin.getDatastore().loadAllGroups(success -> {
if (!success) {
Util.sendPluginMessage(sender, "Unable to load all groups.");
Message.GROUPS_LOAD_ERROR.send(sender);
} else {
Util.sendPluginMessage(sender, "&aGroups: " + Util.listToCommaSep(new ArrayList<>(plugin.getGroupManager().getGroups().keySet())));
Message.GROUPS_LIST.send(sender, Util.listToCommaSep(new ArrayList<>(plugin.getGroupManager().getGroups().keySet())));
}
});
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
@Override
public List<SubCommand> getSubCommands() {
return null;
return Collections.emptyList();
}
@Override
protected boolean canUse(Sender sender) {
return Permission.LIST_GROUPS.isAuthorized(sender);
}
}
@@ -2,28 +2,28 @@ package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupClearCommand extends GroupSubCommand {
public GroupClearCommand() {
super("clear", "Clears a groups permissions",
"/perms group <group> clear", "luckperms.group.clear");
super("clear", "Clears a groups permissions", "/%s group <group> clear", Permission.GROUP_CLEAR);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
group.clearNodes();
Util.sendPluginMessage(sender, "&b" + group.getName() + "&a's permissions were cleared.");
Message.CLEAR_SUCCESS.send(sender, group.getName());
saveGroup(group, sender, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return true;
return false;
}
}
@@ -4,6 +4,7 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import java.util.List;
@@ -11,13 +12,13 @@ import java.util.List;
public class GroupHasPermCommand extends GroupSubCommand {
public GroupHasPermCommand() {
super("haspermission", "Checks to see if a group has a certain permission node",
"/perms group <group> haspermission <node> [server]", "luckperms.group.haspermission");
"/%s group <group> haspermission <node> [server]", Permission.GROUP_HASPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
if (args.size() >= 2) {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1)));
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
if (args.size() == 2) {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1).toLowerCase()));
} else {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, "global"));
}
@@ -25,6 +26,6 @@ public class GroupHasPermCommand extends GroupSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
return argLength != 1 && argLength != 2;
}
}
@@ -2,26 +2,21 @@ package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupInfoCommand extends GroupSubCommand {
public GroupInfoCommand() {
super("info", "Gives info about the group",
"/perms group <group> info", "luckperms.group.info");
super("info", "Gives info about the group", "/%s group <group> info", Permission.GROUP_INFO);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
final String prefix = plugin.getConfiguration().getPrefix();
String sb = prefix + "&d-> &eGroup: &6" + group.getName() + "\n" +
prefix + "&d-> &ePermissions: &6" + group.getNodes().keySet().size() + "\n" +
prefix + "&d-> &bUse &a/perms group " + group.getName() + " listnodes &bto see all permissions.";
sender.sendMessage(Util.color(sb));
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
Message.GROUP_INFO.send(sender, group.getName(), group.getNodes().keySet().size(), label, group.getName());
}
@Override
@@ -0,0 +1,31 @@
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupInheritsPermCommand extends GroupSubCommand {
public GroupInheritsPermCommand() {
super("inheritspermission", "Checks to see if a group inherits a certain permission node",
"/%s group <group> inheritspermission <node> [server]", Permission.GROUP_INHERITSPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
if (args.size() == 2) {
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1).toLowerCase()));
} else {
Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true));
}
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
}
}
@@ -4,20 +4,21 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupListNodesCommand extends GroupSubCommand {
public GroupListNodesCommand() {
super("listnodes", "Lists the permission nodes the group has",
"/perms group <group> listnodes", "luckperms.group.listnodes");
super("listnodes", "Lists the permission nodes the group has", "/%s group <group> listnodes",
Permission.GROUP_LISTNODES);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
Util.sendPluginMessage(sender, "&e" + group.getName() + "'s Nodes:");
sender.sendMessage(Util.color(Util.nodesToString(group.getNodes())));
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
Message.LISTNODES.send(sender, group.getName(), Util.nodesToString(group.getNodes()));
}
@Override
@@ -2,8 +2,9 @@ package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
@@ -12,39 +13,42 @@ import java.util.List;
public class GroupSetInheritCommand extends GroupSubCommand {
public GroupSetInheritCommand() {
super("setinherit", "Sets another group for this group to inherit permissions from",
"/perms group <group> setinherit <group> [server]", "luckperms.group.setinherit");
"/%s group <group> setinherit <group> [server]", Permission.GROUP_SETINHERIT);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
String groupName = args.get(0).toLowerCase();
plugin.getDatastore().loadGroup(groupName, success -> {
if (!success) {
Util.sendPluginMessage(sender, groupName + " does not exist!");
Message.GROUP_LOAD_ERROR.send(sender);
} else {
final String node = "luckperms.group." + groupName;
try {
if (args.size() == 2) {
final String server = args.get(1).toLowerCase();
group.setPermission(node, true, server);
Util.sendPluginMessage(sender, "&b" + group.getName() + "&a now inherits permissions from &b" + groupName + "&a on server &b" + server + "&a.");
group.setPermission("group." + groupName, true, server);
Message.GROUP_SETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
} else {
group.setPermission(node, true);
Util.sendPluginMessage(sender, "&b" + group.getName() + "&a now inherits permissions from &b" + groupName + "&a.");
group.setPermission("group." + groupName, true);
Message.GROUP_SETINHERIT_SUCCESS.send(sender, group.getName(), groupName);
}
saveGroup(group, sender, plugin);
} catch (ObjectAlreadyHasException e) {
Util.sendPluginMessage(sender, group.getName() + " already inherits '" + groupName + "'.");
Message.GROUP_ALREADY_INHERITS.send(sender, group.getName(), groupName);
}
}
});
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getGroupTabComplete(args, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
return argLength != 1 && argLength != 2;
}
}
@@ -2,36 +2,38 @@ package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class GroupSetPermissionCommand extends GroupSubCommand {
public GroupSetPermissionCommand() {
super("set", "Sets a permission for a group",
"/perms group <group> set <node> <true|false> [server]", "luckperms.group.setpermission");
super("set", "Sets a permission for a group", "/%s group <group> set <node> <true|false> [server]",
Permission.GROUP_SETPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
String node = args.get(0);
String bool = args.get(1);
String bool = args.get(1).toLowerCase();
if (node.contains("/")) {
sendUsage(sender);
sendUsage(sender, label);
return;
}
if (node.matches(".*luckperms\\.group\\..*")) {
Util.sendPluginMessage(sender, "Use the inherit command instead of specifying the node.");
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
Message.GROUP_USE_INHERIT.send(sender);
return;
}
if (!bool.equalsIgnoreCase("true") && !bool.equalsIgnoreCase("false")) {
sendUsage(sender);
sendUsage(sender, label);
return;
}
@@ -41,20 +43,25 @@ public class GroupSetPermissionCommand extends GroupSubCommand {
if (args.size() == 3) {
final String server = args.get(2).toLowerCase();
group.setPermission(node, b, server);
Util.sendPluginMessage(sender, "&aSet &b" + node + "&a to &b" + bool + "&a for &b" + group.getName() + "&a on server &b" + server + "&a.");
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server);
} else {
group.setPermission(node, b);
Util.sendPluginMessage(sender, "&aSet &b" + node + "&a to " + bool + " for &b" + group.getName() + "&a.");
Message.SETPERMISSION_SUCCESS.send(sender, node, bool, group.getName());
}
saveGroup(group, sender, plugin);
} catch (ObjectAlreadyHasException e) {
Util.sendPluginMessage(sender, group.getName() + " already has this permission!");
Message.ALREADY_HASPERMISSION.send(sender, group.getName());
}
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getBoolTabComplete(args);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength < 2;
return argLength != 2 && argLength != 3;
}
}
@@ -0,0 +1,37 @@
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import java.util.List;
import java.util.stream.Collectors;
public class GroupShowTracksCommand extends GroupSubCommand {
public GroupShowTracksCommand() {
super("showtracks", "Lists the tracks that this group features on", "/%s group <group> showtracks", Permission.GROUP_SHOWTRACKS);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
plugin.getDatastore().loadAllTracks(success -> {
if (!success) {
Message.TRACKS_LOAD_ERROR.send(sender);
return;
}
Message.TRACKS_LIST.send(sender, Util.listToCommaSep(
plugin.getTrackManager().getApplicableTracks(group.getName()).stream().map(Track::getName).collect(Collectors.toList())));
});
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return false;
}
}
@@ -2,30 +2,32 @@ package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class GroupUnSetPermissionCommand extends GroupSubCommand {
public GroupUnSetPermissionCommand() {
super("unset", "Unsets a permission for a group",
"/perms group <group> unset <node> [server]", "luckperms.group.unsetpermission");
"/%s group <group> unset <node> [server]", Permission.GROUP_UNSETPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
String node = args.get(0);
if (node.contains("/")) {
sendUsage(sender);
sendUsage(sender, label);
return;
}
if (node.matches(".*luckperms\\.group\\..*")) {
Util.sendPluginMessage(sender, "Use the uninherit command instead of specifying the node.");
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
Message.GROUP_USE_UNINHERIT.send(sender);
return;
}
@@ -33,20 +35,20 @@ public class GroupUnSetPermissionCommand extends GroupSubCommand {
if (args.size() == 2) {
final String server = args.get(1).toLowerCase();
group.unsetPermission(node, server);
Util.sendPluginMessage(sender, "&aUnset &b" + node + "&a for &b" + group.getName() + "&a on server &b" + server + "&a.");
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server);
} else {
group.unsetPermission(node);
Util.sendPluginMessage(sender, "&aUnset &b" + node + "&a for &b" + group.getName() + "&a.");
Message.UNSETPERMISSION_SUCCESS.send(sender, node, group.getName());
}
saveGroup(group, sender, plugin);
} catch (ObjectLacksPermissionException e) {
Util.sendPluginMessage(sender, "That group does not have this permission set.");
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVEPERMISSION.send(sender, group.getName());
}
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
return argLength != 1 && argLength != 2;
}
}
@@ -2,9 +2,10 @@ package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import java.util.List;
@@ -12,31 +13,36 @@ import java.util.List;
public class GroupUnsetInheritCommand extends GroupSubCommand {
public GroupUnsetInheritCommand() {
super("unsetinherit", "Unsets another group for this group to inherit permissions from",
"/perms group <group> unsetinherit <group> [server]", "luckperms.group.unsetinherit");
"/%s group <group> unsetinherit <group> [server]", Permission.GROUP_UNSETINHERIT);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
String groupName = args.get(0).toLowerCase();
String server;
if (args.size() == 2) {
server = args.get(1).toLowerCase();
} else {
server = "global";
}
try {
group.unsetPermission("luckperms.group." + groupName, server);
Util.sendPluginMessage(sender, "&b" + group.getName() + "&a no longer inherits permissions from &b" + groupName + "&a on server &b" + server + "&a.");
if (args.size() == 2) {
final String server = args.get(1).toLowerCase();
group.unsetPermission("group." + groupName, server);
Message.GROUP_UNSETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
} else {
group.unsetPermission("group." + groupName);
Message.GROUP_UNSETINHERIT_SUCCESS.send(sender, group.getName(), groupName);
}
saveGroup(group, sender, plugin);
} catch (ObjectLacksPermissionException e) {
Util.sendPluginMessage(sender, "That group does not inherit '" + groupName + "'.");
} catch (ObjectLacksException e) {
Message.GROUP_DOES_NOT_INHERIT.send(sender, group.getName(), groupName);
}
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getGroupTabComplete(args, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
return argLength != 1 && argLength != 2;
}
}
@@ -4,31 +4,36 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class DebugCommand extends MainCommand {
public DebugCommand() {
super("Debug", "/perms debug", 0);
super("Debug", "/%s debug", 0);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.debug")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
Message.DEBUG.send(sender, plugin.getPlayerCount(), plugin.getUserManager().getUsers().size(),
plugin.getGroupManager().getGroups().size(), plugin.getTrackManager().getTracks().size()
);
}
Util.sendPluginMessage(sender, "&d>> Debug Info");
Util.sendPluginMessage(sender, "&eOnline Players: &6" + plugin.getPlayerCount());
Util.sendPluginMessage(sender, "&eLoaded Users: &6" + plugin.getUserManager().getUsers().size());
Util.sendPluginMessage(sender, "&eLoaded Groups: &6" + plugin.getGroupManager().getGroups().size());
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
@Override
public List<? extends SubCommand> getSubCommands() {
return new ArrayList<>();
return Collections.emptyList();
}
@Override
protected boolean canUse(Sender sender) {
return Permission.DEBUG.isAuthorized(sender);
}
}
@@ -4,30 +4,34 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class InfoCommand extends MainCommand {
public InfoCommand() {
super("Info", "/perms info", 0);
super("Info", "/%s info", 0);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.info")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
Message.INFO.send(sender, plugin.getVersion(), plugin.getDatastore().getName());
}
Util.sendPluginMessage(sender, "&6Running &bLuckPerms " + plugin.getVersion() + "&6.");
Util.sendPluginMessage(sender, "&eAuthor: &6Luck");
Util.sendPluginMessage(sender, "&eStorage Method: &6" + plugin.getDatastore().getName());
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
@Override
public List<? extends SubCommand> getSubCommands() {
return new ArrayList<>();
return Collections.emptyList();
}
@Override
protected boolean canUse(Sender sender) {
return Permission.INFO.isAuthorized(sender);
}
}
@@ -4,29 +4,35 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SyncCommand extends MainCommand {
public SyncCommand() {
super("Sync", "/perms sync", 0);
super("Sync", "/%s sync", 0);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.sync")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
Util.sendPluginMessage(sender, "&bRunning update task for all online users.");
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
Message.UPDATE_TASK_RUN.send(sender);
plugin.runUpdateTask();
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
@Override
public List<? extends SubCommand> getSubCommands() {
return new ArrayList<>();
return Collections.emptyList();
}
@Override
protected boolean canUse(Sender sender) {
return Permission.SYNC.isAuthorized(sender);
}
}
@@ -0,0 +1,68 @@
package me.lucko.luckperms.commands.track;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.utils.Patterns;
import java.util.Collections;
import java.util.List;
public class CreateTrackCommand extends MainCommand {
public CreateTrackCommand() {
super("CreateTrack", "/%s createtrack <track>", 1);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (args.size() == 0) {
sendUsage(sender, label);
return;
}
String trackName = args.get(0).toLowerCase();
if (trackName.length() > 36) {
Message.TRACK_NAME_TOO_LONG.send(sender, trackName);
return;
}
if (Patterns.NON_ALPHA_NUMERIC.matcher(trackName).find()) {
Message.TRACK_INVALID_ENTRY.send(sender);
return;
}
plugin.getDatastore().loadTrack(trackName, success -> {
if (success) {
Message.TRACK_ALREADY_EXISTS.send(sender);
} else {
plugin.getDatastore().createAndLoadTrack(trackName, success1 -> {
if (!success1) {
Message.CREATE_TRACK_ERROR.send(sender);
} else {
Message.CREATE_SUCCESS.send(sender, trackName);
plugin.runUpdateTask();
}
});
}
});
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
@Override
public List<? extends SubCommand> getSubCommands() {
return Collections.emptyList();
}
@Override
protected boolean canUse(Sender sender) {
return Permission.CREATE_TRACK.isAuthorized(sender);
}
}
@@ -0,0 +1,76 @@
package me.lucko.luckperms.commands.track;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.tracks.Track;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class DeleteTrackCommand extends MainCommand {
public DeleteTrackCommand() {
super("DeleteTrack", "/%s deletetrack <track>", 1);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (args.size() == 0) {
sendUsage(sender, label);
return;
}
String trackName = args.get(0).toLowerCase();
plugin.getDatastore().loadTrack(trackName, success -> {
if (!success) {
Message.TRACK_DOES_NOT_EXIST.send(sender);
} else {
Track track = plugin.getTrackManager().getTrack(trackName);
if (track == null) {
Message.TRACK_LOAD_ERROR.send(sender);
} else {
plugin.getDatastore().deleteTrack(track, success1 -> {
if (!success1) {
Message.DELETE_TRACK_ERROR.send(sender);
} else {
Message.DELETE_SUCCESS.send(sender, trackName);
plugin.runUpdateTask();
}
});
}
}
});
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
final List<String> tracks = new ArrayList<>(plugin.getTrackManager().getTracks().keySet());
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return tracks;
}
return tracks.stream().filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
}
return Collections.emptyList();
}
@Override
public List<SubCommand> getSubCommands() {
return Collections.emptyList();
}
@Override
protected boolean canUse(Sender sender) {
return Permission.DELETE_TRACK.isAuthorized(sender);
}
}
@@ -0,0 +1,45 @@
package me.lucko.luckperms.commands.track;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ListTracksCommand extends MainCommand {
public ListTracksCommand() {
super("ListTracks", "/%s listtracks", 0);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
plugin.getDatastore().loadAllTracks(success -> {
if (!success) {
Message.TRACKS_LOAD_ERROR.send(sender);
} else {
Message.TRACKS_LIST.send(sender, Util.listToCommaSep(new ArrayList<>(plugin.getTrackManager().getTracks().keySet())));
}
});
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return Collections.emptyList();
}
@Override
public List<SubCommand> getSubCommands() {
return Collections.emptyList();
}
@Override
protected boolean canUse(Sender sender) {
return Permission.LIST_TRACKS.isAuthorized(sender);
}
}
@@ -0,0 +1,94 @@
package me.lucko.luckperms.commands.track;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.tracks.Track;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class TrackMainCommand extends MainCommand {
private final List<TrackSubCommand> subCommands = new ArrayList<>();
public TrackMainCommand() {
super("Track", "/%s track <track>", 2);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (args.size() < 2) {
sendUsage(sender, label);
return;
}
Optional<TrackSubCommand> o = subCommands.stream().filter(s -> s.getName().equalsIgnoreCase(args.get(1))).limit(1).findAny();
if (!o.isPresent()) {
Message.COMMAND_NOT_RECOGNISED.send(sender);
return;
}
final TrackSubCommand sub = o.get();
if (!sub.isAuthorized(sender)) {
Message.COMMAND_NO_PERMISSION.send(sender);
return;
}
List<String> strippedArgs = new ArrayList<>();
if (args.size() > 2) {
strippedArgs.addAll(args.subList(2, args.size()));
}
if (sub.isArgLengthInvalid(strippedArgs.size())) {
sub.sendUsage(sender, label);
return;
}
final String trackName = args.get(0).toLowerCase();
plugin.getDatastore().loadTrack(trackName, success -> {
if (!success) {
Message.TRACK_NOT_FOUND.send(sender);
return;
}
Track track = plugin.getTrackManager().getTrack(trackName);
if (track == null) {
Message.TRACK_NOT_FOUND.send(sender);
return;
}
sub.execute(plugin, sender, track, strippedArgs, label);
});
}
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
final List<String> tracks = new ArrayList<>(plugin.getTrackManager().getTracks().keySet());
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return tracks;
}
return tracks.stream().filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
}
return onAbstractTabComplete(sender, args, plugin);
}
@Override
public List<? extends SubCommand> getSubCommands() {
return subCommands;
}
public void registerSubCommand(TrackSubCommand subCommand) {
subCommands.add(subCommand);
}
}
@@ -0,0 +1,30 @@
package me.lucko.luckperms.commands.track;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.tracks.Track;
import java.util.List;
public abstract class TrackSubCommand extends SubCommand {
public TrackSubCommand(String name, String description, String usage, Permission permission) {
super(name, description, usage, permission);
}
protected abstract void execute(LuckPermsPlugin plugin, Sender sender, Track track, List<String> args, String label);
protected void saveTrack(Track track, Sender sender, LuckPermsPlugin plugin) {
plugin.getDatastore().saveTrack(track, success -> {
if (success) {
Message.TRACK_SAVE_SUCCESS.send(sender);
} else {
Message.TRACK_SAVE_ERROR.send(sender);
}
plugin.runUpdateTask();
});
}
}
@@ -0,0 +1,55 @@
package me.lucko.luckperms.commands.track.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.track.TrackSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import java.util.List;
public class TrackAppendCommand extends TrackSubCommand {
public TrackAppendCommand() {
super("append", "Appends a group onto the end of the track", "/%s track <track> append <group>", Permission.TRACK_APPEND);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Track track, List<String> args, String label) {
String groupName = args.get(0).toLowerCase();
plugin.getDatastore().loadGroup(groupName, success -> {
if (!success) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
} else {
Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
return;
}
try {
track.appendGroup(group);
Message.TRACK_APPEND_SUCCESS.send(sender, group.getName(), track.getName());
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), group.getName()));
saveTrack(track, sender, plugin);
} catch (ObjectAlreadyHasException e) {
Message.TRACK_ALREADY_CONTAINS.send(sender, track.getName(), group.getName());
}
}
});
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getGroupTabComplete(args, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1;
}
}
@@ -0,0 +1,28 @@
package me.lucko.luckperms.commands.track.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.track.TrackSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.tracks.Track;
import java.util.List;
public class TrackClearCommand extends TrackSubCommand {
public TrackClearCommand() {
super("clear", "Clears the groups on the track", "/%s track <track> clear", Permission.TRACK_CLEAR);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Track track, List<String> args, String label) {
track.clearGroups();
Message.TRACK_CLEAR.send(sender, track.getName());
saveTrack(track, sender, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return false;
}
}
@@ -0,0 +1,27 @@
package me.lucko.luckperms.commands.track.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.track.TrackSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.tracks.Track;
import java.util.List;
public class TrackInfoCommand extends TrackSubCommand {
public TrackInfoCommand() {
super("info", "Gives info about the track", "/%s track <track> info", Permission.TRACK_INFO);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Track track, List<String> args, String label) {
Message.TRACK_INFO.send(sender, track.getName(), Util.listToArrowSep(track.getGroups()));
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return false;
}
}
@@ -0,0 +1,65 @@
package me.lucko.luckperms.commands.track.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.track.TrackSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import java.util.List;
public class TrackInsertCommand extends TrackSubCommand {
public TrackInsertCommand() {
super("insert", "Inserts a group at a given position along the track",
"/%s track <track> insert <group> <position>", Permission.TRACK_INSERT);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Track track, List<String> args, String label) {
String groupName = args.get(0).toLowerCase();
int pos;
try {
pos = Integer.parseInt(args.get(1));
} catch (NumberFormatException e) {
Message.TRACK_INSERT_ERROR_NUMBER.send(sender, args.get(1));
return;
}
plugin.getDatastore().loadGroup(groupName, success -> {
if (!success) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
} else {
Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
return;
}
try {
track.insertGroup(group, pos - 1);
Message.TRACK_INSERT_SUCCESS.send(sender, group.getName(), track.getName(), pos);
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), group.getName()));
saveTrack(track, sender, plugin);
} catch (ObjectAlreadyHasException e) {
Message.TRACK_ALREADY_CONTAINS.send(sender, track.getName(), group.getName());
} catch (IndexOutOfBoundsException e) {
Message.TRACK_INSERT_ERROR_INVALID_POS.send(sender, pos);
}
}
});
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getGroupTabComplete(args, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 2;
}
}
@@ -0,0 +1,39 @@
package me.lucko.luckperms.commands.track.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.track.TrackSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.tracks.Track;
import java.util.List;
public class TrackRemoveCommand extends TrackSubCommand {
public TrackRemoveCommand() {
super("remove", "Removes a group from the track", "/%s track <track> remove <group>", Permission.TRACK_REMOVE);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Track track, List<String> args, String label) {
String groupName = args.get(0).toLowerCase();
try {
track.removeGroup(groupName);
Message.TRACK_REMOVE_SUCCESS.send(sender, groupName, track.getName());
saveTrack(track, sender, plugin);
} catch (ObjectLacksException e) {
Message.TRACK_DOES_NOT_CONTAIN.send(sender, track.getName(), groupName);
}
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getGroupTabComplete(args, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1;
}
}
@@ -5,49 +5,40 @@ import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.users.User;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
public class UserMainCommand extends MainCommand{
public class UserMainCommand extends MainCommand {
private final List<UserSubCommand> subCommands = new ArrayList<>();
public UserMainCommand() {
super("User", "/perms user <user>", 2);
super("User", "/%s user <user>", 2);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (args.size() <= 1) {
sendUsage(sender);
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (args.size() < 2) {
sendUsage(sender, label);
return;
}
// The first argument is the name of the user, the second is the command
String command = args.get(1);
UserSubCommand tempSub = null;
Optional<UserSubCommand> o = subCommands.stream().filter(s -> s.getName().equalsIgnoreCase(args.get(1))).limit(1).findAny();
// Try to identify the command used
for (UserSubCommand s : subCommands) {
if (s.getName().equalsIgnoreCase(command)) {
tempSub = s;
break;
}
}
// The command the sender used
final UserSubCommand sub = tempSub;
if (sub == null) {
Util.sendPluginMessage(sender, "Command not recognised.");
if (!o.isPresent()) {
Message.COMMAND_NOT_RECOGNISED.send(sender);
return;
}
final UserSubCommand sub = o.get();
if (!sub.isAuthorized(sender)) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
Message.COMMAND_NO_PERMISSION.send(sender);
return;
}
@@ -57,50 +48,63 @@ public class UserMainCommand extends MainCommand{
strippedArgs.addAll(args.subList(2, args.size()));
}
String user = args.get(0);
if (sub.isArgLengthInvalid(strippedArgs.size())) {
sub.sendUsage(sender, label);
return;
}
final String user = args.get(0);
UUID u = Util.parseUuid(user);
if (u != null) {
runSub(plugin, sender, u, sub, strippedArgs);
runSub(plugin, sender, u, sub, strippedArgs, label);
return;
}
if (user.length() <= 16) {
Util.sendPluginMessage(sender, "&7(Attempting UUID lookup, since you specified a user)");
Message.USER_ATTEMPTING_LOOKUP.send(sender);
plugin.getDatastore().getUUID(user, uuid -> {
if (uuid == null) {
Util.sendPluginMessage(sender, "&eUser could not be found.");
Message.USER_NOT_FOUND.send(sender);
return;
}
runSub(plugin, sender, uuid, sub, strippedArgs);
runSub(plugin, sender, uuid, sub, strippedArgs, label);
});
return;
}
Util.sendPluginMessage(sender, "&d" + user + "&c is not a valid username/uuid.");
Message.USER_INVALID_ENTRY.send(sender, user);
}
private void runSub(LuckPermsPlugin plugin, Sender sender, UUID uuid, UserSubCommand command, List<String> strippedArgs) {
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
final List<String> onlinePlayers = plugin.getPlayerList();
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return onlinePlayers;
}
return onlinePlayers.stream().filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
}
return onAbstractTabComplete(sender, args, plugin);
}
private void runSub(LuckPermsPlugin plugin, Sender sender, UUID uuid, UserSubCommand command, List<String> strippedArgs, String label) {
plugin.getDatastore().loadUser(uuid, success -> {
if (!success) {
Util.sendPluginMessage(sender, "&eUser could not be found.");
Message.USER_NOT_FOUND.send(sender);
return;
}
User user1 = plugin.getUserManager().getUser(uuid);
if (user1 == null) {
Util.sendPluginMessage(sender, "&eUser could not be found.");
User user = plugin.getUserManager().getUser(uuid);
if (user == null) {
Message.USER_NOT_FOUND.send(sender);
}
if (command.isArgLengthInvalid(strippedArgs.size())) {
command.sendUsage(sender);
return;
}
command.execute(plugin, sender, user1, strippedArgs);
plugin.getUserManager().cleanupUser(user1);
command.execute(plugin, sender, user, strippedArgs, label);
plugin.getUserManager().cleanupUser(user);
});
}
@@ -3,26 +3,27 @@ package me.lucko.luckperms.commands.user;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import java.util.List;
public abstract class UserSubCommand extends SubCommand {
public UserSubCommand(String name, String description, String usage, String permission) {
protected UserSubCommand(String name, String description, String usage, Permission permission) {
super(name, description, usage, permission);
}
protected abstract void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args);
protected abstract void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label);
protected void saveUser(User user, Sender sender, LuckPermsPlugin plugin) {
user.refreshPermissions();
plugin.getDatastore().saveUser(user, success -> {
if (success) {
Util.sendPluginMessage(sender, "&7(User data was saved to the datastore)");
Message.USER_SAVE_SUCCESS.send(sender);
} else {
Util.sendPluginMessage(sender, "There was an error whilst saving the user.");
Message.USER_SAVE_ERROR.send(sender);
}
});
}
@@ -2,8 +2,9 @@ package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
@@ -12,34 +13,44 @@ import java.util.List;
public class UserAddGroupCommand extends UserSubCommand {
public UserAddGroupCommand() {
super("addgroup", "Adds the user to a group",
"/perms user <user> addgroup <group> [server]", "luckperms.user.addgroup");
super("addgroup", "Adds the user to a group", "/%s user <user> addgroup <group> [server]", Permission.USER_ADDGROUP);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
String group = args.get(0).toLowerCase();
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
String groupName = args.get(0).toLowerCase();
String server;
if (args.size() != 1) {
server = args.get(1);
} else {
server = "global";
}
plugin.getDatastore().loadGroup(groupName, success -> {
if (!success) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
} else {
Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
return;
}
Group group1 = plugin.getGroupManager().getGroup(group);
if (group1 == null) {
Util.sendPluginMessage(sender, "That group does not exist!");
return;
}
try {
if (args.size() == 2) {
final String server = args.get(1).toLowerCase();
user.addGroup(group, server);
Message.USER_ADDGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
} else {
user.addGroup(group);
Message.USER_ADDGROUP_SUCCESS.send(sender, user.getName(), groupName);
}
try {
user.addGroup(group1, server);
Util.sendPluginMessage(sender, "&b" + user.getName() + "&a successfully added to group &b" + group + "&a on the server &b" + server + "&a.");
} catch (ObjectAlreadyHasException e) {
Util.sendPluginMessage(sender, "The user is already a member of that group.");
}
saveUser(user, sender, plugin);
saveUser(user, sender, plugin);
} catch (ObjectAlreadyHasException e) {
Message.USER_ALREADY_MEMBER_OF.send(sender, user.getName(), group.getName());
}
}
});
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getGroupTabComplete(args, plugin);
}
@Override
@@ -2,23 +2,23 @@ package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserClearCommand extends UserSubCommand {
public UserClearCommand() {
super("clear", "Clears a users permissions and groups",
"/perms user <user> clear", "luckperms.user.clear");
super("clear", "Clears a users permissions and groups", "/%s user <user> clear", Permission.USER_CLEAR);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
user.clearNodes();
user.getNodes().put(plugin.getConfiguration().getDefaultGroupNode(), true);
Util.sendPluginMessage(sender, "&b" + user.getName() + "&a's permissions were cleared.");
plugin.getUserManager().giveDefaults(user);
Message.CLEAR_SUCCESS.send(sender, user.getName());
saveUser(user, sender, plugin);
}
@@ -0,0 +1,91 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserDemoteCommand extends UserSubCommand {
public UserDemoteCommand() {
super("demote", "Demotes a user along a track", "/%s user <user> demote <track>", Permission.USER_DEMOTE);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
final String trackName = args.get(0).toLowerCase();
plugin.getDatastore().loadTrack(trackName, success -> {
if (!success) {
Message.TRACK_DOES_NOT_EXIST.send(sender);
} else {
Track track = plugin.getTrackManager().getTrack(trackName);
if (track == null) {
Message.TRACK_DOES_NOT_EXIST.send(sender);
return;
}
if (track.getSize() <= 1) {
Message.TRACK_EMPTY.send(sender);
return;
}
final String old = user.getPrimaryGroup();
final String previous;
try {
previous = track.getPrevious(old);
} catch (ObjectLacksException e) {
Message.TRACK_DOES_NOT_CONTAIN.send(sender, track.getName(), old);
Message.USER_DEMOTE_ERROR_NOT_CONTAIN_GROUP.send(sender);
return;
}
if (previous == null) {
Message.USER_DEMOTE_ERROR_ENDOFTRACK.send(sender, track.getName());
return;
}
plugin.getDatastore().loadGroup(previous, success1 -> {
if (!success1) {
Message.USER_DEMOTE_ERROR_MALFORMED.send(sender, previous);
} else {
Group previousGroup = plugin.getGroupManager().getGroup(previous);
if (previousGroup == null) {
Message.USER_DEMOTE_ERROR_MALFORMED.send(sender, previous);
return;
}
try {
user.unsetPermission("group." + old);
user.addGroup(previousGroup);
user.setPrimaryGroup(previousGroup.getName());
} catch (ObjectLacksException | ObjectAlreadyHasException ignored) {}
Message.USER_DEMOTE_SUCCESS_PROMOTE.send(sender, track.getName(), old, previousGroup.getName());
Message.USER_DEMOTE_SUCCESS_REMOVE.send(sender, user.getName(), old, previousGroup.getName(), previousGroup.getName());
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), previousGroup.getName(), old, true));
saveUser(user, sender, plugin);
}
});
}
});
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getTrackTabComplete(args, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1;
}
}
@@ -2,20 +2,21 @@ package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserGetUUIDCommand extends UserSubCommand {
public UserGetUUIDCommand() {
super("getuuid", "Get the UUID of a user", "/perms user <user> getuuid", "luckperms.user.getuuid");
super("getuuid", "Get the UUID of a user", "/%s user <user> getuuid", Permission.USER_GETUUID);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
Util.sendPluginMessage(sender, "&bThe UUID of &e" + user.getName() + "&b is &e" + user.getUuid().toString() + "&b.");
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
Message.USER_GETUUID.send(sender, user.getName(), user.getUuid().toString());
}
@Override
@@ -4,6 +4,7 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import java.util.List;
@@ -11,11 +12,11 @@ import java.util.List;
public class UserHasPermCommand extends UserSubCommand {
public UserHasPermCommand() {
super("haspermission", "Checks to see if a user has a certain permission node",
"/perms user <user> haspermission <node> [server]", "luckperms.user.haspermission");
"/%s user <user> haspermission <node> [server]", Permission.USER_HASPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
if (args.size() >= 2) {
Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, args.get(1)));
} else {
@@ -25,6 +26,6 @@ public class UserHasPermCommand extends UserSubCommand {
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
return argLength != 1 && argLength != 2;
}
}
@@ -4,27 +4,23 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserInfoCommand extends UserSubCommand {
public UserInfoCommand() {
super("info", "Gives info about the user",
"/perms user <user> info", "luckperms.user.info");
super("info", "Gives info about the user", "/%s user <user> info", Permission.USER_INFO);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
final String prefix = plugin.getConfiguration().getPrefix();
String sb = prefix + "&d-> &eUser: &6" + user.getName() + "\n" +
prefix + "&d-> &eUUID: &6" + user.getUuid() + "\n" +
prefix + "&d-> &eStatus: " + plugin.getPlayerStatus(user.getUuid()) + "\n" +
prefix + "&d-> &eGroups: &6" + Util.listToCommaSep(user.getGroupNames()) + "\n" +
prefix + "&d-> &ePermissions: &6" + (user.getNodes().keySet().size() - user.getGroupNames().size()) + "\n" +
prefix + "&d-> &bUse &a/perms user " + user.getName() + " listnodes &bto see all permissions.";
sender.sendMessage(Util.color(sb));
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
Message.USER_INFO.send(sender, user.getName(), user.getUuid(), plugin.getPlayerStatus(user.getUuid()),
Util.listToCommaSep(user.getGroupNames()), user.getPrimaryGroup(),
(user.getNodes().keySet().size() - user.getGroupNames().size()), label, user.getName()
);
}
@Override
@@ -0,0 +1,31 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserInheritsPermCommand extends UserSubCommand {
public UserInheritsPermCommand() {
super("inheritspermission", "Checks to see if a user inherits a certain permission node",
"/%s user <user> inheritspermission <node> [server]", Permission.USER_INHERITSPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
if (args.size() >= 2) {
Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true, args.get(1)));
} else {
Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true));
}
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1 && argLength != 2;
}
}
@@ -4,20 +4,20 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserListNodesCommand extends UserSubCommand {
public UserListNodesCommand() {
super("listnodes", "Lists the permission nodes the user has",
"/perms user <user> listnodes", "luckperms.user.listnodes");
super("listnodes", "Lists the permission nodes the user has", "/%s user <user> listnodes", Permission.USER_LISTNODES);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
Util.sendPluginMessage(sender, "&e" + user.getName() + "'s Nodes:");
sender.sendMessage(Util.color(Util.nodesToString(user.getNodes())));
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
Message.LISTNODES.send(sender, user.getName(), Util.nodesToString(user.getNodes()));
}
@Override
@@ -0,0 +1,91 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserPromoteCommand extends UserSubCommand {
public UserPromoteCommand() {
super("promote", "Promotes the user along a track", "/%s user <user> promote <track>", Permission.USER_PROMOTE);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
final String trackName = args.get(0).toLowerCase();
plugin.getDatastore().loadTrack(trackName, success -> {
if (!success) {
Message.TRACK_DOES_NOT_EXIST.send(sender);
} else {
Track track = plugin.getTrackManager().getTrack(trackName);
if (track == null) {
Message.TRACK_DOES_NOT_EXIST.send(sender);
return;
}
if (track.getSize() <= 1) {
Message.TRACK_EMPTY.send(sender);
return;
}
final String old = user.getPrimaryGroup();
final String next;
try {
next = track.getNext(old);
} catch (ObjectLacksException e) {
Message.TRACK_DOES_NOT_CONTAIN.send(sender, track.getName(), old);
Message.USER_PROMOTE_ERROR_NOT_CONTAIN_GROUP.send(sender);
return;
}
if (next == null) {
Message.USER_PROMOTE_ERROR_ENDOFTRACK.send(sender, track.getName());
return;
}
plugin.getDatastore().loadGroup(next, success1 -> {
if (!success1) {
Message.USER_PROMOTE_ERROR_MALFORMED.send(sender, next);
} else {
Group nextGroup = plugin.getGroupManager().getGroup(next);
if (nextGroup == null) {
Message.USER_PROMOTE_ERROR_MALFORMED.send(sender, next);
return;
}
try {
user.unsetPermission("group." + old);
user.addGroup(nextGroup);
user.setPrimaryGroup(nextGroup.getName());
} catch (ObjectLacksException | ObjectAlreadyHasException ignored) {}
Message.USER_PROMOTE_SUCCESS_PROMOTE.send(sender, track.getName(), old, nextGroup.getName());
Message.USER_PROMOTE_SUCCESS_REMOVE.send(sender, user.getName(), old, nextGroup.getName(), nextGroup.getName());
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), old, nextGroup.getName(), false));
saveUser(user, sender, plugin);
}
});
}
});
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getTrackTabComplete(args, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1;
}
}
@@ -2,44 +2,48 @@ package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserRemoveGroupCommand extends UserSubCommand {
public UserRemoveGroupCommand() {
super("removegroup", "Removes a user from a group",
"/perms user <user> removegroup <group> [server]", "luckperms.user.removegroup");
super("removegroup", "Removes a user from a group", "/%s user <user> removegroup <group> [server]", Permission.USER_REMOVEGROUP);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
String group = args.get(0).toLowerCase();
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
String groupName = args.get(0).toLowerCase();
String server;
if (args.size() != 1) {
server = args.get(1);
} else {
server = "global";
}
Group group1 = plugin.getGroupManager().getGroup(group);
if (group1 == null) {
Util.sendPluginMessage(sender, "That group does not exist!");
if ((args.size() == 1 || (args.size() == 2 && args.get(1).equalsIgnoreCase("global")))
&& user.getPrimaryGroup().equalsIgnoreCase(groupName)) {
Message.USER_REMOVEGROUP_ERROR_PRIMARY.send(sender);
return;
}
try {
user.removeGroup(group1, server);
Util.sendPluginMessage(sender, "&b" + user.getName() + "&a was removed from group &b" + group + "&a on server &b" + server + "&a.");
} catch (ObjectLacksPermissionException e) {
Util.sendPluginMessage(sender, "The user is not a member of that group.");
if (args.size() == 2) {
final String server = args.get(1).toLowerCase();
user.unsetPermission("group." + groupName, server);
Message.USER_REMOVEGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
} else {
user.unsetPermission("group." + groupName);
Message.USER_REMOVEGROUP_SUCCESS.send(sender, user.getName(), groupName);
}
saveUser(user, sender, plugin);
} catch (ObjectLacksException e) {
Message.USER_NOT_MEMBER_OF.send(sender, user.getName(), groupName);
}
saveUser(user, sender, plugin);
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getGroupTabComplete(args, plugin);
}
@Override
@@ -2,36 +2,38 @@ package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class UserSetPermissionCommand extends UserSubCommand {
public UserSetPermissionCommand() {
super("set", "Sets a permission for a user",
"/perms user <user> set <node> <true|false> [server]", "luckperms.user.setpermission");
"/%s user <user> set <node> <true|false> [server]", Permission.USER_SETPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
String node = args.get(0);
String bool = args.get(1);
String bool = args.get(1).toLowerCase();
if (node.contains("/")) {
sendUsage(sender);
sendUsage(sender, label);
return;
}
if (node.matches(".*luckperms\\.group\\..*")) {
Util.sendPluginMessage(sender, "Use the addgroup command instead of specifying the node.");
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
Message.USER_USE_ADDGROUP.send(sender);
return;
}
if (!bool.equalsIgnoreCase("true") && !bool.equalsIgnoreCase("false")) {
sendUsage(sender);
sendUsage(sender, label);
return;
}
@@ -41,20 +43,25 @@ public class UserSetPermissionCommand extends UserSubCommand {
if (args.size() == 3) {
final String server = args.get(2).toLowerCase();
user.setPermission(node, b, server);
Util.sendPluginMessage(sender, "&aSet &b" + node + "&a to " + bool + " for &b" + user.getName() + "&a on server &b" + server + "&a.");
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server);
} else {
user.setPermission(node, b);
Util.sendPluginMessage(sender, "&aSet &b" + node + "&a to " + bool + " for &b" + user.getName() + "&a.");
Message.SETPERMISSION_SUCCESS.send(sender, node, bool, user.getName());
}
} catch (ObjectAlreadyHasException e) {
Util.sendPluginMessage(sender, "That user already has this permission!");
}
saveUser(user, sender, plugin);
saveUser(user, sender, plugin);
} catch (ObjectAlreadyHasException e) {
Message.ALREADY_HASPERMISSION.send(sender, user.getName());
}
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getBoolTabComplete(args);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength < 2;
return argLength != 2 && argLength != 3;
}
}
@@ -0,0 +1,52 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserSetPrimaryGroupCommand extends UserSubCommand {
public UserSetPrimaryGroupCommand() {
super("setprimarygroup", "Sets a users primary group",
"/%s user <user> setprimarygroup <group>", Permission.USER_SETPRIMARYGROUP);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
Group group = plugin.getGroupManager().getGroup(args.get(0).toLowerCase());
if (group == null) {
Message.GROUP_DOES_NOT_EXIST.send(sender);
return;
}
if (user.getPrimaryGroup().equalsIgnoreCase(group.getName())) {
Message.USER_PRIMARYGROUP_ERROR_ALREADYHAS.send(sender);
return;
}
if (!user.isInGroup(group)) {
Message.USER_PRIMARYGROUP_ERROR_NOTMEMBER.send(sender, label);
return;
}
user.setPrimaryGroup(group.getName());
Message.USER_PRIMARYGROUP_SUCCESS.send(sender, user.getName(), group.getName());
saveUser(user, sender, plugin);
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getGroupTabComplete(args, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1;
}
}
@@ -0,0 +1,57 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserShowPosCommand extends UserSubCommand {
public UserShowPosCommand() {
super("showpos", "Shows a users position on a track", "/%s user <user> showpos <track>", Permission.USER_SHOWPOS);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
final String trackName = args.get(0).toLowerCase();
plugin.getDatastore().loadTrack(trackName, success -> {
if (!success) {
Message.TRACK_DOES_NOT_EXIST.send(sender);
} else {
Track track = plugin.getTrackManager().getTrack(trackName);
if (track == null) {
Message.TRACK_DOES_NOT_EXIST.send(sender);
return;
}
if (track.getSize() <= 1) {
Message.TRACK_EMPTY.send(sender);
return;
}
if (!track.containsGroup(user.getPrimaryGroup())) {
Message.TRACK_DOES_NOT_CONTAIN.send(sender, track.getName(), user.getPrimaryGroup());
return;
}
Message.USER_SHOWPOS.send(sender, user.getName(), track.getName(), Util.listToArrowSep(track.getGroups(), user.getPrimaryGroup()));
}
});
}
@Override
public List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
return getTrackTabComplete(args, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength != 1;
}
}
@@ -0,0 +1,39 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.util.List;
import java.util.stream.Collectors;
public class UserShowTracksCommand extends UserSubCommand {
public UserShowTracksCommand() {
super("showtracks", "Lists the tracks that this user's primary group features on", "/%s user <user> showtracks",
Permission.USER_SHOWTRACKS);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
plugin.getDatastore().loadAllTracks(success -> {
if (!success) {
Message.TRACKS_LOAD_ERROR.send(sender);
return;
}
Message.USER_SHOWTRACKS_INFO.send(sender, user.getPrimaryGroup(), user.getName());
Message.TRACKS_LIST.send(sender, Util.listToCommaSep(
plugin.getTrackManager().getApplicableTracks(user.getPrimaryGroup()).stream().map(Track::getName).collect(Collectors.toList())));
});
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return false;
}
}
@@ -2,30 +2,32 @@ package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Patterns;
import java.util.List;
public class UserUnSetPermissionCommand extends UserSubCommand {
public UserUnSetPermissionCommand() {
super("unset", "Unsets a permission for a user",
"/perms user <user> unset <node> [server]", "luckperms.user.unsetpermission");
"/%s user <user> unset <node> [server]", Permission.USER_UNSETPERMISSION);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
String node = args.get(0);
if (node.contains("/")) {
sendUsage(sender);
sendUsage(sender, label);
return;
}
if (node.matches(".*luckperms\\.group\\..*")) {
Util.sendPluginMessage(sender, "Use the removegroup command instead of specifying the node.");
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
Message.USER_USE_REMOVEGROUP.send(sender);
return;
}
@@ -33,19 +35,20 @@ public class UserUnSetPermissionCommand extends UserSubCommand {
if (args.size() == 2) {
final String server = args.get(1).toLowerCase();
user.unsetPermission(node, server);
Util.sendPluginMessage(sender, "&aUnset &b" + node + "&a for &b" + user.getName() + "&a on server &b" + server + "&a.");
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server);
} else {
user.unsetPermission(node);
Util.sendPluginMessage(sender, "&aUnset &b" + node + "&a for &b" + user.getName() + "&a.");
Message.UNSETPERMISSION_SUCCESS.send(sender, node, user.getName());
}
} catch (ObjectLacksPermissionException e) {
Util.sendPluginMessage(sender, "That user does not have this permission set.");
saveUser(user, sender, plugin);
} catch (ObjectLacksException e) {
Message.DOES_NOT_HAVEPERMISSION.send(sender, user.getName());
}
saveUser(user, sender, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
return argLength != 1 && argLength != 2;
}
}
@@ -0,0 +1,194 @@
package me.lucko.luckperms.constants;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
@SuppressWarnings("SpellCheckingInspection")
@AllArgsConstructor
public enum Message {
/**
* General & Commands
*/
PREFIX("&7&l[&b&lL&a&lP&7&l] &c", false),
EMPTY("%s", true),
COMMAND_NOT_RECOGNISED("Command not recognised.", true),
COMMAND_NO_PERMISSION("You do not have permission to use this command!", true),
INFO_BRIEF("&6Running &bLuckPerms %s&6.", true),
ALREADY_HASPERMISSION("%s already has this permission!", true),
DOES_NOT_HAVEPERMISSION("%s does not have this permission set.", true),
/**
* Loading / Saving
*/
USER_NOT_FOUND("&eUser could not be found.", true),
USER_SAVE_SUCCESS("&7(User data was saved to the datastore)", true),
USER_SAVE_ERROR("There was an error whilst saving the user.", true),
USER_ATTEMPTING_LOOKUP("&7(Attempting UUID lookup, since you specified a username)", true),
GROUP_NOT_FOUND("&eGroup could not be found.", true),
GROUP_SAVE_SUCCESS("&7(Group data was saved to the datastore)", true),
GROUP_SAVE_ERROR("There was an error whilst saving the group.", true),
TRACK_NOT_FOUND("&eTrack could not be found.", true),
TRACK_SAVE_SUCCESS("&7(Track data was saved to the datastore)", true),
TRACK_SAVE_ERROR("There was an error whilst saving the track.", true),
/**
* Command Syntax
*/
USER_USE_ADDGROUP("Use the addgroup command instead of specifying the node.", true),
USER_USE_REMOVEGROUP("Use the removegroup command instead of specifying the node.", true),
USER_INVALID_ENTRY("&d%s&c is not a valid username/uuid.", true),
GROUP_USE_INHERIT("Use the setinherit command instead of specifying the node.", true),
GROUP_USE_UNINHERIT("Use the unsetinherit command instead of specifying the node.", true),
GROUP_INVALID_ENTRY("Group names can only contain alphanumeric charcters.", true),
TRACK_INVALID_ENTRY("Track names can only contain alphanumeric charcters.", true),
/**
* Commands
*/
CREATE_SUCCESS("&b%s&a was successfully created.", true),
DELETE_SUCCESS("&b%s&a was successfully deleted.", true),
USER_ALREADY_MEMBER_OF("%s is already a member of '%s'.", true),
USER_NOT_MEMBER_OF("%s is not a member of '%s'.", true),
GROUP_ALREADY_INHERITS("%s already inherits '%s'.", true),
GROUP_DOES_NOT_INHERIT("%s does not inherit '%s'.", true),
TRACK_ALREADY_CONTAINS("Track %s already contains the group '%s'.", true),
TRACK_DOES_NOT_CONTAIN("Track %s does not contain the group '%s'.", true),
GROUP_ALREADY_EXISTS("That group already exists!", true),
GROUP_DOES_NOT_EXIST("That group does not exist!", true),
GROUP_NAME_TOO_LONG("Group name '%s' exceeds the maximum length of 36 characters.", true),
GROUP_LOAD_ERROR("An unexpected error occurred. Group not loaded.", true),
GROUPS_LOAD_ERROR("An unexpected error occurred. Unable to load all groups.", true),
TRACK_ALREADY_EXISTS("That track already exists!", true),
TRACK_DOES_NOT_EXIST("That track does not exist!", true),
TRACK_NAME_TOO_LONG("Track name '%s' exceeds the maximum length of 36 characters.", true),
TRACK_LOAD_ERROR("An unexpected error occurred. Track not loaded.", true),
TRACKS_LOAD_ERROR("An unexpected error occurred. Unable to load all tracks.", true),
TRACK_EMPTY("The track cannot be used as it is empty or contains only one group.", true),
UPDATE_TASK_RUN("&bRunning update task for all online users.", true),
INFO(
PREFIX + "&6Running &bLuckPerms %s&6." + "\n" +
PREFIX + "&eAuthor: &6Luck" + "\n" +
PREFIX + "&eStorage Method: &6%s",
false
),
DEBUG(
PREFIX + "&d&l> &dDebug Info" + "\n" +
PREFIX + "&eOnline Players: &6%s" + "\n" +
PREFIX + "&eLoaded Users: &6%s" + "\n" +
PREFIX + "&eLoaded Groups: &6%s" + "\n" +
PREFIX + "&eLoaded Tracks: &6%s",
false
),
CREATE_GROUP_ERROR("There was an error whilst creating the group.", true),
DELETE_GROUP_ERROR("There was an error whilst deleting the group.", true),
DELETE_GROUP_ERROR_DEFAULT("You cannot delete the default group.", true),
GROUPS_LIST("&aGroups: %s", true),
CREATE_TRACK_ERROR("There was an error whilst creating the track.", true),
DELETE_TRACK_ERROR("There was an error whilst deleting the track.", true),
TRACKS_LIST("&aTracks: %s", true),
LISTNODES("&e%s's Nodes:" + "\n" + "%s", true),
SETPERMISSION_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a.", true),
SETPERMISSION_SERVER_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a.", true),
UNSETPERMISSION_SUCCESS("&aUnset &b%s&a for &b%s&a.", true),
UNSETPERMISSION_SERVER_SUCCESS("&aUnset &b%s&a for &b%s&a on server &b%$s&a.", true),
CLEAR_SUCCESS("&b%s&a's permissions were cleared.", true),
USER_INFO(
PREFIX + "&d-> &eUser: &6%s" + "\n" +
PREFIX + "&d-> &eUUID: &6%s" + "\n" +
PREFIX + "&d-> &eStatus: %s" + "\n" +
PREFIX + "&d-> &eGroups: &6%s" + "\n" +
PREFIX + "&d-> &ePrimary Group: &6%s" + "\n" +
PREFIX + "&d-> &ePermissions: &6%s" + "\n" +
PREFIX + "&d-> &bUse &a/%s user %s listnodes &bto see all permissions.",
false
),
USER_GETUUID("&bThe UUID of &e%s&b is &e%s&b.", true),
USER_ADDGROUP_SUCCESS("&b%s&a successfully added to group &b%s&a.", true),
USER_ADDGROUP_SERVER_SUCCESS("&b%s&a successfully added to group &b%s&a on server &b%s&a.", true),
USER_REMOVEGROUP_SUCCESS("&b%s&a was removed from group &b%s&a.", true),
USER_REMOVEGROUP_SERVER_SUCCESS("&b%s&a was removed from group &b%s&a on server &b%s&a.", true),
USER_REMOVEGROUP_ERROR_PRIMARY("You cannot remove a user from their primary group.", true),
USER_PRIMARYGROUP_SUCCESS("&b%s&a's primary group was set to &b%s&a.", true),
USER_PRIMARYGROUP_ERROR_ALREADYHAS("The user already has this group set as their primary group.", true),
USER_PRIMARYGROUP_ERROR_NOTMEMBER("The user must be a member of the group first! Use &4/%s user <user> addgroup <group>", true),
USER_SHOWTRACKS_INFO("&aShowing tracks that contain the group '&b%s&a' (%s's primary group)", true),
USER_PROMOTE_SUCCESS_PROMOTE("&aPromoting user along track &b%s&a from &b%s&a to &b%s&a.", true),
USER_PROMOTE_SUCCESS_REMOVE("&b%s&a was removed from &b%s&a, added to &b%s&a, and their primary group was set to &b%s&a.", true),
USER_PROMOTE_ERROR_ENDOFTRACK("The end of track &4%s&c was reached. Unable to promote user.", true),
USER_PROMOTE_ERROR_MALFORMED(
PREFIX + "The next group on the track, %s, no longer exists. Unable to promote user." + "\n" +
PREFIX + "Either create the group, or remove it from the track and try again.",
false
),
USER_PROMOTE_ERROR_NOT_CONTAIN_GROUP("Promotions are done based on primary groups. The users primary group is not on the track specified.", true),
USER_DEMOTE_SUCCESS_PROMOTE("&aDemoting user along track &b%s&a from &b%s&a to &b%s&a.", true),
USER_DEMOTE_SUCCESS_REMOVE("&b%s&a was removed from &b%s&a, added to &b%s&a, and their primary group was set to &b%s&a.", true),
USER_DEMOTE_ERROR_ENDOFTRACK("The end of track &4%s&c was reached. Unable to demote user.", true),
USER_DEMOTE_ERROR_MALFORMED(
PREFIX + "The previous group on the track, %s, no longer exists. Unable to demote user." + "\n" +
PREFIX + "Either create the group, or remove it from the track and try again.",
false
),
USER_DEMOTE_ERROR_NOT_CONTAIN_GROUP("Demotions are done based on primary groups. The users primary group is not on the track specified.", true),
USER_SHOWPOS("&aShowing &b%s&a's position on track &b%s&a.\n%s", true),
GROUP_INFO(
PREFIX + "&d-> &eGroup: &6%s" + "\n" +
PREFIX + "&d-> &ePermissions: &6%s" + "\n" +
PREFIX + "&d-> &bUse &a/%s group %s listnodes &bto see all permissions.",
false
),
GROUP_SETINHERIT_SUCCESS("&b%s&a now inherits permissions from &b%s&a.", true),
GROUP_SETINHERIT_SERVER_SUCCESS("&b%s&a now inherits permissions from &b%s&a on server &b%s&a.", true),
GROUP_UNSETINHERIT_SUCCESS("&b%s&a no longer inherits permissions from &b%s&a.", true),
GROUP_UNSETINHERIT_SERVER_SUCCESS("&b%s&a no longer inherits permissions from &b%s&a on server &b%s&a.", true),
TRACK_INFO(
PREFIX + "&d-> &eTrack: &6%s" + "\n" +
PREFIX + "&d-> &ePath: &6%s",
false
),
TRACK_CLEAR("&b%s&a's groups track was cleared.", true),
TRACK_APPEND_SUCCESS("&aGroup &b%s&a was successfully appended to track &b%s&a.", true),
TRACK_INSERT_SUCCESS("&aGroup &b%s&a was successfully inserted into to track &b%s&a at position &b%s&a.", true),
TRACK_INSERT_ERROR_NUMBER("Expected number but instead received: %s", true),
TRACK_INSERT_ERROR_INVALID_POS("Unable to insert at position %s. Index out of bounds.", true),
TRACK_REMOVE_SUCCESS("&aGroup &b%s&a was successfully removed from track &b%s&a.", true);
private String message;
private boolean showPrefix;
@Override
public String toString() {
return message;
}
public void send(Sender sender, Object... objects) {
if (showPrefix) {
sender.sendMessage(Util.color(PREFIX + String.format(message, objects)));
} else {
sender.sendMessage(Util.color(String.format(message, objects)));
}
}
}
@@ -0,0 +1,85 @@
package me.lucko.luckperms.constants;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.commands.Sender;
@SuppressWarnings("SpellCheckingInspection")
@AllArgsConstructor
public enum Permission {
SYNC("sync", null),
INFO("info", null),
DEBUG("debug", null),
CREATE_GROUP("creategroup", null),
DELETE_GROUP("deletegroup", null),
LIST_GROUPS("listgroups", null),
CREATE_TRACK("createtrack", null),
DELETE_TRACK("deletetrack", null),
LIST_TRACKS("listtracks", null),
USER_INFO("info", PermissionGroup.USER),
USER_GETUUID("getuuid", PermissionGroup.USER),
USER_LISTNODES("listnodes", PermissionGroup.USER),
USER_HASPERMISSION("haspermission", PermissionGroup.USER),
USER_INHERITSPERMISSION("inheritspermission", PermissionGroup.USER),
USER_SETPERMISSION("setpermission", PermissionGroup.USER),
USER_UNSETPERMISSION("unsetpermission", PermissionGroup.USER),
USER_ADDGROUP("addgroup", PermissionGroup.USER),
USER_REMOVEGROUP("removegroup", PermissionGroup.USER),
USER_SETPRIMARYGROUP("setprimarygroup", PermissionGroup.USER),
USER_SHOWTRACKS("showtracks", PermissionGroup.USER),
USER_PROMOTE("promote", PermissionGroup.USER),
USER_DEMOTE("demote", PermissionGroup.USER),
USER_SHOWPOS("showpos", PermissionGroup.USER),
USER_CLEAR("clear", PermissionGroup.USER),
GROUP_INFO("info", PermissionGroup.GROUP),
GROUP_LISTNODES("listnodes", PermissionGroup.GROUP),
GROUP_HASPERMISSION("haspermission", PermissionGroup.GROUP),
GROUP_INHERITSPERMISSION("inheritspermission", PermissionGroup.GROUP),
GROUP_SETPERMISSION("setpermission", PermissionGroup.GROUP),
GROUP_UNSETPERMISSION("unsetpermission", PermissionGroup.GROUP),
GROUP_SETINHERIT("setinherit", PermissionGroup.GROUP),
GROUP_UNSETINHERIT("unsetinherit", PermissionGroup.GROUP),
GROUP_SHOWTRACKS("showtracks", PermissionGroup.GROUP),
GROUP_CLEAR("clear", PermissionGroup.GROUP),
TRACK_INFO("info", PermissionGroup.TRACK),
TRACK_APPEND("append", PermissionGroup.TRACK),
TRACK_INSERT("insert", PermissionGroup.TRACK),
TRACK_REMOVE("remove", PermissionGroup.TRACK),
TRACK_CLEAR("clear", PermissionGroup.TRACK);
private String node;
private PermissionGroup group;
public boolean isAuthorized(Sender sender) {
if (sender.hasPermission("luckperms.*")) {
return true;
}
if (group != null) {
return group.isAuthorized(sender) || sender.hasPermission("luckperms." + group.getNode() + "." + node);
}
return sender.hasPermission("luckperms." + node);
}
@Getter
@AllArgsConstructor
private enum PermissionGroup {
USER("user"),
GROUP("group"),
TRACK("track");
private String node;
private boolean isAuthorized(Sender sender) {
return sender.hasPermission("luckperms." + node + ".*");
}
}
}
@@ -4,6 +4,7 @@ import lombok.Getter;
import lombok.Setter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.util.UUID;
@@ -12,16 +13,16 @@ public abstract class Datastore {
protected final LuckPermsPlugin plugin;
@Getter
public String name;
public final String name;
@Getter
@Setter
private boolean acceptingLogins;
public Datastore(LuckPermsPlugin plugin, String name) {
protected Datastore(LuckPermsPlugin plugin, String name) {
this.plugin = plugin;
this.name = name;
this.acceptingLogins = true;
this.acceptingLogins = false;
}
/**
@@ -45,9 +46,10 @@ public abstract class Datastore {
}
/*
These methods will block the thread that they're ran on.
These methods are called immediately and in the same thread as they are called in.
*/
public abstract void init(DatastoreConfiguration configuration);
public abstract void init();
public abstract void shutdown();
public abstract boolean loadOrCreateUser(UUID uuid, String username);
public abstract boolean loadUser(UUID uuid);
public abstract boolean saveUser(User user);
@@ -56,16 +58,19 @@ public abstract class Datastore {
public abstract boolean loadAllGroups();
public abstract boolean saveGroup(Group group);
public abstract boolean deleteGroup(Group group);
public abstract boolean createAndLoadTrack(String name);
public abstract boolean loadTrack(String name);
public abstract boolean loadAllTracks();
public abstract boolean saveTrack(Track track);
public abstract boolean deleteTrack(Track track);
public abstract boolean saveUUIDData(String username, UUID uuid);
public abstract UUID getUUID(String username);
/*
These methods will return as soon as they are called. The callback will be ran when the task is complete
They therefore will not block the thread that they're ran on
Callbacks are ran on the main server thread (if applicable)
These methods will schedule the operation to run async. The callback will be ran when the task is complete.
Callbacks are ran on the main Bukkit server thread (if applicable)
*/
public void loadOrCreateUser(UUID uuid, String username, Callback callback) {
doAsync(() -> runCallback(loadOrCreateUser(uuid, username), callback));
@@ -99,6 +104,26 @@ public abstract class Datastore {
doAsync(() -> runCallback(deleteGroup(group), callback));
}
public void createAndLoadTrack(String name, Callback callback) {
doAsync(() -> runCallback(createAndLoadTrack(name), callback));
}
public void loadTrack(String name, Callback callback) {
doAsync(() -> runCallback(loadTrack(name), callback));
}
public void loadAllTracks(Callback callback) {
doAsync(() -> runCallback(loadAllTracks(), callback));
}
public void saveTrack(Track track, Callback callback) {
doAsync(() -> runCallback(saveTrack(track), callback));
}
public void deleteTrack(Track track, Callback callback) {
doAsync(() -> runCallback(deleteTrack(track), callback));
}
public void saveUUIDData(String username, UUID uuid, Callback callback) {
doAsync(() -> runCallback(saveUUIDData(username, uuid), callback));
}
@@ -1,338 +0,0 @@
package me.lucko.luckperms.data;
import com.zaxxer.hikari.HikariDataSource;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.users.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
public class HikariDatastore extends Datastore {
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String USER_INSERT = "INSERT INTO lp_users VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE name=?";
private static final String USER_SELECT = "SELECT * FROM lp_users WHERE uuid=?";
private static final String USER_SAVE = "UPDATE lp_users SET name=?, perms=? WHERE uuid=?";
private static final String GROUP_INSERT = "INSERT INTO lp_groups VALUES(?, ?) ON DUPLICATE KEY UPDATE perms=?";
private static final String GROUP_SELECT = "SELECT perms FROM lp_groups WHERE name=?";
private static final String GROUP_SELECT_ALL = "SELECT * FROM lp_groups";
private static final String GROUP_SAVE = "UPDATE lp_groups SET perms=? WHERE name=?";
private static final String GROUP_DELETE = "DELETE FROM lp_groups WHERE name=?";
private static final String UUIDCACHE_INSERT = "INSERT INTO lp_uuid VALUES(?, ?) ON DUPLICATE KEY UPDATE uuid=?";
private static final String UUIDCACHE_SELECT = "SELECT uuid FROM lp_uuid WHERE name=?";
private HikariDataSource hikari;
public HikariDatastore(LuckPermsPlugin plugin) {
super(plugin, "MySQL");
}
private static void executeQuery(Connection connection, String query) throws SQLException {
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.execute();
preparedStatement.close();
}
private boolean runQuery(Query query) {
boolean success = false;
Connection connection = null;
try {
connection = hikari.getConnection();
success = query.onRun(connection);
} catch (SQLException e) {
e.printStackTrace();
success = false;
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return success;
}
private void setupTables() {
boolean success = runQuery(connection -> {
executeQuery(connection, CREATETABLE_UUID);
executeQuery(connection, CREATETABLE_USERS);
executeQuery(connection, CREATETABLE_GROUPS);
return true;
});
if (!success) {
plugin.getLogger().log(Level.SEVERE, "Error occurred whilst connecting to the database. All connections are disallowed.");
hikari.shutdown();
setAcceptingLogins(false);
}
}
@Override
public void init(DatastoreConfiguration configuration) {
hikari = new HikariDataSource();
final String address = configuration.getAddress();
final String database = configuration.getDatabase();
final String username = configuration.getUsername();
final String password = configuration.getPassword();
hikari.setMaximumPoolSize(10);
hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
hikari.addDataSourceProperty("serverName", address.split(":")[0]);
hikari.addDataSourceProperty("port", address.split(":")[1]);
hikari.addDataSourceProperty("databaseName", database);
hikari.addDataSourceProperty("user", username);
hikari.addDataSourceProperty("password", password);
setupTables();
}
@Override
public boolean loadUser(UUID uuid) {
User user = plugin.getUserManager().makeUser(uuid);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(USER_SELECT);
preparedStatement.setString(1, uuid.toString());
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
user.setName(resultSet.getString("name"));
user.loadNodes(nodes);
preparedStatement.close();
resultSet.close();
return true;
}
preparedStatement.close();
resultSet.close();
return false;
});
if (success) plugin.getUserManager().updateOrSetUser(user);
return success;
}
@Override
public boolean loadOrCreateUser(UUID uuid, String username) {
User user = plugin.getUserManager().makeUser(uuid, username);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(USER_INSERT);
preparedStatement.setString(1, uuid.toString());
preparedStatement.setString(2, username);
preparedStatement.setString(3, plugin.getConfiguration().getDefaultGroupNode());
preparedStatement.setString(4, username);
preparedStatement.execute();
preparedStatement.close();
preparedStatement = connection.prepareStatement(USER_SELECT);
preparedStatement.setString(1, uuid.toString());
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
user.loadNodes(nodes);
preparedStatement.close();
resultSet.close();
return true;
}
preparedStatement.close();
resultSet.close();
return true;
});
if (success) plugin.getUserManager().updateOrSetUser(user);
return success;
}
@Override
public boolean saveUser(User user) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(USER_SAVE);
preparedStatement.setString(1, user.getName());
preparedStatement.setString(2, user.serializeNodes());
preparedStatement.setString(3, user.getUuid().toString());
preparedStatement.execute();
preparedStatement.close();
return true;
});
return success;
}
@Override
public boolean createAndLoadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_INSERT);
preparedStatement.setString(1, name);
preparedStatement.setString(2, "#");
preparedStatement.setString(3, "#");
preparedStatement.execute();
preparedStatement.close();
preparedStatement = connection.prepareStatement(GROUP_SELECT);
preparedStatement.setString(1, name);
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
}
group.loadNodes(nodes);
preparedStatement.close();
resultSet.close();
return true;
});
if (success) plugin.getGroupManager().updateOrSetGroup(group);
return success;
}
@Override
public boolean loadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT);
preparedStatement.setString(1, name);
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
group.loadNodes(nodes);
return true;
}
preparedStatement.close();
resultSet.close();
return false;
});
if (success) plugin.getGroupManager().updateOrSetGroup(group);
return success;
}
@Override
public boolean loadAllGroups() {
List<Group> groups = new ArrayList<>();
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT_ALL);
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
Group group = plugin.getGroupManager().makeGroup(resultSet.getString("name"));
if (!resultSet.getString("perms").equals("#")) {
group.loadNodes(Arrays.asList(resultSet.getString("perms").split(":")));
}
groups.add(group);
}
preparedStatement.close();
resultSet.close();
return true;
});
GroupManager gm = plugin.getGroupManager();
if (success) {
groups.forEach(gm::setGroup);
}
return success;
}
@Override
public boolean saveGroup(Group group) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SAVE);
preparedStatement.setString(1, group.serializeNodes());
preparedStatement.setString(2, group.getName());
preparedStatement.execute();
preparedStatement.close();
return true;
});
return success;
}
@Override
public boolean deleteGroup(Group group) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_DELETE);
preparedStatement.setString(1, group.getName());
preparedStatement.execute();
preparedStatement.close();
return true;
});
if (success) plugin.getGroupManager().unloadGroup(group);
return success;
}
@Override
public boolean saveUUIDData(String username, UUID uuid) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(UUIDCACHE_INSERT);
preparedStatement.setString(1, username);
preparedStatement.setString(2, uuid.toString());
preparedStatement.setString(3, uuid.toString());
preparedStatement.execute();
preparedStatement.close();
return true;
});
return success;
}
@Override
public UUID getUUID(String username) {
final UUID[] uuid = {null};
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(UUIDCACHE_SELECT);
preparedStatement.setString(1, username);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
uuid[0] = UUID.fromString(resultSet.getString("uuid"));
preparedStatement.close();
resultSet.close();
return true;
}
preparedStatement.close();
resultSet.close();
return false;
});
return success ? uuid[0] : null;
}
private interface Query {
boolean onRun(Connection connection) throws SQLException;
}
}
@@ -5,7 +5,7 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
public class DatastoreConfiguration {
public class MySQLConfiguration {
private final String address;
private final String database;
@@ -0,0 +1,564 @@
package me.lucko.luckperms.data.methods;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@SuppressWarnings({"ResultOfMethodCallIgnored", "UnnecessaryLocalVariable"})
public class FlatfileDatastore extends Datastore {
private Map<String, String> uuidCache = new ConcurrentHashMap<>();
private final File pluginDir;
private File usersDir;
private File groupsDir;
private File tracksDir;
private File uuidData;
public FlatfileDatastore(LuckPermsPlugin plugin, File pluginDir) {
super(plugin, "Flatfile - JSON");
this.pluginDir = pluginDir;
}
private boolean doWrite(File file, WriteOperation writeOperation) {
boolean success = false;
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;
JsonWriter jsonWriter = null;
try {
fileWriter = new FileWriter(file);
bufferedWriter = new BufferedWriter(fileWriter);
jsonWriter = new JsonWriter(bufferedWriter);
jsonWriter.setIndent(" ");
success = writeOperation.onRun(jsonWriter);
jsonWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(jsonWriter);
close(bufferedWriter);
close(fileWriter);
}
return success;
}
private boolean doRead(File file, ReadOperation readOperation) {
boolean success = false;
FileReader fileReader = null;
BufferedReader bufferedReader = null;
JsonReader jsonReader = null;
try {
fileReader = new FileReader(file);
bufferedReader = new BufferedReader(fileReader);
jsonReader = new JsonReader(bufferedReader);
success = readOperation.onRun(jsonReader);
} catch (IOException e) {
e.printStackTrace();
} finally {
close(jsonReader);
close(bufferedReader);
close(fileReader);
}
return success;
}
private static void close(AutoCloseable closeable) {
if (closeable == null) return;
try {
closeable.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void init() {
try {
makeFiles();
} catch (IOException e) {
e.printStackTrace();
return;
}
uuidCache.putAll(getUUIDCache());
setAcceptingLogins(true);
}
private void makeFiles() throws IOException {
File data = new File(pluginDir, "data");
data.mkdirs();
usersDir = new File(data, "users");
usersDir.mkdir();
groupsDir = new File(data, "groups");
groupsDir.mkdir();
tracksDir = new File(data, "tracks");
tracksDir.mkdir();
uuidData = new File(data, "uuidcache.txt");
uuidData.createNewFile();
}
@Override
public void shutdown() {
saveUUIDCache(uuidCache);
}
@Override
public boolean loadOrCreateUser(UUID uuid, String username) {
User user = plugin.getUserManager().makeUser(uuid, username);
File userFile = new File(usersDir, uuid.toString() + ".json");
if (!userFile.exists()) {
try {
userFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return false;
}
plugin.getUserManager().giveDefaults(user);
boolean success = doWrite(userFile, writer -> {
writer.beginObject();
writer.name("uuid").value(user.getUuid().toString());
writer.name("name").value(user.getName());
writer.name("primaryGroup").value(user.getPrimaryGroup());
writer.name("perms");
writer.beginObject();
for (Map.Entry<String, Boolean> e : user.getNodes().entrySet()) {
writer.name(e.getKey()).value(e.getValue().booleanValue());
}
writer.endObject();
writer.endObject();
return true;
});
if (!success) return false;
}
boolean success = doRead(userFile, reader -> {
reader.beginObject();
reader.nextName(); // uuid record
reader.nextString(); // uuid
reader.nextName(); // name record
reader.nextString(); // name
reader.nextName(); // primaryGroup record
user.setPrimaryGroup(reader.nextString()); // primaryGroup
reader.nextName(); //perms
reader.beginObject();
while (reader.hasNext()) {
String node = reader.nextName();
boolean b = reader.nextBoolean();
user.getNodes().put(node, b);
}
reader.endObject();
reader.endObject();
return true;
});
if (success) plugin.getUserManager().updateOrSetUser(user);
return success;
}
@Override
public boolean loadUser(UUID uuid) {
User user = plugin.getUserManager().makeUser(uuid);
File userFile = new File(usersDir, uuid.toString() + ".json");
if (!userFile.exists()) {
return false;
}
boolean success = doRead(userFile, reader -> {
reader.beginObject();
reader.nextName(); // uuid record
reader.nextString(); // uuid
reader.nextName(); // name record
user.setName(reader.nextString()); // name
reader.nextName(); // primaryGroup record
user.setPrimaryGroup(reader.nextString()); // primaryGroup
reader.nextName(); // perms record
reader.beginObject();
while (reader.hasNext()) {
String node = reader.nextName();
boolean b = reader.nextBoolean();
user.getNodes().put(node, b);
}
reader.endObject();
reader.endObject();
return true;
});
if (success) plugin.getUserManager().updateOrSetUser(user);
return success;
}
@Override
public boolean saveUser(User user) {
File userFile = new File(usersDir, user.getUuid().toString() + ".json");
if (!userFile.exists()) {
try {
userFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
boolean success = doWrite(userFile, writer -> {
writer.beginObject();
writer.name("uuid").value(user.getUuid().toString());
writer.name("name").value(user.getName());
writer.name("primaryGroup").value(user.getPrimaryGroup());
writer.name("perms");
writer.beginObject();
for (Map.Entry<String, Boolean> e : user.getNodes().entrySet()) {
writer.name(e.getKey()).value(e.getValue().booleanValue());
}
writer.endObject();
writer.endObject();
return true;
});
return success;
}
@Override
public boolean createAndLoadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name);
File groupFile = new File(groupsDir, name + ".json");
if (!groupFile.exists()) {
try {
groupFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return false;
}
boolean success = doWrite(groupFile, writer -> {
writer.beginObject();
writer.name("name").value(group.getName());
writer.name("perms");
writer.beginObject();
for (Map.Entry<String, Boolean> e : group.getNodes().entrySet()) {
writer.name(e.getKey()).value(e.getValue().booleanValue());
}
writer.endObject();
writer.endObject();
return true;
});
if (!success) return false;
}
boolean success = doRead(groupFile, reader -> {
reader.beginObject();
reader.nextName(); // name record
reader.nextString(); // name
reader.nextName(); //perms
reader.beginObject();
while (reader.hasNext()) {
String node = reader.nextName();
boolean b = reader.nextBoolean();
group.getNodes().put(node, b);
}
reader.endObject();
reader.endObject();
return true;
});
if (success) plugin.getGroupManager().updateOrSetGroup(group);
return success;
}
@Override
public boolean loadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name);
File groupFile = new File(groupsDir, name + ".json");
if (!groupFile.exists()) {
return false;
}
boolean success = doRead(groupFile, reader -> {
reader.beginObject();
reader.nextName(); // name record
reader.nextString(); // name
reader.nextName(); //perms
reader.beginObject();
while (reader.hasNext()) {
String node = reader.nextName();
boolean b = reader.nextBoolean();
group.getNodes().put(node, b);
}
reader.endObject();
reader.endObject();
return true;
});
if (success) plugin.getGroupManager().updateOrSetGroup(group);
return success;
}
@Override
public boolean loadAllGroups() {
String[] fileNames = groupsDir.list((dir, name) -> name.endsWith(".json"));
if (fileNames == null) return false;
List<String> groups = Arrays.stream(fileNames).map(s -> s.substring(0, s.length() - 5)).collect(Collectors.toList());
plugin.getGroupManager().unloadAll();
groups.forEach(this::loadGroup);
return true;
}
@Override
public boolean saveGroup(Group group) {
File groupFile = new File(groupsDir, group.getName() + ".json");
if (!groupFile.exists()) {
try {
groupFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
boolean success = doWrite(groupFile, writer -> {
writer.beginObject();
writer.name("name").value(group.getName());
writer.name("perms");
writer.beginObject();
for (Map.Entry<String, Boolean> e : group.getNodes().entrySet()) {
writer.name(e.getKey()).value(e.getValue().booleanValue());
}
writer.endObject();
writer.endObject();
return true;
});
return success;
}
@Override
public boolean deleteGroup(Group group) {
File groupFile = new File(groupsDir, group.getName() + ".json");
if (groupFile.exists()) {
groupFile.delete();
}
return true;
}
@Override
public boolean createAndLoadTrack(String name) {
Track track = plugin.getTrackManager().makeTrack(name);
List<String> groups = new ArrayList<>();
File trackFile = new File(tracksDir, name + ".json");
if (!trackFile.exists()) {
try {
trackFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return false;
}
boolean success = doWrite(trackFile, writer -> {
writer.beginObject();
writer.name("name").value(track.getName());
writer.name("groups");
writer.beginArray();
for (String s : track.getGroups()) {
writer.value(s);
}
writer.endArray();
writer.endObject();
return true;
});
if (!success) return false;
}
boolean success = doRead(trackFile, reader -> {
reader.beginObject();
reader.nextName(); // name record
reader.nextString(); // name
reader.nextName(); // groups record
reader.beginArray();
while (reader.hasNext()) {
groups.add(reader.nextString());
}
reader.endArray();
reader.endObject();
return true;
});
track.setGroups(groups);
if (success) plugin.getTrackManager().updateOrSetTrack(track);
return success;
}
@Override
public boolean loadTrack(String name) {
Track track = plugin.getTrackManager().makeTrack(name);
List<String> groups = new ArrayList<>();
File trackFile = new File(tracksDir, name + ".json");
if (!trackFile.exists()) {
return false;
}
boolean success = doRead(trackFile, reader -> {
reader.beginObject();
reader.nextName(); // name record
reader.nextString(); // name
reader.nextName(); // groups record
reader.beginArray();
while (reader.hasNext()) {
groups.add(reader.nextString());
}
reader.endArray();
reader.endObject();
return true;
});
track.setGroups(groups);
if (success) plugin.getTrackManager().updateOrSetTrack(track);
return success;
}
@Override
public boolean loadAllTracks() {
String[] fileNames = tracksDir.list((dir, name) -> name.endsWith(".json"));
if (fileNames == null) return false;
List<String> tracks = Arrays.stream(fileNames).map(s -> s.substring(0, s.length() - 5)).collect(Collectors.toList());
plugin.getTrackManager().unloadAll();
tracks.forEach(this::loadTrack);
return true;
}
@Override
public boolean saveTrack(Track track) {
File trackFile = new File(tracksDir, track.getName() + ".json");
if (!trackFile.exists()) {
try {
trackFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
boolean success = doWrite(trackFile, writer -> {
writer.beginObject();
writer.name("name").value(track.getName());
writer.name("groups");
writer.beginArray();
for (String s : track.getGroups()) {
writer.value(s);
}
writer.endArray();
writer.endObject();
return true;
});
return success;
}
@Override
public boolean deleteTrack(Track track) {
File trackFile = new File(tracksDir, track.getName() + ".json");
if (trackFile.exists()) {
trackFile.delete();
}
return true;
}
private Map<String, String> getUUIDCache() {
Map<String, String> cache = new HashMap<>();
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
fileReader = new FileReader(uuidData);
bufferedReader = new BufferedReader(fileReader);
Properties props = new Properties();
props.load(bufferedReader);
for (String key : props.stringPropertyNames()) {
cache.put(key, props.getProperty(key));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
close(bufferedReader);
close(fileReader);
}
return cache;
}
private void saveUUIDCache(Map<String, String> cache) {
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;
try {
fileWriter = new FileWriter(uuidData);
bufferedWriter = new BufferedWriter(fileWriter);
Properties properties = new Properties();
properties.putAll(cache);
properties.store(bufferedWriter, null);
} catch (IOException e) {
e.printStackTrace();
} finally {
close(bufferedWriter);
close(fileWriter);
}
}
@Override
public boolean saveUUIDData(String username, UUID uuid) {
uuidCache.put(username, uuid.toString());
return true;
}
@Override
public UUID getUUID(String username) {
if (uuidCache.get(username) == null) return null;
return UUID.fromString(uuidCache.get(username));
}
interface WriteOperation {
boolean onRun(JsonWriter writer) throws IOException;
}
interface ReadOperation {
boolean onRun(JsonReader reader) throws IOException;
}
}
@@ -0,0 +1,62 @@
package me.lucko.luckperms.data.methods;
import com.zaxxer.hikari.HikariDataSource;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.MySQLConfiguration;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.logging.Level;
public class MySQLDatastore extends SQLDatastore {
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private final MySQLConfiguration configuration;
private HikariDataSource hikari;
public MySQLDatastore(LuckPermsPlugin plugin, MySQLConfiguration configuration) {
super(plugin, "MySQL");
this.configuration = configuration;
}
@Override
public void init() {
hikari = new HikariDataSource();
final String address = configuration.getAddress();
final String database = configuration.getDatabase();
final String username = configuration.getUsername();
final String password = configuration.getPassword();
hikari.setMaximumPoolSize(10);
hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
hikari.addDataSourceProperty("serverName", address.split(":")[0]);
hikari.addDataSourceProperty("port", address.split(":")[1]);
hikari.addDataSourceProperty("databaseName", database);
hikari.addDataSourceProperty("user", username);
hikari.addDataSourceProperty("password", password);
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS)) {
plugin.getLogger().log(Level.SEVERE, "Error occurred whilst initialising the database. All connections are disallowed.");
shutdown();
} else {
setAcceptingLogins(true);
}
}
@Override
public void shutdown() {
if (hikari != null) {
hikari.close();
}
}
@Override
Connection getConnection() throws SQLException {
return hikari.getConnection();
}
}
@@ -0,0 +1,503 @@
package me.lucko.luckperms.data.methods;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.User;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@SuppressWarnings("UnnecessaryLocalVariable")
abstract class SQLDatastore extends Datastore {
private static final Type NM_TYPE = new TypeToken<Map<String, Boolean>>(){}.getType();
private static final Type T_TYPE = new TypeToken<List<String>>(){}.getType();
private static final String USER_INSERT = "INSERT INTO lp_users VALUES(?, ?, ?, ?)";
private static final String USER_SELECT = "SELECT * FROM lp_users WHERE uuid=?";
private static final String USER_UPDATE = "UPDATE lp_users SET name=?, primary_group = ?, perms=? WHERE uuid=?";
private static final String GROUP_INSERT = "INSERT INTO lp_groups VALUES(?, ?)";
private static final String GROUP_SELECT = "SELECT perms FROM lp_groups WHERE name=?";
private static final String GROUP_SELECT_ALL = "SELECT * FROM lp_groups";
private static final String GROUP_UPDATE = "UPDATE lp_groups SET perms=? WHERE name=?";
private static final String GROUP_DELETE = "DELETE FROM lp_groups WHERE name=?";
private static final String TRACK_INSERT = "INSERT INTO lp_tracks VALUES(?, ?)";
private static final String TRACK_SELECT = "SELECT groups FROM lp_tracks WHERE name=?";
private static final String TRACK_SELECT_ALL = "SELECT * FROM lp_tracks";
private static final String TRACK_UPDATE = "UPDATE lp_tracks SET groups=? WHERE name=?";
private static final String TRACK_DELETE = "DELETE FROM lp_tracks WHERE name=?";
private static final String UUIDCACHE_INSERT = "INSERT INTO lp_uuid VALUES(?, ?)";
private static final String UUIDCACHE_SELECT = "SELECT uuid FROM lp_uuid WHERE name=?";
private static final String UUIDCACHE_UPDATE = "UPDATE lp_uuid SET uuid=? WHERE name=?";
private final Gson gson;
SQLDatastore(LuckPermsPlugin plugin, String name) {
super(plugin, name);
gson = new Gson();
}
abstract Connection getConnection() throws SQLException;
private static void close(AutoCloseable closeable) {
if (closeable == null) return;
try {
closeable.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean runQuery(QueryPS queryPS) {
boolean success = false;
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = getConnection();
if (connection == null) {
throw new IllegalStateException("SQL connection is null");
}
preparedStatement = connection.prepareStatement(queryPS.getQuery());
queryPS.onRun(preparedStatement);
preparedStatement.execute();
success = true;
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(preparedStatement);
close(connection);
}
return success;
}
private boolean runQuery(QueryRS queryRS) {
boolean success = false;
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = getConnection();
if (connection == null) {
throw new IllegalStateException("SQL connection is null");
}
preparedStatement = connection.prepareStatement(queryRS.getQuery());
queryRS.onRun(preparedStatement);
preparedStatement.execute();
resultSet = preparedStatement.executeQuery();
success = queryRS.onResult(resultSet);
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(resultSet);
close(preparedStatement);
close(connection);
}
return success;
}
boolean setupTables(String... tableQueries) {
boolean success = true;
for (String q : tableQueries) {
if (!runQuery(new Query(q))) success = false;
}
return success;
}
@Override
public boolean loadUser(UUID uuid) {
User user = plugin.getUserManager().makeUser(uuid);
boolean success = runQuery(new QueryRS(USER_SELECT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, uuid.toString());
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
if (resultSet.next()) {
user.setName(resultSet.getString("name"));
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
user.setPrimaryGroup(resultSet.getString("primary_group"));
return true;
}
return false;
}
});
if (success) plugin.getUserManager().updateOrSetUser(user);
return success;
}
@Override
public boolean loadOrCreateUser(UUID uuid, String username) {
User user = plugin.getUserManager().makeUser(uuid, username);
boolean success = runQuery(new QueryRS(USER_SELECT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, user.getUuid().toString());
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
boolean success = true;
if (!resultSet.next()) {
plugin.getUserManager().giveDefaults(user);
success = runQuery(new QueryPS(USER_INSERT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, user.getUuid().toString());
preparedStatement.setString(2, user.getName());
preparedStatement.setString(3, user.getPrimaryGroup());
preparedStatement.setString(4, gson.toJson(user.getNodes()));
}
});
} else {
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
user.setPrimaryGroup(resultSet.getString("primary_group"));
}
return success;
}
});
if (success) plugin.getUserManager().updateOrSetUser(user);
return success;
}
@Override
public boolean saveUser(User user) {
boolean success = runQuery(new QueryPS(USER_UPDATE) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, user.getName());
preparedStatement.setString(2, user.getPrimaryGroup());
preparedStatement.setString(3, gson.toJson(user.getNodes()));
preparedStatement.setString(4, user.getUuid().toString());
}
});
return success;
}
@Override
public boolean createAndLoadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name);
boolean success = runQuery(new QueryRS(GROUP_SELECT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, group.getName());
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
boolean success = true;
if (!resultSet.next()) {
success = runQuery(new QueryPS(GROUP_INSERT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, group.getName());
preparedStatement.setString(2, gson.toJson(group.getNodes()));
}
});
} else {
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
}
return success;
}
});
if (success) plugin.getGroupManager().updateOrSetGroup(group);
return success;
}
@Override
public boolean loadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name);
boolean success = runQuery(new QueryRS(GROUP_SELECT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, name);
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
if (resultSet.next()) {
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
return true;
}
return false;
}
});
if (success) plugin.getGroupManager().updateOrSetGroup(group);
return success;
}
@Override
public boolean loadAllGroups() {
List<Group> groups = new ArrayList<>();
boolean success = runQuery(new QueryRS(GROUP_SELECT_ALL) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
while (resultSet.next()) {
Group group = plugin.getGroupManager().makeGroup(resultSet.getString("name"));
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
groups.add(group);
}
return true;
}
});
if (success) {
GroupManager gm = plugin.getGroupManager();
gm.unloadAll();
groups.forEach(gm::setGroup);
}
return success;
}
@Override
public boolean saveGroup(Group group) {
boolean success = runQuery(new QueryPS(GROUP_UPDATE) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, gson.toJson(group.getNodes()));
preparedStatement.setString(2, group.getName());
}
});
return success;
}
@Override
public boolean deleteGroup(Group group) {
boolean success = runQuery(new QueryPS(GROUP_DELETE) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, group.getName());
}
});
if (success) plugin.getGroupManager().unloadGroup(group);
return success;
}
@Override
public boolean createAndLoadTrack(String name) {
Track track = plugin.getTrackManager().makeTrack(name);
boolean success = runQuery(new QueryRS(TRACK_SELECT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, track.getName());
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
boolean success = true;
if (!resultSet.next()) {
success = runQuery(new QueryPS(TRACK_INSERT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, track.getName());
preparedStatement.setString(2, gson.toJson(track.getGroups()));
}
});
} else {
track.setGroups(gson.fromJson(resultSet.getString("groups"), T_TYPE));
}
return success;
}
});
if (success) plugin.getTrackManager().updateOrSetTrack(track);
return success;
}
@Override
public boolean loadTrack(String name) {
Track track = plugin.getTrackManager().makeTrack(name);
boolean success = runQuery(new QueryRS(TRACK_SELECT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, name);
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
if (resultSet.next()) {
track.setGroups(gson.fromJson(resultSet.getString("groups"), T_TYPE));
return true;
}
return false;
}
});
if (success) plugin.getTrackManager().updateOrSetTrack(track);
return success;
}
@Override
public boolean loadAllTracks() {
List<Track> tracks = new ArrayList<>();
boolean success = runQuery(new QueryRS(TRACK_SELECT_ALL) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
while (resultSet.next()) {
Track track = plugin.getTrackManager().makeTrack(resultSet.getString("name"));
track.setGroups(gson.fromJson(resultSet.getString("groups"), T_TYPE));
tracks.add(track);
}
return true;
}
});
if (success) {
TrackManager tm = plugin.getTrackManager();
tm.unloadAll();
tracks.forEach(tm::setTrack);
}
return success;
}
@Override
public boolean saveTrack(Track track) {
boolean success = runQuery(new QueryPS(TRACK_UPDATE) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, gson.toJson(track.getGroups()));
preparedStatement.setString(2, track.getName());
}
});
return success;
}
@Override
public boolean deleteTrack(Track track) {
boolean success = runQuery(new QueryPS(TRACK_DELETE) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, track.getName());
}
});
return success;
}
@Override
public boolean saveUUIDData(String username, UUID uuid) {
boolean success = runQuery(new QueryRS(UUIDCACHE_SELECT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, username);
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
boolean success;
if (resultSet.next()) {
success = runQuery(new QueryPS(UUIDCACHE_UPDATE) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, uuid.toString());
preparedStatement.setString(2, username);
}
});
} else {
success = runQuery(new QueryPS(UUIDCACHE_INSERT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, username);
preparedStatement.setString(2, uuid.toString());
}
});
}
return success;
}
});
return success;
}
@Override
public UUID getUUID(String username) {
final UUID[] uuid = {null};
boolean success = runQuery(new QueryRS(UUIDCACHE_SELECT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, username);
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
if (resultSet.next()) {
uuid[0] = UUID.fromString(resultSet.getString("uuid"));
return true;
}
return false;
}
});
return success ? uuid[0] : null;
}
private class Query extends QueryPS {
Query(String query) {
super(query);
}
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
// Do nothing
}
}
@Getter
@AllArgsConstructor
private abstract class QueryPS {
private final String query;
abstract void onRun(PreparedStatement preparedStatement) throws SQLException;
}
@Getter
@AllArgsConstructor
private abstract class QueryRS {
private final String query;
abstract void onRun(PreparedStatement preparedStatement) throws SQLException;
abstract boolean onResult(ResultSet resultSet) throws SQLException;
}
}
@@ -0,0 +1,59 @@
package me.lucko.luckperms.data.methods;
import me.lucko.luckperms.LuckPermsPlugin;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
public class SQLiteDatastore extends SQLDatastore {
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`));";
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`));";
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`));";
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`));";
private final File file;
private Connection connection = null;
public SQLiteDatastore(LuckPermsPlugin plugin, File file) {
super(plugin, "SQLite");
this.file = file;
}
@Override
public void init() {
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS)) {
plugin.getLogger().log(Level.SEVERE, "Error occurred whilst initialising the database. All connections are disallowed.");
shutdown();
} else {
setAcceptingLogins(true);
}
}
@Override
public void shutdown() {
try {
if (connection != null && !connection.isClosed()) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
Connection getConnection() throws SQLException {
if (connection == null || connection.isClosed()) {
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException ignored) {}
connection = DriverManager.getConnection("jdbc:sqlite:" + file.getAbsolutePath());
}
return connection;
}
}
@@ -0,0 +1,4 @@
package me.lucko.luckperms.exceptions;
public class ObjectLacksException extends Exception {
}
@@ -1,4 +0,0 @@
package me.lucko.luckperms.exceptions;
public class ObjectLacksPermissionException extends Exception {
}
@@ -12,7 +12,7 @@ public class Group extends PermissionObject {
@Getter
private final String name;
public Group(String name, LuckPermsPlugin plugin) {
Group(String name, LuckPermsPlugin plugin) {
super(plugin, name);
this.name = name;
}
@@ -17,7 +17,6 @@ public class GroupManager {
public GroupManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
loadAllGroups();
}
/**
@@ -42,7 +41,7 @@ public class GroupManager {
* @param group The group to update or set
*/
public void updateOrSetGroup(Group group) {
if (!groups.containsKey(group.getName())) {
if (!isLoaded(group.getName())) {
// The group isn't already loaded
groups.put(group.getName(), group);
} else {
@@ -69,6 +68,13 @@ public class GroupManager {
}
}
/**
* Unloads all groups from the manager
*/
public void unloadAll() {
groups.clear();
}
/**
* Load all groups from the datastore
*/
@@ -0,0 +1,27 @@
package me.lucko.luckperms.runnables;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
@AllArgsConstructor
public class UpdateTask implements Runnable {
private final LuckPermsPlugin plugin;
@Override
public void run() {
plugin.getLogger().info("Running update task.");
// Reload all of the groups
plugin.getDatastore().loadAllGroups();
String defaultGroup = plugin.getConfiguration().getDefaultGroupName();
if (!plugin.getGroupManager().isLoaded(defaultGroup)) {
plugin.getDatastore().createAndLoadGroup(defaultGroup);
}
// Reload all of the tracks
plugin.getDatastore().loadAllTracks();
// Refresh all online users.
plugin.getUserManager().updateAllUsers();
}
}
@@ -0,0 +1,197 @@
package me.lucko.luckperms.tracks;
import lombok.Getter;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Track {
/**
* The name of the track
*/
@Getter
private final String name;
/**
* The groups within this track
*/
private List<String> groups = new ArrayList<>();
Track(String name) {
this.name = name;
}
/**
* 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() {
return Collections.unmodifiableList(groups);
}
public void setGroups(List<String> groups) {
this.groups.clear();
this.groups.addAll(groups);
}
/**
* Gets the number of groups on this track
* @return the number of groups on this track
*/
public int getSize() {
return groups.size();
}
/**
* 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
*/
public String getNext(Group current) throws ObjectLacksException {
return getNext(current.getName());
}
/**
* 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
*/
public String getPrevious(Group current) throws ObjectLacksException {
return getPrevious(current.getName());
}
/**
* 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
*/
public String getNext(String current) throws ObjectLacksException {
assertContains(current);
if (groups.indexOf(current) == groups.size() - 1) {
return null;
}
return groups.get(groups.indexOf(current) + 1);
}
/**
* 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
*/
public String getPrevious(String current) throws ObjectLacksException {
assertContains(current);
if (groups.indexOf(current) == 0) {
return null;
}
return groups.get(groups.indexOf(current) - 1);
}
/**
* 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
*/
public void appendGroup(Group group) throws ObjectAlreadyHasException {
assertNotContains(group);
groups.add(group.getName());
}
/**
* Inserts a group at a certain position on this track
* @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
*/
public void insertGroup(Group group, int position) throws ObjectAlreadyHasException, IndexOutOfBoundsException {
assertNotContains(group);
groups.add(position, group.getName());
}
/**
* Removes a group from this track
* @param group the group to remove
* @throws ObjectLacksException if the group is not on this track
*/
public void removeGroup(Group group) throws ObjectLacksException {
removeGroup(group.getName());
}
/**
* Removes a group from this track
* @param group the group to remove
* @throws ObjectLacksException if the group is not on this track
*/
public void removeGroup(String group) throws ObjectLacksException {
assertContains(group);
groups.remove(group);
}
/**
* Checks if a group features on this track
* @param group the group to check
* @return true if the group is on this track
*/
public boolean containsGroup(Group group) {
return containsGroup(group.getName());
}
/**
* Checks if a group features on this track
* @param group the group to check
* @return true if the group is on this track
*/
public boolean containsGroup(String group) {
return groups.contains(group);
}
/**
* Clear all of the groups within this track
*/
public void clearGroups() {
groups.clear();
}
private void assertContains(Group g) throws ObjectLacksException {
if (!containsGroup(g)) {
throw new ObjectLacksException();
}
}
private void assertNotContains(Group g) throws ObjectAlreadyHasException {
if (containsGroup(g)) {
throw new ObjectAlreadyHasException();
}
}
private void assertContains(String g) throws ObjectLacksException {
if (!containsGroup(g)) {
throw new ObjectLacksException();
}
}
private void assertNotContains(String g) throws ObjectAlreadyHasException {
if (containsGroup(g)) {
throw new ObjectAlreadyHasException();
}
}
@Override
public String toString() {
return name;
}
}
@@ -0,0 +1,104 @@
package me.lucko.luckperms.tracks;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
public class TrackManager {
private final LuckPermsPlugin plugin;
/**
* A {@link Map} containing all loaded tracks
*/
@Getter
private final Map<String, Track> tracks = new ConcurrentHashMap<>();
public TrackManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
}
/**
* Get a track object by name
* @param name the name to search by
* @return a {@link Track} object if the track is loaded, else returns null
*/
public Track getTrack(String name) {
return tracks.get(name);
}
/**
* Returns a set of tracks that contain at least one of the groups from the Set provided
* @param group the group to filter by
* @return a set of tracks that the groups could be a member of
*/
public Set<Track> getApplicableTracks(String group) {
return tracks.values().stream().filter(t -> t.containsGroup(group)).collect(Collectors.toSet());
}
/**
* Add a track to the loaded tracks map
* @param track The track to add
*/
public void setTrack(Track track) {
tracks.put(track.getName(), track);
}
/**
* Updates (or sets if the track wasn't already loaded) a track in the tracks map
* @param track The track to update or set
*/
public void updateOrSetTrack(Track track) {
if (!isLoaded(track.getName())) {
// The track isn't already loaded
tracks.put(track.getName(), track);
} else {
tracks.get(track.getName()).setGroups(track.getGroups());
}
}
/**
* Check to see if a track is loaded or not
* @param name The name of the track
* @return true if the track is loaded
*/
public boolean isLoaded(String name) {
return tracks.containsKey(name);
}
/**
* Removes and unloads the track from the plugins internal storage
* @param track The track to unload
*/
public void unloadTrack(Track track) {
if (track != null) {
tracks.remove(track.getName());
}
}
/**
* Unloads all tracks from the manager
*/
public void unloadAll() {
tracks.clear();
}
/**
* Load all tracks from the datastore
*/
public void loadAllTracks() {
plugin.getDatastore().loadAllTracks(success -> {});
}
/**
* Makes a new track object
* @param name The name of the track
* @return a new {@link Track} object
*/
public Track makeTrack(String name) {
return new Track(name);
}
}
@@ -4,13 +4,13 @@ import lombok.Getter;
import lombok.Setter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Patterns;
import me.lucko.luckperms.utils.PermissionObject;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
public abstract class User extends PermissionObject {
@@ -27,13 +27,20 @@ public abstract class User extends PermissionObject {
@Setter
private String name;
public User(UUID uuid, LuckPermsPlugin plugin) {
/**
* The users primary group
*/
@Getter
@Setter
private String primaryGroup = null;
User(UUID uuid, LuckPermsPlugin plugin) {
super(plugin, uuid.toString());
this.uuid = uuid;
this.name = null;
}
public User(UUID uuid, String name, LuckPermsPlugin plugin) {
User(UUID uuid, String name, LuckPermsPlugin plugin) {
super(plugin, uuid.toString());
this.uuid = uuid;
this.name = name;
@@ -60,7 +67,7 @@ public abstract class User extends PermissionObject {
* @return true if the user is a member of the group
*/
public boolean isInGroup(Group group, String server) {
return getLocalGroups(server).contains(group.getName());
return hasPermission("group." + group.getName(), true, server);
}
/**
@@ -83,23 +90,15 @@ public abstract class User extends PermissionObject {
server = "global";
}
if (isInGroup(group, server)) {
throw new ObjectAlreadyHasException();
}
if (server.equalsIgnoreCase("global")) {
getNodes().put("luckperms.group." + group.getName(), true);
} else {
getNodes().put(server + "/luckperms.group." + group.getName(), true);
}
setPermission("group." + group.getName(), true, server);
}
/**
* Remove the user from a group
* @param group the group to remove the user from
* @throws ObjectLacksPermissionException
* @throws ObjectLacksException if the user isn't a member of the group
*/
public void removeGroup(Group group) throws ObjectLacksPermissionException {
public void removeGroup(Group group) throws ObjectLacksException {
removeGroup(group, "global");
}
@@ -107,22 +106,14 @@ public abstract class User extends PermissionObject {
* Remove the user from a group
* @param group The group to remove the user from
* @param server The server to remove the group on
* @throws ObjectLacksPermissionException if the user isn't a member of the group
* @throws ObjectLacksException if the user isn't a member of the group
*/
public void removeGroup(Group group, String server) throws ObjectLacksPermissionException {
public void removeGroup(Group group, String server) throws ObjectLacksException {
if (server == null) {
server = "global";
}
if (!getLocalGroups(server).contains(group.getName())) {
throw new ObjectLacksPermissionException();
}
if (server.equalsIgnoreCase("global")) {
getNodes().remove("luckperms.group." + group.getName());
} else {
getNodes().remove(server + "/luckperms.group." + group.getName());
}
unsetPermission("group." + group.getName(), server);
}
/**
@@ -139,7 +130,7 @@ public abstract class User extends PermissionObject {
* @return a {@link List} of group names
*/
public List<String> getGroupNames() {
return getGroups(null, true, true);
return getGroups(null, null, true);
}
/**
@@ -148,45 +139,89 @@ public abstract class User extends PermissionObject {
* @return a {@link List} of group names
*/
public List<String> getLocalGroups(String server) {
return getGroups(server, false, false);
return getGroups(server, null, false);
}
/**
* Get a {@link List} of the groups the user is a member of on a specific server with the option to include global groups or all groups
* @param server Which server to check on
* @param excludedGroups groups to exclude (prevents circular inheritance issues)
* @param includeGlobal Whether to include global groups
* @param includeAll Whether to get all groups
* @return a {@link List} of group names
*/
public List<String> getGroups(String server, boolean includeGlobal, boolean includeAll) {
private List<String> getGroups(String server, List<String> excludedGroups, boolean includeGlobal) {
if (excludedGroups == null) {
excludedGroups = new ArrayList<>();
}
excludedGroups.add(getObjectName());
List<String> groups = new ArrayList<>();
if (server == null || server.equals("")) {
server = "global";
}
for (String node : getNodes().keySet()) {
String originalNode = node;
// Has a defined server
if (node.contains("/")) {
String[] parts = node.split("\\/", 2);
if (!parts[0].equalsIgnoreCase(server) && !includeAll) {
/*
Priority:
1. server specific group nodes
2. group nodes
*/
final Map<String, Boolean> serverSpecificGroups = new HashMap<>();
final Map<String, Boolean> groupNodes = new HashMap<>();
// Sorts the permissions and puts them into a priority order
for (Map.Entry<String, Boolean> node : getNodes().entrySet()) {
serverSpecific:
if (node.getKey().contains("/")) {
String[] parts = node.getKey().split("\\/", 2);
if (parts[0].equalsIgnoreCase("global")) {
// REGULAR
break serverSpecific;
}
if (!parts[0].equalsIgnoreCase(server)) {
// SERVER SPECIFIC BUT DOES NOT APPLY
continue;
}
node = parts[1];
} else {
if (!includeGlobal) {
if (Patterns.GROUP_MATCH.matcher(parts[1]).matches()) {
// SERVER SPECIFIC AND GROUP
serverSpecificGroups.put(node.getKey(), node.getValue());
continue;
}
continue;
}
if (node.matches("luckperms\\.group\\..*")) {
if (getNodes().get(originalNode)) {
String groupName = node.split("\\.", 3)[2];
groups.add(groupName);
}
// Skip adding global permissions if they are not requested
if (!includeGlobal) continue;
if (Patterns.GROUP_MATCH.matcher(node.getKey()).matches()) {
// GROUP
groupNodes.put(node.getKey(), node.getValue());
}
}
// If a group is negated at a higher priority, the group should not then be applied at a lower priority
serverSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
groupNodes.remove(node.getKey());
groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
});
groups.addAll(serverSpecificGroups.entrySet().stream()
.filter(Map.Entry::getValue)
.map(e -> Patterns.DOT_SPLIT.split(e.getKey(), 2)[1])
.collect(Collectors.toList())
);
groups.addAll(groupNodes.entrySet().stream()
.filter(Map.Entry::getValue)
.map(e -> Patterns.DOT_SPLIT.split(e.getKey(), 2)[1])
.collect(Collectors.toList())
);
return groups;
}
@@ -1,17 +1,15 @@
package me.lucko.luckperms.users;
import lombok.Getter;
import lombok.NoArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@NoArgsConstructor
public abstract class UserManager {
/**
@@ -20,6 +18,15 @@ public abstract class UserManager {
@Getter
private final Map<UUID, User> users = new ConcurrentHashMap<>();
/**
* Reference to main plugin instance
*/
private final LuckPermsPlugin plugin;
public UserManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
}
/**
* Get a user object by UUID
* @param uuid The uuid to search by
@@ -34,17 +41,13 @@ public abstract class UserManager {
* @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
*/
@SuppressWarnings("OptionalGetWithoutIsPresent")
public User getUser(String name) {
User user = null;
for (User u : users.values()) {
if (u.getName().equalsIgnoreCase(name)) {
user = u;
break;
}
try {
return users.values().stream().filter(u -> u.getName().equalsIgnoreCase(name)).limit(1).findAny().get();
} catch (NoSuchElementException e) {
return null;
}
return user;
}
/**
@@ -60,7 +63,7 @@ public abstract class UserManager {
* @param user The user to update or set
*/
public void updateOrSetUser(User user) {
if (!users.containsKey(user.getUuid())) {
if (!isLoaded(user.getUuid())) {
// The user isn't already loaded, so we can just add
users.put(user.getUuid(), user);
// They're probably not online, but in case they are...
@@ -68,6 +71,7 @@ public abstract class UserManager {
} else {
// Override the user's current loaded nodes, and force a refresh
users.get(user.getUuid()).setNodes(user.getNodes());
users.get(user.getUuid()).setPrimaryGroup(user.getPrimaryGroup());
users.get(user.getUuid()).refreshPermissions();
}
}
@@ -82,6 +86,18 @@ public abstract class UserManager {
datastore.saveUser(user, success -> {});
}
/**
* Set a user to the default group
* @param user the user to give to
*/
public void giveDefaults(User user) {
// Setup the new user with default values
try {
user.setPermission(plugin.getConfiguration().getDefaultGroupNode(), true);
} catch (ObjectAlreadyHasException ignored) {}
user.setPrimaryGroup(plugin.getConfiguration().getDefaultGroupName());
}
/**
* Check to see if a user is loaded or not
* @param uuid the UUID of the user
@@ -117,4 +133,9 @@ public abstract class UserManager {
* @return a new {@link User} object
*/
public abstract User makeUser(UUID uuid, String username);
/**
* Reloads the data of all online users
*/
public abstract void updateAllUsers();
}
@@ -3,11 +3,11 @@ package me.lucko.luckperms.utils;
public interface LPConfiguration {
String getServer();
String getPrefix();
int getSyncTime();
String getDefaultGroupNode();
String getDefaultGroupName();
boolean getIncludeGlobalPerms();
String getDatabaseValue(String value);
String getStorageMethod();
}
@@ -0,0 +1,14 @@
package me.lucko.luckperms.utils;
import java.util.regex.Pattern;
public class Patterns {
public static final Pattern SERVER_SPLIT = Pattern.compile("\\/");
public static final Pattern DOT_SPLIT = Pattern.compile("\\.");
public static final Pattern GROUP_MATCH = Pattern.compile("group\\..*");
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[^A-Za-z0-9]");
private Patterns() {}
}
@@ -2,17 +2,15 @@ package me.lucko.luckperms.utils;
import lombok.Getter;
import lombok.Setter;
import lombok.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Represents an object that can hold permissions
@@ -36,7 +34,6 @@ public abstract class PermissionObject {
* If false, only permissions specific to the server are applied
*/
@Setter
private boolean includeGlobalPermissions;
/**
@@ -45,7 +42,7 @@ public abstract class PermissionObject {
@Setter
private Map<String, Boolean> nodes = new HashMap<>();
public PermissionObject(LuckPermsPlugin plugin, String objectName) {
protected PermissionObject(LuckPermsPlugin plugin, String objectName) {
this.objectName = objectName;
this.plugin = plugin;
this.includeGlobalPermissions = plugin.getConfiguration().getIncludeGlobalPerms();
@@ -59,10 +56,7 @@ public abstract class PermissionObject {
*/
public boolean hasPermission(String node, Boolean b) {
if (node.startsWith("global/")) node = node.replace("global/", "");
if (b) {
return getNodes().containsKey(node) && getNodes().get(node);
}
return getNodes().containsKey(node) && !getNodes().get(node);
return b ? getNodes().containsKey(node) && getNodes().get(node) : getNodes().containsKey(node) && !getNodes().get(node);
}
/**
@@ -76,6 +70,34 @@ public abstract class PermissionObject {
return hasPermission(server + "/" + node, b);
}
/**
* Checks to see if the object inherits a certain permission
* @param node The permission node
* @param b If the node is true/false(negated)
* @return true if the user inherits the permission
*/
public boolean inheritsPermission(String node, Boolean b) {
if (node.contains("/")) {
// Use other method
final String[] parts = Patterns.SERVER_SPLIT.split(node, 2);
return inheritsPermission(parts[1], b, parts[0]);
}
return inheritsPermission(node, b, "global");
}
/**
* Checks to see the the object inherits a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @return true if the user inherits the permission
*/
public boolean inheritsPermission(String node, Boolean b, String server) {
final Map<String, Boolean> local = getLocalPermissions(server, null);
return b ? local.containsKey(node) && local.get(node) : local.containsKey(node) && !local.get(node);
}
/**
* Sets a permission for the object
* @param node The node to be set
@@ -104,14 +126,13 @@ public abstract class PermissionObject {
/**
* Unsets a permission for the object
* @param node The node to be unset
* @throws ObjectLacksPermissionException if the node wasn't already set
* @throws ObjectLacksException if the node wasn't already set
*/
public void unsetPermission(String node) throws ObjectLacksPermissionException {
public void unsetPermission(String node) throws ObjectLacksException {
if (node.startsWith("global/")) node = node.replace("global/", "");
if (!getNodes().containsKey(node)) {
throw new ObjectLacksPermissionException();
throw new ObjectLacksException();
}
getNodes().remove(node);
}
@@ -119,9 +140,9 @@ public abstract class PermissionObject {
* Unsets a permission for the object
* @param node The node to be unset
* @param server The server to unset the node on
* @throws ObjectLacksPermissionException if the node wasn't already set
* @throws ObjectLacksException if the node wasn't already set
*/
public void unsetPermission(String node, String server) throws ObjectLacksPermissionException {
public void unsetPermission(String node, String server) throws ObjectLacksException {
unsetPermission(server + "/" + node);
}
@@ -133,7 +154,6 @@ public abstract class PermissionObject {
*/
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups) {
return getPermissions(server, excludedGroups, includeGlobalPermissions);
}
private Map<String, Boolean> getPermissions(String server, List<String> excludedGroups, boolean includeGlobal) {
@@ -148,87 +168,118 @@ public abstract class PermissionObject {
server = "global";
}
for (String node : getNodes().keySet()) {
String originalNode = node;
// Has a defined server
if (node.contains("/")) {
String[] parts = node.split("\\/", 2);
/*
Priority:
1. server specific nodes
2. user nodes
3. server specific group nodes
4. group nodes
*/
final Map<String, Boolean> serverSpecificNodes = new HashMap<>();
final Map<String, Boolean> userNodes = new HashMap<>();
final Map<String, Boolean> serverSpecificGroups = new HashMap<>();
final Map<String, Boolean> groupNodes = new HashMap<>();
// Sorts the permissions and puts them into a priority order
for (Map.Entry<String, Boolean> node : getNodes().entrySet()) {
serverSpecific:
if (node.getKey().contains("/")) {
String[] parts = Patterns.SERVER_SPLIT.split(node.getKey(), 2);
if (parts[0].equalsIgnoreCase("global")) {
// REGULAR
break serverSpecific;
}
if (!parts[0].equalsIgnoreCase(server)) {
// SERVER SPECIFIC BUT DOES NOT APPLY
continue;
}
node = parts[1];
perms.put(node, getNodes().get(originalNode));
continue;
}
if (node.matches("luckperms\\.group\\..*")) {
if (getNodes().get(originalNode)) {
String groupName = node.split("\\.", 3)[2];
Group group = plugin.getGroupManager().getGroup(groupName);
if (!excludedGroups.contains(groupName)) {
if (group != null) {
perms.putAll(group.getLocalPermissions(server, excludedGroups));
} else {
plugin.getLogger().warning("Error whilst refreshing the permissions of '" + objectName + "'." +
"\n The group '" + groupName + "' is not loaded.");
}
}
if (Patterns.GROUP_MATCH.matcher(parts[1]).matches()) {
// SERVER SPECIFIC AND GROUP
serverSpecificGroups.put(node.getKey(), node.getValue());
continue;
}
perms.put(node, getNodes().get(originalNode));
// SERVER SPECIFIC
serverSpecificNodes.put(node.getKey(), node.getValue());
continue;
}
if (includeGlobal) perms.put(node, getNodes().get(originalNode));
// Skip adding global permissions if they are not requested
if (!includeGlobal) continue;
if (Patterns.GROUP_MATCH.matcher(node.getKey()).matches()) {
// GROUP
groupNodes.put(node.getKey(), node.getValue());
continue;
}
// JUST NORMAL
userNodes.put(node.getKey(), node.getValue());
}
// If a group is negated at a higher priority, the group should not then be applied at a lower priority
serverSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> {
groupNodes.remove(node.getKey());
groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]);
});
// Apply lowest priority: groupNodes
for (Map.Entry<String, Boolean> groupNode : groupNodes.entrySet()) {
// Add the actual group perm node, so other plugins can hook
perms.put(groupNode.getKey(), groupNode.getValue());
// Don't add negated groups
if (!groupNode.getValue()) continue;
String groupName = Patterns.DOT_SPLIT.split(groupNode.getKey(), 2)[1];
if (!excludedGroups.contains(groupName)) {
Group group = plugin.getGroupManager().getGroup(groupName);
if (group != null) {
perms.putAll(group.getLocalPermissions(server, excludedGroups));
} else {
plugin.getLogger().warning("Error whilst refreshing the permissions of '" + objectName + "'." +
"\n The group '" + groupName + "' is not loaded.");
}
}
}
// Apply next priority: serverSpecificGroups
for (Map.Entry<String, Boolean> groupNode : serverSpecificGroups.entrySet()) {
final String rawNode = Patterns.SERVER_SPLIT.split(groupNode.getKey())[1];
// Add the actual group perm node, so other plugins can hook
perms.put(rawNode, groupNode.getValue());
// Don't add negated groups
if (!groupNode.getValue()) continue;
String groupName = Patterns.DOT_SPLIT.split(rawNode, 2)[1];
if (!excludedGroups.contains(groupName)) {
Group group = plugin.getGroupManager().getGroup(groupName);
if (group != null) {
perms.putAll(group.getLocalPermissions(server, excludedGroups));
} else {
plugin.getLogger().warning("Error whilst refreshing the permissions of '" + objectName + "'." +
"\n The group '" + groupName + "' is not loaded.");
}
}
}
// Apply next priority: userNodes
perms.putAll(userNodes);
// Apply highest priority: serverSpecificNodes
for (Map.Entry<String, Boolean> node : serverSpecificNodes.entrySet()) {
final String rawNode = Patterns.SERVER_SPLIT.split(node.getKey())[1];
perms.put(rawNode, node.getValue());
}
return perms;
}
/**
* Loads a list of semi-serialised nodes into the object
* @param data The data to be loaded
*/
public void loadNodes(List<String> data) {
// String is the node in format "server/plugin.command-false" or "plugin.command-false" or "server/plugin.command"
// or just "plugin.command"
for (String s : data) {
String[] parts = s.split("-", 2);
if (parts.length == 2) {
nodes.put(parts[0], Boolean.valueOf(parts[1]));
} else {
nodes.put(parts[0], true);
}
}
}
/**
* Convert the permission nodes map to a list of strings
* @return a {@link List} of nodes
*/
public List<String> getNodesAsString() {
List<String> data = new ArrayList<>();
for (String node : nodes.keySet()) {
if (nodes.get(node)) {
data.add(node);
} else {
data.add(node + "-false");
}
}
return data;
}
/**
* Serialize the nodes in the object to be saved in the datastore
* @return A serialized string
*/
public String serializeNodes() {
if (nodes.isEmpty()) return "#";
return getNodesAsString().stream().collect(Collectors.joining(":"));
}
}
+13 -11
View File
@@ -7,7 +7,7 @@
<groupId>me.lucko</groupId>
<artifactId>luckperms</artifactId>
<version>1.0-SNAPSHOT</version>
<version>1.1</version>
<modules>
<module>bukkit</module>
<module>common</module>
@@ -35,27 +35,29 @@
<!-- HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-java6</artifactId>
<version>2.0.1</version>
<artifactId>HikariCP</artifactId>
<version>2.4.7</version>
<scope>compile</scope>
</dependency>
<!-- Javaassist library -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.1-GA</version>
</dependency>
<!-- slf4j library -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
<version>1.7.9</version>
<scope>compile</scope>
</dependency>
<!-- gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
<scope>provided</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.8</version>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
</dependencies>