Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.mvplugins.multiverse.inventories.command;

import com.google.common.collect.Streams;
import org.bukkit.Bukkit;
import org.bukkit.generator.WorldInfo;
import org.jetbrains.annotations.NotNull;
Expand All @@ -14,8 +15,10 @@
import org.mvplugins.multiverse.inventories.config.InventoriesConfig;
import org.mvplugins.multiverse.inventories.dataimport.DataImportManager;
import org.mvplugins.multiverse.inventories.profile.PlayerNamesMapper;
import org.mvplugins.multiverse.inventories.profile.ProfileDataSource;
import org.mvplugins.multiverse.inventories.profile.group.WorldGroup;
import org.mvplugins.multiverse.inventories.profile.group.WorldGroupManager;
import org.mvplugins.multiverse.inventories.profile.key.ContainerType;
import org.mvplugins.multiverse.inventories.profile.key.GlobalProfileKey;
import org.mvplugins.multiverse.inventories.profile.key.ProfileType;
import org.mvplugins.multiverse.inventories.profile.key.ProfileTypes;
Expand All @@ -26,6 +29,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
Expand All @@ -39,25 +43,31 @@ public final class MVInvCommandCompletion {
private final WorldGroupManager worldGroupManager;
private final DataImportManager dataImportManager;
private final PlayerNamesMapper playerNamesMapper;
private final ProfileDataSource profileDataSource;

@Inject
private MVInvCommandCompletion(
@NotNull InventoriesConfig inventoriesConfig,
@NotNull WorldGroupManager worldGroupManager,
@NotNull DataImportManager dataImportManager,
@NotNull MVCommandManager mvCommandManager,
@NotNull PlayerNamesMapper playerNamesMapper
@NotNull PlayerNamesMapper playerNamesMapper,
@NotNull ProfileDataSource profileDataSource
) {
this.inventoriesConfig = inventoriesConfig;
this.worldGroupManager = worldGroupManager;
this.dataImportManager = dataImportManager;
this.playerNamesMapper = playerNamesMapper;
this.profileDataSource = profileDataSource;

MVCommandCompletions commandCompletions = mvCommandManager.getCommandCompletions();
commandCompletions.registerAsyncCompletion("dataimporters", this::suggestDataImporters);
commandCompletions.registerStaticCompletion("mvinvconfigs", inventoriesConfig.getStringPropertyHandle().getAllPropertyNames());
commandCompletions.registerAsyncCompletion("mvinvconfigvalues", this::suggestConfigValues);
commandCompletions.registerAsyncCompletion("mvinvplayername", this::suggestPlayerName);
commandCompletions.registerAsyncCompletion("mvinvplayernames", this::suggestPlayerNames);
commandCompletions.registerAsyncCompletion("mvinvcontainerkey", this::suggestContainerKey);
commandCompletions.registerAsyncCompletion("mvinvcontainerkeys", this::suggestContainerKeys);
commandCompletions.registerAsyncCompletion("mvinvprofiletypes", this::suggestProfileTypes);
commandCompletions.registerAsyncCompletion("sharables", this::suggestSharables);
commandCompletions.registerAsyncCompletion("shares", this::suggestShares);
Expand All @@ -77,6 +87,10 @@ private Collection<String> suggestConfigValues(BukkitCommandCompletionContext co
.getOrElse(Collections.emptyList());
}

private Collection<String> suggestPlayerName(BukkitCommandCompletionContext context) {
return getPlayerNames();
}

private Collection<String> suggestPlayerNames(BukkitCommandCompletionContext context) {
if (Objects.equals(context.getInput(), "@all")) {
return Collections.emptyList();
Expand All @@ -96,6 +110,21 @@ private List<String> getPlayerNames() {
.collect(Collectors.toList());
}

private Collection<String> suggestContainerKey(BukkitCommandCompletionContext context) {
return Arrays.stream(ContainerType.values())
.flatMap(containerType -> profileDataSource.listContainerDataNames(containerType)
.stream()
.map(dataName -> containerType.name().toLowerCase(Locale.ENGLISH) + "=" + dataName))
.collect(Collectors.toList());
}

private Collection<String> suggestContainerKeys(BukkitCommandCompletionContext context) {
//todo handle multiple worlds and/or groups
Collection<String> strings = suggestContainerKey(context);
strings.add("@all");
return strings;
}

private Collection<String> suggestProfileTypes(BukkitCommandCompletionContext context) {
if (!context.hasConfig("multiple")) {
return ProfileTypes.getTypes().stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.mvplugins.multiverse.external.jakarta.inject.Inject;
import org.mvplugins.multiverse.external.jetbrains.annotations.NotNull;
import org.mvplugins.multiverse.external.vavr.control.Option;
import org.mvplugins.multiverse.external.vavr.control.Try;
import org.mvplugins.multiverse.inventories.config.InventoriesConfig;
import org.mvplugins.multiverse.inventories.profile.PlayerNamesMapper;
import org.mvplugins.multiverse.inventories.profile.ProfileDataSource;
Expand All @@ -29,6 +30,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Service
public final class MVInvCommandContexts {
Expand All @@ -52,7 +54,9 @@ private MVInvCommandContexts(
this.profileDataSource = profileDataSource;

CommandContexts<BukkitCommandExecutionContext> commandContexts = commandManager.getCommandContexts();
commandContexts.registerContext(ContainerKey.class, this::parseContainerKey);
commandContexts.registerContext(ContainerKey[].class, this::parseContainerKeyArray);
commandContexts.registerContext(GlobalProfileKey.class, this::parseGlobalProfileKey);
commandContexts.registerContext(GlobalProfileKey[].class, this::parseGlobalProfileKeyArray);
commandContexts.registerIssuerAwareContext(ProfileType.class, this::parseProfileType);
commandContexts.registerIssuerAwareContext(ProfileType[].class, this::parseProfileTypeArray);
Expand All @@ -70,6 +74,22 @@ private ProfileType parseProfileType(BukkitCommandExecutionContext context) {
.getOrElseThrow(() -> new InvalidCommandArgument("Invalid profile type: " + profileType));
}

private ContainerKey parseContainerKey(BukkitCommandExecutionContext context) {
String input = context.popFirstArg();
String[] keyValueSplit = REPatterns.EQUALS.split(input, 2);
if (keyValueSplit.length != 2) {
throw new InvalidCommandArgument("Invalid world/group format: " + input + ". Expected format: type=name");
}
ContainerType containerType = Try.of(() -> ContainerType.valueOf(keyValueSplit[0].toUpperCase()))
.getOrElseThrow(() -> new InvalidCommandArgument("Unknown container type: " + keyValueSplit[0]));
String dataName = keyValueSplit[1];
List<String> availableDataNames = profileDataSource.listContainerDataNames(containerType);
if (!availableDataNames.contains(dataName)) {
throw new InvalidCommandArgument("The " + keyValueSplit[0] + " name " + dataName + " does not have any data.");
}
return ContainerKey.create(containerType, dataName);
}

private ContainerKey[] parseContainerKeyArray(BukkitCommandExecutionContext context) {
String keyStrings = context.popFirstArg();
if (keyStrings.equals("@all")) {
Expand All @@ -84,8 +104,7 @@ private ContainerKey[] parseContainerKeyArray(BukkitCommandExecutionContext cont
for (String typeSplit : typesSplit) {
String[] keyValueSplit = REPatterns.EQUALS.split(typeSplit, 2);
if (keyValueSplit.length != 2) {
// todo: Probably error invalid format
continue;
throw new InvalidCommandArgument("Invalid worlds/groups format: " + typeSplit + ". Expected format: type=name1,name2;type2=name3");
}
ContainerType containerType = ContainerType.valueOf(keyValueSplit[0].toUpperCase());
String[] dataNameSplit = REPatterns.COMMA.split(keyValueSplit[1]);
Expand All @@ -99,9 +118,16 @@ private ContainerKey[] parseContainerKeyArray(BukkitCommandExecutionContext cont
return containerKeys.toArray(new ContainerKey[0]);
}

private GlobalProfileKey parseGlobalProfileKey(BukkitCommandExecutionContext context) {
String keyString = context.popFirstArg();
// todo: UUID parsing
return playerNamesMapper.getKey(keyString)
.getOrElseThrow(() -> new InvalidCommandArgument("Unknown player name: " + keyString));
}

private GlobalProfileKey[] parseGlobalProfileKeyArray(BukkitCommandExecutionContext context) {
String keyStrings = context.popFirstArg();
if (keyStrings.equals("@all")) {
if (Objects.equals(keyStrings, "@all")) {
return playerNamesMapper.getKeys().toArray(GlobalProfileKey[]::new);
}
// todo: UUID parsing
Expand All @@ -114,16 +140,26 @@ private GlobalProfileKey[] parseGlobalProfileKeyArray(BukkitCommandExecutionCont
}

private ProfileType[] parseProfileTypeArray(BukkitCommandExecutionContext context) {
String keyStrings = context.popFirstArg();
if (keyStrings.equals("@all")) {
String keyStrings = context.getFirstArg();
if (keyStrings == null) {
return ProfileTypes.getTypes().toArray(ProfileType[]::new);
}
if (Objects.equals(keyStrings, "@all")) {
context.popFirstArg();
return ProfileTypes.getTypes().toArray(ProfileType[]::new);
}
String[] profileNames = REPatterns.COMMA.split(keyStrings);
return Arrays.stream(profileNames)
List<ProfileType> list = Arrays.stream(profileNames)
.map(ProfileTypes::forName)
.filter(Option::isDefined)
.map(Option::get)
.toArray(ProfileType[]::new);
.toList();
if (list.isEmpty()) {
return ProfileTypes.getTypes().toArray(ProfileType[]::new);
}

context.popFirstArg();
return list.toArray(new ProfileType[0]);
}

private Sharable<?> parseSharable(BukkitCommandExecutionContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.jvnet.hk2.annotations.Contract;
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
import org.mvplugins.multiverse.core.utils.StringFormatter;
import org.mvplugins.multiverse.external.acf.commands.annotation.Subcommand;
import org.mvplugins.multiverse.external.jakarta.inject.Inject;
import org.mvplugins.multiverse.inventories.commands.InventoriesCommand;
import org.mvplugins.multiverse.inventories.profile.bulkedit.BulkEditAction;
Expand All @@ -12,6 +13,7 @@

@Contract
@ApiStatus.Internal
@Subcommand("bulkedit")
public abstract class BulkEditCommand extends InventoriesCommand {

protected final BulkEditCreator bulkEditCreator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ final class ClearCommand extends BulkEditCommand {
this.flags = flags;
}

@Subcommand("bulkedit globalprofile clear")
@Subcommand("globalprofile clear")
@CommandPermission("multiverse.inventories.bulkedit")
@CommandCompletion("@mvinvplayernames @flags:groupName=" + Flags.NAME)
@Syntax("<players> [--clear-all-player-profiles]")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ final class ModifyCommand extends InventoriesCommand {
this.profileDataSource = profileDataSource;
}

@Subcommand("bulkedit globalprofile modify")
@Subcommand("globalprofile modify")
@CommandPermission("multiverse.inventories.bulkedit")
@CommandCompletion("load-on-login|last-world @empty @mvinvplayernames")
@Syntax("<property> <value> <players>")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,23 @@ final class ClearCommand extends BulkEditCommand {
this.flags = flags;
}

@Subcommand("bulkedit playerprofile clear")
@Subcommand("playerprofile clear")
@CommandPermission("multiverse.inventories.bulkedit")
@CommandCompletion("@mvinvplayernames @empty @mvinvprofiletypes:multiple @flags:groupName=" + IncludeGroupsWorldsFlag.NAME)
@Syntax("<players> <groups|worlds> [profile-type] [--include-groups-worlds]")
@CommandCompletion("@mvinvplayernames @mvinvcontainerkeys @mvinvprofiletypes:multiple @flags:groupName=" + IncludeGroupsWorldsFlag.NAME)
@Syntax("<players> <groups/worlds> [profile-type] [--include-groups-worlds]")
void onCommand(
MVCommandIssuer issuer,

@Syntax("<players>")
GlobalProfileKey[] globalProfileKeys,

@Syntax("<groups/worlds>")
ContainerKey[] containerKeys,

@Syntax("[profile-types]")
ProfileType[] profileTypes,

@Syntax("[--include-groups-worlds]")
String[] flagArray
) {
ParsedCommandFlags parsedFlags = flags.parse(flagArray);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.mvplugins.multiverse.inventories.commands.bulkedit.playerprofile;

import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.command.MVCommandIssuer;
import org.mvplugins.multiverse.core.command.flag.ParsedCommandFlags;
import org.mvplugins.multiverse.core.command.queue.CommandQueueManager;
import org.mvplugins.multiverse.core.command.queue.CommandQueuePayload;
import org.mvplugins.multiverse.core.locale.message.Message;
import org.mvplugins.multiverse.external.acf.commands.annotation.CommandCompletion;
import org.mvplugins.multiverse.external.acf.commands.annotation.CommandPermission;
import org.mvplugins.multiverse.external.acf.commands.annotation.Subcommand;
import org.mvplugins.multiverse.external.acf.commands.annotation.Syntax;
import org.mvplugins.multiverse.external.jakarta.inject.Inject;
import org.mvplugins.multiverse.external.jetbrains.annotations.NotNull;
import org.mvplugins.multiverse.inventories.commands.bulkedit.BulkEditCommand;
import org.mvplugins.multiverse.inventories.profile.bulkedit.BulkEditAction;
import org.mvplugins.multiverse.inventories.profile.bulkedit.BulkEditCreator;
import org.mvplugins.multiverse.inventories.profile.bulkedit.PlayerProfilesPayload;
import org.mvplugins.multiverse.inventories.profile.key.ContainerKey;
import org.mvplugins.multiverse.inventories.profile.key.GlobalProfileKey;
import org.mvplugins.multiverse.inventories.profile.key.ProfileType;

@Service
public class ClonePlayerCommand extends BulkEditCommand {

private final @NotNull CommandQueueManager commandQueueManager;
private final @NotNull IncludeGroupsWorldsFlag flags;

@Inject
ClonePlayerCommand(@NotNull BulkEditCreator bulkEditCreator,
@NotNull CommandQueueManager commandQueueManager,
@NotNull IncludeGroupsWorldsFlag flags
) {
super(bulkEditCreator);
this.commandQueueManager = commandQueueManager;
this.flags = flags;
}

@Subcommand("playerprofile clone-player")
@CommandPermission("multiverse.inventories.bulkedit")
@CommandCompletion("@mvinvplayername @mvinvplayername @mvinvcontainerkeys @mvinvprofiletypes:multiple " +
"@flags:groupName=" + IncludeGroupsWorldsFlag.NAME)
@Syntax("<from-player> <to-player> <groups/worlds> [profile-types] [--include-groups-worlds]")
void onCommand(
MVCommandIssuer issuer,

@Syntax("<from-player>")
GlobalProfileKey fromPlayer,

@Syntax("<to-player>")
GlobalProfileKey[] toPlayers,

@Syntax("<groups/worlds>")
ContainerKey[] containerKeys,

@Syntax("[profile-types]")
ProfileType[] profileTypes,

@Syntax("[--include-groups-worlds]")
String[] flagArray
) {
ParsedCommandFlags parsedFlags = flags.parse(flagArray);

BulkEditAction<?> bulkEditAction = bulkEditCreator.playerProfileClonePlayer(
fromPlayer,
new PlayerProfilesPayload(
toPlayers,
containerKeys,
profileTypes,
parsedFlags.hasFlag(flags.includeGroupsWorlds)
)
);

outputActionSummary(issuer, bulkEditAction);

commandQueueManager.addToQueue(CommandQueuePayload.issuer(issuer)
.prompt(Message.of("Are you sure you want to clone profiles from %s to %s for the selected groups/worlds?"
.formatted(fromPlayer.getPlayerName(),
toPlayers.length == 1 ? toPlayers[0].getPlayerName() : toPlayers.length + " players")))
.action(() -> runBulkEditAction(issuer, bulkEditAction)));
}
}
Loading
Loading