diff --git a/README.md b/README.md index db7d1ac..a3fbf00 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,10 @@ _✨ MC备份 / 回档模组 ✨_ 重构自MCDR插件: [QuickBackupMulti](https://github.com/TISUnion/QuickBackupM) 与 Mod [QuickBackupMulti-Fabric](https://github.com/QuickBackupMultiMod-Dev/QuickBackupM-Fabric) + +## 警告 +### 如果你使用的是v3.1.0之后的mod, 你的之前的备份将会永久丢失, 因为3.1.0更换了更优秀的备份算法, 请做好数据备份 + > [!WARNING] @@ -43,7 +47,7 @@ _✨ MC备份 / 回档模组 ✨_ ## 指令 `/qb` 或 `/quickbackupmulti`均可触发mod -## todo +## 特性 - [ ] 定时备份 - [x] 无限槽位 - [x] Hash对比并仅备份差异文件 diff --git a/build.gradle b/build.gradle index 40318c8..5a3e470 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,7 @@ subprojects { minecraft "net.minecraft:minecraft:$rootProject.minecraft_version" mappings loom.officialMojangMappings() - implementation("io.github.skydynamic:incremental-storage-lib:1.1.0") + implementation("io.github.skydynamic:incremental-storage-lib:1.2.0+build.25062418.20") implementation("org.jetbrains.exposed:exposed-core:0.57.0") implementation("org.jetbrains.exposed:exposed-jdbc:0.57.0") implementation("com.h2database:h2:2.2.224") diff --git a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/QuickbakcupmultiReforged.java b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/QuickbakcupmultiReforged.java index 3d8830c..a90a236 100644 --- a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/QuickbakcupmultiReforged.java +++ b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/QuickbakcupmultiReforged.java @@ -1,7 +1,7 @@ package io.github.skydynamic.quickbakcupmulti; import io.github.skydynamic.increment.storage.lib.database.Database; -import io.github.skydynamic.increment.storage.lib.util.Storager; +import io.github.skydynamic.increment.storage.lib.utils.StorageManager; import io.github.skydynamic.quickbakcupmulti.command.ModCommand; import io.github.skydynamic.quickbakcupmulti.config.ModConfig; import io.github.skydynamic.quickbakcupmulti.translate.Translate; @@ -20,7 +20,7 @@ public final class QuickbakcupmultiReforged { @Getter @Setter private static Database database; @Getter @Setter - private static Storager storager; + private static StorageManager manager; @Getter @Setter private static ServerManager serverManager; @Getter @Setter 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 c8ec979..c7bb851 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 @@ -68,7 +68,7 @@ public void run() { private static final ConcurrentHashMap> restoreDataMap = new ConcurrentHashMap<>(); private static int restoreBackup(CommandSourceStack commandSource, String name) { - if (!QuickbakcupmultiReforged.getStorager().storageExists(name)) { + if (!QuickbakcupmultiReforged.getDatabase().storageExists(name)) { commandSource.sendSystemMessage(Component.nullToEmpty(tr("quickbackupmulti.restore.fail"))); return 0; } @@ -86,7 +86,7 @@ private static int restoreBackup(CommandSourceStack commandSource, String name) private static void executeRestore(CommandSourceStack commandSource) { synchronized (restoreDataMap) { if (restoreDataMap.containsKey("QBM")) { - if (!QuickbakcupmultiReforged.getStorager().storageExists(restoreDataMap.get("QBM").get("Slot").toString())) { + if (!QuickbakcupmultiReforged.getDatabase().storageExists(restoreDataMap.get("QBM").get("Slot").toString())) { commandSource.sendSystemMessage(Component.nullToEmpty(tr("quickbackupmulti.restore.fail"))); restoreDataMap.clear(); return; diff --git a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/config/ModConfig.java b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/config/ModConfig.java index fa26296..8b7d0cf 100644 --- a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/config/ModConfig.java +++ b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/config/ModConfig.java @@ -2,7 +2,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import io.github.skydynamic.increment.storage.lib.Interface.IConfig; +import io.github.skydynamic.increment.storage.lib.manager.IConfig; import lombok.Getter; import lombok.Setter; import org.slf4j.Logger; diff --git a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/database/DatabaseManager.java b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/database/DatabaseManager.java index c110da8..d4ced3b 100644 --- a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/database/DatabaseManager.java +++ b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/database/DatabaseManager.java @@ -1,6 +1,6 @@ package io.github.skydynamic.quickbakcupmulti.database; -import io.github.skydynamic.increment.storage.lib.Interface.IDatabaseManager; +import io.github.skydynamic.increment.storage.lib.manager.IDatabaseManager; import lombok.Getter; import lombok.Setter; diff --git a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/mixin/MixinMinecraftServer.java b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/mixin/MixinMinecraftServer.java index 5b925f7..8bc0874 100644 --- a/common/src/main/java/io/github/skydynamic/quickbakcupmulti/mixin/MixinMinecraftServer.java +++ b/common/src/main/java/io/github/skydynamic/quickbakcupmulti/mixin/MixinMinecraftServer.java @@ -2,8 +2,7 @@ import com.mojang.datafixers.DataFixer; import io.github.skydynamic.increment.storage.lib.database.Database; -import io.github.skydynamic.increment.storage.lib.util.IndexUtil; -import io.github.skydynamic.increment.storage.lib.util.Storager; +import io.github.skydynamic.increment.storage.lib.utils.StorageManager; import io.github.skydynamic.quickbakcupmulti.DatabaseCache; import io.github.skydynamic.quickbakcupmulti.QuickbakcupmultiReforged; import io.github.skydynamic.quickbakcupmulti.database.DatabaseManager; @@ -50,9 +49,7 @@ private void onLoadLevel(CallbackInfoReturnable cir) { ); QuickbakcupmultiReforged.getModContainer().setCurrentSavePath(this.getWorldPath(LevelResource.ROOT)); QuickbakcupmultiReforged.setDatabase(new Database(databaseManager)); - QuickbakcupmultiReforged.setStorager(new Storager(QuickbakcupmultiReforged.getDatabase())); - IndexUtil.setConfig(QuickbakcupmultiReforged.getModConfig()); - IndexUtil.setDatabase(QuickbakcupmultiReforged.getDatabase()); + QuickbakcupmultiReforged.setManager(new StorageManager(QuickbakcupmultiReforged.getDatabase(), QuickbakcupmultiReforged.getModConfig())); if (QuickbakcupmultiReforged.getModConfig().isCacheDatabase()) { DatabaseCache.updateStorageInfoCaches(); } 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 85ba321..188ead2 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 @@ -1,7 +1,5 @@ package io.github.skydynamic.quickbakcupmulti.utils; -import io.github.skydynamic.increment.storage.lib.database.StorageInfo; -import io.github.skydynamic.increment.storage.lib.util.IndexUtil; import io.github.skydynamic.quickbakcupmulti.QuickbakcupmultiReforged; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; @@ -20,6 +18,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.function.Consumer; @@ -43,7 +42,7 @@ public static Path getBackupPath() { } private static void getBackupExists(File file, Consumer consumer) { - if (file.isDirectory() && QuickbakcupmultiReforged.getStorager().storageExists(file.getName())) { + if (file.isDirectory() && QuickbakcupmultiReforged.getDatabase().storageExists(file.getName())) { consumer.accept(file.getName()); } } @@ -61,7 +60,7 @@ public static List getBackupsList() { } public static void makeBackup(CommandSourceStack commandSource, String name, String desc) { - if (QuickbakcupmultiReforged.getStorager().storageExists(name)) { + if (QuickbakcupmultiReforged.getDatabase().storageExists(name)) { commandSource.sendSystemMessage(Component.nullToEmpty(tr("quickbackupmulti.make.fail_exists"))); return; } @@ -75,14 +74,13 @@ public static void makeBackup(CommandSourceStack commandSource, String name, Str serverLevel.noSave = true; } - StorageInfo storageInfo = new StorageInfo(name, desc, System.currentTimeMillis(), true, new ArrayList<>()); - - QuickbakcupmultiReforged.getStorager() - .incrementalStorage( - storageInfo, QuickbakcupmultiReforged.getModContainer().getCurrentSavePath(), - BackupManager.getBackupPath().resolve(name), - fileFilter, folderFilter - ); + QuickbakcupmultiReforged.getManager().incrementalStorage( + name, + desc, + QuickbakcupmultiReforged.getModContainer().getCurrentSavePath().toFile(), + fileFilter, + folderFilter + ); long endTime = System.currentTimeMillis(); double intervalTime = (endTime - startTime) / 1000.0; @@ -97,43 +95,30 @@ public static void makeBackup(CommandSourceStack commandSource, String name, Str } catch (Exception e) { logger.error("Make Backup Failed", e); commandSource.sendSystemMessage(Component.nullToEmpty(tr("quickbackupmulti.make.fail", e.toString()))); - try { - FileUtils.forceDeleteOnExit(getBackupPath().resolve(name).toFile()); - } catch (IOException ex) { - logger.error("Delete Backup Failed", ex); - } } } public static boolean deleteBackup(CommandSourceStack commandSource, String name) { - if (QuickbakcupmultiReforged.getStorager().storageExists(name)) { - try { - IndexUtil.reIndex(name, ""); - QuickbakcupmultiReforged.getStorager().deleteStorage(name); - FileUtils.deleteDirectory(getBackupPath().resolve(name).toFile()); - return true; - } catch (IOException e) { - logger.error("Delete Backup Failed", e); - return false; - } - } else return false; + if (QuickbakcupmultiReforged.getDatabase().storageExists(name)) { + QuickbakcupmultiReforged.getManager().deleteStorage(name); + return true; + } else { + return false; + } } public static void restoreBackup(String name) { - File targetBackupSlot = getBackupPath().resolve(name).toFile(); + Map hashMap = QuickbakcupmultiReforged.getDatabase().getFileHashMap(name); Path savePath = QuickbakcupmultiReforged.getModContainer().getCurrentSavePath(); try { - for (File file : FileUtils.listFiles(savePath.toFile(), fileFilter, folderFilter)) { - if (file.equals(savePath.toFile())) continue; - FileUtils.forceDelete(file); + for (Map.Entry entry : hashMap.entrySet()) { + String fileHash = entry.getKey(); + String fileName = entry.getValue(); + String hashStart = fileHash.substring(0, 2); + File hashFile = new File(QuickbakcupmultiReforged.getModConfig().getStoragePath(), "blogs/" + hashStart + "/" + fileHash); + File targetDir = savePath.resolve(fileName).toFile(); + FileUtils.copyFile(hashFile, targetDir); } - - FileUtils.copyDirectory(targetBackupSlot, savePath.toFile()); - IndexUtil.copyIndexFile( - name, - Path.of(QuickbakcupmultiReforged.getModConfig().getStoragePath()).resolve(""), - savePath.toFile() - ); } catch (IOException e) { logger.error("Restore Failed", e); } 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 7653521..5f721ba 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 @@ -68,7 +68,7 @@ private static MutableComponent getNextPageText(int page, int totalPage) { return getPageNavigationText("[->]", page, totalPage, 1); } - private static MutableComponent getSlotText(StorageInfo info, int page, int num, long backupSizeB) throws IOException { + private static MutableComponent getSlotText(StorageInfo info, int page, int num) throws IOException { String name = info.getName(); MutableComponent backText = Component.literal("§2[▷] "); MutableComponent deleteText = Component.literal("§c[×] "); @@ -89,14 +89,10 @@ private static MutableComponent getSlotText(StorageInfo info, int page, int num, String desc = info.getDesc(); if (desc.isEmpty()) desc = "Empty"; - double backupSizeMB = (double) backupSizeB / FileUtils.ONE_MB; - double backupSizeGB = (double) backupSizeB / FileUtils.ONE_GB; - String sizeString = (backupSizeMB >= 1000) ? String.format("%.2fGB", backupSizeGB) : String.format("%.2fMB", backupSizeMB); resultText.append("\n" + tr("quickbackupmulti.list_backup.slot.header", num + (5 * (page - 1))) + " ") .append(nameText) .append(backText) .append(deleteText) - .append("§a" + sizeString) .append(String.format(" §b%s§7: §r%s", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(info.getTimestamp()), truncateString(desc, 10))); return resultText; } @@ -116,6 +112,10 @@ public static MutableComponent list(int page) { return Component.literal(tr("quickbackupmulti.list_empty")); } int totalPage = getTotalPage(backupsInfoList); + File blogsDir = backupPath.resolve("blogs").toFile(); + if (blogsDir.exists()) { + totalBackupSizeB = getDirSize(blogsDir); + } MutableComponent resultText = Component.literal(tr("quickbackupmulti.list_backup.title", page)); MutableComponent backPageText = getBackPageText(page, totalPage); @@ -130,9 +130,7 @@ public static MutableComponent list(int page) { try { StorageInfo info = backupsInfoList.get(((j - 1) + BACKUPS_PER_PAGE * (page - 1))); String name = info.getName(); - long backupSizeB = getDirSize(backupPath.resolve(name).toFile()); - totalBackupSizeB += backupSizeB; - resultText.append(getSlotText(info, page, j, backupSizeB)); + resultText.append(getSlotText(info, page, j)); } catch (IOException e) { logger.error("Error while listing backups", e); return Component.literal("Error while listing backups").withStyle(ChatFormatting.RED); @@ -151,8 +149,7 @@ public static MutableComponent search(List searchResultList) { try { String name = searchResultList.get(i - 1); StorageInfo result = QuickbakcupmultiReforged.getDatabase().getStorageInfoWithName(name); - long backupSizeB = getDirSize(backupPath.resolve(name).toFile()); - resultText.append(getSlotText(result, 1, i, backupSizeB)); + resultText.append(getSlotText(result, 1, i)); } catch (IOException e) { logger.error("Error while searching backups", e); return Component.literal("Error while searching backups").withStyle(ChatFormatting.RED); @@ -163,7 +160,7 @@ public static MutableComponent search(List searchResultList) { public static MutableComponent show(String name) { MutableComponent resultText; - if (QuickbakcupmultiReforged.getStorager().storageExists(name)) { + if (QuickbakcupmultiReforged.getDatabase().storageExists(name)) { StorageInfo backupInfo = QuickbakcupmultiReforged.getDatabase().getStorageInfoWithName(name); resultText = Component.literal(tr("quickbackupmulti.show.header")); String desc = backupInfo.getDesc(); diff --git a/gradle.properties b/gradle.properties index ad94c9c..72803d3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs = -Xmx2G org.gradle.parallel = true # Mod properties -mod_version = 3.0.2 +mod_version = 3.1.0 maven_group = io.github.skydynamic mod_id = quickbakcupmulti_reforged archives_name = QuickBakcupMulti-Reforged