Move migration commands to a separate jar

This commit is contained in:
Luck 2020-12-22 14:53:22 +00:00
parent 142cdc8e89
commit 5c44333892
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
26 changed files with 157 additions and 2501 deletions

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}
}

View File

@ -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(); }
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -56,9 +56,6 @@ luckperms {
}
}
}
migration {
plugin brigadier:string single_word;
}
translations {
install;
}

View File

@ -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 {

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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())

View File

@ -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),

View File

@ -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;

View File

@ -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) {
}
}

View File

@ -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();
}
}

View File

@ -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")

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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));
}

View File

@ -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;