diff --git a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/command/RestoreCommand.java b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/command/RestoreCommand.java index d25f6c8..f3398cc 100644 --- a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/command/RestoreCommand.java +++ b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/command/RestoreCommand.java @@ -31,17 +31,25 @@ public class RestoreCommand { public static final LiteralArgumentBuilder restoreCmd = Commands.literal("restore") .requires(it -> PermissionManager.hasPermission(it, 4, PermissionType.ADMIN)) - .then(Commands.argument("name", StringArgumentType.string()) + .then(Commands.argument("target", StringArgumentType.string()) .suggests(((context, builder) -> { - for (StorageInfo info : BackupManager.getBackupsList()) { - if (info.getName().contains(builder.getRemaining())) { - builder.suggest(info.getName()); + List backups = BackupManager.getSortedBackups(); + String remaining = builder.getRemaining(); + int index = 1; + for (StorageInfo info : backups) { + String name = info.getName(); + if (name.contains(remaining)) { + builder.suggest(name); + } + String idx = String.valueOf(index++); + if (idx.startsWith(remaining)) { + builder.suggest(idx); } } return builder.buildFuture(); })) .executes(it -> - restoreBackup(it.getSource(), StringArgumentType.getString(it, "name")) + restoreBackup(it.getSource(), StringArgumentType.getString(it, "target")) ) ); @@ -63,8 +71,9 @@ public class RestoreCommand { @Getter private static final ConcurrentHashMap> restoreDataMap = new ConcurrentHashMap<>(); - private static int restoreBackup(CommandSourceStack commandSource, String name) { - if (!QuickbakcupmultiReforged.getDatabase().storageExists(name)) { + private static int restoreBackup(CommandSourceStack commandSource, String target) { + String name = resolveBackupName(target); + if (name == null || !QuickbakcupmultiReforged.getDatabase().storageExists(name)) { commandSource.sendSystemMessage(Component.nullToEmpty(tr("quickbackupmulti.restore.fail"))); return 0; } @@ -141,4 +150,22 @@ private static int cancelRestore(CommandSourceStack commandSource) { } return 1; } + + private static String resolveBackupName(String target) { + String trimmed = target.trim(); + if (trimmed.isEmpty()) { + return null; + } + if (trimmed.chars().allMatch(Character::isDigit)) { + try { + int index = Integer.parseInt(trimmed); + StorageInfo info = BackupManager.getBackupByIndex(index); + if (info != null) { + return info.getName(); + } + } catch (NumberFormatException ignored) { + } + } + return trimmed; + } } diff --git a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/utils/BackupManager.java b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/utils/BackupManager.java index 68d3f64..c79e72c 100644 --- a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/utils/BackupManager.java +++ b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/utils/BackupManager.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.UUID; @@ -54,6 +55,30 @@ public static List getBackupsList() { return backupList; } + public static List getSortedBackups() { + return getBackupsList().stream() + .sorted(Comparator.comparingLong(StorageInfo::getTimestamp)) + .toList(); + } + + public static StorageInfo getBackupByIndex(int index) { + List backups = getSortedBackups(); + if (index < 1 || index > backups.size()) { + return null; + } + return backups.get(index - 1); + } + + public static int getBackupIndex(String name) { + List backups = getSortedBackups(); + for (int i = 0; i < backups.size(); i++) { + if (backups.get(i).getName().equals(name)) { + return i + 1; + } + } + return -1; + } + public static void makeBackup(CommandSourceStack commandSource, String name, String desc) { if (QuickbakcupmultiReforged.getDatabase().storageExists(name)) { commandSource.sendSystemMessage(Component.nullToEmpty(tr("quickbackupmulti.make.fail_exists"))); diff --git a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/utils/ListBackupsUtils.java b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/utils/ListBackupsUtils.java index 398e920..19bae22 100644 --- a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/utils/ListBackupsUtils.java +++ b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/utils/ListBackupsUtils.java @@ -1,7 +1,6 @@ package io.github.skydynamic.quickbakcupmulti.utils; import io.github.skydynamic.increment.storage.lib.database.StorageInfo; -import io.github.skydynamic.quickbakcupmulti.DatabaseCache; import io.github.skydynamic.quickbakcupmulti.QuickbakcupmultiReforged; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.ClickEvent; @@ -16,7 +15,6 @@ import java.io.IOException; import java.nio.file.Path; import java.text.SimpleDateFormat; -import java.util.Comparator; import java.util.List; import static io.github.skydynamic.quickbakcupmulti.translate.Translate.tr; @@ -67,14 +65,16 @@ private static MutableComponent getNextPageText(int page, int totalPage) { return getPageNavigationText("[->]", page, totalPage, 1); } - private static MutableComponent getSlotText(StorageInfo info, int page, int num) throws IOException { + private static MutableComponent getSlotText(StorageInfo info, int page, int num, int globalIndex) throws IOException { String name = info.getName(); MutableComponent backText = Component.literal("§2[▷] "); MutableComponent deleteText = Component.literal("§c[×] "); MutableComponent nameText = Component.literal("§6" + truncateString(name, 8) + "§r "); + MutableComponent indexText = Component.literal("#" + globalIndex + " ") + .withStyle(style -> style.withColor(ChatFormatting.GRAY)); MutableComponent resultText = Component.literal(""); - backText.withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/qb restore \"%s\"".formatted(name)))) + backText.withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/qb restore " + globalIndex))) .withStyle(style -> style.withHoverEvent( new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.nullToEmpty(tr("quickbackupmulti.list_backup.slot.restore", name))))); @@ -89,6 +89,7 @@ private static MutableComponent getSlotText(StorageInfo info, int page, int num) String desc = info.getDesc(); if (desc.isEmpty()) desc = "Empty"; resultText.append("\n" + tr("quickbackupmulti.list_backup.slot.header", num + (5 * (page - 1))) + " ") + .append(indexText) .append(nameText) .append(backText) .append(deleteText) @@ -98,10 +99,7 @@ private static MutableComponent getSlotText(StorageInfo info, int page, int num) public static MutableComponent list(int page) { long totalBackupSizeB = 0; - List backupList = BackupManager.getBackupsList(); - List backupsInfoList = backupList.stream() - .sorted(Comparator.comparingLong(StorageInfo::getTimestamp)) - .toList(); + List backupsInfoList = BackupManager.getSortedBackups(); if (backupsInfoList.isEmpty() || getPageCount(backupsInfoList, page) == 0) { return Component.literal(tr("quickbackupmulti.list_empty")); } @@ -123,8 +121,8 @@ public static MutableComponent list(int page) { for (int j = 1; j <= getPageCount(backupsInfoList, page); j++) { try { StorageInfo info = backupsInfoList.get(((j - 1) + BACKUPS_PER_PAGE * (page - 1))); - String name = info.getName(); - resultText.append(getSlotText(info, page, j)); + int globalIndex = (page - 1) * BACKUPS_PER_PAGE + j; + resultText.append(getSlotText(info, page, j, globalIndex)); } catch (IOException e) { logger.error("Error while listing backups", e); return Component.literal("Error while listing backups").withStyle(ChatFormatting.RED); @@ -143,7 +141,11 @@ public static MutableComponent search(List searchResultList) { try { String name = searchResultList.get(i - 1); StorageInfo result = QuickbakcupmultiReforged.getDatabase().getStorageInfoWithName(name); - resultText.append(getSlotText(result, 1, i)); + int globalIndex = BackupManager.getBackupIndex(name); + if (globalIndex <= 0) { + globalIndex = i; + } + resultText.append(getSlotText(result, 1, i, globalIndex)); } catch (IOException e) { logger.error("Error while searching backups", e); return Component.literal("Error while searching backups").withStyle(ChatFormatting.RED);