diff --git a/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java
index 545d374a..11949eb4 100644
--- a/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java
+++ b/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java
@@ -156,6 +156,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return getDescription().getVersion();
}
+ @Override
+ public Type getType() {
+ return Type.BUKKIT;
+ }
+
@Override
public File getMainDir() {
return getDataFolder();
@@ -198,6 +203,21 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return perms;
}
+ @Override
+ public Object getPlugin(String name) {
+ return getServer().getPluginManager().getPlugin(name);
+ }
+
+ @Override
+ public Object getService(Class clazz) {
+ return getServer().getServicesManager().load(clazz);
+ }
+
+ @Override
+ public boolean isPluginLoaded(String name) {
+ return getServer().getPluginManager().isPluginEnabled(name);
+ }
+
@Override
public void runUpdateTask() {
getServer().getScheduler().runTaskAsynchronously(this, new UpdateTask(this));
diff --git a/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java b/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java
index 39b59411..00a5f0e6 100644
--- a/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java
+++ b/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java
@@ -126,6 +126,11 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
return getDescription().getVersion();
}
+ @Override
+ public Type getType() {
+ return Type.BUNGEE;
+ }
+
@Override
public File getMainDir() {
return getDataFolder();
@@ -162,6 +167,24 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
return Collections.emptyList();
}
+ @Override
+ public Object getPlugin(String name) {
+ return getProxy().getPluginManager().getPlugin(name);
+ }
+
+ @Override
+ public Object getService(Class clazz) {
+ return null;
+ }
+
+ @Override
+ public boolean isPluginLoaded(String name) {
+ return getProxy().getPluginManager().getPlugins().stream()
+ .filter(p -> p.getDescription().getName().equalsIgnoreCase(name))
+ .findAny()
+ .isPresent();
+ }
+
@Override
public void runUpdateTask() {
doAsync(new UpdateTask(this));
diff --git a/common/pom.xml b/common/pom.xml
index 6c3303dc..80b4dd49 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -88,6 +88,37 @@
1.16.10
provided
+
+
+ org.tyrannyofheaven.bukkit
+ zPermissions
+ 1.3
+ provided
+
+
+ ru.tehkode
+ PermissionsEx
+ 1.23
+ provided
+
+
+ org.bukkit
+ bukkit
+
+
+
+
+ com.github.cheesesoftware
+ PowerfulPermsAPI
+ 1.0.1
+ provided
+
+
+ org.anjocaido
+ GroupManager
+ 1.4
+ provided
+
diff --git a/common/src/main/java/me/lucko/luckperms/LuckPermsPlugin.java b/common/src/main/java/me/lucko/luckperms/LuckPermsPlugin.java
index e339f9f8..85cfda78 100644
--- a/common/src/main/java/me/lucko/luckperms/LuckPermsPlugin.java
+++ b/common/src/main/java/me/lucko/luckperms/LuckPermsPlugin.java
@@ -63,6 +63,12 @@ public interface LuckPermsPlugin {
*/
String getVersion();
+
+ /**
+ * @return the platform type
+ */
+ Type getType();
+
/**
* @return the main plugin directory
*/
@@ -114,6 +120,27 @@ public interface LuckPermsPlugin {
*/
Set getIgnoringLogs();
+ /**
+ * Gets a loaded plugins instance from the platform
+ * @param name the name of the plugin
+ * @return a plugin instance
+ */
+ Object getPlugin(String name);
+
+ /**
+ * Gets a provided service from the platform.
+ * @param clazz the class of the service
+ * @return the service instance, if it is provided for
+ */
+ Object getService(Class clazz);
+
+ /**
+ * Checks if a plugin is loaded on the platform
+ * @param name the name of the plugin
+ * @return true if the plugin is loaded
+ */
+ boolean isPluginLoaded(String name);
+
/**
* Runs an update task
*/
@@ -130,4 +157,9 @@ public interface LuckPermsPlugin {
* @param r the task to run
*/
void doSync(Runnable r);
+
+
+ enum Type {
+ BUKKIT, BUNGEE, SPONGE;
+ }
}
diff --git a/common/src/main/java/me/lucko/luckperms/commands/CommandManager.java b/common/src/main/java/me/lucko/luckperms/commands/CommandManager.java
index 38a6208d..58ca429c 100644
--- a/common/src/main/java/me/lucko/luckperms/commands/CommandManager.java
+++ b/common/src/main/java/me/lucko/luckperms/commands/CommandManager.java
@@ -63,6 +63,7 @@ public class CommandManager {
.add(new InfoCommand())
.add(new DebugCommand())
.add(new ImportCommand())
+ // .add(new MigrationMainCommand()) TODO
.add(new CreateGroup())
.add(new DeleteGroup())
.add(new ListGroups())
diff --git a/common/src/main/java/me/lucko/luckperms/commands/MainCommand.java b/common/src/main/java/me/lucko/luckperms/commands/MainCommand.java
index 885f852d..0cf202de 100644
--- a/common/src/main/java/me/lucko/luckperms/commands/MainCommand.java
+++ b/common/src/main/java/me/lucko/luckperms/commands/MainCommand.java
@@ -76,7 +76,7 @@ public abstract class MainCommand {
return CommandResult.INVALID_ARGS;
}
- Optional> o = subCommands.stream()
+ Optional> o = getSubCommands().stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(requiredArgsLength - 1)))
.limit(1)
.findAny();
diff --git a/common/src/main/java/me/lucko/luckperms/commands/migration/MigrationMainCommand.java b/common/src/main/java/me/lucko/luckperms/commands/migration/MigrationMainCommand.java
new file mode 100644
index 00000000..ef071c13
--- /dev/null
+++ b/common/src/main/java/me/lucko/luckperms/commands/migration/MigrationMainCommand.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016 Lucko (Luck)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.lucko.luckperms.commands.migration;
+
+import me.lucko.luckperms.LuckPermsPlugin;
+import me.lucko.luckperms.commands.CommandResult;
+import me.lucko.luckperms.commands.MainCommand;
+import me.lucko.luckperms.commands.Sender;
+import me.lucko.luckperms.commands.SubCommand;
+import me.lucko.luckperms.commands.migration.subcommands.MigrationPowerfulPerms;
+import me.lucko.luckperms.constants.Constants;
+import me.lucko.luckperms.constants.Message;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class MigrationMainCommand extends MainCommand {
+ private final List> subCommands = new ArrayList<>();
+
+ public MigrationMainCommand() {
+ super("Migration", "/%s migration", 1, null);
+
+ try {
+ subCommands.add(new MigrationPowerfulPerms());
+ } catch (Throwable ignored) {
+ }
+
+ }
+
+ @Override
+ public List> getSubCommands() {
+ return subCommands;
+ }
+
+ @Override
+ protected boolean isAuthorized(Sender sender) {
+ return sender.getUuid().equals(Constants.getConsoleUUID());
+ }
+
+ @Override
+ protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List args, String label) {
+ if (!sender.getUuid().equals(Constants.getConsoleUUID())) {
+ Message.MIGRATION_NOT_CONSOLE.send(sender);
+ return CommandResult.NO_PERMISSION;
+ }
+
+ return super.execute(plugin, sender, args, label);
+ }
+
+ @Override
+ protected Object getTarget(String target, LuckPermsPlugin plugin, Sender sender) {
+ return new Object();
+ }
+
+ @Override
+ protected void cleanup(Object object, LuckPermsPlugin plugin) {
+
+ }
+
+ @Override
+ protected List getObjects(LuckPermsPlugin plugin) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ protected List onTabComplete(Sender sender, List args, LuckPermsPlugin plugin) {
+ return Collections.emptyList();
+ }
+
+}
diff --git a/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationGroupManager.java b/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationGroupManager.java
new file mode 100644
index 00000000..9bcc8928
--- /dev/null
+++ b/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationGroupManager.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Lucko (Luck)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.lucko.luckperms.commands.migration.subcommands;
+
+import me.lucko.luckperms.LuckPermsPlugin;
+import me.lucko.luckperms.api.Logger;
+import me.lucko.luckperms.commands.CommandResult;
+import me.lucko.luckperms.commands.Predicate;
+import me.lucko.luckperms.commands.Sender;
+import me.lucko.luckperms.commands.SubCommand;
+import me.lucko.luckperms.constants.Permission;
+import org.anjocaido.groupmanager.GroupManager;
+
+import java.util.List;
+
+public class MigrationGroupManager extends SubCommand {
+ public MigrationGroupManager() {
+ super("groupmanager", "Migration from GroupManager",
+ "/%s migration groupmanager [world names]", Permission.MIGRATION, Predicate.alwaysFalse());
+ }
+
+ @Override
+ public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List args, String label) {
+ final Logger log = plugin.getLog();
+ if (!plugin.isPluginLoaded("GroupManager")) {
+ log.severe("GroupManager Migration: Error -> GroupManager is not loaded.");
+ return CommandResult.STATE_ERROR;
+ }
+
+ GroupManager gm = (GroupManager) plugin.getPlugin("GroupManager");
+
+ // Migrate all users.
+ log.info("GroupManager Migration: Starting user migration.");
+
+ // gm.getWorldsHolder().getWorldData().
+ // TODO
+ return null;
+ }
+}
diff --git a/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationPermissionsEx.java b/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationPermissionsEx.java
new file mode 100644
index 00000000..fa5cb44a
--- /dev/null
+++ b/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationPermissionsEx.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2016 Lucko (Luck)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.lucko.luckperms.commands.migration.subcommands;
+
+import me.lucko.luckperms.LuckPermsPlugin;
+import me.lucko.luckperms.api.Logger;
+import me.lucko.luckperms.commands.CommandResult;
+import me.lucko.luckperms.commands.Predicate;
+import me.lucko.luckperms.commands.Sender;
+import me.lucko.luckperms.commands.SubCommand;
+import me.lucko.luckperms.constants.Permission;
+import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
+import me.lucko.luckperms.groups.Group;
+import me.lucko.luckperms.users.User;
+import ru.tehkode.permissions.PermissionGroup;
+import ru.tehkode.permissions.PermissionManager;
+import ru.tehkode.permissions.PermissionUser;
+import ru.tehkode.permissions.bukkit.PermissionsEx;
+
+import java.util.List;
+import java.util.UUID;
+
+public class MigrationPermissionsEx extends SubCommand {
+ public MigrationPermissionsEx() {
+ super("permissionsex", "Migration from PermissionsEx",
+ "/%s migration permissionsex [world names]", Permission.MIGRATION, Predicate.alwaysFalse());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List args, String label) {
+ final Logger log = plugin.getLog();
+ if (!plugin.isPluginLoaded("PermissionsEx")) {
+ log.severe("PermissionsEx Migration: Error -> PermissionsEx is not loaded.");
+ return CommandResult.STATE_ERROR;
+ }
+
+ PermissionsEx pex = (PermissionsEx) plugin.getPlugin("PermissionsEx");
+ PermissionManager manager = null; // TODO
+
+ // Migrate all users
+ log.info("PermissionsEx Migration: Starting user migration.");
+ for (PermissionUser user : manager.getUsers()) {
+ UUID u = UUID.fromString(user.getIdentifier());
+ plugin.getDatastore().loadOrCreateUser(u, "null");
+ User lpUser = plugin.getUserManager().get(u);
+
+ try {
+ for (String node : user.getOwnPermissions(null)) {
+ boolean value = true;
+ if (node.startsWith("!")) {
+ node = node.substring(1);
+ value = false;
+ }
+
+ try {
+ lpUser.setPermission(node, value);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ } catch (NullPointerException ignored) {
+ // Probably won't happen. I have no API docs on getOwnPermissions#null though.
+ }
+
+ if (args != null && !args.isEmpty()) {
+ for (String world : args) {
+ for (String node : user.getOwnPermissions(world)) {
+ boolean value = true;
+ if (node.startsWith("!")) {
+ node = node.substring(1);
+ value = false;
+ }
+
+ try {
+ lpUser.setPermission(node, value, "global", world);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ }
+ }
+
+ for (String s : user.getGroupNames()) {
+ try {
+ lpUser.setPermission("group." + s.toLowerCase(), true);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+
+ if (args != null && !args.isEmpty()) {
+ for (String world : args) {
+ for (String s : user.getGroupNames(world)) {
+ try {
+ lpUser.setPermission("group." + s.toLowerCase(), true, "global", world);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ }
+ }
+
+ plugin.getUserManager().cleanup(lpUser);
+ plugin.getDatastore().saveUser(lpUser);
+ }
+
+ // Migrate all groups.
+ log.info("PermissionsEx Migration: Starting group migration.");
+ for (PermissionGroup group : manager.getGroupList()) {
+ final String name = group.getName().toLowerCase();
+ plugin.getDatastore().createAndLoadGroup(name);
+ Group lpGroup = plugin.getGroupManager().get(name);
+
+ try {
+ for (String node : group.getOwnPermissions(null)) {
+ boolean value = true;
+ if (node.startsWith("!")) {
+ node = node.substring(1);
+ value = false;
+ }
+
+ try {
+ lpGroup.setPermission(node, value);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ } catch (NullPointerException ignored) {
+ // Probably won't happen. I have no API docs on getOwnPermissions#null though.
+ }
+
+ if (args != null && !args.isEmpty()) {
+ for (String world : args) {
+ for (String node : group.getOwnPermissions(world)) {
+ boolean value = true;
+ if (node.startsWith("!")) {
+ node = node.substring(1);
+ value = false;
+ }
+
+ try {
+ lpGroup.setPermission(node, value, "global", world);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ }
+ }
+
+ for (PermissionGroup g : group.getParents()) {
+ try {
+ lpGroup.setPermission("group." + g.getName().toLowerCase(), true);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+
+ if (args != null && !args.isEmpty()) {
+ for (String world : args) {
+ for (PermissionGroup g : group.getParents(world)) {
+ try {
+ lpGroup.setPermission("group." + g.getName().toLowerCase(), true, "global", world);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ }
+ }
+ }
+
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationPowerfulPerms.java b/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationPowerfulPerms.java
new file mode 100644
index 00000000..e8db26c2
--- /dev/null
+++ b/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationPowerfulPerms.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2016 Lucko (Luck)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.lucko.luckperms.commands.migration.subcommands;
+
+import com.github.cheesesoftware.PowerfulPermsAPI.*;
+import com.zaxxer.hikari.HikariDataSource;
+import lombok.Cleanup;
+import me.lucko.luckperms.LuckPermsPlugin;
+import me.lucko.luckperms.api.Logger;
+import me.lucko.luckperms.commands.CommandResult;
+import me.lucko.luckperms.commands.Predicate;
+import me.lucko.luckperms.commands.Sender;
+import me.lucko.luckperms.commands.SubCommand;
+import me.lucko.luckperms.core.PermissionHolder;
+import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
+import me.lucko.luckperms.users.User;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+
+import static me.lucko.luckperms.constants.Permission.MIGRATION;
+
+public class MigrationPowerfulPerms extends SubCommand {
+ /*
+ What kind of API requires reflection to function with multiple versions...
+ Doesn't that just defeat the whole god damn point of having an API in the first place?
+ Whatever happened to the concept of depreciation and responsible API creation?
+ I tried to keep reflection to a minimum, but in some places there's no other option.
+ This class is a complete fucking mess for that reason. I sad now :(
+ */
+ private static Method getPlayerGroupsMethod = null;
+ private static Method getGroupMethod = null;
+ private static boolean legacy = true;
+
+ static {
+ try {
+ getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerOwnGroups", UUID.class, ResultRunnable.class);
+ getPlayerGroupsMethod.setAccessible(true);
+ } catch (NoSuchMethodException e) {
+ try {
+ getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerGroups", UUID.class, ResultRunnable.class);
+ getPlayerGroupsMethod.setAccessible(true);
+ } catch (NoSuchMethodException e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ try {
+ getGroupMethod = CachedGroup.class.getMethod("getGroup");
+ getGroupMethod.setAccessible(true);
+ legacy = true;
+ } catch (NoSuchMethodException ignored) {
+ }
+ }
+
+
+ public MigrationPowerfulPerms() {
+ super("powerfulperms", "Migration from PowerfulPerms",
+ "/%s migration powerfulperms ", MIGRATION, Predicate.not(5));
+ }
+
+ @Override
+ public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List args, String label) {
+ try {
+ return run(plugin, args);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ return CommandResult.FAILURE;
+ }
+ }
+
+ private CommandResult run(LuckPermsPlugin plugin, List args) {
+ final Logger log = plugin.getLog();
+ if (!plugin.isPluginLoaded("PowerfulPerms")) {
+ log.severe("PowerfulPerms Migration: Error -> PowerfulPerms is not loaded.");
+ return CommandResult.STATE_ERROR;
+ }
+
+ final String address = args.get(0);
+ final String database = args.get(1);
+ final String username = args.get(2);
+ final String password = args.get(3);
+ final String dbTable = args.get(4);
+
+ // Find a list of UUIDs
+ log.info("PowerfulPerms Migration: Getting a list of UUIDs to migrate.");
+
+ HikariDataSource hikari = new HikariDataSource();
+ hikari.setMaximumPoolSize(2);
+ hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
+ hikari.addDataSourceProperty("serverName", address.split(":")[0]);
+ hikari.addDataSourceProperty("port", address.split(":")[1]);
+ hikari.addDataSourceProperty("databaseName", database);
+ hikari.addDataSourceProperty("user", username);
+ hikari.addDataSourceProperty("password", password);
+
+ Set uuids = new HashSet<>();
+
+ try {
+ @Cleanup Connection connection = hikari.getConnection();
+ DatabaseMetaData meta = connection.getMetaData();
+
+ @Cleanup ResultSet tables = meta.getTables(null, null, dbTable, null);
+ if (!tables.next()) {
+ log.severe("PowerfulPerms Migration: Error - Couldn't find table.");
+ return CommandResult.FAILURE;
+
+ } else {
+ @Cleanup PreparedStatement preparedStatement = connection.prepareStatement("SELECT `uuid` FROM " + dbTable);
+ ResultSet resultSet = preparedStatement.executeQuery();
+
+ while (resultSet.next()) {
+ uuids.add(UUID.fromString(resultSet.getString("uuid")));
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return CommandResult.FAILURE;
+ }
+
+ if (uuids.isEmpty()) {
+ log.severe("PowerfulPerms Migration: Error - Unable to find any UUIDs to migrate.");
+ return CommandResult.FAILURE;
+ }
+
+ log.info("PowerfulPerms Migration: Found " + uuids.size() + " uuids. Starting migration.");
+
+ PowerfulPermsPlugin ppPlugin = (PowerfulPermsPlugin) plugin.getPlugin("PowerfulPerms");
+ PermissionManager pm = ppPlugin.getPermissionManager();
+
+ final Map progress = new HashMap<>();
+
+ // Migrate all users and their groups
+ for (UUID uuid : uuids) {
+ progress.put(uuid, new CountDownLatch(2));
+
+ // Create a LuckPerms user for the UUID
+ plugin.getDatastore().loadOrCreateUser(uuid, "null");
+ User user = plugin.getUserManager().get(uuid);
+
+ // Get a list of Permissions held by the user from the PP API.
+ pm.getPlayerOwnPermissions(uuid, new LPResultRunnable>() {
+ @Override
+ public void run() {
+ List perms = this.getResult();
+ perms.forEach(p -> applyPerm(user, p));
+
+ // Update the progress so the user can be saved and unloaded.
+ synchronized (progress) {
+ progress.get(uuid).countDown();
+ if (progress.get(uuid).getCount() == 0) {
+ plugin.getDatastore().saveUser(user);
+ plugin.getUserManager().cleanup(user);
+ }
+ }
+
+ }
+ });
+
+ // Migrate the user's groups to LuckPerms from PP.
+ try {
+ getPlayerGroupsMethod.invoke(pm, uuid, new LPResultRunnable>>() {
+ @Override
+ public void run() {
+ Map> groups = getResult();
+
+ for (Map.Entry> e : groups.entrySet()) {
+ final String server;
+ if (e.getKey() != null && (e.getKey().equals("") || e.getKey().equalsIgnoreCase("all"))) {
+ server = null;
+ } else {
+ server = e.getKey();
+ }
+
+ // This is horrible. So many random API changes through versions, no depreciation.
+ if (legacy) {
+ e.getValue().stream()
+ .filter(cg -> !cg.isNegated())
+ .map(cg -> {
+ try {
+ return (Group) getGroupMethod.invoke(cg);
+ } catch (IllegalAccessException | InvocationTargetException e1) {
+ e1.printStackTrace();
+ return null;
+ }
+ })
+ .forEach(g -> {
+ if (g != null) {
+ if (server == null) {
+ try {
+ user.setPermission("group." + g.getName().toLowerCase(), true);
+ } catch (ObjectAlreadyHasException ignored) {}
+ } else {
+ try {
+ user.setPermission("group." + g.getName().toLowerCase(), true, server);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ }
+ });
+ } else {
+ e.getValue().stream()
+ .filter(g -> !g.hasExpired() && !g.isNegated())
+ .forEach(g -> {
+ final Group group = pm.getGroup(g.getGroupId());
+ if (g.willExpire()) {
+ if (server == null) {
+ try {
+ user.setPermission("group." + group.getName().toLowerCase(), true, g.getExpirationDate().getTime() / 1000L);
+ } catch (ObjectAlreadyHasException ignored) {}
+ } else {
+ try {
+ user.setPermission("group." + group.getName().toLowerCase(), true, server, g.getExpirationDate().getTime() / 1000L);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+
+ } else {
+ if (server == null) {
+ try {
+ user.setPermission("group." + group.getName().toLowerCase(), true);
+ } catch (ObjectAlreadyHasException ignored) {}
+ } else {
+ try {
+ user.setPermission("group." + group.getName().toLowerCase(), true, server);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ }
+ });
+ }
+ }
+
+ // Update the progress so the user can be saved and unloaded.
+ synchronized (progress) {
+ progress.get(uuid).countDown();
+ if (progress.get(uuid).getCount() == 0) {
+ plugin.getDatastore().saveUser(user);
+ plugin.getUserManager().cleanup(user);
+ }
+ }
+ }
+ });
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ log.info("PowerfulPerms Migration: Error");
+ e.printStackTrace();
+ }
+ }
+
+ // The user processes will run individually in separate threads.
+ // In the meantime, it's should be safe to load in the groups on this thread.
+ log.info("PowerfulPerms Migration: User migration is now running. Starting group migration.");
+
+ // Let's import groups. yay
+ Map groups = pm.getGroups();
+ for (Group g : groups.values()) {
+ plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase());
+ final me.lucko.luckperms.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
+
+ for (Permission p : g.getOwnPermissions()) {
+ applyPerm(group, p);
+ }
+
+ for (Group parent : g.getParents()) {
+ try {
+ group.setPermission("group." + parent.getName().toLowerCase(), true);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+
+ plugin.getDatastore().saveGroup(group);
+ }
+
+ // All groups are now migrated, but there may still be some users being migrated.
+ // This block will wait for all users to be completed.
+ log.info("PowerfulPerms Migration: All groups are now migrated. Waiting for user migration to complete.");
+ log.info("PowerfulPerms Migration: This may take some time.");
+ boolean sleep = true;
+ while (sleep) {
+ sleep = false;
+
+ for (Map.Entry e : progress.entrySet()) {
+ if (e.getValue().getCount() != 0) {
+ sleep = true;
+ break;
+ }
+ }
+
+ if (sleep) {
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ // We done.
+ log.info("PowerfulPerms Migration: Success! Migration completed without any errors.");
+ return CommandResult.SUCCESS;
+ }
+
+ private void applyPerm(PermissionHolder holder, Permission p) {
+ String node = p.getPermissionString();
+ boolean value = true;
+ if (node.startsWith("!")) {
+ node = node.substring(1);
+ value = false;
+ }
+
+ String server = p.getServer();
+ if (server != null && server.equalsIgnoreCase("all")) {
+ server = null;
+ }
+
+ String world = p.getWorld();
+ if (world != null && world.equalsIgnoreCase("all")) {
+ world = null;
+ }
+
+ long expireAt = 0L;
+ if (!legacy) {
+ if (p.willExpire()) {
+ expireAt = p.getExpirationDate().getTime() / 1000L;
+ }
+ }
+
+ if (world != null && server == null) {
+ server = "global";
+ }
+
+ if (world != null) {
+ if (expireAt == 0L) {
+ try {
+ holder.setPermission(node, value, server, world);
+ } catch (ObjectAlreadyHasException e) {
+ e.printStackTrace();
+ }
+ } else {
+ try {
+ holder.setPermission(node, value, server, world, expireAt);
+ } catch (ObjectAlreadyHasException e) {
+ e.printStackTrace();
+ }
+ }
+
+ } else if (server != null) {
+ if (expireAt == 0L) {
+ try {
+ holder.setPermission(node, value, server);
+ } catch (ObjectAlreadyHasException ignored) {}
+ } else {
+ try {
+ holder.setPermission(node, value, server, expireAt);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ } else {
+ if (expireAt == 0L) {
+ try {
+ holder.setPermission(node, value);
+ } catch (ObjectAlreadyHasException ignored) {}
+ } else {
+ try {
+ holder.setPermission(node, value, expireAt);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ }
+ }
+
+ /**
+ * Overrides the default ResultRunnable, callbacks will always run in the same thread. (an async one, hopefully.)
+ * @param type
+ */
+ @SuppressWarnings("WeakerAccess")
+ public abstract class LPResultRunnable extends ResultRunnable {
+
+ public LPResultRunnable() {
+ super();
+ super.sameThread = true;
+ }
+
+ public T getResult() {
+ return super.result;
+ }
+
+ }
+}
diff --git a/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationZPermissions.java b/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationZPermissions.java
new file mode 100644
index 00000000..9a8e00ae
--- /dev/null
+++ b/common/src/main/java/me/lucko/luckperms/commands/migration/subcommands/MigrationZPermissions.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016 Lucko (Luck)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.lucko.luckperms.commands.migration.subcommands;
+
+import me.lucko.luckperms.LuckPermsPlugin;
+import me.lucko.luckperms.api.Logger;
+import me.lucko.luckperms.commands.CommandResult;
+import me.lucko.luckperms.commands.Predicate;
+import me.lucko.luckperms.commands.Sender;
+import me.lucko.luckperms.commands.SubCommand;
+import me.lucko.luckperms.constants.Permission;
+import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
+import me.lucko.luckperms.groups.Group;
+import me.lucko.luckperms.tracks.Track;
+import me.lucko.luckperms.users.User;
+import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * <3 <3 zPermissions <3 <3
+ * Finally a permissions plugin with a decent API. *sigh*
+ */
+public class MigrationZPermissions extends SubCommand {
+ public MigrationZPermissions() {
+ super("zpermissions", "Migration from zPermissions",
+ "/%s migration zpermissions [world names]", Permission.MIGRATION, Predicate.alwaysFalse());
+ }
+
+ @Override
+ public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, List args, String label) {
+ final Logger log = plugin.getLog();
+ if (!plugin.isPluginLoaded("zPermissions")) {
+ log.severe("zPermissions Migration: Error -> zPermissions is not loaded.");
+ return CommandResult.STATE_ERROR;
+ }
+
+ ZPermissionsService service = (ZPermissionsService) plugin.getService(ZPermissionsService.class);
+ if (service == null) {
+ log.severe("zPermissions Migration: Error -> zPermissions is not loaded.");
+ return CommandResult.STATE_ERROR;
+ }
+
+ // Migrate all users.
+ log.info("zPermissions Migration: Starting user migration.");
+ for (UUID u : service.getAllPlayersUUID()) {
+ plugin.getDatastore().loadOrCreateUser(u, "null");
+ User user = plugin.getUserManager().get(u);
+
+ for (Map.Entry e : service.getPlayerPermissions(null, null, u).entrySet()) {
+ try {
+ user.setPermission(e.getKey(), e.getValue());
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+
+ if (args != null && !args.isEmpty()) {
+ for (String world : args) {
+ for (Map.Entry e : service.getPlayerPermissions(world, null, u).entrySet()) {
+ try {
+ user.setPermission(e.getKey(), e.getValue(), "global", world);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ }
+ }
+
+ for (String g : service.getPlayerAssignedGroups(u)) {
+ try {
+ user.setPermission("group." + g.toLowerCase(), true);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+
+ user.setPrimaryGroup(service.getPlayerPrimaryGroup(u));
+ plugin.getUserManager().cleanup(user);
+ plugin.getDatastore().saveUser(user);
+ }
+
+ // Migrate all tracks
+ log.info("zPermissions Migration: Starting track migration.");
+ for (String t : service.getAllTracks()) {
+ plugin.getDatastore().createAndLoadTrack(t.toLowerCase());
+ Track track = plugin.getTrackManager().get(t.toLowerCase());
+
+ track.setGroups(service.getTrackGroups(t));
+
+ plugin.getDatastore().saveTrack(track);
+ }
+
+ // Migrate all groups
+ log.info("zPermissions Migration: Starting group migration.");
+ for (String g : service.getAllGroups()) {
+ plugin.getDatastore().createAndLoadGroup(g.toLowerCase());
+ Group group = plugin.getGroupManager().get(g.toLowerCase());
+
+ for (Map.Entry e : service.getGroupPermissions(null, null, g).entrySet()) {
+ try {
+ group.setPermission(e.getKey(), e.getValue());
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+
+ if (args != null && !args.isEmpty()) {
+ for (String world : args) {
+ for (Map.Entry e : service.getGroupPermissions(world, null, g).entrySet()) {
+ try {
+ group.setPermission(e.getKey(), e.getValue(), "global", world);
+ } catch (ObjectAlreadyHasException ignored) {}
+ }
+ }
+ }
+
+ plugin.getDatastore().saveGroup(group);
+ }
+
+ log.info("zPermissions Migration: Complete!");
+ return CommandResult.SUCCESS;
+ }
+}
diff --git a/common/src/main/java/me/lucko/luckperms/constants/Message.java b/common/src/main/java/me/lucko/luckperms/constants/Message.java
index 75bcda0f..3d3c0a9f 100644
--- a/common/src/main/java/me/lucko/luckperms/constants/Message.java
+++ b/common/src/main/java/me/lucko/luckperms/constants/Message.java
@@ -298,7 +298,9 @@ public enum Message {
),
IMPORT_END_ERROR_CONTENT("&e(Import) &d-> &c%s", true),
- IMPORT_END_ERROR_FOOTER("&e(Import) &7<------------------------------------------>", true);
+ IMPORT_END_ERROR_FOOTER("&e(Import) &7<------------------------------------------>", true),
+
+ MIGRATION_NOT_CONSOLE("Migration must be performed from the Console.", true);
private String message;
private boolean showPrefix;
diff --git a/common/src/main/java/me/lucko/luckperms/constants/Permission.java b/common/src/main/java/me/lucko/luckperms/constants/Permission.java
index 6921476f..491ef988 100644
--- a/common/src/main/java/me/lucko/luckperms/constants/Permission.java
+++ b/common/src/main/java/me/lucko/luckperms/constants/Permission.java
@@ -89,7 +89,9 @@ public enum Permission {
LOG_TRACK_HISTORY("trackhistory", "log"),
LOG_SEARCH("search", "log"),
LOG_NOTIFY("notify", "log"),
- LOG_EXPORT("export", "log");
+ LOG_EXPORT("export", "log"),
+
+ MIGRATION("migration", null);
private String node;
private String group;
diff --git a/pom.xml b/pom.xml
index bdf02ba5..2b45b66e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -71,5 +71,13 @@
sponge-repo
https://repo.spongepowered.org/maven
+
+ pex-repo
+ http://pex-repo.aoeu.xyz
+
+
+ alskebo-repo
+ http://repo.alskebo.com/repository/maven-releases
+
diff --git a/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java b/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java
index edf168f3..acd90a9a 100644
--- a/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java
+++ b/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java
@@ -190,6 +190,11 @@ public class LPSpongePlugin implements LuckPermsPlugin {
return "null";
}
+ @Override
+ public Type getType() {
+ return Type.SPONGE;
+ }
+
@Override
public Message getPlayerStatus(UUID uuid) {
return game.getServer().getPlayer(getUuidCache().getExternalUUID(uuid)).isPresent() ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
@@ -224,6 +229,21 @@ public class LPSpongePlugin implements LuckPermsPlugin {
return p.get().getDescriptions().stream().map(PermissionDescription::getId).collect(Collectors.toList());
}
+ @Override
+ public Object getPlugin(String name) {
+ return game.getPluginManager().getPlugin(name).get().getInstance().get();
+ }
+
+ @Override
+ public Object getService(Class clazz) {
+ return Sponge.getServiceManager().provideUnchecked(clazz);
+ }
+
+ @Override
+ public boolean isPluginLoaded(String name) {
+ return game.getPluginManager().isLoaded(name);
+ }
+
@Override
public void runUpdateTask() {
scheduler.createTaskBuilder().async().execute(new UpdateTask(this)).submit(LPSpongePlugin.this);