mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-12-28 03:57:36 +01:00
Move migration commands to a separate jar
This commit is contained in:
parent
142cdc8e89
commit
5c44333892
@ -17,25 +17,6 @@ dependencies {
|
||||
exclude(module: 'bukkit')
|
||||
}
|
||||
compileOnly 'lilypad.client.connect:api:0.0.1-SNAPSHOT'
|
||||
|
||||
// migration plugins
|
||||
compileOnly 'org.tyrannyofheaven.bukkit:zPermissions:1.3'
|
||||
compileOnly('ru.tehkode:PermissionsEx:1.23.5') {
|
||||
exclude(module: 'bukkit')
|
||||
exclude(module: 'updater')
|
||||
exclude(module: 'commons-dbcp')
|
||||
exclude(module: 'AccountsClient')
|
||||
}
|
||||
compileOnly 'com.github.gustav9797:PowerfulPermsAPI:4.5.2'
|
||||
compileOnly 'org.anjocaido:GroupManager:1.4'
|
||||
compileOnly('nl.svenar:powerranks:1.9.2') {
|
||||
exclude(module: 'nametagedit')
|
||||
}
|
||||
compileOnly 'de.bananaco:bpermissions-api:2.12'
|
||||
compileOnly('com.platymuus:bukkit-permissions:2.5') {
|
||||
exclude(module: 'bukkit')
|
||||
exclude(module: 'metrics')
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
import me.lucko.luckperms.common.util.Uuids;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class BukkitUuids {
|
||||
private BukkitUuids() {}
|
||||
|
||||
public static UUID lookupUuid(ProgressLogger log, String s) {
|
||||
UUID uuid = Uuids.parse(s);
|
||||
if (uuid == null) {
|
||||
try {
|
||||
//noinspection deprecation
|
||||
uuid = Bukkit.getOfflinePlayer(s).getUniqueId();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (uuid == null) {
|
||||
log.logError("Unable to get a UUID for user identifier: " + s);
|
||||
}
|
||||
return uuid;
|
||||
}
|
||||
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import de.bananaco.bpermissions.api.Calculable;
|
||||
import de.bananaco.bpermissions.api.CalculableType;
|
||||
import de.bananaco.bpermissions.api.Permission;
|
||||
import de.bananaco.bpermissions.api.World;
|
||||
import de.bananaco.bpermissions.api.WorldManager;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.model.manager.group.GroupManager;
|
||||
import me.lucko.luckperms.common.node.factory.NodeBuilders;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
import me.lucko.luckperms.common.node.types.Meta;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import me.lucko.luckperms.common.node.types.Suffix;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Iterators;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.event.cause.CreationCause;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class MigrationBPermissions extends ChildCommand<Object> {
|
||||
private static final Field UCONFIG_FIELD;
|
||||
static {
|
||||
try {
|
||||
UCONFIG_FIELD = Class.forName("de.bananaco.bpermissions.imp.YamlWorld").getDeclaredField("uconfig");
|
||||
UCONFIG_FIELD.setAccessible(true);
|
||||
} catch (ClassNotFoundException | NoSuchFieldException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public MigrationBPermissions() {
|
||||
super(CommandSpec.MIGRATION_COMMAND, "bpermissions", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object ignored, ArgumentList args, String label) {
|
||||
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "bPermissions");
|
||||
log.addListener(plugin.getConsoleSender());
|
||||
log.addListener(sender);
|
||||
|
||||
log.log("Starting.");
|
||||
|
||||
WorldManager worldManager = WorldManager.getInstance();
|
||||
if (worldManager == null) {
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
log.log("Forcing the plugin to load all data. This could take a while.");
|
||||
for (World world : worldManager.getAllWorlds()) {
|
||||
log.log("Loading users in world " + world.getName());
|
||||
|
||||
YamlConfiguration yamlWorldUsers = null;
|
||||
try {
|
||||
yamlWorldUsers = (YamlConfiguration) UCONFIG_FIELD.get(world);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
||||
if (yamlWorldUsers == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigurationSection configSection = yamlWorldUsers.getConfigurationSection("users");
|
||||
if (configSection == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Set<String> users = configSection.getKeys(false);
|
||||
if (users == null) {
|
||||
log.logError("Couldn't get a list of users.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
AtomicInteger userLoadCount = new AtomicInteger(0);
|
||||
for (String user : users) {
|
||||
world.loadOne(user, CalculableType.USER);
|
||||
log.logProgress("Forcefully loaded {} users so far.", userLoadCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
|
||||
}
|
||||
}
|
||||
log.log("Forcefully loaded all users.");
|
||||
|
||||
// Migrate one world at a time.
|
||||
log.log("Starting world migration.");
|
||||
Iterators.tryIterate(worldManager.getAllWorlds(), world -> {
|
||||
log.log("Migrating world: " + world.getName());
|
||||
|
||||
// Migrate all groups
|
||||
log.log("Starting group migration in world " + world.getName() + ".");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
|
||||
Iterators.tryIterate(world.getAll(CalculableType.GROUP), group -> {
|
||||
String groupName = MigrationUtils.standardizeName(group.getName());
|
||||
if (group.getName().equalsIgnoreCase(world.getDefaultGroup())) {
|
||||
groupName = GroupManager.DEFAULT_GROUP_NAME;
|
||||
}
|
||||
|
||||
// Make a LuckPerms group for the one being migrated.
|
||||
Group lpGroup = plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
|
||||
|
||||
MigrationUtils.setGroupWeight(lpGroup, group.getPriority());
|
||||
migrateHolder(world, group, lpGroup);
|
||||
|
||||
plugin.getStorage().saveGroup(lpGroup);
|
||||
|
||||
log.logAllProgress("Migrated {} groups so far.", groupCount.incrementAndGet());
|
||||
});
|
||||
log.log("Migrated " + groupCount.get() + " groups in world " + world.getName() + ".");
|
||||
|
||||
|
||||
// Migrate all users
|
||||
log.log("Starting user migration in world " + world.getName() + ".");
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
Iterators.tryIterate(world.getAll(CalculableType.USER), user -> {
|
||||
// There is no mention of UUIDs in the API. I assume that name = uuid. idk?
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, user.getName());
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a LuckPerms user for the one being migrated.
|
||||
User lpUser = plugin.getStorage().loadUser(uuid, null).join();
|
||||
|
||||
migrateHolder(world, user, lpUser);
|
||||
|
||||
plugin.getStorage().saveUser(lpUser);
|
||||
plugin.getUserManager().getHouseKeeper().cleanup(lpUser.getUniqueId());
|
||||
|
||||
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
|
||||
});
|
||||
|
||||
log.log("Migrated " + userCount.get() + " users in world " + world.getName() + ".");
|
||||
});
|
||||
|
||||
log.log("Success! Migration complete.");
|
||||
log.log("Don't forget to remove the bPermissions jar from your plugins folder & restart the server. " +
|
||||
"LuckPerms may not take over as the server permission handler until this is done.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static void migrateHolder(World world, Calculable c, PermissionHolder holder) {
|
||||
// Migrate the groups permissions in this world
|
||||
for (Permission p : c.getPermissions()) {
|
||||
if (p.name().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
holder.setNode(DataType.NORMAL, NodeBuilders.determineMostApplicable(p.name()).value(p.isTrue()).withContext(DefaultContextKeys.SERVER_KEY, "global").withContext(DefaultContextKeys.WORLD_KEY, world.getName()).build(), true);
|
||||
|
||||
// Include any child permissions
|
||||
for (Map.Entry<String, Boolean> child : p.getChildren().entrySet()) {
|
||||
if (child.getKey().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
holder.setNode(DataType.NORMAL, NodeBuilders.determineMostApplicable(child.getKey()).value((boolean) child.getValue()).withContext(DefaultContextKeys.SERVER_KEY, "global").withContext(DefaultContextKeys.WORLD_KEY, world.getName()).build(), true);
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate any inherited groups
|
||||
c.getGroups().forEach(parent -> {
|
||||
String parentName = MigrationUtils.standardizeName(parent.getName());
|
||||
if (parent.getName().equalsIgnoreCase(world.getDefaultGroup())) {
|
||||
parentName = GroupManager.DEFAULT_GROUP_NAME;
|
||||
}
|
||||
|
||||
holder.setNode(DataType.NORMAL, Inheritance.builder(parentName).value(true).withContext(DefaultContextKeys.SERVER_KEY, "global").withContext(DefaultContextKeys.WORLD_KEY, world.getName()).build(), true);
|
||||
});
|
||||
|
||||
// Migrate existing meta
|
||||
for (Map.Entry<String, String> meta : c.getMeta().entrySet()) {
|
||||
if (meta.getKey().isEmpty() || meta.getValue().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (meta.getKey().equalsIgnoreCase("prefix")) {
|
||||
holder.setNode(DataType.NORMAL, Prefix.builder(meta.getValue(), c.getPriority()).withContext(DefaultContextKeys.WORLD_KEY, world.getName()).build(), true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (meta.getKey().equalsIgnoreCase("suffix")) {
|
||||
holder.setNode(DataType.NORMAL, Suffix.builder(meta.getValue(), c.getPriority()).withContext(DefaultContextKeys.WORLD_KEY, world.getName()).build(), true);
|
||||
continue;
|
||||
}
|
||||
|
||||
holder.setNode(DataType.NORMAL, Meta.builder(meta.getKey(), meta.getValue()).withContext(DefaultContextKeys.WORLD_KEY, world.getName()).build(), true);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,269 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.model.UserIdentifier;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
import me.lucko.luckperms.common.node.types.Meta;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import me.lucko.luckperms.common.node.types.Suffix;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Iterators;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
import me.lucko.luckperms.common.util.Uuids;
|
||||
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.event.cause.CreationCause;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.node.Node;
|
||||
|
||||
import org.anjocaido.groupmanager.GlobalGroups;
|
||||
import org.anjocaido.groupmanager.GroupManager;
|
||||
import org.anjocaido.groupmanager.dataholder.WorldDataHolder;
|
||||
import org.anjocaido.groupmanager.dataholder.worlds.WorldsHolder;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MigrationGroupManager extends ChildCommand<Object> {
|
||||
public MigrationGroupManager() {
|
||||
super(CommandSpec.MIGRATION_GROUPMANAGER, "groupmanager", CommandPermission.MIGRATION, Predicates.is(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object ignored, ArgumentList args, String label) {
|
||||
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "GroupManager");
|
||||
log.addListener(plugin.getConsoleSender());
|
||||
log.addListener(sender);
|
||||
|
||||
log.log("Starting.");
|
||||
|
||||
if (!args.get(0).equalsIgnoreCase("true") && !args.get(0).equalsIgnoreCase("false")) {
|
||||
log.logError("Was expecting true/false, but got " + args.get(0) + " instead.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
final boolean migrateAsGlobal = Boolean.parseBoolean(args.get(0));
|
||||
final Function<String, String> worldMappingFunc = s -> migrateAsGlobal || s == null ? "global" : s;
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("GroupManager")) {
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
List<String> worlds = Bukkit.getWorlds().stream().map(World::getName).map(String::toLowerCase).collect(Collectors.toList());
|
||||
GroupManager gm = (GroupManager) Bukkit.getPluginManager().getPlugin("GroupManager");
|
||||
|
||||
// Migrate Global Groups
|
||||
log.log("Starting global group migration.");
|
||||
GlobalGroups gg = GroupManager.getGlobalGroups();
|
||||
|
||||
AtomicInteger globalGroupCount = new AtomicInteger(0);
|
||||
Iterators.tryIterate(gg.getGroupList(), g -> {
|
||||
String groupName = MigrationUtils.standardizeName(g.getName());
|
||||
Group group = plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
|
||||
|
||||
for (String node : g.getPermissionList()) {
|
||||
if (node.isEmpty()) continue;
|
||||
group.setNode(DataType.NORMAL, MigrationUtils.parseNode(node, true).build(), true);
|
||||
}
|
||||
for (String s : g.getInherits()) {
|
||||
if (s.isEmpty()) continue;
|
||||
group.setNode(DataType.NORMAL, Inheritance.builder(MigrationUtils.standardizeName(s)).build(), true);
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(group);
|
||||
log.logAllProgress("Migrated {} groups so far.", globalGroupCount.incrementAndGet());
|
||||
});
|
||||
log.log("Migrated " + globalGroupCount.get() + " global groups");
|
||||
|
||||
// Collect data
|
||||
Map<UserIdentifier, Set<Node>> users = new HashMap<>();
|
||||
Map<UUID, String> primaryGroups = new HashMap<>();
|
||||
Map<String, Set<Node>> groups = new HashMap<>();
|
||||
|
||||
WorldsHolder wh = gm.getWorldsHolder();
|
||||
|
||||
// Collect data for all users and groups.
|
||||
log.log("Collecting user and group data.");
|
||||
Iterators.tryIterate(worlds, String::toLowerCase, world -> {
|
||||
log.log("Querying world " + world);
|
||||
|
||||
WorldDataHolder wdh = wh.getWorldData(world);
|
||||
|
||||
AtomicInteger groupWorldCount = new AtomicInteger(0);
|
||||
Iterators.tryIterate(wdh.getGroupList(), group -> {
|
||||
String groupName = MigrationUtils.standardizeName(group.getName());
|
||||
|
||||
groups.putIfAbsent(groupName, new HashSet<>());
|
||||
|
||||
for (String node : group.getPermissionList()) {
|
||||
if (node.isEmpty()) continue;
|
||||
groups.get(groupName).add(MigrationUtils.parseNode(node, true).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build());
|
||||
}
|
||||
for (String s : group.getInherits()) {
|
||||
if (s.isEmpty()) continue;
|
||||
groups.get(groupName).add(Inheritance.builder(MigrationUtils.standardizeName(s)).value(true).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build());
|
||||
}
|
||||
|
||||
String[] metaKeys = group.getVariables().getVarKeyList();
|
||||
for (String key : metaKeys) {
|
||||
String value = group.getVariables().getVarString(key);
|
||||
key = key.toLowerCase();
|
||||
if (key.isEmpty() || value.isEmpty()) continue;
|
||||
if (key.equals("build")) continue;
|
||||
|
||||
if (key.equals("prefix")) {
|
||||
groups.get(groupName).add(Prefix.builder(value, 50).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build());
|
||||
} else if (key.equals("suffix")) {
|
||||
groups.get(groupName).add(Suffix.builder(value, 50).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build());
|
||||
} else {
|
||||
groups.get(groupName).add(Meta.builder(key, value).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build());
|
||||
}
|
||||
}
|
||||
|
||||
log.logAllProgress("Migrated {} groups so far in world " + world, groupWorldCount.incrementAndGet());
|
||||
});
|
||||
log.log("Migrated " + groupWorldCount.get() + " groups in world " + world);
|
||||
|
||||
AtomicInteger userWorldCount = new AtomicInteger(0);
|
||||
Iterators.tryIterate(wdh.getUserList(), user -> {
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, user.getUUID());
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String lastName = user.getLastName();
|
||||
if (lastName != null && Uuids.parse(lastName) != null) {
|
||||
lastName = null;
|
||||
}
|
||||
|
||||
UserIdentifier id = UserIdentifier.of(uuid, lastName);
|
||||
|
||||
users.putIfAbsent(id, new HashSet<>());
|
||||
|
||||
for (String node : user.getPermissionList()) {
|
||||
if (node.isEmpty()) continue;
|
||||
users.get(id).add(MigrationUtils.parseNode(node, true).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build());
|
||||
}
|
||||
|
||||
// Collect sub groups
|
||||
String finalWorld = worldMappingFunc.apply(world);
|
||||
users.get(id).addAll(user.subGroupListStringCopy().stream()
|
||||
.filter(n -> !n.isEmpty())
|
||||
.map(MigrationUtils::standardizeName)
|
||||
.map(n -> Inheritance.builder(n).value(true).withContext(DefaultContextKeys.WORLD_KEY, finalWorld).build())
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
|
||||
// Get primary group
|
||||
primaryGroups.put(uuid, MigrationUtils.standardizeName(user.getGroupName()));
|
||||
|
||||
String[] metaKeys = user.getVariables().getVarKeyList();
|
||||
for (String key : metaKeys) {
|
||||
String value = user.getVariables().getVarString(key);
|
||||
key = key.toLowerCase();
|
||||
if (key.isEmpty() || value.isEmpty()) continue;
|
||||
if (key.equals("build")) continue;
|
||||
|
||||
if (key.equals("prefix")) {
|
||||
users.get(id).add(Prefix.builder(value, 100).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build());
|
||||
} else if (key.equals("suffix")) {
|
||||
users.get(id).add(Suffix.builder(value, 100).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build());
|
||||
} else {
|
||||
users.get(id).add(Meta.builder(key, value).withContext(DefaultContextKeys.WORLD_KEY, worldMappingFunc.apply(world)).build());
|
||||
}
|
||||
}
|
||||
|
||||
log.logProgress("Migrated {} users so far in world " + world, userWorldCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
|
||||
});
|
||||
log.log("Migrated " + userWorldCount.get() + " users in world " + world);
|
||||
});
|
||||
|
||||
log.log("All data has now been processed, now starting the import process.");
|
||||
log.log("Found a total of " + users.size() + " users and " + groups.size() + " groups.");
|
||||
|
||||
log.log("Starting group migration.");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
Iterators.tryIterate(groups.entrySet(), e -> {
|
||||
Group group = plugin.getStorage().createAndLoadGroup(e.getKey(), CreationCause.INTERNAL).join();
|
||||
|
||||
for (Node node : e.getValue()) {
|
||||
group.setNode(DataType.NORMAL, node, true);
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(group);
|
||||
log.logAllProgress("Migrated {} groups so far.", groupCount.incrementAndGet());
|
||||
});
|
||||
log.log("Migrated " + groupCount.get() + " groups");
|
||||
|
||||
log.log("Starting user migration.");
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
Iterators.tryIterate(users.entrySet(), e -> {
|
||||
User user = plugin.getStorage().loadUser(e.getKey().getUniqueId(), e.getKey().getUsername().orElse(null)).join();
|
||||
|
||||
for (Node node : e.getValue()) {
|
||||
user.setNode(DataType.NORMAL, node, true);
|
||||
}
|
||||
|
||||
String primaryGroup = primaryGroups.get(e.getKey().getUniqueId());
|
||||
if (primaryGroup != null && !primaryGroup.isEmpty()) {
|
||||
user.setNode(DataType.NORMAL, Inheritance.builder(primaryGroup).build(), true);
|
||||
user.getPrimaryGroup().setStoredValue(primaryGroup);
|
||||
user.unsetNode(DataType.NORMAL, Inheritance.builder(me.lucko.luckperms.common.model.manager.group.GroupManager.DEFAULT_GROUP_NAME).build());
|
||||
}
|
||||
|
||||
plugin.getStorage().saveUser(user);
|
||||
plugin.getUserManager().getHouseKeeper().cleanup(user.getUniqueId());
|
||||
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
|
||||
});
|
||||
|
||||
log.log("Migrated " + userCount.get() + " users.");
|
||||
log.log("Success! Migration complete.");
|
||||
log.log("Don't forget to remove the GroupManager jar from your plugins folder & restart the server. " +
|
||||
"LuckPerms may not take over as the server permission handler until this is done.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import com.platymuus.bukkit.permissions.PermissionsPlugin;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Iterators;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.event.cause.CreationCause;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class MigrationPermissionsBukkit extends ChildCommand<Object> {
|
||||
public MigrationPermissionsBukkit() {
|
||||
super(CommandSpec.MIGRATION_COMMAND, "permissionsbukkit", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object ignored, ArgumentList args, String label) {
|
||||
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "PermissionsBukkit");
|
||||
log.addListener(plugin.getConsoleSender());
|
||||
log.addListener(sender);
|
||||
|
||||
log.log("Starting.");
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("PermissionsBukkit")) {
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
PermissionsPlugin permissionsBukkit = (PermissionsPlugin) Bukkit.getPluginManager().getPlugin("PermissionsBukkit");
|
||||
FileConfiguration config = permissionsBukkit.getConfig();
|
||||
|
||||
// Migrate all groups
|
||||
log.log("Starting group migration.");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
|
||||
ConfigurationSection groupsSection = config.getConfigurationSection("groups");
|
||||
|
||||
Iterators.tryIterate(groupsSection.getKeys(false), key -> {
|
||||
final String groupName = MigrationUtils.standardizeName(key);
|
||||
Group lpGroup = plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
|
||||
|
||||
// migrate data
|
||||
if (groupsSection.isConfigurationSection(key)) {
|
||||
migrate(lpGroup, groupsSection.getConfigurationSection(key));
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(lpGroup).join();
|
||||
log.logAllProgress("Migrated {} groups so far.", groupCount.incrementAndGet());
|
||||
});
|
||||
log.log("Migrated " + groupCount.get() + " groups");
|
||||
|
||||
// Migrate all users
|
||||
log.log("Starting user migration.");
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
|
||||
ConfigurationSection usersSection = config.getConfigurationSection("users");
|
||||
|
||||
Iterators.tryIterate(usersSection.getKeys(false), key -> {
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, key);
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
User lpUser = plugin.getStorage().loadUser(uuid, null).join();
|
||||
|
||||
// migrate data
|
||||
if (usersSection.isConfigurationSection(key)) {
|
||||
migrate(lpUser, usersSection.getConfigurationSection(key));
|
||||
}
|
||||
|
||||
plugin.getUserManager().getHouseKeeper().cleanup(lpUser.getUniqueId());
|
||||
plugin.getStorage().saveUser(lpUser);
|
||||
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
|
||||
});
|
||||
|
||||
log.log("Migrated " + userCount.get() + " users.");
|
||||
log.log("Success! Migration complete.");
|
||||
log.log("Don't forget to remove the PermissionsBukkit jar from your plugins folder & restart the server. " +
|
||||
"LuckPerms may not take over as the server permission handler until this is done.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static void migrate(PermissionHolder holder, ConfigurationSection data) {
|
||||
// migrate permissions
|
||||
if (data.isConfigurationSection("permissions")) {
|
||||
ConfigurationSection permsSection = data.getConfigurationSection("permissions");
|
||||
for (String perm : permsSection.getKeys(false)) {
|
||||
boolean value = permsSection.getBoolean(perm);
|
||||
holder.setNode(DataType.NORMAL, MigrationUtils.parseNode(perm, value).build(), true);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.isConfigurationSection("worlds")) {
|
||||
ConfigurationSection worldSection = data.getConfigurationSection("worlds");
|
||||
for (String world : worldSection.getKeys(false)) {
|
||||
if (worldSection.isConfigurationSection(world)) {
|
||||
ConfigurationSection permsSection = worldSection.getConfigurationSection(world);
|
||||
for (String perm : permsSection.getKeys(false)) {
|
||||
boolean value = permsSection.getBoolean(perm);
|
||||
holder.setNode(DataType.NORMAL, MigrationUtils.parseNode(perm, value).withContext(DefaultContextKeys.WORLD_KEY, world).build(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// migrate parents
|
||||
if (data.isList("groups")) {
|
||||
List<String> groups = data.getStringList("groups");
|
||||
for (String group : groups) {
|
||||
holder.setNode(DataType.NORMAL, Inheritance.builder(MigrationUtils.standardizeName(group)).build(), true);
|
||||
}
|
||||
}
|
||||
if (data.isList("inheritance")) {
|
||||
List<String> groups = data.getStringList("inheritance");
|
||||
for (String group : groups) {
|
||||
holder.setNode(DataType.NORMAL, Inheritance.builder(MigrationUtils.standardizeName(group)).build(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,418 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.model.manager.group.GroupManager;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
import me.lucko.luckperms.common.node.types.Meta;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import me.lucko.luckperms.common.node.types.Suffix;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Iterators;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.event.cause.CreationCause;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.types.InheritanceNode;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import ru.tehkode.permissions.NativeInterface;
|
||||
import ru.tehkode.permissions.PermissionEntity;
|
||||
import ru.tehkode.permissions.PermissionGroup;
|
||||
import ru.tehkode.permissions.PermissionManager;
|
||||
import ru.tehkode.permissions.PermissionUser;
|
||||
import ru.tehkode.permissions.PermissionsData;
|
||||
import ru.tehkode.permissions.bukkit.PermissionsEx;
|
||||
import ru.tehkode.permissions.events.PermissionEvent;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MigrationPermissionsEx extends ChildCommand<Object> {
|
||||
private static final Method GET_DATA_METHOD;
|
||||
private static final Field TIMED_PERMISSIONS_FIELD;
|
||||
private static final Field TIMED_PERMISSIONS_TIME_FIELD;
|
||||
private static final Field NATIVE_INTERFACE_FIELD;
|
||||
static {
|
||||
try {
|
||||
GET_DATA_METHOD = PermissionEntity.class.getDeclaredMethod("getData");
|
||||
GET_DATA_METHOD.setAccessible(true);
|
||||
|
||||
TIMED_PERMISSIONS_FIELD = PermissionEntity.class.getDeclaredField("timedPermissions");
|
||||
TIMED_PERMISSIONS_FIELD.setAccessible(true);
|
||||
|
||||
TIMED_PERMISSIONS_TIME_FIELD = PermissionEntity.class.getDeclaredField("timedPermissionsTime");
|
||||
TIMED_PERMISSIONS_TIME_FIELD.setAccessible(true);
|
||||
|
||||
NATIVE_INTERFACE_FIELD = PermissionManager.class.getDeclaredField("nativeI");
|
||||
NATIVE_INTERFACE_FIELD.setAccessible(true);
|
||||
} catch (NoSuchMethodException | NoSuchFieldException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public MigrationPermissionsEx() {
|
||||
super(CommandSpec.MIGRATION_COMMAND, "permissionsex", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object ignored, ArgumentList args, String label) {
|
||||
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "PermissionsEx");
|
||||
log.addListener(plugin.getConsoleSender());
|
||||
log.addListener(sender);
|
||||
|
||||
log.log("Starting.");
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("PermissionsEx")) {
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
PermissionsEx pex = (PermissionsEx) Bukkit.getPluginManager().getPlugin("PermissionsEx");
|
||||
PermissionManager manager = pex.getPermissionsManager();
|
||||
|
||||
// hack to work around accessing pex async
|
||||
try {
|
||||
disablePexEvents(manager);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
log.log("Calculating group weightings.");
|
||||
int i = 0;
|
||||
for (PermissionGroup group : manager.getGroupList()) {
|
||||
i = Math.max(i, group.getRank());
|
||||
}
|
||||
int maxWeight = i + 5;
|
||||
|
||||
// Migrate all groups.
|
||||
log.log("Starting group migration.");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
Set<String> ladders = new HashSet<>();
|
||||
Iterators.tryIterate(manager.getGroupList(), group -> {
|
||||
int groupWeight = maxWeight - group.getRank();
|
||||
|
||||
final String groupName = MigrationUtils.standardizeName(group.getName());
|
||||
Group lpGroup = plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
|
||||
|
||||
MigrationUtils.setGroupWeight(lpGroup, groupWeight);
|
||||
|
||||
// migrate data
|
||||
migrateEntity(group, lpGroup, groupWeight);
|
||||
|
||||
// remember known ladders
|
||||
if (group.isRanked()) {
|
||||
ladders.add(group.getRankLadder().toLowerCase());
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(lpGroup).join();
|
||||
log.logAllProgress("Migrated {} groups so far.", groupCount.incrementAndGet());
|
||||
});
|
||||
log.log("Migrated " + groupCount.get() + " groups");
|
||||
|
||||
// Migrate all ladders/tracks.
|
||||
log.log("Starting tracks migration.");
|
||||
for (String rankLadder : ladders) {
|
||||
Track track = plugin.getStorage().createAndLoadTrack(rankLadder, CreationCause.INTERNAL).join();
|
||||
|
||||
// Get a list of all groups in a ladder
|
||||
List<String> ladder = manager.getRankLadder(rankLadder).entrySet().stream()
|
||||
.sorted(Comparator.<Map.Entry<Integer, PermissionGroup>>comparingInt(Map.Entry::getKey).reversed())
|
||||
.map(e -> MigrationUtils.standardizeName(e.getValue().getName()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
track.setGroups(ladder);
|
||||
plugin.getStorage().saveTrack(track);
|
||||
}
|
||||
log.log("Migrated " + ladders.size() + " tracks");
|
||||
|
||||
// Migrate all users
|
||||
log.log("Starting user migration.");
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
|
||||
// Increment the max weight from the group migrations. All user meta should override.
|
||||
int userWeight = maxWeight + 5;
|
||||
|
||||
Collection<String> userIdentifiers = manager.getBackend().getUserIdentifiers();
|
||||
Iterators.tryIterate(userIdentifiers, id -> {
|
||||
PermissionUser user = new PermissionUser(id, manager.getBackend().getUserData(id), manager);
|
||||
if (isUserEmpty(user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UUID u = BukkitUuids.lookupUuid(log, id);
|
||||
if (u == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// load in a user instance
|
||||
User lpUser = plugin.getStorage().loadUser(u, user.getName()).join();
|
||||
|
||||
// migrate data
|
||||
migrateEntity(user, lpUser, userWeight);
|
||||
|
||||
plugin.getUserManager().getHouseKeeper().cleanup(lpUser.getUniqueId());
|
||||
plugin.getStorage().saveUser(lpUser);
|
||||
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
|
||||
});
|
||||
|
||||
// re-enable events
|
||||
try {
|
||||
enablePexEvents(manager);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
log.log("Migrated " + userCount.get() + " users.");
|
||||
log.log("Success! Migration complete.");
|
||||
log.log("Don't forget to remove the PermissionsEx jar from your plugins folder & restart the server. " +
|
||||
"LuckPerms may not take over as the server permission handler until this is done.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> getPermanentPermissions(PermissionEntity entity) {
|
||||
try {
|
||||
PermissionsData data = (PermissionsData) GET_DATA_METHOD.invoke(entity);
|
||||
return data.getPermissionsMap();
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isUserEmpty(PermissionUser user) {
|
||||
for (List<String> permissions : user.getAllPermissions().values()) {
|
||||
if (!permissions.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (List<PermissionGroup> parents : user.getAllParents().values()) {
|
||||
if (!parents.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (Map<String, String> options : user.getAllOptions().values()) {
|
||||
if (!options.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void migrateEntity(PermissionEntity entity, PermissionHolder holder, int weight) {
|
||||
// migrate permanent permissions
|
||||
for (Map.Entry<String, List<String>> worldData : getPermanentPermissions(entity).entrySet()) {
|
||||
String world = standardizeWorld(worldData.getKey());
|
||||
for (String node : worldData.getValue()) {
|
||||
if (node.isEmpty()) continue;
|
||||
holder.setNode(DataType.NORMAL, MigrationUtils.parseNode(node, true).withContext(DefaultContextKeys.WORLD_KEY, world).build(), true);
|
||||
}
|
||||
}
|
||||
|
||||
// migrate temporary permissions
|
||||
Map<String, List<String>> timedPermissions;
|
||||
Map<String, Long> timedPermissionsTime;
|
||||
|
||||
try {
|
||||
//noinspection unchecked
|
||||
timedPermissions = (Map<String, List<String>>) TIMED_PERMISSIONS_FIELD.get(entity);
|
||||
//noinspection unchecked
|
||||
timedPermissionsTime = (Map<String, Long>) TIMED_PERMISSIONS_TIME_FIELD.get(entity);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, List<String>> worldData : timedPermissions.entrySet()) {
|
||||
String world = standardizeWorld(worldData.getKey());
|
||||
for (String node : worldData.getValue()) {
|
||||
if (node.isEmpty()) continue;
|
||||
long expiry = timedPermissionsTime.getOrDefault(Strings.nullToEmpty(world) + ":" + node, 0L);
|
||||
Node n = MigrationUtils.parseNode(node, true).withContext(DefaultContextKeys.WORLD_KEY, world).expiry(expiry).build();
|
||||
if (!n.hasExpired()) {
|
||||
holder.setNode(DataType.NORMAL, n, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// migrate parents
|
||||
for (Map.Entry<String, List<PermissionGroup>> worldData : entity.getAllParents().entrySet()) {
|
||||
String world = standardizeWorld(worldData.getKey());
|
||||
|
||||
// keep track of primary group
|
||||
String primary = null;
|
||||
int primaryWeight = Integer.MAX_VALUE;
|
||||
|
||||
for (PermissionGroup parent : worldData.getValue()) {
|
||||
String parentName = parent.getName();
|
||||
long expiry = 0L;
|
||||
|
||||
// check for temporary parent
|
||||
if (entity instanceof PermissionUser) {
|
||||
String expiryOption = entity.getOption("group-" + parentName + "-until", world);
|
||||
if (expiryOption != null) {
|
||||
try {
|
||||
expiry = Long.parseLong(expiryOption);
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InheritanceNode n = Inheritance.builder(MigrationUtils.standardizeName(parentName)).withContext(DefaultContextKeys.WORLD_KEY, world).expiry(expiry).build();
|
||||
if (n.hasExpired()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
holder.setNode(DataType.NORMAL, n, true);
|
||||
|
||||
// migrate primary groups
|
||||
if (world.equals("global") && holder instanceof User && expiry == 0) {
|
||||
if (parent.getRank() < primaryWeight) {
|
||||
primary = parent.getName();
|
||||
primaryWeight = parent.getRank();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (primary != null && !primary.isEmpty() && !primary.equalsIgnoreCase(GroupManager.DEFAULT_GROUP_NAME)) {
|
||||
User user = ((User) holder);
|
||||
user.getPrimaryGroup().setStoredValue(primary);
|
||||
holder.unsetNode(DataType.NORMAL, Inheritance.builder(GroupManager.DEFAULT_GROUP_NAME).build());
|
||||
}
|
||||
}
|
||||
|
||||
// migrate prefix / suffix
|
||||
String prefix = entity.getOwnPrefix();
|
||||
String suffix = entity.getOwnSuffix();
|
||||
|
||||
if (prefix != null && !prefix.isEmpty()) {
|
||||
holder.setNode(DataType.NORMAL, Prefix.builder(prefix, weight).build(), true);
|
||||
}
|
||||
|
||||
if (suffix != null && !suffix.isEmpty()) {
|
||||
holder.setNode(DataType.NORMAL, Suffix.builder(suffix, weight).build(), true);
|
||||
}
|
||||
|
||||
// migrate options
|
||||
for (Map.Entry<String, Map<String, String>> worldData : entity.getAllOptions().entrySet()) {
|
||||
String world = standardizeWorld(worldData.getKey());
|
||||
for (Map.Entry<String, String> opt : worldData.getValue().entrySet()) {
|
||||
if (opt.getKey() == null || opt.getKey().isEmpty() || opt.getValue() == null || opt.getValue().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String key = opt.getKey().toLowerCase();
|
||||
boolean ignore = key.equals("prefix") ||
|
||||
key.equals("suffix") ||
|
||||
key.equals("weight") ||
|
||||
key.equals("rank") ||
|
||||
key.equals("rank-ladder") ||
|
||||
key.equals("name") ||
|
||||
key.equals("username") ||
|
||||
(key.startsWith("group-") && key.endsWith("-until"));
|
||||
|
||||
if (ignore) {
|
||||
continue;
|
||||
}
|
||||
|
||||
holder.setNode(DataType.NORMAL, Meta.builder(opt.getKey(), opt.getValue()).withContext(DefaultContextKeys.WORLD_KEY, world).build(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String standardizeWorld(String world) {
|
||||
if (world == null || world.isEmpty() || world.equals("*")) {
|
||||
world = "global";
|
||||
}
|
||||
return world.toLowerCase();
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack to workaround issue with accessing PEX async.
|
||||
* See: https://github.com/lucko/LuckPerms/issues/2102
|
||||
*/
|
||||
|
||||
private static void disablePexEvents(PermissionManager manager) throws ReflectiveOperationException {
|
||||
NativeInterface nativeInterface = (NativeInterface) NATIVE_INTERFACE_FIELD.get(manager);
|
||||
NATIVE_INTERFACE_FIELD.set(manager, new DisabledEventsNativeInterface(nativeInterface));
|
||||
}
|
||||
|
||||
private static void enablePexEvents(PermissionManager manager) throws ReflectiveOperationException {
|
||||
NativeInterface nativeInterface = (NativeInterface) NATIVE_INTERFACE_FIELD.get(manager);
|
||||
while (nativeInterface instanceof DisabledEventsNativeInterface) {
|
||||
nativeInterface = ((DisabledEventsNativeInterface) nativeInterface).delegate;
|
||||
NATIVE_INTERFACE_FIELD.set(manager, nativeInterface);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class DisabledEventsNativeInterface implements NativeInterface {
|
||||
private final NativeInterface delegate;
|
||||
|
||||
private DisabledEventsNativeInterface(NativeInterface delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callEvent(PermissionEvent permissionEvent) {
|
||||
// do nothing!
|
||||
}
|
||||
|
||||
@Override public String UUIDToName(UUID uuid) { return this.delegate.UUIDToName(uuid); }
|
||||
@Override public UUID nameToUUID(String s) { return this.delegate.nameToUUID(s); }
|
||||
@Override public boolean isOnline(UUID uuid) { return this.delegate.isOnline(uuid); }
|
||||
@Override public UUID getServerUUID() { return this.delegate.getServerUUID(); }
|
||||
}
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.event.cause.CreationCause;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
|
||||
import nl.svenar.PowerRanks.Cache.CachedPlayers;
|
||||
import nl.svenar.PowerRanks.Cache.PowerConfigurationSection;
|
||||
import nl.svenar.PowerRanks.Data.Users;
|
||||
import nl.svenar.PowerRanks.PowerRanks;
|
||||
import nl.svenar.PowerRanks.api.PowerRanksAPI;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class MigrationPowerRanks extends ChildCommand<Object> {
|
||||
public MigrationPowerRanks() {
|
||||
super(CommandSpec.MIGRATION_COMMAND, "powerranks", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object ignored, ArgumentList args, String label) {
|
||||
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "PowerRanks");
|
||||
log.addListener(plugin.getConsoleSender());
|
||||
log.addListener(sender);
|
||||
|
||||
log.log("Starting.");
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("PowerRanks")) {
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
PowerRanks pr = (PowerRanks) Bukkit.getServer().getPluginManager().getPlugin("PowerRanks");
|
||||
PowerRanksAPI prApi = (pr).loadAPI();
|
||||
Users prUsers = new Users(pr);
|
||||
|
||||
// Migrate all groups
|
||||
log.log("Starting groups migration.");
|
||||
Set<String> ranks = prApi.getRanks();
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
for (String rank : ranks) {
|
||||
Group group = plugin.getStorage().createAndLoadGroup(rank, CreationCause.INTERNAL).join();
|
||||
|
||||
for (String node : prApi.getPermissions(rank)) {
|
||||
if (node.isEmpty()) continue;
|
||||
group.setNode(DataType.NORMAL, MigrationUtils.parseNode(node, true).build(), true);
|
||||
}
|
||||
|
||||
for (String parent : prApi.getInheritances(rank)) {
|
||||
if (parent.isEmpty()) continue;
|
||||
group.setNode(DataType.NORMAL, Inheritance.builder(MigrationUtils.standardizeName(parent)).build(), true);
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(group);
|
||||
log.logAllProgress("Migrated {} groups so far.", groupCount.incrementAndGet());
|
||||
}
|
||||
log.log("Migrated " + groupCount.get() + " groups");
|
||||
|
||||
// Migrate all users
|
||||
log.log("Starting user migration.");
|
||||
Set<String> playerUuids = prUsers.getCachedPlayers();
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
for (String uuidString : playerUuids) {
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, uuidString);
|
||||
if (uuid == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
User user = plugin.getStorage().loadUser(uuid, null).join();
|
||||
|
||||
user.setNode(DataType.NORMAL, Inheritance.builder(CachedPlayers.getString("players." + uuidString + ".rank")).build(), true);
|
||||
|
||||
final PowerConfigurationSection subGroups = CachedPlayers.getConfigurationSection("players." + uuidString + ".subranks");
|
||||
if (subGroups != null) {
|
||||
for (String subGroup : subGroups.getKeys(false)) {
|
||||
Inheritance.Builder builder = Inheritance.builder(subGroup);
|
||||
for (String worldName : CachedPlayers.getStringList("players." + uuidString + ".subranks." + subGroup + ".worlds")) {
|
||||
if (!worldName.equalsIgnoreCase("all")) {
|
||||
builder.withContext(DefaultContextKeys.WORLD_KEY, worldName);
|
||||
}
|
||||
}
|
||||
user.setNode(DataType.NORMAL, builder.build(), true);
|
||||
}
|
||||
}
|
||||
|
||||
for (String node : CachedPlayers.getStringList("players." + uuidString + ".permissions")) {
|
||||
if (node.isEmpty()) continue;
|
||||
user.setNode(DataType.NORMAL, MigrationUtils.parseNode(node, true).build(), true);
|
||||
}
|
||||
|
||||
user.getPrimaryGroup().setStoredValue(CachedPlayers.getString("players." + uuidString + ".rank"));
|
||||
|
||||
plugin.getUserManager().getHouseKeeper().cleanup(user.getUniqueId());
|
||||
plugin.getStorage().saveUser(user);
|
||||
log.logAllProgress("Migrated {} users so far.", userCount.incrementAndGet());
|
||||
}
|
||||
|
||||
log.log("Migrated " + userCount.get() + " users.");
|
||||
log.log("Success! Migration complete.");
|
||||
log.log("Don't forget to remove the PowerRanks jar from your plugins folder & restart the server. " +
|
||||
"LuckPerms may not take over as the server permission handler until this is done.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
}
|
@ -1,401 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import com.github.gustav9797.PowerfulPermsAPI.CachedGroup;
|
||||
import com.github.gustav9797.PowerfulPermsAPI.Group;
|
||||
import com.github.gustav9797.PowerfulPermsAPI.Permission;
|
||||
import com.github.gustav9797.PowerfulPermsAPI.PermissionManager;
|
||||
import com.github.gustav9797.PowerfulPermsAPI.PowerfulPermsPlugin;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.model.manager.group.GroupManager;
|
||||
import me.lucko.luckperms.common.node.factory.NodeBuilders;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import me.lucko.luckperms.common.node.types.Suffix;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.StorageType;
|
||||
import me.lucko.luckperms.common.util.Iterators;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.event.cause.CreationCause;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.node.NodeBuilder;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
// Only supports the latest versions of the PP API. (it seems to change randomly almost every release)
|
||||
public class MigrationPowerfulPerms extends ChildCommand<Object> {
|
||||
public MigrationPowerfulPerms() {
|
||||
super(CommandSpec.MIGRATION_POWERFULPERMS, "powerfulperms", CommandPermission.MIGRATION, Predicates.not(5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object ignored, ArgumentList args, String label) {
|
||||
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "PowerfulPerms");
|
||||
log.addListener(plugin.getConsoleSender());
|
||||
log.addListener(sender);
|
||||
|
||||
log.log("Starting.");
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("PowerfulPerms")) {
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
StorageType type = plugin.getConfiguration().get(ConfigKeys.STORAGE_METHOD);
|
||||
if (type != StorageType.MYSQL) {
|
||||
// We need to load the Hikari/MySQL stuff.
|
||||
plugin.getDependencyManager().loadStorageDependencies(ImmutableSet.of(StorageType.MYSQL));
|
||||
}
|
||||
|
||||
String address = args.get(0);
|
||||
String database = args.get(1);
|
||||
String username = args.get(2);
|
||||
String password = args.get(3);
|
||||
String dbTable = args.get(4);
|
||||
|
||||
// Find a list of UUIDs
|
||||
log.log("Getting a list of UUIDs to migrate.");
|
||||
Set<UUID> uuids = new HashSet<>();
|
||||
|
||||
try (HikariSupplier hikari = new HikariSupplier(address, database, username, password)) {
|
||||
hikari.setup("powerfulperms-migrator-pool");
|
||||
|
||||
try (Connection c = hikari.getConnection()) {
|
||||
DatabaseMetaData meta = c.getMetaData();
|
||||
try (ResultSet rs = meta.getTables(null, null, dbTable, null)) {
|
||||
if (!rs.next()) {
|
||||
log.log("Error - Couldn't find table.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try (Connection c = hikari.getConnection()) {
|
||||
try (PreparedStatement ps = c.prepareStatement("SELECT COLUMN_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=?")) {
|
||||
ps.setString(1, dbTable);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
log.log("Found table: " + dbTable);
|
||||
while (rs.next()) {
|
||||
log.log(rs.getString("COLUMN_NAME") + " - " + rs.getString("COLUMN_TYPE"));
|
||||
}
|
||||
}
|
||||
}
|
||||
try (PreparedStatement ps = c.prepareStatement("SELECT `uuid` FROM " + dbTable)) {
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
uuids.add(UUID.fromString(rs.getString("uuid")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (uuids.isEmpty()) {
|
||||
log.logError("Unable to find any UUIDs to migrate.");
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
log.log("Found " + uuids.size() + " uuids. Starting migration.");
|
||||
|
||||
PowerfulPermsPlugin ppPlugin = (PowerfulPermsPlugin) Bukkit.getPluginManager().getPlugin("PowerfulPerms");
|
||||
PermissionManager pm = ppPlugin.getPermissionManager();
|
||||
|
||||
Collection<Group> groups = pm.getGroups().values();
|
||||
|
||||
AtomicInteger maxWeight = new AtomicInteger(0);
|
||||
|
||||
// Groups first.
|
||||
log.log("Starting group migration.");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
Iterators.tryIterate(groups, g -> {
|
||||
maxWeight.set(Math.max(maxWeight.get(), g.getRank()));
|
||||
|
||||
String groupName = MigrationUtils.standardizeName(g.getName());
|
||||
me.lucko.luckperms.common.model.Group group = plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
|
||||
|
||||
MigrationUtils.setGroupWeight(group, g.getRank());
|
||||
|
||||
for (Permission p : g.getOwnPermissions()) {
|
||||
applyPerm(group, p);
|
||||
}
|
||||
|
||||
for (Group parent : g.getParents()) {
|
||||
group.setNode(DataType.NORMAL, Inheritance.builder(parent.getName().toLowerCase()).build(), true);
|
||||
}
|
||||
|
||||
// server --> prefix afaik
|
||||
for (Map.Entry<String, String> prefix : g.getPrefixes().entrySet()) {
|
||||
if (prefix.getValue().isEmpty()) continue;
|
||||
|
||||
String server = prefix.getKey().toLowerCase();
|
||||
if (prefix.getKey().equals("*") || prefix.getKey().equals("all")) {
|
||||
server = null;
|
||||
}
|
||||
|
||||
if (server != null) {
|
||||
group.setNode(DataType.NORMAL, Prefix.builder(prefix.getValue(), g.getRank()).withContext(DefaultContextKeys.SERVER_KEY, server).build(), true);
|
||||
} else {
|
||||
group.setNode(DataType.NORMAL, Prefix.builder(prefix.getValue(), g.getRank()).build(), true);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> suffix : g.getSuffixes().entrySet()) {
|
||||
if (suffix.getValue().isEmpty()) continue;
|
||||
|
||||
String server = suffix.getKey().toLowerCase();
|
||||
if (suffix.getKey().equals("*") || suffix.getKey().equals("all")) {
|
||||
server = null;
|
||||
}
|
||||
|
||||
if (server != null) {
|
||||
group.setNode(DataType.NORMAL, Suffix.builder(suffix.getValue(), g.getRank()).withContext(DefaultContextKeys.SERVER_KEY, server).build(), true);
|
||||
} else {
|
||||
group.setNode(DataType.NORMAL, Suffix.builder(suffix.getValue(), g.getRank()).build(), true);
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(group);
|
||||
log.logAllProgress("Migrated {} groups so far.", groupCount.incrementAndGet());
|
||||
});
|
||||
log.log("Migrated " + groupCount.get() + " groups");
|
||||
|
||||
// Migrate all users
|
||||
log.log("Starting user migration.");
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
|
||||
// Increment the max weight from the group migrations. All user meta should override.
|
||||
maxWeight.addAndGet(5);
|
||||
|
||||
// Migrate all users and their groups
|
||||
Iterators.tryIterate(uuids, uuid -> {
|
||||
|
||||
// Create a LuckPerms user for the UUID
|
||||
User user = plugin.getStorage().loadUser(uuid, null).join();
|
||||
|
||||
List<Permission> permissions = joinFuture(pm.getPlayerOwnPermissions(uuid));
|
||||
|
||||
for (Permission p : permissions) {
|
||||
applyPerm(user, p);
|
||||
}
|
||||
|
||||
// server --> list of groups
|
||||
Map<String, List<CachedGroup>> parents = joinFuture(pm.getPlayerOwnGroups(uuid));
|
||||
for (Map.Entry<String, List<CachedGroup>> parent : parents.entrySet()) {
|
||||
String server = parent.getKey().toLowerCase();
|
||||
if (parent.getKey().equals("*") || parent.getKey().equals("all")) {
|
||||
server = null;
|
||||
}
|
||||
|
||||
for (CachedGroup group : parent.getValue()) {
|
||||
applyGroup(pm, user, group, server);
|
||||
}
|
||||
}
|
||||
|
||||
String prefix = joinFuture(pm.getPlayerOwnPrefix(uuid));
|
||||
String suffix = joinFuture(pm.getPlayerOwnSuffix(uuid));
|
||||
|
||||
if (prefix != null && !prefix.isEmpty()) {
|
||||
user.setNode(DataType.NORMAL, Prefix.builder(prefix, maxWeight.get()).build(), true);
|
||||
}
|
||||
|
||||
if (suffix != null && !suffix.isEmpty()) {
|
||||
user.setNode(DataType.NORMAL, Suffix.builder(suffix, maxWeight.get()).build(), true);
|
||||
}
|
||||
|
||||
Group primaryGroup = joinFuture(pm.getPlayerPrimaryGroup(uuid));
|
||||
if (primaryGroup != null && primaryGroup.getName() != null) {
|
||||
String primary = primaryGroup.getName().toLowerCase();
|
||||
if (!primary.equals(GroupManager.DEFAULT_GROUP_NAME)) {
|
||||
user.setNode(DataType.NORMAL, Inheritance.builder(primary).build(), true);
|
||||
user.getPrimaryGroup().setStoredValue(primary);
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getUserManager().getHouseKeeper().cleanup(user.getUniqueId());
|
||||
plugin.getStorage().saveUser(user);
|
||||
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
|
||||
});
|
||||
|
||||
log.log("Migrated " + userCount.get() + " users.");
|
||||
log.log("Success! Migration complete.");
|
||||
log.log("Don't forget to remove the PowerfulPerms jar from your plugins folder & restart the server. " +
|
||||
"LuckPerms may not take over as the server permission handler until this is done.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private void applyPerm(PermissionHolder holder, Permission p) {
|
||||
String node = p.getPermissionString();
|
||||
boolean value = true;
|
||||
if (node.startsWith("!") || node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
|
||||
if (node.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String server = p.getServer();
|
||||
if (server != null && (server.equalsIgnoreCase("all") || server.equalsIgnoreCase("*") || server.isEmpty())) {
|
||||
server = null;
|
||||
}
|
||||
|
||||
String world = p.getWorld();
|
||||
if (world != null && (world.equalsIgnoreCase("all") || world.equalsIgnoreCase("*") || world.isEmpty())) {
|
||||
world = null;
|
||||
}
|
||||
|
||||
long expireAt = 0L;
|
||||
if (p.willExpire()) {
|
||||
expireAt = p.getExpirationDate().getTime() / 1000L;
|
||||
}
|
||||
|
||||
if (world != null && server == null) {
|
||||
server = "global";
|
||||
}
|
||||
|
||||
NodeBuilder<?, ?> nb = NodeBuilders.determineMostApplicable(node).value(value);
|
||||
if (expireAt != 0) nb.expiry(expireAt);
|
||||
if (server != null) nb.withContext(DefaultContextKeys.SERVER_KEY, server);
|
||||
if (world != null) nb.withContext(DefaultContextKeys.WORLD_KEY, world);
|
||||
|
||||
holder.setNode(DataType.NORMAL, nb.build(), true);
|
||||
}
|
||||
|
||||
private void applyGroup(PermissionManager pm, PermissionHolder holder, CachedGroup g, String server) {
|
||||
Group group = pm.getGroup(g.getGroupId());
|
||||
|
||||
long expireAt = 0L;
|
||||
if (g.willExpire()) {
|
||||
expireAt = g.getExpirationDate().getTime() / 1000L;
|
||||
}
|
||||
|
||||
NodeBuilder<?, ?> nb = Inheritance.builder(MigrationUtils.standardizeName(group.getName()));
|
||||
|
||||
if (expireAt != 0) {
|
||||
nb.expiry(expireAt);
|
||||
}
|
||||
|
||||
if (server != null) {
|
||||
nb.withContext(DefaultContextKeys.SERVER_KEY, server);
|
||||
}
|
||||
|
||||
holder.setNode(DataType.NORMAL, nb.build(), true);
|
||||
}
|
||||
|
||||
private static <T> T joinFuture(Future<T> future) {
|
||||
try {
|
||||
return future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple hikari wrapper
|
||||
*/
|
||||
public static final class HikariSupplier implements AutoCloseable {
|
||||
|
||||
private final String host;
|
||||
private final String port;
|
||||
private final String database;
|
||||
private final String username;
|
||||
private final String password;
|
||||
|
||||
private HikariDataSource hikari;
|
||||
|
||||
public HikariSupplier(String address, String database, String username, String password) {
|
||||
this.database = database;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
|
||||
String[] split = address.split(":");
|
||||
if (split.length != 2) {
|
||||
throw new IllegalArgumentException("Address argument should be in the format hostname:port");
|
||||
}
|
||||
|
||||
this.host = split[0];
|
||||
this.port = split[1];
|
||||
}
|
||||
|
||||
public void setup(String poolName) {
|
||||
this.hikari = new HikariDataSource();
|
||||
this.hikari.setPoolName(poolName);
|
||||
this.hikari.setMaximumPoolSize(2);
|
||||
this.hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
|
||||
this.hikari.addDataSourceProperty("serverName", this.host);
|
||||
this.hikari.addDataSourceProperty("port", this.port);
|
||||
this.hikari.addDataSourceProperty("databaseName", this.database);
|
||||
this.hikari.addDataSourceProperty("user", this.username);
|
||||
this.hikari.addDataSourceProperty("password", this.password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.hikari.close();
|
||||
}
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
return this.hikari.getConnection();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,238 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.bukkit.migration;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.factory.NodeBuilders;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
import me.lucko.luckperms.common.node.types.Meta;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import me.lucko.luckperms.common.node.types.Suffix;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Iterators;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.event.cause.CreationCause;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.node.Node;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
|
||||
import org.tyrannyofheaven.bukkit.zPermissions.dao.PermissionService;
|
||||
import org.tyrannyofheaven.bukkit.zPermissions.model.EntityMetadata;
|
||||
import org.tyrannyofheaven.bukkit.zPermissions.model.Entry;
|
||||
import org.tyrannyofheaven.bukkit.zPermissions.model.Membership;
|
||||
import org.tyrannyofheaven.bukkit.zPermissions.model.PermissionEntity;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class MigrationZPermissions extends ChildCommand<Object> {
|
||||
public MigrationZPermissions() {
|
||||
super(CommandSpec.MIGRATION_COMMAND, "zpermissions", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object ignored, ArgumentList args, String label) {
|
||||
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "zPermissions");
|
||||
log.addListener(plugin.getConsoleSender());
|
||||
log.addListener(sender);
|
||||
|
||||
log.log("Starting.");
|
||||
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("zPermissions")) {
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
if (!Bukkit.getServicesManager().isProvidedFor(ZPermissionsService.class)) {
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
ZPermissionsService service = Bukkit.getServicesManager().getRegistration(ZPermissionsService.class).getProvider();
|
||||
|
||||
PermissionService internalService;
|
||||
try {
|
||||
Field psField = service.getClass().getDeclaredField("permissionService");
|
||||
psField.setAccessible(true);
|
||||
internalService = (PermissionService) psField.get(service);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
// Migrate all groups
|
||||
log.log("Starting group migration.");
|
||||
|
||||
Map<UUID, Set<Node>> userParents = new HashMap<>();
|
||||
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
AtomicInteger maxWeight = new AtomicInteger(0);
|
||||
Iterators.tryIterate(internalService.getEntities(true), entity -> {
|
||||
String groupName = MigrationUtils.standardizeName(entity.getDisplayName());
|
||||
Group group = plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
|
||||
|
||||
int weight = entity.getPriority();
|
||||
maxWeight.set(Math.max(maxWeight.get(), weight));
|
||||
migrateEntity(group, entity, weight);
|
||||
MigrationUtils.setGroupWeight(group, weight);
|
||||
|
||||
// store user data for later
|
||||
Set<Membership> members = entity.getMemberships();
|
||||
for (Membership membership : members) {
|
||||
UUID uuid = BukkitUuids.lookupUuid(log, membership.getMember());
|
||||
if (uuid == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Set<Node> nodes = userParents.computeIfAbsent(uuid, u -> new HashSet<>());
|
||||
if (membership.getExpiration() == null) {
|
||||
nodes.add(Inheritance.builder(groupName).build());
|
||||
} else {
|
||||
long expiry = membership.getExpiration().toInstant().getEpochSecond();
|
||||
nodes.add(Inheritance.builder(groupName).expiry(expiry).build());
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getStorage().saveGroup(group);
|
||||
log.logAllProgress("Migrated {} groups so far.", groupCount.incrementAndGet());
|
||||
});
|
||||
log.log("Migrated " + groupCount.get() + " groups");
|
||||
|
||||
// Migrate all tracks
|
||||
log.log("Starting track migration.");
|
||||
AtomicInteger trackCount = new AtomicInteger(0);
|
||||
Iterators.tryIterate(service.getAllTracks(), t -> {
|
||||
String trackName = MigrationUtils.standardizeName(t);
|
||||
Track track = plugin.getStorage().createAndLoadTrack(trackName, CreationCause.INTERNAL).join();
|
||||
track.setGroups(service.getTrackGroups(t));
|
||||
plugin.getStorage().saveTrack(track);
|
||||
|
||||
log.logAllProgress("Migrated {} tracks so far.", trackCount.incrementAndGet());
|
||||
});
|
||||
log.log("Migrated " + trackCount.get() + " tracks");
|
||||
|
||||
// Migrate all users.
|
||||
log.log("Starting user migration.");
|
||||
maxWeight.addAndGet(10);
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
|
||||
Set<UUID> usersToMigrate = new HashSet<>(userParents.keySet());
|
||||
usersToMigrate.addAll(service.getAllPlayersUUID());
|
||||
|
||||
Iterators.tryIterate(usersToMigrate, u -> {
|
||||
PermissionEntity entity = internalService.getEntity(null, u, false);
|
||||
|
||||
String username = null;
|
||||
if (entity != null) {
|
||||
username = entity.getDisplayName();
|
||||
}
|
||||
|
||||
User user = plugin.getStorage().loadUser(u, username).join();
|
||||
|
||||
// migrate permissions & meta
|
||||
if (entity != null) {
|
||||
migrateEntity(user, entity, maxWeight.get());
|
||||
}
|
||||
|
||||
// migrate groups
|
||||
Set<Node> parents = userParents.get(u);
|
||||
if (parents != null) {
|
||||
parents.forEach(node -> user.setNode(DataType.NORMAL, node, true));
|
||||
}
|
||||
|
||||
user.getPrimaryGroup().setStoredValue(MigrationUtils.standardizeName(service.getPlayerPrimaryGroup(u)));
|
||||
|
||||
plugin.getUserManager().getHouseKeeper().cleanup(user.getUniqueId());
|
||||
plugin.getStorage().saveUser(user);
|
||||
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
|
||||
});
|
||||
|
||||
log.log("Migrated " + userCount.get() + " users.");
|
||||
log.log("Success! Migration complete.");
|
||||
log.log("Don't forget to remove the zPermissions jar from your plugins folder & restart the server. " +
|
||||
"LuckPerms may not take over as the server permission handler until this is done.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private void migrateEntity(PermissionHolder holder, PermissionEntity entity, int weight) {
|
||||
for (Entry e : entity.getPermissions()) {
|
||||
if (e.getPermission().isEmpty()) continue;
|
||||
|
||||
if (e.getWorld() != null && !e.getWorld().getName().isEmpty()) {
|
||||
holder.setNode(DataType.NORMAL, NodeBuilders.determineMostApplicable(e.getPermission()).value(e.isValue()).withContext(DefaultContextKeys.WORLD_KEY, e.getWorld().getName()).build(), true);
|
||||
} else {
|
||||
holder.setNode(DataType.NORMAL, NodeBuilders.determineMostApplicable(e.getPermission()).value(e.isValue()).build(), true);
|
||||
}
|
||||
}
|
||||
|
||||
// only migrate inheritances for groups
|
||||
if (entity.isGroup()) {
|
||||
for (PermissionEntity inheritance : entity.getParents()) {
|
||||
if (!inheritance.getDisplayName().equals(holder.getObjectName())) {
|
||||
holder.setNode(DataType.NORMAL, Inheritance.builder(MigrationUtils.standardizeName(inheritance.getDisplayName())).build(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (EntityMetadata metadata : entity.getMetadata()) {
|
||||
String key = metadata.getName().toLowerCase();
|
||||
Object value = metadata.getValue();
|
||||
|
||||
if (key.isEmpty() || value == null) continue;
|
||||
|
||||
String valueString = value.toString();
|
||||
if (valueString.isEmpty()) continue;
|
||||
|
||||
if (key.equals("prefix")) {
|
||||
holder.setNode(DataType.NORMAL, Prefix.builder(valueString, weight).build(), true);
|
||||
} else if (key.equals("suffix")) {
|
||||
holder.setNode(DataType.NORMAL, Suffix.builder(valueString, weight).build(), true);
|
||||
} else {
|
||||
holder.setNode(DataType.NORMAL, Meta.builder(key, valueString).build(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -56,9 +56,6 @@ luckperms {
|
||||
}
|
||||
}
|
||||
}
|
||||
migration {
|
||||
plugin brigadier:string single_word;
|
||||
}
|
||||
translations {
|
||||
install;
|
||||
}
|
||||
|
@ -8,17 +8,6 @@ dependencies {
|
||||
compileOnly 'net.md-5:bungeecord-api:1.15-SNAPSHOT'
|
||||
compileOnly 'me.lucko:adventure-platform-bungeecord:4.0.0' // re: this artifact - see note in common/build.gradle
|
||||
compileOnly 'com.imaginarycode.minecraft:RedisBungee:0.4'
|
||||
|
||||
// migration plugins
|
||||
compileOnly('net.alpenblock:BungeePerms:3.0') {
|
||||
exclude(module: 'bungeecord-api')
|
||||
exclude(module: 'lombok')
|
||||
exclude(module: 'spigot-api')
|
||||
exclude(module: 'worldedit')
|
||||
exclude(module: 'Vault')
|
||||
exclude(module: 'Essentials')
|
||||
exclude(module: 'EssentialsX')
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
@ -1,176 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* 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.bungee.migration;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.commands.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import me.lucko.luckperms.common.node.types.Suffix;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Iterators;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
|
||||
import net.alpenblock.bungeeperms.BungeePerms;
|
||||
import net.alpenblock.bungeeperms.Group;
|
||||
import net.alpenblock.bungeeperms.PermEntity;
|
||||
import net.alpenblock.bungeeperms.Server;
|
||||
import net.alpenblock.bungeeperms.World;
|
||||
import net.luckperms.api.context.DefaultContextKeys;
|
||||
import net.luckperms.api.event.cause.CreationCause;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class MigrationBungeePerms extends ChildCommand<Object> {
|
||||
public MigrationBungeePerms() {
|
||||
super(CommandSpec.MIGRATION_COMMAND, "bungeeperms", CommandPermission.MIGRATION, Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object ignored, ArgumentList args, String label) {
|
||||
ProgressLogger log = new ProgressLogger(Message.MIGRATION_LOG, Message.MIGRATION_LOG_PROGRESS, "BungeePerms");
|
||||
log.addListener(plugin.getConsoleSender());
|
||||
log.addListener(sender);
|
||||
|
||||
log.log("Starting.");
|
||||
|
||||
// Get BungeePerms instance
|
||||
BungeePerms bp = BungeePerms.getInstance();
|
||||
if (bp == null) {
|
||||
log.logError("Plugin not loaded.");
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
List<Group> groups = bp.getPermissionsManager().getBackEnd().loadGroups();
|
||||
|
||||
log.log("Calculating group weightings.");
|
||||
int i = 0;
|
||||
for (Group group : groups) {
|
||||
i = Math.max(i, group.getRank());
|
||||
}
|
||||
int maxWeight = i + 5;
|
||||
|
||||
// Migrate all groups.
|
||||
log.log("Starting group migration.");
|
||||
AtomicInteger groupCount = new AtomicInteger(0);
|
||||
Iterators.tryIterate(groups, g -> {
|
||||
int groupWeight = maxWeight - g.getRank();
|
||||
|
||||
// Make a LuckPerms group for the one being migrated
|
||||
String groupName = MigrationUtils.standardizeName(g.getName());
|
||||
me.lucko.luckperms.common.model.Group group = plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
|
||||
|
||||
MigrationUtils.setGroupWeight(group, groupWeight);
|
||||
migrateHolder(g, g.getInheritances(), groupWeight, group);
|
||||
|
||||
plugin.getStorage().saveGroup(group);
|
||||
log.logAllProgress("Migrated {} groups so far.", groupCount.incrementAndGet());
|
||||
});
|
||||
log.log("Migrated " + groupCount.get() + " groups");
|
||||
|
||||
// Migrate all users.
|
||||
log.log("Starting user migration.");
|
||||
AtomicInteger userCount = new AtomicInteger(0);
|
||||
|
||||
// Increment the max weight from the group migrations. All user meta should override.
|
||||
int userWeight = maxWeight + 5;
|
||||
|
||||
Iterators.tryIterate(bp.getPermissionsManager().getBackEnd().loadUsers(), u -> {
|
||||
if (u.getUUID() == null) {
|
||||
log.logError("Could not parse UUID for user: " + u.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a LuckPerms user for the one being migrated.
|
||||
me.lucko.luckperms.common.model.User user = plugin.getStorage().loadUser(u.getUUID(), u.getName()).join();
|
||||
|
||||
migrateHolder(u, u.getGroupsString(), userWeight, user);
|
||||
|
||||
plugin.getStorage().saveUser(user);
|
||||
plugin.getUserManager().getHouseKeeper().cleanup(user.getUniqueId());
|
||||
|
||||
log.logProgress("Migrated {} users so far.", userCount.incrementAndGet(), ProgressLogger.DEFAULT_NOTIFY_FREQUENCY);
|
||||
});
|
||||
|
||||
log.log("Migrated " + userCount.get() + " users.");
|
||||
log.log("Success! Migration complete.");
|
||||
log.log("Don't forget to remove the BungeePerms jar from your plugins folder & restart the server. " +
|
||||
"LuckPerms may not take over as the server permission handler until this is done.");
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static void migrateHolder(PermEntity entity, List<String> parents, int weight, PermissionHolder holder) {
|
||||
// Migrate global perms
|
||||
for (String perm : entity.getPerms()) {
|
||||
if (perm.isEmpty()) continue;
|
||||
holder.setNode(DataType.NORMAL, MigrationUtils.parseNode(perm, true).build(), true);
|
||||
}
|
||||
|
||||
// Migrate per-server perms
|
||||
for (Map.Entry<String, Server> e : entity.getServers().entrySet()) {
|
||||
for (String perm : e.getValue().getPerms()) {
|
||||
if (perm.isEmpty()) continue;
|
||||
holder.setNode(DataType.NORMAL, MigrationUtils.parseNode(perm, true).withContext(DefaultContextKeys.SERVER_KEY, e.getKey()).build(), true);
|
||||
}
|
||||
|
||||
// Migrate per-world perms
|
||||
for (Map.Entry<String, World> we : e.getValue().getWorlds().entrySet()) {
|
||||
for (String perm : we.getValue().getPerms()) {
|
||||
if (perm.isEmpty()) continue;
|
||||
holder.setNode(DataType.NORMAL, MigrationUtils.parseNode(perm, true).withContext(DefaultContextKeys.SERVER_KEY, e.getKey()).withContext(DefaultContextKeys.WORLD_KEY, we.getKey()).build(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate any parent groups
|
||||
for (String inherit : parents) {
|
||||
if (inherit.isEmpty()) continue;
|
||||
holder.setNode(DataType.NORMAL, Inheritance.builder(MigrationUtils.standardizeName(inherit)).build(), true);
|
||||
}
|
||||
|
||||
// Migrate prefix and suffix
|
||||
String prefix = entity.getPrefix();
|
||||
String suffix = entity.getSuffix();
|
||||
|
||||
if (prefix != null && !prefix.isEmpty()) {
|
||||
holder.setNode(DataType.NORMAL, Prefix.builder(prefix, weight).build(), true);
|
||||
}
|
||||
if (suffix != null && !suffix.isEmpty()) {
|
||||
holder.setNode(DataType.NORMAL, Suffix.builder(suffix, weight).build(), true);
|
||||
}
|
||||
}
|
||||
}
|
@ -38,11 +38,12 @@ import me.lucko.luckperms.common.node.utils.NodeJsonSerializer;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.Storage;
|
||||
import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
||||
import me.lucko.luckperms.common.util.gson.JArray;
|
||||
import me.lucko.luckperms.common.util.gson.JObject;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@ -90,7 +91,7 @@ public abstract class Exporter implements Runnable {
|
||||
this.includeUsers = includeUsers;
|
||||
this.includeGroups = includeGroups;
|
||||
|
||||
this.log = new ProgressLogger(Message.EXPORT_LOG, Message.EXPORT_LOG_PROGRESS);
|
||||
this.log = new ProgressLogger();
|
||||
this.log.addListener(plugin.getConsoleSender());
|
||||
this.log.addListener(executor);
|
||||
}
|
||||
@ -203,7 +204,7 @@ public abstract class Exporter implements Runnable {
|
||||
break;
|
||||
} catch (TimeoutException e) {
|
||||
// still executing - send a progress report and continue waiting
|
||||
this.log.logAllProgress("Exported {} users so far.", userCount.get());
|
||||
this.log.logProgress("Exported " + userCount.get() + " users so far.");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -272,4 +273,31 @@ public abstract class Exporter implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ProgressLogger {
|
||||
private final Set<Sender> listeners = new HashSet<>();
|
||||
|
||||
public void addListener(Sender sender) {
|
||||
this.listeners.add(sender);
|
||||
}
|
||||
|
||||
public Set<Sender> getListeners() {
|
||||
return this.listeners;
|
||||
}
|
||||
|
||||
public void log(String msg) {
|
||||
dispatchMessage(Message.EXPORT_LOG, msg);
|
||||
}
|
||||
|
||||
public void logProgress(String msg) {
|
||||
dispatchMessage(Message.EXPORT_LOG_PROGRESS, msg);
|
||||
}
|
||||
|
||||
private void dispatchMessage(Message.Args1<String> messageType, String content) {
|
||||
final Component message = messageType.build(content);
|
||||
for (Sender s : this.listeners) {
|
||||
s.sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,6 @@ import me.lucko.luckperms.common.commands.group.DeleteGroup;
|
||||
import me.lucko.luckperms.common.commands.group.GroupParentCommand;
|
||||
import me.lucko.luckperms.common.commands.group.ListGroups;
|
||||
import me.lucko.luckperms.common.commands.log.LogParentCommand;
|
||||
import me.lucko.luckperms.common.commands.migration.MigrationParentCommand;
|
||||
import me.lucko.luckperms.common.commands.misc.ApplyEditsCommand;
|
||||
import me.lucko.luckperms.common.commands.misc.BulkUpdateCommand;
|
||||
import me.lucko.luckperms.common.commands.misc.CheckCommand;
|
||||
@ -114,7 +113,6 @@ public class CommandManager {
|
||||
.add(new ExportCommand())
|
||||
.add(new ReloadConfigCommand())
|
||||
.add(new BulkUpdateCommand())
|
||||
.add(new MigrationParentCommand())
|
||||
.add(new TranslationsCommand())
|
||||
.add(new ApplyEditsCommand())
|
||||
.add(new CreateGroup())
|
||||
|
@ -45,7 +45,6 @@ public enum CommandPermission {
|
||||
RELOAD_CONFIG("reloadconfig", Type.NONE),
|
||||
BULK_UPDATE("bulkupdate", Type.NONE),
|
||||
APPLY_EDITS("applyedits", Type.NONE),
|
||||
MIGRATION("migration", Type.NONE),
|
||||
TRANSLATIONS("translations", Type.NONE),
|
||||
|
||||
CREATE_GROUP("creategroup", Type.NONE),
|
||||
|
@ -86,7 +86,6 @@ public enum CommandSpec {
|
||||
arg("action value", false),
|
||||
arg("constraint...", false)
|
||||
),
|
||||
MIGRATION("/%s migration"),
|
||||
TRANSLATIONS("/%s translations",
|
||||
arg("install", false)
|
||||
),
|
||||
@ -413,18 +412,6 @@ public enum CommandSpec {
|
||||
),
|
||||
SPONGE_OPTION_CLEAR(
|
||||
arg("contexts...", false)
|
||||
),
|
||||
|
||||
MIGRATION_COMMAND,
|
||||
MIGRATION_GROUPMANAGER(
|
||||
arg("migrate as global", true)
|
||||
),
|
||||
MIGRATION_POWERFULPERMS(
|
||||
arg("address", true),
|
||||
arg("database", true),
|
||||
arg("username", true),
|
||||
arg("password", true),
|
||||
arg("db table", true)
|
||||
);
|
||||
|
||||
private final String usage;
|
||||
|
@ -1,143 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.commands.migration;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
|
||||
import me.lucko.luckperms.common.command.abstraction.Command;
|
||||
import me.lucko.luckperms.common.command.abstraction.ParentCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class MigrationParentCommand extends ParentCommand<Object, Void> {
|
||||
private static final Map<String, String> PLUGINS = ImmutableMap.<String, String>builder()
|
||||
// bukkit
|
||||
.put("org.anjocaido.groupmanager.GroupManager", "me.lucko.luckperms.bukkit.migration.MigrationGroupManager")
|
||||
.put("ru.tehkode.permissions.bukkit.PermissionsEx", "me.lucko.luckperms.bukkit.migration.MigrationPermissionsEx")
|
||||
.put("com.github.gustav9797.PowerfulPermsAPI.PowerfulPermsPlugin", "me.lucko.luckperms.bukkit.migration.MigrationPowerfulPerms")
|
||||
.put("org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService", "me.lucko.luckperms.bukkit.migration.MigrationZPermissions")
|
||||
.put("de.bananaco.bpermissions.api.WorldManager", "me.lucko.luckperms.bukkit.migration.MigrationBPermissions")
|
||||
.put("com.platymuus.bukkit.permissions.PermissionsPlugin", "me.lucko.luckperms.bukkit.migration.MigrationPermissionsBukkit")
|
||||
.put("nl.svenar.PowerRanks.PowerRanks", "me.lucko.luckperms.bukkit.migration.MigrationPowerRanks")
|
||||
// bungee
|
||||
.put("net.alpenblock.bungeeperms.BungeePerms", "me.lucko.luckperms.bungee.migration.MigrationBungeePerms")
|
||||
.build();
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
private List<Command<Object>> commands = null;
|
||||
private boolean display = true;
|
||||
|
||||
public MigrationParentCommand() {
|
||||
super(CommandSpec.MIGRATION, "Migration", Type.NO_TARGET_ARGUMENT, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized @NonNull List<Command<Object>> getChildren() {
|
||||
if (this.commands == null) {
|
||||
this.commands = getAvailableCommands();
|
||||
|
||||
// Add dummy command to show in the list.
|
||||
if (this.commands.isEmpty()) {
|
||||
this.display = false;
|
||||
this.commands.add(new ChildCommand<Object>(CommandSpec.MIGRATION_COMMAND, "No available plugins to migrate from", CommandPermission.MIGRATION, Predicates.alwaysFalse()) {
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Object o, ArgumentList args, String label) {
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return this.commands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(Sender sender) {
|
||||
return sender.hasPermission(CommandPermission.MIGRATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldDisplay() {
|
||||
getChildren();
|
||||
return this.display;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<Command<Object>> getAvailableCommands() {
|
||||
List<Command<Object>> available = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, String> plugin : PLUGINS.entrySet()) {
|
||||
try {
|
||||
Class.forName(plugin.getKey());
|
||||
available.add((ChildCommand<Object>) Class.forName(plugin.getValue()).getConstructor().newInstance());
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReentrantLock getLockForTarget(Void target) {
|
||||
return this.lock; // share a lock between all migration commands
|
||||
}
|
||||
|
||||
/* Dummy */
|
||||
|
||||
@Override
|
||||
protected List<String> getTargets(LuckPermsPlugin plugin) {
|
||||
// should never be called if we specify Type.NO_TARGET_ARGUMENT in the constructor
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void parseTarget(String target, LuckPermsPlugin plugin, Sender sender) {
|
||||
// should never be called if we specify Type.NO_TARGET_ARGUMENT in the constructor
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getTarget(Void target, LuckPermsPlugin plugin, Sender sender) {
|
||||
return this; // can't return null, but we don't need a target
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanup(Object o, LuckPermsPlugin plugin) {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.commands.migration;
|
||||
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.node.factory.NodeBuilders;
|
||||
import me.lucko.luckperms.common.node.types.Weight;
|
||||
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.node.NodeBuilder;
|
||||
import net.luckperms.api.node.NodeType;
|
||||
|
||||
public final class MigrationUtils {
|
||||
private MigrationUtils() {}
|
||||
|
||||
public static NodeBuilder<?, ?> parseNode(String permission, boolean value) {
|
||||
if (permission.length() > 1) {
|
||||
if (permission.charAt(0) == '-' || permission.charAt(0) == '!') {
|
||||
permission = permission.substring(1);
|
||||
value = false;
|
||||
} else if (permission.charAt(0) == '+') {
|
||||
permission = permission.substring(1);
|
||||
value = true;
|
||||
}
|
||||
}
|
||||
|
||||
return NodeBuilders.determineMostApplicable(permission).value(value);
|
||||
}
|
||||
|
||||
public static void setGroupWeight(Group group, int weight) {
|
||||
group.removeIf(DataType.NORMAL, null, NodeType.WEIGHT::matches, false);
|
||||
group.setNode(DataType.NORMAL, Weight.builder(weight).build(), true);
|
||||
}
|
||||
|
||||
public static String standardizeName(String string) {
|
||||
return string.trim()
|
||||
.replace(':', '-')
|
||||
.replace(' ', '-')
|
||||
.replace('.', '-')
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
}
|
@ -349,38 +349,6 @@ public interface Message {
|
||||
.append(text(msg, GRAY))
|
||||
);
|
||||
|
||||
Args2<String, String> MIGRATION_LOG = (pluginName, msg) -> prefixed(text()
|
||||
// "&3MIGRATION &7[&3{}&7] &3&l> &f{}"
|
||||
.append(translatable("luckperms.logs.migration-prefix", DARK_AQUA))
|
||||
.append(space())
|
||||
.append(text()
|
||||
.color(GRAY)
|
||||
.append(text('['))
|
||||
.append(text(pluginName, DARK_AQUA))
|
||||
.append(text(']'))
|
||||
)
|
||||
.append(space())
|
||||
.append(text('>', DARK_AQUA, BOLD))
|
||||
.append(space())
|
||||
.append(text(msg, WHITE))
|
||||
);
|
||||
|
||||
Args2<String, String> MIGRATION_LOG_PROGRESS = (pluginName, msg) -> prefixed(text()
|
||||
// "&3MIGRATION &7[&3{}&7] &3&l> &7{}"
|
||||
.append(translatable("luckperms.logs.migration-prefix", DARK_AQUA))
|
||||
.append(space())
|
||||
.append(text()
|
||||
.color(GRAY)
|
||||
.append(text('['))
|
||||
.append(text(pluginName, DARK_AQUA))
|
||||
.append(text(']'))
|
||||
)
|
||||
.append(space())
|
||||
.append(text('>', DARK_AQUA, BOLD))
|
||||
.append(space())
|
||||
.append(text(msg, GRAY))
|
||||
);
|
||||
|
||||
Args0 COMMAND_NOT_RECOGNISED = () -> prefixed(translatable()
|
||||
// "&cCommand not recognised."
|
||||
.key("luckperms.commandsystem.command-not-recognised")
|
||||
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ProgressLogger {
|
||||
public static final int DEFAULT_NOTIFY_FREQUENCY = 500;
|
||||
|
||||
private final Function<String, Component> logMessage;
|
||||
private final Function<String, Component> logProgressMessage;
|
||||
|
||||
private final Set<Sender> listeners = new HashSet<>();
|
||||
|
||||
public ProgressLogger(Message.Args1<String> logMessage, Message.Args1<String> logProgressMessage) {
|
||||
this.logMessage = logMessage::build;
|
||||
this.logProgressMessage = logProgressMessage::build;
|
||||
}
|
||||
|
||||
public ProgressLogger(Message.Args2<String, String> logMessage, Message.Args2<String, String> logProgressMessage, String logPrefixParam) {
|
||||
this.logMessage = message -> logMessage.build(logPrefixParam, message);
|
||||
this.logProgressMessage = message -> logProgressMessage.build(logPrefixParam, message);
|
||||
}
|
||||
|
||||
public void addListener(Sender sender) {
|
||||
this.listeners.add(sender);
|
||||
}
|
||||
|
||||
public Set<Sender> getListeners() {
|
||||
return this.listeners;
|
||||
}
|
||||
|
||||
public void log(String msg) {
|
||||
dispatchMessage(this.logMessage, msg);
|
||||
}
|
||||
|
||||
public void logError(String msg) {
|
||||
dispatchMessage(this.logMessage, "Error -> " + msg);
|
||||
}
|
||||
|
||||
public void logAllProgress(String msg, int amount) {
|
||||
dispatchMessage(this.logProgressMessage, msg.replace("{}", Integer.toString(amount)));
|
||||
}
|
||||
|
||||
public void logProgress(String msg, int amount, int notifyFrequency) {
|
||||
if (amount % notifyFrequency == 0) {
|
||||
logAllProgress(msg, amount);
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchMessage(Function<String, Component> messageType, String content) {
|
||||
final Component message = messageType.apply(content);
|
||||
for (Sender s : this.listeners) {
|
||||
s.sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
luckperms.logs.actionlog-prefix=LOG
|
||||
luckperms.logs.verbose-prefix=VB
|
||||
luckperms.logs.export-prefix=EXPORT
|
||||
luckperms.logs.migration-prefix=MIGRATION
|
||||
luckperms.commandsystem.available-commands=Use {0} to view available commands
|
||||
luckperms.commandsystem.command-not-recognised=Command not recognised
|
||||
luckperms.commandsystem.no-permission=You do not have permission to use this command!
|
||||
@ -385,7 +384,6 @@ luckperms.usage.bulk-update.argument.action=the action to perform on the data. (
|
||||
luckperms.usage.bulk-update.argument.action-field=the field to act upon. only required for ''update''. (''permission'', ''server'' or ''world'')
|
||||
luckperms.usage.bulk-update.argument.action-value=the value to replace with. only required for ''update''.
|
||||
luckperms.usage.bulk-update.argument.constraint=the constraints required for the update
|
||||
luckperms.usage.migration.description=Migration commands
|
||||
luckperms.usage.translations.description=Manage translations
|
||||
luckperms.usage.translations.argument.install=subcommand to install translations
|
||||
luckperms.usage.apply-edits.description=Applies permission changes made from the web editor
|
||||
@ -628,12 +626,3 @@ luckperms.usage.sponge-option-unset.argument.key=the key to unset
|
||||
luckperms.usage.sponge-option-unset.argument.contexts=the contexts to unset the key in
|
||||
luckperms.usage.sponge-option-clear.description=Clears the Subjects options
|
||||
luckperms.usage.sponge-option-clear.argument.contexts=the contexts to clear options in
|
||||
luckperms.usage.migration-command.description=Migration command
|
||||
luckperms.usage.migration-groupmanager.description=Migration command
|
||||
luckperms.usage.migration-groupmanager.argument.migrate-as-global=if world permissions should be ignored, and just migrated as global
|
||||
luckperms.usage.migration-powerfulperms.description=Migration command
|
||||
luckperms.usage.migration-powerfulperms.argument.address=the address of the PP database
|
||||
luckperms.usage.migration-powerfulperms.argument.database=the name of the PP database
|
||||
luckperms.usage.migration-powerfulperms.argument.username=the username to log into the DB
|
||||
luckperms.usage.migration-powerfulperms.argument.password=the password to log into the DB
|
||||
luckperms.usage.migration-powerfulperms.argument.db-table=the name of the PP table where player data is stored
|
||||
|
@ -1,3 +1,28 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -1,3 +1,28 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
@ -1,3 +1,28 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
@ -1,3 +1,28 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@ -37,7 +62,7 @@ public class PaginatedTest {
|
||||
assertEquals("five", page3.get(0).value());
|
||||
assertEquals(5, page3.get(0).position());
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> paginated.getPage(4, 2));
|
||||
assertThrows(IllegalStateException.class, () -> paginated.getPage(4, 2));
|
||||
assertThrows(IllegalArgumentException.class, () -> paginated.getPage(0, 2));
|
||||
assertThrows(IllegalArgumentException.class, () -> paginated.getPage(-1, 2));
|
||||
}
|
||||
|
@ -1,3 +1,28 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.verbose;
|
||||
|
||||
import me.lucko.luckperms.common.verbose.expression.BooleanExpressionCompiler;
|
||||
|
Loading…
Reference in New Issue
Block a user